ich muss Listen mit requirements auf Kompatibilität prüfen, mir raucht der Kopf. Wer kann löschen?

Leider schlagen noch einige Tests fehl und ich bekomme es nicht hin. Ich sitze schon etliche Stunden dran und sehe schon bunte Farbbälle vor meinem geistigem Auge ( nein, ich nehme keine Drogen).
Hat da jemand Tipps für mich und sieht den/die Fehler? Mir raucht der Kopf
Der TestCase
Code: Alles auswählen
class TestCompareVersions(TestCase):
def test_exact_match(self):
self.assertTrue(compare_versions("==1.2.3", "==1.2.3"))
self.assertFalse(compare_versions("==1.2.3", "==1.2.4"))
def test_minimum_version(self):
self.assertTrue(compare_versions("==2.1.0", ">=2.0.0"))
self.assertFalse(compare_versions("==1.2.3", ">=2.0.0"))
def test_maximum_version(self):
self.assertTrue(compare_versions("==1.2.3", "<=2.0.0"))
self.assertFalse(compare_versions("==2.1.0", "<=2.0.0"))
def test_range_versions(self):
self.assertTrue(compare_versions("==1.2.3", ">=1.2,<2.0"))
self.assertFalse(compare_versions("==2.0.0", ">=1.2,<2.0"))
def test_tilde_operator(self):
self.assertTrue(compare_versions("==1.2.3", "~=1.2.0"))
self.assertTrue(compare_versions("==1.2.4", "~=1.2.0"))
self.assertFalse(compare_versions("==1.3.0", "~=1.2.0"))
self.assertFalse(compare_versions("==2.0.0", "~=1.2.0"))
def test_caret_operator(self):
self.assertTrue(compare_versions("==1.2.3", "^1.2.0"))
self.assertTrue(compare_versions("==1.2.4", "^1.2.0"))
self.assertFalse(compare_versions("==2.0.0", "^1.2.0"))
def test_invalid_syntax(self):
# Hier werden Versionen mit ungültiger Syntax getestet
self.assertFalse(compare_versions("==1.2.3", "abc"))
self.assertFalse(compare_versions("==1.2.3", ">1.2,<=2.0"))
self.assertFalse(compare_versions("==1.2.3", ">=1.2,<2.0,<=3.0"))
def test_all_operators(self):
# Teste alle Operatoren im ersten Parameter
self.assertTrue(compare_versions("<=2.1.0", ">=2.0.0"))
self.assertTrue(compare_versions("<=2.1.0", ">2.0.0"))
self.assertTrue(compare_versions("<=2.1.0", "<3.0.0"))
self.assertTrue(compare_versions("!=1.0.0", "<3.0.0"))
self.assertFalse(compare_versions("!=1.0.0", "==1.0.0"))
self.assertTrue(compare_versions("!=1.0.0", "!=1.0.1"))
self.assertFalse(compare_versions("!=1.0.0", "!=1.0.0"))
self.assertTrue(compare_versions("==1.2.3", "==1.2.3"))
self.assertFalse(compare_versions("==1.2.3", "==1.2.4"))
def test_combined_ranges(self):
# Teste kombinierte Bereichsangaben
self.assertTrue(compare_versions(">=1.2,<3.0", "~=2.5"))
self.assertFalse(compare_versions(">=1.2,<3.0", "~=3.0"))
self.assertTrue(compare_versions(">=1.2,<3.0", "^2.0"))
self.assertFalse(compare_versions(">=1.2,<3.0", "^3.0"))
def test_invalid_operator_combination(self):
# Teste ungültige Operator-Kombinationen
self.assertFalse(compare_versions("<=2.1.0", ">2.0.0"))
self.assertFalse(compare_versions("~=1.2.3", "<3.0.0"))
self.assertFalse(compare_versions("^2.1.0", "==2.1.0"))
Die Funktion
Code: Alles auswählen
def compare_versions(version, constraint):
operators: List[str] = ["==", ">=", "<=", ">=", "~=", "=^", "<", ">"]
def version_tuple(ver):
try:
return tuple(map(int, ver.split(".")))
except ValueError:
return ()
# Verwenden von regulären Ausdrücken, um den Constraint-String zu analysieren
match = re.match(r"^([<>=~^!]*)([\d+\.]+|\d+)$", constraint)
if match:
contraint_op, required_ver = match.groups()
else:
return False
match = re.match(r"^([<>=~^!]*)([\d+\.]+|\d+)$", version)
if match:
version_op, version_ver = match.groups()
else:
return False
# prüfe den Operator
if contraint_op not in operators:
return False
if version_op not in operators:
return False
# Prüfen, ob die Version dem Constraint entspricht
if contraint_op == "~":
# Tilde-Operator
tolerance = 0 if not required_ver.endswith(".0") else 1
return all(
abs(version_tuple(version_ver)[i] - int(ver)) <= tolerance
for i, ver in enumerate(required_ver.split("."))
)
elif contraint_op == "^":
# Caret-Operator
tolerance = 0 if not required_ver.endswith(".0") else 1
return all(
version_tuple(version_ver)[i] <= int(ver) + tolerance
for i, ver in enumerate(required_ver.split("."))
)
elif contraint_op == ">=":
# Mindestversion
return version_tuple(version_ver) >= version_tuple(required_ver)
elif contraint_op == "<=":
# Maximale Version
return version_tuple(version_ver) <= version_tuple(required_ver)
elif contraint_op == ">":
return version_tuple(version_ver) > version_tuple(required_ver)
elif contraint_op == "<":
return version_tuple(version_ver) < version_tuple(required_ver)
elif contraint_op == "":
return version_ver == required_ver
elif contraint_op == "!":
return version_tuple(version_ver) != version_tuple(required_ver)
elif contraint_op == "==":
# Exakte Versionsnummer
return version_tuple(version_ver) == version_tuple(required_ver)
# Unterstützung für kombinierte Bereichsangaben
if "," in required_ver:
range_parts = required_ver.split(",")
return all(
compare_versions(version_ver, f"{contraint_op}{part}") for part in range_parts
)
return False
Code: Alles auswählen
test_all_operators
self.assertTrue(compare_versions("<=2.1.0", ">=2.0.0"))
AssertionError: False is not true
test_caret_operator
self.assertTrue(compare_versions("1.2.3", "^1.2.0"))
AssertionError: False is not true
test_combined_ranges
self.assertTrue(compare_versions(">=1.2,<3.0", "~=2.5"))
AssertionError: False is not true
test_invalid_operator_combination
self.assertFalse(compare_versions("~=1.2.3", "<3.0.0"))
AssertionError: True is not false
test_range_versions
self.assertTrue(compare_versions("1.2.3", ">=1.2,<2.0"))
AssertionError: False is not true
test_tilde_operator
self.assertTrue(compare_versions("1.2.3", "~=1.2.0"))
AssertionError: False is not true