-
Notifications
You must be signed in to change notification settings - Fork 3k
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
Add PEP 513 support (manylinux1 platform tag) #3497
Conversation
The |
@@ -189,6 +236,11 @@ def get_supported(versions=None, noarch=False): | |||
else: | |||
# arch pattern didn't match (?!) | |||
arches = [arch] | |||
elif sys.platform == 'linux': | |||
if is_manylinux1_compatible(): | |||
arches = [arch, arch.replace('linux', 'manylinux1')] |
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.
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.
I don't know, either what the effect is or what the preferred behavior is... To check what the effect is I guess it would be easy to check (you can trivially run pip out of a source checkout by running python -m pip
while in the root of the checkout). And in terms of what behavior we want, I think it's pretty arbitrary really -- the case where it comes up is very unlikely, and in this unlikely case, I can't think of any strong reason to prefer one outcome or another.
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.
I did the test, and the current ordering make pip install
select the linux
arch over the manylinux1
arch when both wheels are available on the index (in my case a local folder). Switching the ordering at that line yield the opposite behavior.
- pro: this is backward compatible with the behavior of pip 8.0 (and earlier)
- con: this is less specific, one could expect pip to select the most platform specific wheel instead.
Note that pip wheel
does not seem to be impacted by this change as it calls python setup.py bdist_wheel
in a subprocess (I think) and therefore always name the generated file with the linux
arch. I think this is good as to generate a valid manylinux1 wheel file extract care is required (e.g. using auditwheel repair
to embed system shared libraries not provided a manylinux1 compatible system).
@dstufft any opinion on this ordering issue?
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.
pip should always select the most specific available.
dd8cb40
to
624066e
Compare
@dstufft I amended the change to make sure the most specific supported tag comes first and added a test for this. |
@@ -198,7 +247,8 @@ def get_supported(versions=None, noarch=False): | |||
supported.append(('%s%s' % (impl, versions[0]), abi, arch)) | |||
|
|||
# Has binaries, does not use the Python API: | |||
supported.append(('py%s' % (versions[0][0]), 'none', arch)) | |||
for arch in arches: | |||
supported.append(('py%s' % (versions[0][0]), 'none', arch)) |
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.
@dstufft this change also impacts macosx: previously it would use the arch
from get_platform()
instead of all possible arches
expanded in this function. I think this was a bug but I am not 100% sure.
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.
I also think it is a bug fix, and for a bug that was never noticed before because it only affects wheels that combine a none
ABI tag + a non-trivial platform tag, which is a rare (but totally valid) configuration.
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.
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.
I think ~2000 should not cause any performance issue for pip but it would be worth auditing the codebase to check that this list of tags is not used by any algorithm with quadratic complexity or more.
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.
get_supported()
is used directly in 3 places:
- index.py#L245:
len(tags)
: O(1) - wheel.py#L656:
[tags.index(c) for c in self.file_tags if c in tags]
:self.file_tags
is the set of tag combinations in a wheel filename so won't be very large.c in tags
complexity is O(len(tags)) = O(n). Not sure what the complexity oftags.index(c)
is but I assume it's implemented the same way asc in tags
and should then be O(n), so this whole statement is O(n). - wheel.py#L663:
bool(set(tags).intersection(self.file_tags))
: Set construction is O(len(tags)) = O(n) and set intersection is O(len(tags)) = O(n) so the whole thing is also O(n).
I don't see any loops or recursion in the callers that would cause any of these to be called len(tags) times since they're used on lists of wheels discovered e.g. from the index or in a cache directory. So I suppose the danger would be if an index had thousands of wheels.
Also do we need a functional test for this new feature or are the unit tests enough? |
@ogrisel I think |
@Ivoz alright, I will do that. |
aa27185
to
309d403
Compare
Done. |
309d403
to
8fe9302
Compare
@rmcgibbo sorry I lost authorship information in the process or splitting the commit into 2. |
8fe9302
to
3e67145
Compare
I fixed the authorship of the last commit. Let me know if there are any other problem with this PR. |
@@ -124,7 +124,54 @@ def get_platform(): | |||
split_ver = release.split('.') | |||
return 'macosx_{0}_{1}_{2}'.format(split_ver[0], split_ver[1], machine) | |||
# XXX remove distutils dependency | |||
return distutils.util.get_platform().replace('.', '_').replace('-', '_') | |||
result = distutils.util.get_platform().replace('.', '_').replace('-', '_') | |||
if result == "linux_x86_64" and sys.maxsize == 2147483647: |
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.
What's up with this check? Can we add a comment as to why it exists?
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.
BTW, is it somewhat related to this quite old PR #1377 ?
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.
If you run 32 bit Python on a 64 bit linux (e.g. via anaconda or even if you debootstrap a i686 ubuntu inside a 64 bit ubuntu), then distutils.util.get_platform()
returns "linux-x86_64"
even though Python itself is 32 bit.
I don't know if this is a bug of distutils or not.
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 occurs because distutils.util.get_platform()
relies on os.uname()
(and thus POSIX uname()
) for the architecture of the platform. It does not make any attempt to determine the "platform" of the interpreter itself.
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.
Yeah, this fixes the same bug that PR #1377 was trying to address; see also this mailing list message. The bug has been around a long time, but it becomes much more urgent to fix as soon manylinux support lands; in the past it only caused a problem if you specifically did pip install -f <directory with 64 bit wheels>
from a 32-bit userland, but once 64-bit linux wheels are on pypi [edit: and people are using manylinux-enabled pip], then it will become possible to hit by just doing pip install
. So it's important to land this fix at the same time we enable manylinux support.
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.
Just a note, that it's likely that the wheel project has this bug too.
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.
3e67145
to
99e8493
Compare
result = distutils.util.get_platform().replace('.', '_').replace('-', '_') | ||
if result == "linux_x86_64" and sys.maxsize == 2147483647: | ||
# 32 bit Python program (running on a 64 bit Linux): pip should only | ||
# install and run 32 bit compiled extensions in that case. |
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.
@dstufft I amended the commit to add this comment to explain this particular case. Let me know if would prefer another phrasing.
I amended the last commit to move the ctypes import. Github has folded the unrelated #3497 (comment) comment as the result even though this remark has not been addressed yet. |
|
||
# Parse string and check against requested version. | ||
version = [int(piece) for piece in version_str.split(".")] | ||
assert len(version) == 2 |
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.
I don't think we want an assert here: we'd rather return False and not crash pip.
99e8493
to
d83957b
Compare
Thanks @xavfernandez, I addressed your comments. |
d83957b
to
b0351b3
Compare
Add PEP 513 support (manylinux1 platform tag)
This is a rebased and squashed version of #3446 with fixes for the failed flake8 checks. The goal is to add support for the manylinux1 platform tag.