Entry points

The entry_points parameter is arguably the most useful feature of setuptools. It allows you to add hooks to many things within setuptools but the most useful two are the possibility to add both the command line and GUI commands and to extend the setuptools commands. The command line and GUI commands will even be converted to executables on Windows. The example in the first section already demonstrated both the features:

entry_points={
    'distutils.commands': [
        'command_name = your_package:YourClass',
    ],
    'console_scripts': [
        'spam = your_package:SpamClass',
    ],
},

This demonstration only shows how to call the functions but it doesn't show the actual functions.

Creating global commands

The first, a simple example, is nothing special at all; just a function that gets called as a regular main function where you need to specify sys.argv yourself (or better, use argparse). This is the setup.py file:

import setuptools


if __name__ == '__main__':
    setuptools.setup(
        name='Our little project',
        entry_points={
            'console_scripts': [
                'spam = spam.main:main',
            ],
        },
    )

And, of course, here's the spam/main.py file:

import sys


def main():
    print('Args:', sys.argv)

Be sure not to forget to create a spam/__init__.py file. It can be empty but it needs to exist for Python to know that it's a package.

Now, let's give it a try by installing the package:

# pip install -e .
Installing collected packages: Our-little-project
  Running setup.py develop for Our-little-project
Successfully installed Our-little-project
# spam 123 abc
Args: ['~/envs/mastering_python/bin/spam', '123', 'abc']

See how easy it was to create a spam command that installs in your regular command line shell! On Windows it will actually give you an executable which will be added to your path but regardless of the platform it will be as a separate executable that's callable.

Custom setup.py commands

Writing custom setup.py commands can be very useful. One example is sphinx-pypi-upload-2 which I use in all my packages and is my fork of the unmaintained sphinx-pypi-upload package. It's a package that makes it trivial to build and upload Sphinx documentation to the Python package index, which is very useful when distributing your packages. With the sphinx-pypi-upload-2 package you can do the following (which I do when distributing any of the packages I maintain):

python setup.py sdist bdist_wheel upload build_sphinx upload_sphinx

This command builds your package and uploads it to PyPI, and builds the Sphinx documentation and uploads it to PyPI as well.

But you want to see how this works, of course. First, here's setup.py for our spam command:

import setuptools


if __name__ == '__main__':
    setuptools.setup(
        name='Our little project',
        entry_points={
            'distutils.commands': [
                'spam = spam.command:SpamCommand',
            ],
        },
    )

Second, the SpamCommand class. The basic essentials are inheriting setuptools.Command and making sure to implement all the needed methods. Note that all of these need to be implemented but can be left empty if desired. Here is the spam/command.py file:

import setuptools


class SpamCommand(setuptools.Command):
    description = 'Make some spam!'
# Specify the commandline arguments for this command here. This
# parameter uses the getopt module for parsing'
    user_options = [
        ('spam=', 's', 'Set the amount of spams'),
    ]

    def initialize_options(self):
# This method can be used to set default values for the
# options. These defaults can be overridden by
# command-line, configuration files and the setup script
# itself.
        self.spam = 3

    def finalize_options(self):
# This method allows you to override the values for the
# options, useful for automatically disabling
# incompatible options and for validation.
        self.spam = max(0, int(self.spam))

    def run(self):
        # The actual running of the command.
        print('spam' * self.spam)

Executing it is simple enough:

# pip install -e .
Installing collected packages: Our-little-project
  Running setup.py develop for Our-little-project
Successfully installed Our-little-project-0.0.0
# python setup.py --help-commands
[...]
Extra commands:
  [...]
  spam              Make some spam!
  test              run unit tests after in-place build
  [...]

usage: setup.py [global_opts] cmd1 [cmd1_opts] [cmd2 [cmd2_opts] ...]
   or: setup.py --help [cmd1 cmd2 ...]
   or: setup.py --help-commands
   or: setup.py cmd –help

# python setup.py --help spam
Common commands: (see '--help-commands' for more)

[...]

Options for 'SpamCommand' command:
  --spam (-s)  Set the amount of spams

usage: setup.py [global_opts] cmd1 [cmd1_opts] [cmd2 [cmd2_opts] ...]
   or: setup.py --help [cmd1 cmd2 ...]
   or: setup.py --help-commands
   or: setup.py cmd --help

# python setup.py spam
running spam
spamspamspam
# python setup.py spam -s 5
running spam
spamspamspamspamspam

There are very few cases where you will actually need the custom setup.py commands, but the example is still useful since it is currently an undocumented part of setuptools.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset