takluyver / entrypoints

Discover and load entry points from installed packages
https://entrypoints.readthedocs.io/
MIT License
74 stars 29 forks source link

Support loading of entrypoints from importable wheels #24

Closed jaraco closed 5 years ago

jaraco commented 6 years ago

One use-case that the import ecosystem intends to support is importable wheels - wheels that much like zip eggs of the past can be added to sys.path and imported. Consider this environment:

draft $ python -m venv env
draft $ env/bin/pip install -q -U pip importlib_metadata
draft $ env/bin/pip download --no-deps keyring
Collecting keyring
  Using cached https://files.pythonhosted.org/packages/85/25/55798660a50bd2fd7a8ef58a4394fd4fbb474e6b87d55a8d3e49e300d2a4/keyring-16.0.0-py2.py3-none-any.whl
  Saved ./keyring-16.0.0-py2.py3-none-any.whl
draft $ env/bin/pip install entrypoints
Collecting entrypoints
  Using cached https://files.pythonhosted.org/packages/cc/8b/4eefa9b47f1910b3d2081da67726b066e379b04ca897acfe9f92bac56147/entrypoints-0.2.3-py2.py3-none-any.whl
Installing collected packages: entrypoints
Successfully installed entrypoints-0.2.3

keyring (which has entry points) is present as an importable wheel but isn't on sys.path (by default).

One can readily see that the entry points are visible using importlib_metadata.

draft $ env PYTHONPATH=./keyring-16.0.0-py2.py3-none-any.whl env/bin/python
Python 3.7.1 (v3.7.1:260ec2c36a, Oct 20 2018, 03:13:28)
[Clang 6.0 (clang-600.0.57)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import importlib_metadata
>>> list(importlib_metadata.entry_points('keyring')['keyring.backends'])
['kwallet', 'secretservice', 'windows', 'macos']

But with entrypoints, the metadata is missing even though keyring is importable:

draft $ env PYTHONPATH=./keyring-16.0.0-py2.py3-none-any.whl env/bin/python
Python 3.7.1 (v3.7.1:260ec2c36a, Oct 20 2018, 03:13:28)
[Clang 6.0 (clang-600.0.57)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import keyring
>>> import entrypoints
>>> entrypoints.get_group_all('keyring.backends')
[]

I suggest entrypoints should support loading of entrypoints from importable wheels in addition to eggs.

jaraco commented 6 years ago

I might even suggest that entrypoints could re-use the entry_points exposed by importlib_metadata, except that they don't support eggs.

cas-- commented 5 years ago

I couldn't get the wheel to import on Python 3.5 or 3.6 is this a feature of Python 3.7?

jaraco commented 5 years ago

Zip import should work on any zip file. The feature goes back to very early versions of Python 2. It's the same functionality that supports import from eggs. Which wheel doesn't import? I suspect the issue is there's some other import in the wheel that's not satisfied (although I would expect a meaningful error message). Can you provide a replication script?

cas-- commented 5 years ago

Hmm so it's not Python version related. For some reason it imports on Ubuntu 18.10 but not on Ubuntu 16.04, with any Python version. I did check with pip installing the package and that imports ok. Rather odd...

I have been following the steps you provided with keyring.

Edit: After a bit of testing with docker images it seems that keyring is not a good candidate for testing this with. Creating a simple package wheel works

takluyver commented 5 years ago

I think I've ignored zip imports entirely. Shouldn't be too complex to add. Anyone want to do a PR?

takluyver commented 5 years ago

This should now be fixed in master - can someone test to make sure it's working with a real-world wheel used like that (as opposed to the simplified example in the tests).

jaraco commented 5 years ago

Looks to be working great for me:

draft $ env/bin/pip install git+https://github.com/takluyver/entrypoints                                                                                                                 
Collecting git+https://github.com/takluyver/entrypoints
  Cloning https://github.com/takluyver/entrypoints to /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-req-build-bltt4y9o
  Installing build dependencies ... done
  Getting requirements to build wheel ... done
  Installing backend dependencies ... done
    Preparing wheel metadata ... done
Building wheels for collected packages: entrypoints
  Building wheel for entrypoints (PEP 517) ... done
  Stored in directory: /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-ephem-wheel-cache-2nx7hm3l/wheels/b5/b3/7c/7548e85cf128911948edd1ff8112e70b3611a406960ca8498d
Successfully built entrypoints
Installing collected packages: entrypoints
Successfully installed entrypoints-0.3
draft $ env PYTHONPATH=./keyring-17.1.1-py2.py3-none-any.whl env/bin/python                                                                                                              
Python 3.7.2 (v3.7.2:9a3ffc0492, Dec 24 2018, 02:44:43) 
[Clang 6.0 (clang-600.0.57)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import keyring
>>> import entrypoints
>>> entrypoints.get_group_all('keyring.backends')
[EntryPoint('KWallet', 'keyring.backends.kwallet', None, Distribution('keyring', '17.1.1')), EntryPoint('SecretService', 'keyring.backends.SecretService', None, Distribution('keyring', '17.1.1')), EntryPoint('Windows', 'keyring.backends.Windows', None, Distribution('keyring', '17.1.1')), EntryPoint('chainer', 'keyring.backends.chainer', None, Distribution('keyring', '17.1.1')), EntryPoint('macOS', 'keyring.backends.OS_X', None, Distribution('keyring', '17.1.1'))]