Skip to content
This repository was archived by the owner on Apr 26, 2024. It is now read-only.

Commit bf9d549

Browse files
David Robertsonsquahtx
David Robertson
andauthored
Try to detect borked package installations. (#12244)
* Try to detect borked package installations. Fixes #12223. Co-authored-by: Sean Quah <8349537+squahtx@users.noreply.github.com>
1 parent 8fe930c commit bf9d549

File tree

3 files changed

+38
-2
lines changed

3 files changed

+38
-2
lines changed

changelog.d/12244.misc

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Improve error message when dependencies check finds a broken installation.

synapse/util/check_dependencies.py

+23-1
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,19 @@ def _incorrect_version(
128128
)
129129

130130

131+
def _no_reported_version(requirement: Requirement, extra: Optional[str] = None) -> str:
132+
if extra:
133+
return (
134+
f"Synapse {VERSION} needs {requirement} for {extra}, "
135+
f"but can't determine {requirement.name}'s version"
136+
)
137+
else:
138+
return (
139+
f"Synapse {VERSION} needs {requirement}, "
140+
f"but can't determine {requirement.name}'s version"
141+
)
142+
143+
131144
def check_requirements(extra: Optional[str] = None) -> None:
132145
"""Check Synapse's dependencies are present and correctly versioned.
133146
@@ -163,8 +176,17 @@ def check_requirements(extra: Optional[str] = None) -> None:
163176
deps_unfulfilled.append(requirement.name)
164177
errors.append(_not_installed(requirement, extra))
165178
else:
179+
if dist.version is None:
180+
# This shouldn't happen---it suggests a borked virtualenv. (See #12223)
181+
# Try to give a vaguely helpful error message anyway.
182+
# Type-ignore: the annotations don't reflect reality: see
183+
# https://github.com/python/typeshed/issues/7513
184+
# https://bugs.python.org/issue47060
185+
deps_unfulfilled.append(requirement.name) # type: ignore[unreachable]
186+
errors.append(_no_reported_version(requirement, extra))
187+
166188
# We specify prereleases=True to allow prereleases such as RCs.
167-
if not requirement.specifier.contains(dist.version, prereleases=True):
189+
elif not requirement.specifier.contains(dist.version, prereleases=True):
168190
deps_unfulfilled.append(requirement.name)
169191
errors.append(_incorrect_version(requirement, dist.version, extra))
170192

tests/util/test_check_dependencies.py

+14-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313

1414
class DummyDistribution(metadata.Distribution):
15-
def __init__(self, version: str):
15+
def __init__(self, version: object):
1616
self._version = version
1717

1818
@property
@@ -30,6 +30,7 @@ def read_text(self, filename):
3030
old_release_candidate = DummyDistribution("0.1.2rc3")
3131
new = DummyDistribution("1.2.3")
3232
new_release_candidate = DummyDistribution("1.2.3rc4")
33+
distribution_with_no_version = DummyDistribution(None)
3334

3435
# could probably use stdlib TestCase --- no need for twisted here
3536

@@ -67,6 +68,18 @@ def test_mandatory_dependency(self) -> None:
6768
# should not raise
6869
check_requirements()
6970

71+
def test_version_reported_as_none(self) -> None:
72+
"""Complain if importlib.metadata.version() returns None.
73+
74+
This shouldn't normally happen, but it was seen in the wild (#12223).
75+
"""
76+
with patch(
77+
"synapse.util.check_dependencies.metadata.requires",
78+
return_value=["dummypkg >= 1"],
79+
):
80+
with self.mock_installed_package(distribution_with_no_version):
81+
self.assertRaises(DependencyException, check_requirements)
82+
7083
def test_checks_ignore_dev_dependencies(self) -> None:
7184
"""Bot generic and per-extra checks should ignore dev dependencies."""
7285
with patch(

0 commit comments

Comments
 (0)