"""
Exercise 1: version comparison and specifiers (medium)

Implement (a simplified PEP 440):
  - parse_version("1.4.2") -> (1, 4, 2); missing parts are 0 ("2" -> (2, 0, 0), "2.1" -> (2, 1, 0)).
  - satisfies(version, spec): spec is a comma-separated list of clauses, ALL must hold:
        "==X", "!=X", ">=X", ">X", "<=X", "<X", "~=X"
    "~=X.Y" means >= X.Y and same major X (compatible release: == X.*).
    "~=X.Y.Z" means >= X.Y.Z and same X.Y (== X.Y.*).
    Spaces around clauses should be ignored.
  - best_match(versions, spec): the highest version (string) satisfying spec, or None.
"""

def parse_version(v):
    return (0, 0, 0)  # TODO


def satisfies(version, spec):
    return True  # TODO


def best_match(versions, spec):
    return None  # TODO


# --- self-check: do not modify below this line ---
checks = []
checks.append(("parse", (parse_version("1.4.2"), parse_version("2"), parse_version("2.1")), ((1, 4, 2), (2, 0, 0), (2, 1, 0))))
checks.append(("range", (satisfies("2.5.0", ">=2.1,<3"), satisfies("3.0", ">=2.1,<3")), (True, False)))
checks.append(("exclusion", satisfies("2.1.5", ">=2, !=2.1.5"), False))
checks.append(("compatible ~=2.1", (satisfies("2.9.1", "~=2.1"), satisfies("3.0", "~=2.1"), satisfies("2.0.9", "~=2.1")), (True, False, False)))
checks.append(("compatible ~=2.1.3", (satisfies("2.1.9", "~=2.1.3"), satisfies("2.2.0", "~=2.1.3")), (True, False)))
vs = ["1.9.0", "2.0.0", "2.4.1", "2.10.0", "3.0.0"]
checks.append(("best match uses numeric order", best_match(vs, ">=2,<3"), "2.10.0"))
checks.append(("no match", best_match(vs, ">=4"), None))

passed = 0
for label, actual, expected in checks:
    ok = actual == expected
    passed += ok
    print(f"{'PASS' if ok else 'FAIL'}: {label} (got {actual!r}, expected {expected!r})")

print("PASS" if passed == len(checks) else "FAIL")
