-
-
Notifications
You must be signed in to change notification settings - Fork 72
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Poetry deps w/ python version and platform, and multiple constraints dependencies #592
Changes from 3 commits
536df60
1a3a85f
8ed0792
c04e184
4493140
f5fb7aa
e5a1053
aa72c62
5abdffd
602c447
ee3a6d6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -236,3 +236,109 @@ def encode_poetry_version(poetry_specifier: str) -> str: | |||||
conda_clauses.append(poetry_clause) | ||||||
|
||||||
return ",".join(conda_clauses) | ||||||
|
||||||
|
||||||
def encode_poetry_platform_to_selector_item(poetry_platform: str) -> str: | ||||||
""" | ||||||
Encodes Poetry Platform specifier as a Conda selector. | ||||||
|
||||||
Example: "darwin" => "osx" | ||||||
""" | ||||||
|
||||||
platform_selectors = {"windows": "win", "linux": "linux", "darwin": "osx"} | ||||||
poetry_platform = poetry_platform.lower().strip() | ||||||
if poetry_platform in platform_selectors: | ||||||
return platform_selectors[poetry_platform] | ||||||
else: # unknown | ||||||
return "" | ||||||
|
||||||
|
||||||
def encode_poetry_python_version_to_selector_item(poetry_specifier: str) -> str: | ||||||
""" | ||||||
Encodes Poetry Python version specifier as a Conda selector. | ||||||
|
||||||
Example: ">=3.8,<3.12" => "py>=38 or py<312" | ||||||
|
||||||
# handle exact version specifiers correctly | ||||||
>>> encode_poetry_python_version_to_selector_item("3.8") | ||||||
"py==38" | ||||||
>>> encode_poetry_python_version_to_selector_item("==3.8") | ||||||
"py==38" | ||||||
>>> encode_poetry_python_version_to_selector_item("!=3.8") | ||||||
"py!=38" | ||||||
|
||||||
# handle caret operator correctly | ||||||
>>> encode_poetry_python_version_to_selector_item("^3.10") | ||||||
# renders '>=3.10.0,<4.0.0' | ||||||
"py>=310 or py<4" | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. fixed |
||||||
|
||||||
# handle tilde operator correctly | ||||||
>>> encode_poetry_python_version_to_selector_item("~3.10") | ||||||
# renders '>=3.10.0,<3.11.0' | ||||||
"py>=310 or py<311" | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. fixed |
||||||
""" | ||||||
|
||||||
if not poetry_specifier: | ||||||
return "" | ||||||
|
||||||
version_specifier = encode_poetry_version(poetry_specifier) | ||||||
|
||||||
conda_clauses = version_specifier.split(",") | ||||||
|
||||||
conda_selectors = [] | ||||||
for conda_clause in conda_clauses: | ||||||
operator, version = parse_python_version(conda_clause) | ||||||
version_selector = version.replace(".", "") | ||||||
conda_selectors.append(f"py{operator}{version_selector}") | ||||||
selectors = " or ".join(conda_selectors) | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. fixed |
||||||
return selectors | ||||||
|
||||||
|
||||||
def parse_python_version(selector: str): | ||||||
""" | ||||||
Return operator and normalized version from a version selector | ||||||
|
||||||
Examples: | ||||||
">=3.8" -> ">=", "3.8" | ||||||
">=3.8.0" -> ">=", "3.8" | ||||||
"<4.0.0" -> "<", "4" | ||||||
"3.12" -> "==", 3.12" | ||||||
"=3.8" -> "==", "3.8" | ||||||
|
||||||
The version is normalized to "major.minor" (drop patch if present) | ||||||
or "major" if minor is 0 | ||||||
""" | ||||||
# Regex to split operator and version | ||||||
pattern = r"^(?P<operator>\^|~|>=|<=|!=|==|>|<|=)?(?P<version>\d+(\.\d+){0,2})$" | ||||||
match = re.match(pattern, selector) | ||||||
if not match: | ||||||
raise ValueError(f"Invalid version selector: {selector}") | ||||||
|
||||||
# Extract operator and version | ||||||
operator = match.group("operator") | ||||||
# Default to "==" if no operator is provided or "=" | ||||||
operator = "==" if operator in {None, "="} else operator | ||||||
version = match.group("version") | ||||||
|
||||||
# Split into major, minor, and discard the rest (patch or additional parts) | ||||||
major, minor, *_ = version.split(".") | ||||||
|
||||||
# Return only major if minor is "0", otherwise return major.minor | ||||||
return operator, major if minor == "0" else f"{major}.{minor}" | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we probably need this to also support:
When I tried that, I see (as I expected I might):
Could you add a test for this situation and make the necessary changes to support a single digit as well? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Added support for 1 digit and three dots case (e.g. |
||||||
|
||||||
|
||||||
def combine_conda_selectors(python_selector: str, platform_selector: str): | ||||||
""" | ||||||
Combine selectors based on presence | ||||||
""" | ||||||
if python_selector and platform_selector: | ||||||
if " or " in python_selector: | ||||||
python_selector = f"({python_selector})" | ||||||
selector = f"{python_selector} and {platform_selector}" | ||||||
elif python_selector: | ||||||
selector = f"{python_selector}" | ||||||
elif platform_selector: | ||||||
selector = f"{platform_selector}" | ||||||
else: | ||||||
selector = "" | ||||||
return f" # [{selector}]" if selector else "" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
pytest is running your doctests here as well, that is why it is failing on ci
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is interesting, I've fixed the examples output format. Thanks for having a look at it!