python pip install wheel with custom entry points

3.5k views Asked by At

In a python virtualenv on Windows, I've installed a custom package that over-rides setuptools.command.install.easy_install.get_script_args to create a new custom type of entry point 'custom_entry'

I have another package that I want to prepare with setuptools exposing a custom entry point.

If I prepare an egg distribution of this package and install it with my modified easy_install.exe, this creates the custom entry points correctly.

However, if I prepare a wheel distribution and install it with a modified pip.exe, the custom entry points do not get added.

Why does pip not follow the same install procedure as easy_install?

Reading the source for pip, it seems that the function get_entrypoints in wheel.py excludes all entry points other than console_scripts and gui_scripts. Is this correct?

If so, how should I install custom entry points for pip installations?

---- Edit

It looks like I should provide more details.

In my first package, custom-installer, I'm over-riding (monkey-patching, really) easy_install.get_script_args, in custom_install.__init__.py:

from setuptools.command import easy_install

_GET_SCRIPT_ARGS = easy_install.get_script_args

def get_script_args(dist, executable, wininst):

    for script_arg in _GET_SCRIPT_ARGS(dist, executable, wininst):
        yield script_arg # replicate existing behaviour, handles console_scripts and other entry points

    for group in ['custom_entry']:
        for name, _ in dist.get_entry_map(group).items():
            script_text = (
                ## some custom stuff
            )
            ## do something else
            yield (## yield some other stuff) # to create adjunct files to the -custom.py script
            yield (name + '-custom.py', script_text, 't')

easy_install.get_script_args = get_script_args
main = easy_install.main

And in that package's setup.py, I provide a (console_script) entry point for my custom installer:

entry_points={
    'console_scripts': [
        'custom_install = custom_install.__init__:main'
    ]
}

Installing this package with pip correctly creates the installer script /venv/Scripts/custom_install.exe

With my second package, customized, I have both regular and custom entry points to install from setup.py, for two modules custom and console.

entry_points={
    'console_scripts': [
        'console = console.__main__:main'
    ],
    'custom_entry': [
        'custom = custom.__main__:main'
    ]
}

I would like to see both of these entry points installed regardless of the install procedure.

If I build the package customized as an egg distribution and install this with custom_install.exe created by custom-installer, then both entry points of customized are installed.

I would like to be able to install this package as a wheel file using pip, but from reading the source code, pip seems to explicitly skip and any entry points other than 'console_scripts' and 'gui_scripts':

def get_entrypoints(filename):
    if not os.path.exists(filename):
        return {}, {}
    # This is done because you can pass a string to entry_points wrappers which
    # means that they may or may not be valid INI files. The attempt here is to
    # strip leading and trailing whitespace in order to make them valid INI
    # files.
    with open(filename) as fp:
        data = StringIO()
        for line in fp:
            data.write(line.strip())
            data.write("\n")
        data.seek(0)
    cp = configparser.RawConfigParser()
    cp.readfp(data)
    console = {}
    gui = {}
    if cp.has_section('console_scripts'):
        console = dict(cp.items('console_scripts'))
    if cp.has_section('gui_scripts'):
        gui = dict(cp.items('gui_scripts'))
    return console, gui

Subsequently, pip generates entry point scripts using a completely different set of code to easy_install. Presumably, I could over-ride pip's implementations of these, as done with easy_install, to create my custom entry points, but I feel like I'm going the wrong way.

Can anyone suggest a simpler way of implementing my custom entry points that is compatible with pip? If not, I can override get_entrypoints and move_wheel_files.

1

There are 1 answers

1
Mike Driscoll On

You will probably need to use the keyword console_scripts in your setup.py file. See the following answer:

It basically states that you need to do the following in your setup.py script:

entry_points = {
       'console_scripts': ['custom_entry_point = mypackage.mymod.test:foo']
       }

See also: http://calvinx.com/2012/09/09/python-packaging-define-an-entry-point-for-console-commands/