Slide 1

Slide 1 text

PYTHON PACKAGING FOR HUMANS by Dan Crosta @lazlofruvous

Slide 2

Slide 2 text

JUST DO THIS: from setuptools import setup, find_packages from distutils.core import Extension setup( name='mypackage', version='0.1', description='My New Packaging Technique is Unstoppable', long_description=__doc__, author='Dan Crosta', author_email='[email protected]', license='BSD', classifiers=[ 'Development Status :: 3 - Alpha', 'Programming Language :: Python :: 2'], packages=find_packages(), ext_modules=[Extension('_cmypackage', ['_cmypackage.c'])], setup_requires=['nose'], tests_require=['coverage'], )

Slide 3

Slide 3 text

BACK IN MY DAY... • Google "python " • Search for download link • Extract tarball • python setup.py install • ... • Ugh.

Slide 4

Slide 4 text

BACK IN MY DAY... • PyPI launches in 2003 • setuptools/easy_install • distribute/pip • Py3k packaging/distutils2

Slide 5

Slide 5 text

BACK IN MY DAY... • Most of this has existed for a decade. • Why isn't *everything* packaged?

Slide 6

Slide 6 text

WHY PACKAGE? • Dead simple for users • Good for package authors • Really not hard

Slide 7

Slide 7 text

GOOD FOR USERS: • Single interface to package management • Lots of "do what I mean" baked in • Makes deployment way easier

Slide 8

Slide 8 text

GOOD FOR AUTHORS: • Development helpers • Plays nice with others • Know what users are getting

Slide 9

Slide 9 text

This is how you do it.

Slide 10

Slide 10 text

REPOSITORY LAYOUT + mypackage/ + README + LICENSE + distribute_setup.py + setup.py + setup.cfg + mypackage/ | + __init__.py | + foo.py | + bar.py + _cmypackage.c + tests/ + test_foo.py + test_bar.py

Slide 11

Slide 11 text

SETUP.PY #1: JUST ENOUGH from setuptools import setup setup( name='mypackage', version='0.1', description='My New Packaging Technique is Unstoppable', author='Dan Crosta', author_email='[email protected]', license='BSD', packages=['mypackage'], )

Slide 12

Slide 12 text

SETUP.PY #1: JUST ENOUGH from setuptools import setup, find_packages setup( name='mypackage', version='0.1', description='My New Packaging Technique is Unstoppable', author='Dan Crosta', author_email='[email protected]', license='BSD', packages=find_packages(), )

Slide 13

Slide 13 text

SETUP.PY #2: DEPENDENCIES from setuptools import setup setup( # ... install_requires=[ 'somepackage == 0.1', 'otherpackage >= 0.2', 'yetanother != 0.3'], )

Slide 14

Slide 14 text

SETUP.PY #3: CLASSIFIERS from setuptools import setup setup( # ... classifiers=[ 'Development Status :: 3 - Alpha', 'Programming Language :: Python :: 2'], ) • See http://pypi.python.org/pypi for full list

Slide 15

Slide 15 text

SETUP.PY #4: SCRIPTS from setuptools import setup setup( # ... entry_points={ 'console_scripts': [ 'packagescript=mypackage.scripts:main'], }, )

Slide 16

Slide 16 text

SETUP.PY #5: PACKAGE DATA from setuptools import setup setup( # ... include_package_data=True, )

Slide 17

Slide 17 text

SETUP.PY #6: C EXTENSIONS from setuptools import setup setup( # ... ext_modules=[ Extension('_cmypackage', ['_cmypackage.c']) ], )

Slide 18

Slide 18 text

This is how you make sure it works.

Slide 19

Slide 19 text

VIRTUALENV • Packaging's best friend • Use --no-site-packages

Slide 20

Slide 20 text

VIRTUALENV # In your source tree $ python setup.py sdist $ ls dist/ mypackage-0.1.tar.gz # In a clean virtualenv $ pip install /path/to/mypackage-0.1.tar.gz

Slide 21

Slide 21 text

This is how you share it with everyone.

Slide 22

Slide 22 text

PYPI • Python Package Index • aka "Cheeseshop" • pip, easy_install, buildout all look here • You want your package here.

Slide 23

Slide 23 text

PYPI • Create an account at http://pypi.python.org/pypi

Slide 24

Slide 24 text

PYPI $ python setup.py register We need to know who you are, so please choose either: 1. use your existing login, 2. register as a new user, 3. have the server generate a new password for you, or 4. quit Your selection [default 1]: 1 Username: dcrosta Password: ******* Registering mypackage to http://pypi.python.org/pypi Server response (200): OK

Slide 25

Slide 25 text

PYPI $ python setup.py sdist upload running upload Submitting dist/mypackage-0.1.tar.gz to pypi.python.org/pypi Server response (200): OK

Slide 26

Slide 26 text

This is how you get the most out of setup.py.

Slide 27

Slide 27 text

NOSETESTS from setuptools import setup setup( # ... setup_requires=['nose'], tests_require=['coverage'], )

Slide 28

Slide 28 text

NOSETESTS # setup.cfg, read by setup.py [nosetests] verbosity = 0 detailed-errors = 1 with-coverage = 1 cover-package = mypackage cover-inclusive = 1

Slide 29

Slide 29 text

NOSETESTS $ python setup.py nosetests running nosetests Name Stmts Miss Cover Missing -------------------------------------------------- mypackage 2 0 100% mypackcage.foo 19 4 79% 13, 31-33 mypackage.bar 16 6 63% 13, 22-26 -------------------------------------------------- TOTAL 37 10 73% -------------------------------------------------- Ran 12 tests in 0.027s

Slide 30

Slide 30 text

TRAVIS-CI # .travis.yml language: python python: - 2.5 - 2.6 - 2.7 install: python setup.py -q install script: python setup.py -q nosetests

Slide 31

Slide 31 text

TRAVIS-CI

Slide 32

Slide 32 text

This is how you extend it.

Slide 33

Slide 33 text

BUILDING DOCS class doc(Command): description = "generate sphinx documentation" user_options = [] boolean_options = [] def initialize_options(self): pass def finalize_options(self): pass def run(self): status = subprocess.call(["make", "-C", "docs", "html"]) if status: raise RuntimeError("documentation build failed")