Search code examples
pythonsetuptoolssoftware-distribution

How to register Entry Points for network python package installs?


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'],
    }
) 

Solution

  • Run 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
    

    Roll your own

    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