setup.py, distutils and testing.

In releasing the web framework I've been working on, I went about providing the things any upstanding python project does: a CI configuration file, a setup.py and some tests.

The setup.py file was simple enough. PyCharm wrote one automatically. I was surprised to learn that when using distutils defining dependencies in your setup.py doesn't install them with easyinstall or pip. Its just a bit of metadata that is sent upstream.

The other gotcha is that I wanted single-command access to running my tests. The easier tests are to run and write, the more likely they are to be run and written. From setuptools land, a simple python setup.py test and a setup.py entry was all it took to get started. Unfortuantely, there is no specific information about setting this up in either the distutils2 documentation or in the packaging guide for Python. When attempting to cargo-cult my setup.py together, I stumbled upon simplejson's setup.py and came across a custom test runner. You add a cmdclass keyword argument to your setup.py with a dict value mapping the command to the correct distutils.core.Command object to run.

The simplest example is something akin to what I've commited:

from distutils.cmd import Command
from distutils.core import setup


class TestCommand(Command):
    user_options = []

    def initialize_options(self):
        pass

    def finalize_options(self):
        pass

    def run(self):
        import sys, subprocess

        raise SystemExit(
            subprocess.call([sys.executable,
                             '-m',
                             'pisces.test']))


setup(
    name='pisces',
    version='0.0.1',
    packages=['pisces'],
    url='https://github.com/justinabrahms/pisces',
    license='MIT',
    author='Justin Abrahms',
    author_email='justin@abrah.ms',
    description='A testable python web framework',
    requires=['werkzeug'],
    cmdclass={
        'test': TestCommand
    }
)

It seems the bulk of the information out there recommends distutils2 and distribute, but there's not much by way of how to accomplish similar things in distutils. Hopefully this accomplishes a small part of that.