I have a user environment where most python packages are installed on a network share and are made available via the PYTHONPATH
environment variable. Python itself is still installed locally. Some of those packages need to register setuptools Entry Points. Normally, this would happen by running the setup.py
file for the package, but because these are installed to a network location, that setup.py
is never run with the local installation of python.
Is there a way to register Entry Points without installing a package in the local python installation?
An example of an entrypoint that registers a callback for a plugin system
setup(
...
entry_points={
'xx_plugin': ['value = package.module:func'],
}
)
setup.py
The console_scripts
and gui_scripts
entry points create standalone scripts that wrap a callable object. The coverage
package is a good example of this. It has an entry point to create a wrapper script for convenience. Example setup.py
snippet to create a console script:
setup(
...
entry_points = {
'console_scripts': [
'script_name = package.module:function'
]
}
)
It's possible to only install the scripts to a specified directory via setup.py
. An existing script will not be overwritten unless the --force
argument is passed.
python setup.py install_scripts --install-dir /some/alternate/location
For a plugin, the entry point is stored as metadata in an egg that's typically installed with the package. Example plugin entry point:
setup(
...
entry_points = {
'group_name': [
'plugin_name = package.module:function'
]
}
)
It's possible to only install the metadata of a package (including any entry points) to a specified directory via setup.py
.
python setup.py egg_info --egg-base $PYTHONPATH
If setup.py
can't be run to write the egg metadata, it's totally possible to roll your own, as it's only a text file in a directory. Example metadata based on the above entry point:
# $PYTHONPATH/entry_points.egg-info/entry_points.txt
[group_name]
plugin_name = package.module:function
To test entry point lookup:
import pkg_resources as pkg
for entry_point in pkg.iter_entry_points('group_name'):
plugin_name = entry_point.name
plugin_module_name = entry_point.module_name
plugin_callable = entry_point.load()
# do something with plugin