Skip to content

vendoring logic subtly breaks later usage of unvendored system versions after importing pkg_resources.extern #1383

@eli-schwartz

Description

@eli-schwartz

In theory, if pkg_resources.extern is devendored, it should defer to the system installation of e.g. packaging, which means that:

>>> packaging.version
<module 'pip._vendor.packaging.version' from '/usr/lib/python3.6/site-packages/packaging/version.py'>
>>> pkg_resources.extern.packaging.version
<module 'pip._vendor.packaging.version' from '/usr/lib/python3.6/site-packages/packaging/version.py'>

It would be expected that I could then compare the results, since they're the same thing.

>>> pkg_resources.extern.packaging.version.parse('3.0') == packaging.version.parse('2.0')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: '>' not supported between instances of 'Version' and 'Version'

Oops?

For comparison, this works fine when using the similarly devendored pip.

>>> pip._vendor.packaging.version
<module 'packaging.version' from '/usr/lib/python3.6/site-packages/packaging/version.py'>
>>> packaging.version
<module 'packaging.version' from '/usr/lib/python3.6/site-packages/packaging/version.py'>
>>> pip._vendor.packaging.version.parse('3.0') > packaging.version.parse('2.0')
True

Note that pkg_resources must not be devendored from pip, or else it must be deleted from vendor/__init__.py, since otherwise it will be automatically imported. Even importing pkg_resources causes pip to fail as well.

>>> import pip._vendor.packaging.version
>>> import packaging.version
>>> pip._vendor.packaging.version.parse('3.0') > packaging.version.parse('2.0')
True

vs.

>>> import pip._vendor.packaging.version
>>> import pkg_resources.extern
>>> import packaging.version
>>> pip._vendor.packaging.version.parse('3.0') > packaging.version.parse('2.0')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: '>' not supported between instances of 'Version' and 'Version'

pypa/pip#5429 (comment) suggested the problem is deleting the global module unconditionally, whenever something vendored is in use. This strikes me as incredibly dangerous.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions