jaraco / pip-run

pip-run - dynamic dependency loader for Python
MIT License
136 stars 19 forks source link

Namespace packages fail when namespace is installed #5

Closed jaraco closed 7 years ago

jaraco commented 8 years ago

Distinct from #1, where the namespace package isn't recognized at all, there's another issue that affects all versions of Python.

$ python -m rwt backports.functools_lru_cache -- -c "import backports.functools_lru_cache"
Loading requirements using backports.functools_lru_cache
$ python -c "import backports"                                                          
Traceback (most recent call last):
  File "<string>", line 1, in <module>
ImportError: No module named 'backports'
$ python -m pip install backports.unittest_mock
Collecting backports.unittest_mock
  Downloading backports.unittest_mock-1.1.1-py2.py3-none-any.whl
Installing collected packages: backports.unittest-mock
Successfully installed backports.unittest-mock-1.1.1
$ python -c "import backports"
$ python -m rwt backports.functools_lru_cache -- -c "import backports.functools_lru_cache"
Loading requirements using backports.functools_lru_cache
Traceback (most recent call last):
  File "<string>", line 1, in <module>
ImportError: No module named 'backports.functools_lru_cache'

The problem is that the -nspkg.pth handler is interfering with the PEP-420 loader. Remove it and both packages import nicely.

$ rm /python/lib/python3.5/site-packages/backports.unittest_mock-1.1.1-py3.5-nspkg.pth
$ python -m rwt backports.functools_lru_cache -- -c "import backports.functools_lru_cache; import backports.unittest_mock"
Loading requirements using backports.functools_lru_cache
jaraco commented 8 years ago

The same issue exists if the system packages were installed as eggs (via pip or easy_install).

jaraco commented 8 years ago

Here's more information about what's affected by the -nspkg.pth file:

$ python -m pip install backports.unittest_mock
Collecting backports.unittest_mock
  Using cached backports.unittest_mock-1.1.1-py2.py3-none-any.whl
Installing collected packages: backports.unittest-mock
Successfully installed backports.unittest-mock-1.1.1
$ python -c "import backports, pprint; pprint.pprint(vars(backports))"
{'__doc__': None,
 '__loader__': None,
 '__name__': 'backports',
 '__package__': None,
 '__path__': ['/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/backports'],
 '__spec__': None}
$ rm /python/lib/python3.5/site-packages/backports.unittest_mock-1.1.1-py3.5-nspkg.pth 
$ python -c "import backports, pprint; pprint.pprint(vars(backports))"                
{'__doc__': None,
 '__loader__': <_frozen_importlib_external._NamespaceLoader object at 0x101c06630>,
 '__name__': 'backports',
 '__package__': 'backports',
 '__path__': _NamespacePath(['/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/backports']),
 '__spec__': ModuleSpec(name='backports', loader=None, origin='namespace', submodule_search_locations=_NamespacePath(['/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/backports']))}
$ python -m rwt backports.functools_lru_cache -- -c "import backports, pprint; pprint.pprint(vars(backports))" 
Loading requirements using backports.functools_lru_cache
{'__doc__': None,
 '__loader__': <_frozen_importlib_external._NamespaceLoader object at 0x1013d9668>,
 '__name__': 'backports',
 '__package__': 'backports',
 '__path__': _NamespacePath(['/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/rwt-a3slebdy/backports', '/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/backports']),
 '__spec__': ModuleSpec(name='backports', loader=None, origin='namespace', submodule_search_locations=_NamespacePath(['/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/rwt-a3slebdy/backports', '/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/backports']))}

Namely, if the -nspkg.pth file is removed, the NamespaceLoader takes over and the __spec__ and __package__ values get populated, and __path__ is a _NamespacePath. I'm not sure which of these factors is necessary for additional paths on sys.path to be processed.

jaraco commented 8 years ago

This issue may be addressed by the fix for pypa/setuptools#805.

jaraco commented 7 years ago

Using late versions of setuptools, the issue no longer exists:

$ pip install backports.unittest_mock
Collecting backports.unittest_mock
  Using cached backports.unittest_mock-1.2.1-py2.py3-none-any.whl
Installing collected packages: backports.unittest-mock
Successfully installed backports.unittest-mock-1.2.1
$ python -m rwt backports.functools_lru_cache -- -c "import backports.functools_lru_cache"
Collecting backports.functools_lru_cache
  Using cached backports.functools_lru_cache-1.3-py2.py3-none-any.whl
Installing collected packages: backports.functools-lru-cache
Successfully installed backports.functools-lru-cache-1.3