rmed

blog

Introduction to distutils (III)

2014-01-29 10:20

Hey there! We have already seen how to write the setup script and how to build and install the Python module, but how about we distribute it so that anyone can download it? For this, we'll use the Python Package Index.

Registering in PyPI

Although I say PyPI, as we are testing things here, it would be better to use the test server available here. All the steps that are going to be followed can be performed in the official PyPI in the same way.

First we need to register our account in the server. With this account, we will be able to register packages in the index and upload code to those packages. Now we need to let distutils know our credentials when uploading anything to the index. The easiest way to do this is by creating a file named .pypirc in your home directory, but take into account that the password is stored as plain text! The content of the file would be as follows:

[distutils]
index-servers =
    pypi
    test

[test]
repository:https://testpypi.python.org/pypi
username:your_username
password:your_password

[pypi]
repository:https://pypi.python.org/pypi
username:your_username
password:your_password

By structuring the file this way, you can use both official and test indexes at the same time, for this tutorial, we only care for the test server, so the resulting file:

[distutils]
index-servers =
    test

[test]
repository:https://testpypi.python.org/pypi
username:your_username
password:your_password

Applying classifiers to the package

As we are uploading the package to a package index, it is best to use classifiers in order to facilitate finding it. Here you can find the complete list of available classifiers, so choose to your heart's content.

Now we need to apply those classifiers to our setup script. For this, again, we will be using the dummy superfoo module. If we open the setup script, we find:

""" Setup script for superfoo """
from distutils.core import setup

setup(
    # Module name
    name = 'superfoo',
    # Module version
    version = '1.0.0',
    # Short description
    description = 'Simple Python module example',
    # Author
    author = 'YOUR_NAME_HERE',
    # Contact email
    author_email = 'YOUR_EMAIL_HERE',
    # Support url
    url = 'YOUR_URL_HERE',
    # License (if any)
    license = '',
    # Packages to include in the build
    packages = ['superfoo']
)

One way of adding classifiers to the script is by including the classifiers attribute in the setup() function, for instance:

    classifiers = [
        'Development Status :: 3 - Alpha',
        'Environment :: Console',
        'Intended Audience :: Education',
        'Operating System :: OS Independent',
        'Programming Language :: Python',
        'Programming Language :: Python :: 2.7',
        'Topic :: Education',
        'Topic :: Education :: Testing'
        ]

This will tell the package index that our package is an Alpha/development version, that it runs on console, that is intended for use in education, that it runs independently of the OS it is executed in, that is written in Python, specifically version 2.7 and that its main topic is education and testing.

Registering the package in the index

Before we can upload the package to the index, we need to register it. This is done by running the following command from the project's root:

$ python setup.py register -r test

Now, what does the parameter -r test do? Remember that we had the credentials for both the official PyPI and the test one? Well, this allows us to choose the repository in which we want to work. If you were trying to register a package in the official index, you would use pypi instead of test in the command.

If you log into your test PyPI account, you will see that the package superfoo appears listed under the "Your Packages" section. Fine, we have registered the package correctly, but now we need to properly upload the code. Usually, you want to use a source distribution, but you could also use a built distribution, especially when dealing with Windows systems, as it will provide an installable file. First we will do a source distribution:

$ python setup.py sdist

If we now look in the dist directory that has been created in our project's root, we will see a compressed file that contains the source code for our package. Thats neat, but we want to upload it to the index, so we need to use:

$ python setup.py sdist upload -r test

Note that the -r test parameter is also important here! The upload command will upload the built packages you specify before it (in this case sdist), but you can specify as many distribution types as you want before upload, for instance:

$ python setup.py sdist bdist upload -r test

This would create a source distribution and a built distribution and upload both to the index.

Installing uploaded packages

Now that our package has been uploaded and we can manually download it from the index, we need to know how to install it from the index. Of course we can download it and run setup.py install, but there are tools that make things easier, like pip. Installing a package with pip is as easy as doing:

# pip install package_name

In our case, as the package is uploaded to the test server, we would need to write:

# pip install --index-url https://testpypi.python.org/pypi superfoo

For more information on pip, you can have a look at the official documentation.

Built distributions for Windows systems

Let's face it, using a console or terminal in Windows can be a real pain, especially to those who don't really know how to do it, and this also applies to installing packages from the PyPI. Because of this, it is possible to create installable executables (in a Windows environment) that allow users to download, double-click and install. The way to do this is:

$ python setup.py bdist_wininst

Starting with Python 2.6, it is also possible to cross-compile installers (for 32 and 64 bits) if you have the necessary tools. Here's how to create a 32-bit installer:

$ python setup.py bdist_wininst --plat-name=win32

And a 64-bit installer:

$ python setup.py bdist_wininst --plat-name=win-amd64

If you want to upload the installer, simply add upload -r test at the end of the command.