Skip to content
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

Refactor manylinux tag logic #1

Merged

Conversation

maresb
Copy link

@maresb maresb commented Dec 9, 2023

I was struggling to follow the previous logic, so I read the manylinux PEPs and decided to refactor.

I wanted to make sure we were covering all possible edge cases.

Also, I agree that using packaging.version.Version is overkill here, but throughout conda-lock we're parsing versions all over the place, and so things get a bit crazy if locally we're constantly reimplementing string-parsing logic. And indeed, I uncovered that the previous commit was mixing _ and . separators:

In [1]: from conda_lock.pypi_solver import PlatformEnv

In [2]: e = PlatformEnv("3.12", "linux-64", {"x": {"name": "not_glibc"}})
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Cell In[2], line 1
----> 1 e = PlatformEnv("3.12", "linux-64", {"x": {"name": "not_glibc"}})

File ~/repos/conda-lock/conda_lock/pypi_solver.py:80, in PlatformEnv.__init__(self, python_version, platform, platform_virtual_packages)
     78     if p["name"] == "__glibc":
     79         glibc_version = p["version"]
---> 80 glibc_version_splits = list(map(int, glibc_version.split(".")))
     81 for tag in MANYLINUX_TAGS:
     82     if tag[0] == "_":
     83         # Compare to see if glibc_version is greater than this version

ValueError: invalid literal for int() with base 10: '_2_28'

Does this refactor look clear and correct? (Feel free to skip looking at the new test I wrote; it's pretty tedious.) Thanks!!

Copy link
Owner

@romain-intel romain-intel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is definitely a lot clearer and easier to follow. A few minor nits but otherwise this is definitely better than the quick hack I had written. Thanks for making this so much better. Let me know what you think about the comments. Happy to make the modifications as well and merge it into this branch.

@@ -39,6 +42,7 @@
if TYPE_CHECKING:
from packaging.tags import Tag

logger = logging.getLogger(__name__)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: unused

Copy link
Author

@maresb maresb Dec 10, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, fixed!

@@ -55,6 +59,12 @@ class PlatformEnv(Env):
Fake poetry Env to match PyPI distributions to the target conda environment
"""

_sys_platform: Literal["darwin", "linux", "win32"]
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is this for?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a type annotation, so if you're running a type checker like mypy or pyright it will know what are the valid values of _sys_platform. I find it really useful because if you're in another file and you hover over a variable it'll show you the type and hence the possible values, making it much easier to figure out what's going on without needing to infer it from reading the code.

So in this case I was reading the code, I figured out that these are the possible values, and I declared them as such. And now the type checker statically verifies this and can offer hints.

elif len(matches) == 1:
return matches[0]
else:
lowest = min(matches)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this will technically not work for those "special cases" because Version("2010") > Version("2.27") I suspect. I don't think this is a case that is very common though so maybe we can ignore it or error out? Or special case the special cases like you do below.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

According to my understanding, there is no glibc v2010, so this should never happen. I made an attempt to explain this in the docstring.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah yes, you are right, 2010 was actually the old manylinux name for 2.12 so yes, the glibc version would be 2.12.

# is most preferred so we reverse the order.
compatible_manylinux_tags = [
tag
for tag in reversed(MANYLINUX_TAGS)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

small nit: there is a tad of a wasted thing here because once one matches, all the rest will match. I don't think it has a huge consequence though and this code is definitely easier to follow.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You mean that we could break the iteration early? Technically yes, but that's more of a nanosecond optimization, right?

@maresb
Copy link
Author

maresb commented Dec 10, 2023

I really appreciate the very thorough review! I think I've addressed all your points. Feel free to squash-merge if you think it's ready.

@romain-intel romain-intel merged commit 48c8a69 into romain-intel:fix/respect-glibc-version Dec 10, 2023
5 checks passed
romain-intel pushed a commit that referenced this pull request Dec 10, 2023
* Refactor manylinux tag logic

* Run doctests

* Remove unused logger

* Clarify that legacy manylinux tags aren't glibc versions
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants