Source code for conda_pypi.specifiers

"""
Responsible for PEP 440 <=> Conda Version conversions
"""

from packaging.specifiers import SpecifierSet
from packaging.version import Version


[docs] def specifier_bounds_to_conda(specifier: SpecifierSet) -> str: """Return a conda MatchSpec version string built from PEP 440 specifiers. Exclusive upper bounds (``<V``) that are not themselves pre-releases get ``a0`` appended. PEP 440's ``<V`` excludes pre-releases of ``V``, but conda's ``<`` only compares versions, and pre-releases sort below ``V``, so ``<3.12`` would match ``3.12.0rc1``. ``<3.12a0`` excludes them. Bounds are sorted the same way as ``str(SpecifierSet)`` so the output is deterministic. Converts PEP 440 comparative operator ``~=`` Specifiers to Conda equivalent. For example: ``~=X.Y.Z`` becomes ``<X.(Y + 1).0a0,>=X.Y.Z``. Matches all versions greater than or equal to original version as long as the release segments above the last stay the same. """ bounds = [] for spec in sorted(specifier, key=str): new_bound = f"{spec.operator}{spec.version}" if spec.operator == "<" and not Version(spec.version).is_prerelease: new_bound += "a0" if spec.operator == "~=": version = Version(spec.version) epoch = f"{version.epoch}!" if version.epoch else "" segments = list(version.release) segments[-2] += 1 new_bound = f"<{epoch}{'.'.join(str(release_segment) for release_segment in segments[:-1])}.0a0,>={spec.version}" bounds.append(new_bound) return ",".join(bounds)
[docs] def specifier_bounds_to_pep440(specifier: SpecifierSet) -> str: """Return a PEP 440 version string from a converted conda MatchSpec version string. PEP 440 exclusive upper bounds that have ``a0`` appended will enable matching prereleases. Removing the ``a0`` added from specifier_bounds_to_conda ensures that the PEP 440 compares specifications as intended. Affected bounds that have ``a0`` stripped will exclude all versions such as ``X.Y.devN``. """ bounds = [] for spec in sorted(specifier, key=str): version = spec.version if spec.operator == "<" and version.endswith("a0"): version = version.removesuffix("a0") bounds.append(f"{spec.operator}{version}") return ",".join(bounds)