Small intro to Python packaging

Vasyl Dizhak

Small intro to Python packaging

Vasyl Dizhak @rootart

Project Lead at Django Stars, vasyl.dizhak@djangostars.com

http://bit.ly/lvivpy-packaging

Packages are a way of structuring Python's module namespace by using "dotted module names".

An Introduction to Python by Guido van Rossum and Fred L. Drake, Jr

Why I should use it?

  1. Extremely simple for users

Software is like sex: it's better when it's free.

Linus Torvalds
The Hitchhiker's Guide to Packaging 1.0 documentation link

Minimal structure

        
          ➜  development $ tree -L 2 VotePackage
          VotePackage
          ├── MANIFEST
          ├── README.txt
          ├── setup.py
          └── votepackage
              └── __init__.py
          2 directories, 6 files
        
      

Minimal setup.py data

        
          from distutils.core import setup
          setup(
              name='VotePackage',
              version='0.1dev',
              author='Vasyl Dizhak',
              author_email='vasyl.dizhak@djangostars.com',
              description='Centralized system for python package voting',
              packages=['votepackage',],
              license='Simplified BSD License',
              long_description=open('README.txt').read(),
          )
        
      

Minimal setup.py data: name

        
          ...
          name='VotePackage'
          ...
        
      
Has to be unique name.
        
          http://pypi.python.org/pypi/<name>
        
      

Minimal setup.py data: packages


packages=['votepackage', 'votepackage.tests']
        
      

Minimal setup.py data: version

PEP 386 -- Changing the version comparison module in Distutils http://www.peps.io/386/
        
 >>> from distutils.version import LooseVersion as V
 >>> v1 = V('1.0dev')
 >>> v2 = V('1.0.9alpha')
 >>> v2 > v1
 >>> False
        
      
        
$ pip install -U name
        
      

Minimal setup.py data: author

People may buy you a beer www.gittip.com
        
  author='Vasyl Dizhak',
  author_email='vasyl.dizhak@djangostars.com',
  
  
  maintainer='Vasyl Dizhak',
  maintainer_email='vasyl.dizhak@djangostars.com',
 
        
      

Minimal setup.py data: description

May be a first or even the only place where users will look and decide whether they will use your package. PYPI will render long_description with docutils reStructuredText renderer

long_description=open('README.md').read(),
        
      

Minimal setup.py data: MANIFEST.in

Only Python modules and packages are included in the package by default. To include additional files, we’ll need to create a MANIFEST.in file

include LICENSE
include README.rst
recursive-include votepackage/static *
recursive-include votepackage/templates *
        
      

setup: requirements


        install_requires = [
            'requests',
            'pycli'
        ],

        
      

Relay on platform or python version


        if sys.version_info[:2] in ((2, 6), (3, 1)):
            # argparse has been added in Python 3.2 / 2.7
            requirements.append('argparse>=1.2.1')
        if 'win32' in str(sys.platform).lower():
            # Terminal colors for Windows
            requirements.append('colorama>=0.2.4')
        
      

Classifiers

PEP 301 -- Package Index and Metadata for Distutils http://peps.io/0301/

        classifiers=[
            'Development Status :: 1 - Planning',
            'Intended Audience :: Developers',
            'Environment :: Console',
            'Programming Language :: Python :: 2.5',
            'Programming Language :: Python :: 2.6',
            'Programming Language :: Python :: 2.7',
            'Programming Language :: Python :: 3.3'
            'Framework :: Django'
        ]
        python setup.py register --list-classifiers
        
      

Console scripts


        scripts=['django/bin/django-admin.py']
        
      

Lean release

$ python setup.py register

$ python setup.py sdist upload

What have been done?

  1. Build distributition VotePackage-0.1dev.tar.gz and upload it to PYPI

Testing

Tox

Use tox to automate package testing against different python versions

      
        import sys
        from setuptools.command.test import test as TestCommand
        class Tox(TestCommand):
            def finalize_options(self):
                TestCommand.finalize_options(self)
                self.test_args = []
                self.test_suite = True
            def run_tests(self):
                #import here, cause outside the eggs aren't loaded
                import tox
                errno = tox.cmdline(self.test_args)
                sys.exit(errno)
      
    

Tox.ini & setup.py

      
        # content of: tox.ini , put in same dir as setup.py
        [tox]
        envlist = py25,py26,py27,py33
        [testenv]
        deps=pytest       # install pytest in the venvs
        commands=py.test  # or 'nosetests' or ...

      
    
      
        # setup.py
        ...
        tests_require=['tox'], #install tox package
        cmdclass = {'test': Tox},
      
      
    

Test your package

      
        $ python setup.py test
        ...
        py27 inst-nodeps: /Users/rootart/development/
          VotePackage/.tox/dist/VotePackage-0.1dev.zip
        py27 runtests: commands[0]
        ...
        py25: commands succeeded
        py26: commands succeeded
        py27: commands succeeded
        py33: commands succeeded
        congratulations :)
      
    

Use CI system for constant builds

As a user

PIP & virtualenv

      
        $ virtualenv env
        $ pip install/uninstall package
        $ pip freeze > requirements-dev.txt
        $ pip install -r requirements-dev.txt
        $ pip install ... -M (--mirrors) #PEP-381
        $ pip install -e git/hg/svn
      
    

PIP useful configuration options

      
        # $HOME/.pip/pip.conf
        [global]
        timeout = 60
        index-url = http://local.cheeseshop/
        download_cache = ~/.cache/pip
      
    

The Wheel Binary Package Format

PEP-427
      
        pip wheel [options]  ...
        pip wheel [options] -r  ...
        pip wheel [options]  ...
        pip wheel [options]  ...
        pip wheel [options]  ...
      
    

Future of python packaging

Future of python packaging

  1. standalone setup tool that install and uninstall packages

Some of the distutils2 features

http://peps.io/426/
      
        Requires-External: C
        Requires-External: libpng (>=1.5) #PIL :)
        
        Requires-Dist package; python_version == '2.5'
        
        Obsoletes-Dist: OtherProject (<3.0)
      
    
  1. KISS

Thank you! LvivPy#2 is awesome :)

Question?

Fork me on Github