Skip to content

Commit a8a318b

Browse files
committed
Add error handling for connectivity issues in filters latest_volto and latest_plone (Fixes #110)
1 parent 5bba381 commit a8a318b

File tree

5 files changed

+78
-11
lines changed

5 files changed

+78
-11
lines changed

cookieplone/filters/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,14 +73,14 @@ def use_prerelease_versions(_: str) -> str:
7373
def latest_volto(use_prerelease_versions: str) -> str:
7474
"""Return the latest released version of Volto."""
7575
allow_prerelease = parse_boolean(use_prerelease_versions)
76-
return versions.latest_volto(allow_prerelease=allow_prerelease)
76+
return versions.latest_volto(allow_prerelease=allow_prerelease) or ""
7777

7878

7979
@simple_filter
8080
def latest_plone(use_prerelease_versions: str) -> str:
8181
"""Return the latest released version of Plone."""
8282
allow_prerelease = parse_boolean(use_prerelease_versions)
83-
return versions.latest_plone(allow_prerelease=allow_prerelease)
83+
return versions.latest_plone(allow_prerelease=allow_prerelease) or ""
8484

8585

8686
@simple_filter

cookieplone/settings.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,3 +73,6 @@ class PythonVersionSupport:
7373
REPO_LOCATION = "COOKIEPLONE_REPOSITORY"
7474
REPO_TAG = "COOKIEPLONE_REPOSITORY_TAG"
7575
REPO_PASSWORD = "COOKIEPLONE_REPO_PASSWORD" # noQA:S105
76+
77+
# Connectivity
78+
REQUESTS_TIMEOUT = 10

cookieplone/utils/versions.py

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,10 @@ def convert_pep440_semver(version: str) -> str:
4646
def get_npm_package_versions(package: str) -> list[str]:
4747
"""Get versions for a npm package."""
4848
url: str = f"https://registry.npmjs.org/{package}"
49-
resp = requests.get( # noQA: S113
50-
url, headers={"Accept": "application/vnd.npm.install-v1+json"}
49+
resp = requests.get(
50+
url,
51+
headers={"Accept": "application/vnd.npm.install-v1+json"},
52+
timeout=settings.REQUESTS_TIMEOUT,
5153
)
5254
data = resp.json()
5355
return list(data["dist-tags"].values())
@@ -56,7 +58,7 @@ def get_npm_package_versions(package: str) -> list[str]:
5658
def get_pypi_package_versions(package: str) -> list[str]:
5759
"""Get versions for a PyPi package."""
5860
url: str = f"https://pypi.org/pypi/{package}/json"
59-
resp = requests.get(url) # noQA: S113
61+
resp = requests.get(url, timeout=settings.REQUESTS_TIMEOUT)
6062
data = resp.json()
6163
return list(data.get("releases").keys())
6264

@@ -84,15 +86,15 @@ def version_latest(
8486
max_version: str | None = None,
8587
allow_prerelease: bool = False,
8688
) -> str | None:
87-
min_version = Version(min_version) if min_version else None
88-
max_version = Version(max_version) if max_version else None
89+
min_version_ = Version(min_version) if min_version else None
90+
max_version_ = Version(max_version) if max_version else None
8991
versions_ = sorted(
9092
[(Version(v.replace("v", "")), v) for v in versions], reverse=True
9193
)
9294
valid = [
9395
(version, raw_version)
9496
for version, raw_version in versions_
95-
if is_valid_version(version, min_version, max_version, allow_prerelease)
97+
if is_valid_version(version, min_version_, max_version_, allow_prerelease)
9698
]
9799
return valid[0][1] if valid else None
98100

@@ -103,7 +105,10 @@ def latest_volto(
103105
allow_prerelease: bool = False,
104106
) -> str | None:
105107
"""Return the latest volto version."""
106-
versions = get_npm_package_versions("@plone/volto")
108+
try:
109+
versions = get_npm_package_versions("@plone/volto")
110+
except requests.RequestException:
111+
versions = []
107112
return version_latest(
108113
versions,
109114
min_version=min_version,
@@ -118,7 +123,11 @@ def latest_plone(
118123
allow_prerelease: bool = False,
119124
) -> str | None:
120125
"""Return the latest Plone version."""
121-
versions = get_pypi_package_versions("Plone")
126+
127+
try:
128+
versions = get_pypi_package_versions("Plone")
129+
except requests.RequestException:
130+
versions = []
122131
return version_latest(
123132
versions,
124133
min_version=min_version,
@@ -138,7 +147,7 @@ def python_versions_for_plone(plone_version: str) -> settings.PythonVersionSuppo
138147
major = Version(plone_version).major
139148
minor = Version(plone_version).minor
140149
version = f"{major}.{minor}"
141-
return settings.PLONE_PYTHON.get(version)
150+
return settings.PLONE_PYTHON[version]
142151

143152

144153
def python_version_for_plone(plone_version: str) -> str:

news/110.bugfix

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Add error handling for connectivity issues in filters `latest_volto` and `latest_plone`. @ericof

tests/utils/test_versions.py

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,17 @@ def get_pypi_package_versions(*args, **kwargs):
113113
)
114114

115115

116+
@pytest.fixture
117+
def mock_packages_with_raise(monkeypatch, volto_versions):
118+
import requests
119+
120+
def get_package_versions(*args, **kwargs):
121+
raise requests.ConnectionError("Unable to connect")
122+
123+
monkeypatch.setattr(versions, "get_npm_package_versions", get_package_versions)
124+
monkeypatch.setattr(versions, "get_pypi_package_versions", get_package_versions)
125+
126+
116127
@pytest.mark.parametrize(
117128
"version,min_version,max_version,allow_prerelease,expected",
118129
[
@@ -202,6 +213,28 @@ def test_latest_volto(
202213
assert func(min_version, max_version, allow_prerelease) == expected
203214

204215

216+
@pytest.mark.parametrize(
217+
"min_version,max_version,allow_prerelease,expected",
218+
[
219+
[None, None, True, None],
220+
[None, None, False, None],
221+
["17", None, False, None],
222+
["17", "18", False, None],
223+
["17", "18", True, None],
224+
["17", "17.99", True, None],
225+
],
226+
)
227+
def test_latest_volto_no_connection(
228+
mock_packages_with_raise,
229+
min_version: str,
230+
max_version: str,
231+
allow_prerelease: bool,
232+
expected: str,
233+
):
234+
func = versions.latest_volto
235+
assert func(min_version, max_version, allow_prerelease) == expected
236+
237+
205238
@pytest.mark.parametrize(
206239
"min_version,max_version,allow_prerelease,expected",
207240
[
@@ -223,6 +256,27 @@ def test_latest_plone(
223256
assert func(min_version, max_version, allow_prerelease) == expected
224257

225258

259+
@pytest.mark.parametrize(
260+
"min_version,max_version,allow_prerelease,expected",
261+
[
262+
[None, None, False, None],
263+
[None, None, True, None],
264+
[None, "5.99", False, None],
265+
["5", "5.2", False, None],
266+
["5", "6", False, None],
267+
],
268+
)
269+
def test_latest_plone_no_connection(
270+
mock_packages_with_raise,
271+
min_version: str,
272+
max_version: str,
273+
allow_prerelease: bool,
274+
expected: str,
275+
):
276+
func = versions.latest_plone
277+
assert func(min_version, max_version, allow_prerelease) == expected
278+
279+
226280
@pytest.mark.parametrize(
227281
"plone_version,supported,earliest,latest",
228282
[

0 commit comments

Comments
 (0)