Skip to content

Instantly share code, notes, and snippets.

@yyolk
Last active August 21, 2024 20:43
Show Gist options
  • Save yyolk/35d633db79d142acf07077d9b4b895f0 to your computer and use it in GitHub Desktop.
Save yyolk/35d633db79d142acf07077d9b4b895f0 to your computer and use it in GitHub Desktop.
# /// script
# requires-python = ">=3.10"
# dependencies = [
# "semver",
# ]
# ///
"""Converts poetry's caret requirements to vanila pip compatible qualifier.
Poetry's caret qualifier is unique to poetry:
https://python-poetry.org/docs/dependency-specification/#caret-requirements
"""
import semver
def max_version(ver: semver.Version) -> str:
if ver.major > 0:
return f"{ver.major + 1}"
if ver.minor > 0:
return f"0.{ver.minor + 1}"
return f"0.0.{ver.patch + 1}"
def convert_dependency_list(dependency_list: list[str]) -> list[str]:
result_dependency_list = []
for dep in dependency_list:
dep_name, dep_ver = dep.split("^")
try:
dep_semver = semver.Version.parse(dep_ver)
except ValueError:
# fallback to stripping tail end of whatever they include in their
# semver that is not parsable by semver package
# e.g. "2.9.0.post0"
dep_semver = semver.Version.parse(".".join(dep_ver.split(".")[:3]))
result_dependency_list.append(
f"{dep_name}>={dep_ver},<{max_version(dep_semver)}"
)
return result_dependency_list
# Example usage - read out a poetry pyproject.toml and print the vanilla
# pyproject.toml equivalent
if __name__ == "__main__":
import tomllib
import sys
with open("pyproject.toml", "rb") as fp:
toml = tomllib.load(fp)
dependency_table = toml["tool"]["poetry"]["dependencies"]
dependency_list = [
f"{key}{value}"
for key, value in dependency_table.items()
if key != "python" and "^" in value
]
converted_dependency_list = convert_dependency_list(dependency_list)
for dep in converted_dependency_list:
print(dep)
if sys.argv[-1] == "--extra":
# Include other things that aren't qualified with ^, not very robust
# and doesn't work on any inline table dependencies, but could.
extra_dependencies = [
f"{key}{'=='+value if value[0].isdigit() else value}"
for key, value in dependency_table.items()
if key != "python" and isinstance(value, str) and "^" not in value
]
for extra_dep in extra_dependencies:
print(extra_dep)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment