58 lines
2.0 KiB
Python
58 lines
2.0 KiB
Python
from typing import Optional
|
|
|
|
from packaging.specifiers import InvalidSpecifier, SpecifierSet
|
|
from packaging.version import InvalidVersion, Version
|
|
|
|
|
|
def is_compatible_version(
|
|
version: str, constraint: str, prereleases: bool = True
|
|
) -> Optional[bool]:
|
|
"""Check if a version (e.g. "2.0.0") is compatible given a version
|
|
constraint (e.g. ">=1.9.0,<2.2.1"). If the constraint is a specific version,
|
|
it's interpreted as =={version}.
|
|
|
|
version (str): The version to check.
|
|
constraint (str): The constraint string.
|
|
prereleases (bool): Whether to allow prereleases. If set to False,
|
|
prerelease versions will be considered incompatible.
|
|
RETURNS (bool / None): Whether the version is compatible, or None if the
|
|
version or constraint are invalid.
|
|
"""
|
|
# Handle cases where exact version is provided as constraint
|
|
if constraint[0].isdigit():
|
|
constraint = f"=={constraint}"
|
|
try:
|
|
spec = SpecifierSet(constraint)
|
|
version = Version(version) # type: ignore[assignment]
|
|
except (InvalidSpecifier, InvalidVersion):
|
|
return None
|
|
spec.prereleases = prereleases
|
|
return version in spec
|
|
|
|
|
|
def get_minor_version(version: str) -> Optional[str]:
|
|
"""Get the major + minor version (without patch or prerelease identifiers).
|
|
|
|
version (str): The version.
|
|
RETURNS (str): The major + minor version or None if version is invalid.
|
|
"""
|
|
try:
|
|
v = Version(version)
|
|
except (TypeError, InvalidVersion):
|
|
return None
|
|
return f"{v.major}.{v.minor}"
|
|
|
|
|
|
def is_minor_version_match(version_a: str, version_b: str) -> bool:
|
|
"""Compare two versions and check if they match in major and minor, without
|
|
patch or prerelease identifiers. Used internally for compatibility checks
|
|
that should be insensitive to patch releases.
|
|
|
|
version_a (str): The first version
|
|
version_b (str): The second version.
|
|
RETURNS (bool): Whether the versions match.
|
|
"""
|
|
a = get_minor_version(version_a)
|
|
b = get_minor_version(version_b)
|
|
return a is not None and b is not None and a == b
|