From 6374d2a5e6560efa453972542f4fafdefa14308a Mon Sep 17 00:00:00 2001 From: Jacob Coffee Date: Wed, 8 Oct 2025 09:40:36 -0500 Subject: [PATCH 1/2] fix: handle release objects with 'invalid' names --- downloads/models.py | 5 ++++- downloads/tests/test_models.py | 8 ++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/downloads/models.py b/downloads/models.py index 3c0a74f97..cea9dd45a 100644 --- a/downloads/models.py +++ b/downloads/models.py @@ -128,8 +128,11 @@ def get_version(self): return None def is_version_at_least(self, min_version_tuple): + version = self.get_version() + if version is None: + return False v1 = [] - for b in self.get_version().split('.'): + for b in version.split('.'): try: v1.append(int(b)) except ValueError: diff --git a/downloads/tests/test_models.py b/downloads/tests/test_models.py index d31afae5c..70de52262 100644 --- a/downloads/tests/test_models.py +++ b/downloads/tests/test_models.py @@ -87,3 +87,11 @@ def test_is_version_at_least(self): release_310 = Release.objects.create(name='Python 3.10.0') self.assertTrue(release_310.is_version_at_least_3_9) self.assertTrue(release_310.is_version_at_least_3_5) + + def test_is_version_at_least_with_invalid_name(self): + """Test that is_version_at_least returns False for releases with invalid names""" + invalid_release = Release.objects.create(name='Python install manager') + # Should return False instead of raising AttributeError + self.assertFalse(invalid_release.is_version_at_least_3_5) + self.assertFalse(invalid_release.is_version_at_least_3_9) + self.assertFalse(invalid_release.is_version_at_least_3_14) From f809fd19933ff7c9da6cde8799fe1d77fd5c8951 Mon Sep 17 00:00:00 2001 From: Jacob Coffee Date: Wed, 8 Oct 2025 10:23:13 -0500 Subject: [PATCH 2/2] fix: handle release objects with 'invalid' names but on the method side --- downloads/models.py | 9 +++------ downloads/tests/test_models.py | 2 +- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/downloads/models.py b/downloads/models.py index cea9dd45a..6a810c393 100644 --- a/downloads/models.py +++ b/downloads/models.py @@ -125,14 +125,11 @@ def get_version(self): version = re.match(r'Python\s([\d.]+)', self.name) if version is not None: return version.group(1) - return None + return "" def is_version_at_least(self, min_version_tuple): - version = self.get_version() - if version is None: - return False v1 = [] - for b in version.split('.'): + for b in self.get_version().split('.'): try: v1.append(int(b)) except ValueError: @@ -294,7 +291,7 @@ def purge_fastly_download_pages(sender, instance, **kwargs): purge_url('/downloads/source/') purge_url('/downloads/windows/') purge_url('/ftp/python/') - if instance.get_version() is not None: + if instance.get_version(): purge_url(f'/ftp/python/{instance.get_version()}/') # See issue #584 for details purge_url('/box/supernav-python-downloads/') diff --git a/downloads/tests/test_models.py b/downloads/tests/test_models.py index 70de52262..e73858d3b 100644 --- a/downloads/tests/test_models.py +++ b/downloads/tests/test_models.py @@ -74,7 +74,7 @@ def test_get_version_invalid(self): with self.subTest(name=name): release = Release.objects.create(name=name) self.assertEqual(release.name, name) - self.assertIsNone(release.get_version()) + self.assertEqual(release.get_version(), "") def test_is_version_at_least(self): self.assertFalse(self.release_275.is_version_at_least_3_5)