Upgrade to Pro — share decks privately, control downloads, hide ads and more …

PyCon 2017 - Share Your Code! Python Packaging Without Complication

PyCon 2017 - Share Your Code! Python Packaging Without Complication

Dave Forgac

May 21, 2017
Tweet

More Decks by Dave Forgac

Other Decks in Technology

Transcript

  1. Share Your Code!
    Python Packaging without
    Complication
    daveops.com/pycon2017
    [email protected]
    @tylerdave

    View Slide

  2. def beautiful_code():
    """This code is so beautiful."""

    print('Hello, PyCon!')

    View Slide

  3. “I want to share my code!
    What do I need to do?”

    View Slide

  4. Package

    View Slide

  5. Documentation

    View Slide

  6. Source Hosting

    View Slide

  7. Tests

    View Slide

  8. CI

    View Slide

  9. License

    View Slide

  10. Contributing

    View Slide

  11. we need
    Code
    Package
    Documentation
    Source Hosting
    Tests
    CI
    License
    Contributing

    View Slide

  12. “But I just wanted to share
    my code!”

    View Slide

  13. TL;DR

    View Slide

  14. TL;DR

    View Slide

  15. Terminology

    View Slide

  16. Module
    Saved Python code

    View Slide

  17. Import Package
    namespace / directory

    View Slide

  18. Distribution
    Package
    Shareable / installable

    View Slide

  19. Source Distribution
    sdist

    View Slide

  20. Built Distribution
    Wheel

    View Slide

  21. Wheel

    View Slide

  22. Wheel
    Universal

    View Slide

  23. Wheel
    Universal
    Pure Python

    View Slide

  24. Wheel
    Universal
    Pure Python
    Platform

    View Slide

  25. History

    View Slide

  26. History
    Copy / Replace

    View Slide

  27. History
    Copy / Replace
    PyPA

    View Slide

  28. History
    Copy / Replace
    PyPA
    PyPUG
    https://packaging.python.org/

    View Slide

  29. “Let's make a package!”

    View Slide

  30. Using cookiecutter
    $ cookiecutter cookiecutter-python-package

    full_name (default is "Dave Forgac")?
    email (default is "[email protected]")?
    github_username (default is "tylerdave")?
    project_name (default is "Example")? Example Package
    repo_name (default is "boilerplate")? Example-Package
    project_short_description (default is "A short description")?
    Example package for PyCon talk.
    release_date (default is "2017-05-21")?
    year (default is "2017")?
    version (default is "0.1.0")?

    View Slide

  31. Layout
    .
    ├── data
    │ └── data_file
    ├── DESCRIPTION.rst
    ├── MANIFEST.in
    ├── README.rst
    ├── sample
    │ ├── __init__.py
    │ └── package_data.dat
    ├── setup.cfg
    ├── setup.py
    └── tests
    ├── __init__.py
    └── test_sample.py

    View Slide

  32. Code
    .
    ├── data
    │ └── data_file
    ├── DESCRIPTION.rst
    ├── MANIFEST.in
    ├── README.rst
    ├── sample
    │ ├── __init__.py
    │ └── package_data.dat
    ├── setup.cfg
    ├── setup.py
    └── tests
    ├── __init__.py
    └── test_sample.py

    View Slide

  33. setup.py
    .
    ├── data
    │ └── data_file
    ├── DESCRIPTION.rst
    ├── MANIFEST.in
    ├── README.rst
    ├── sample
    │ ├── __init__.py
    │ └── package_data.dat
    ├── setup.cfg
    ├── setup.py
    └── tests
    ├── __init__.py
    └── test_sample.py

    View Slide

  34. setup.cfg
    .
    ├── data
    │ └── data_file
    ├── DESCRIPTION.rst
    ├── MANIFEST.in
    ├── README.rst
    ├── sample
    │ ├── __init__.py
    │ └── package_data.dat
    ├── setup.cfg
    ├── setup.py
    └── tests
    ├── __init__.py
    └── test_sample.py

    View Slide

  35. MANIFEST.in
    .
    ├── data
    │ └── data_file
    ├── DESCRIPTION.rst
    ├── MANIFEST.in
    ├── README.rst
    ├── sample
    │ ├── __init__.py
    │ └── package_data.dat
    ├── setup.cfg
    ├── setup.py
    └── tests
    ├── __init__.py
    └── test_sample.py

    View Slide

  36. README.rst
    .
    ├── data
    │ └── data_file
    ├── DESCRIPTION.rst
    ├── MANIFEST.in
    ├── README.rst
    ├── sample
    │ ├── __init__.py
    │ └── package_data.dat
    ├── setup.cfg
    ├── setup.py
    └── tests
    ├── __init__.py
    └── test_sample.py

    View Slide

  37. setup.py (1/2)
    from setuptools import setup, find_packages

    setup(
    name='Example Package',
    version='0.1.0', # PEP440-compliant version
    description='Example package for PyCon talk.',
    long_description='Displayed on PyPI project page.',
    url='https://github.com/tylerdave/Example-Package',
    author='Dave Forgac',
    author_email='[email protected]',
    packages=find_packages(exclude=['docs', 'tests'])
    install_requires=['requests'],
    package_data={
    'sample': ['package_data.dat']
    }

    View Slide

  38. setup.py (1/2)
    from setuptools import setup, find_packages

    setup(
    name='Example Package',
    version='0.1.0', # PEP440-compliant version
    description='Example package for PyCon talk.',
    long_description='Displayed on PyPI project page.',
    url='https://github.com/tylerdave/Example-Package',
    author='Dave Forgac',
    author_email='[email protected]',
    packages=find_packages(exclude=['docs', 'tests'])
    install_requires=['requests'],
    package_data={
    'sample': ['package_data.dat']
    }

    View Slide

  39. setup.py (1/2)
    from setuptools import setup, find_packages

    setup(
    name='Example Package',
    version='0.1.0', # PEP440-compliant version
    description='Example package for PyCon talk.',
    long_description='Displayed on PyPI project page.',
    url='https://github.com/tylerdave/Example-Package',
    author='Dave Forgac',
    author_email='[email protected]',
    packages=find_packages(exclude=['docs', 'tests'])
    install_requires=['requests'],
    package_data={
    'sample': ['package_data.dat']
    }

    View Slide

  40. setup.py (1/2)
    from setuptools import setup, find_packages

    setup(
    name='Example Package',
    version='0.1.0', # PEP440-compliant version
    description='Example package for PyCon talk.',
    long_description='Displayed on PyPI project page.',
    url='https://github.com/tylerdave/Example-Package',
    author='Dave Forgac',
    author_email='[email protected]',
    packages=find_packages(exclude=['docs', 'tests'])
    install_requires=['requests'],
    package_data={
    'sample': ['package_data.dat']
    }

    View Slide

  41. setup.py (1/2)
    from setuptools import setup, find_packages

    setup(
    name='Example Package',
    version='0.1.0', # PEP440-compliant version
    description='Example package for PyCon talk.',
    long_description='Displayed on PyPI project page.',
    url='https://github.com/tylerdave/Example-Package',
    author='Dave Forgac',
    author_email='[email protected]',
    packages=find_packages(exclude=['docs', 'tests'])
    install_requires=['requests'],
    package_data={
    'sample': ['package_data.dat']
    }

    View Slide

  42. setup.py (2/2)

    entry_points={
    'console_scripts': [
    'hello=example_package.cli:say_hello',
    ],
    }
    license='MIT',
    classifiers=[
    'Development Status :: 3 - Alpha',
    'License :: OSI Approved :: MIT License',
    'Programming Language :: Python :: 2',
    'Programming Language :: Python :: 2.7',
    'Programming Language :: Python :: 3',
    'Programming Language :: Python :: 3.4',
    'Programming Language :: Python :: 3.5',

    View Slide

  43. setup.py (2/2)

    entry_points={
    'console_scripts': [
    'hello=example_package.cli:say_hello',
    ],
    }
    license='MIT',
    classifiers=[
    'Development Status :: 3 - Alpha',
    'License :: OSI Approved :: MIT License',
    'Programming Language :: Python :: 2',
    'Programming Language :: Python :: 2.7',
    'Programming Language :: Python :: 3',
    'Programming Language :: Python :: 3.4',
    'Programming Language :: Python :: 3.5',

    View Slide

  44. setup.py (2/2)

    entry_points={
    'console_scripts': [
    'hello=example_package.cli:say_hello',
    ],
    }
    license='MIT',
    classifiers=[
    'Development Status :: 3 - Alpha',
    'License :: OSI Approved :: MIT License',
    'Programming Language :: Python :: 2',
    'Programming Language :: Python :: 2.7',
    'Programming Language :: Python :: 3',
    'Programming Language :: Python :: 3.4',
    'Programming Language :: Python :: 3.5',

    View Slide

  45. setup.cfg
    [bdist_wheel]
    universal = 1        

    [flake8]
    exclude = docs

    View Slide

  46. MANIFEST.in
    include LICENSE
    include README.rst

    recursive-include tests *
    recursive-exclude * __pycache__
    recursive-exclude * *.py[co]

    View Slide

  47. README.rst
    ===============================
    Example Package
    ===============================

    License: MIT

    Documentation: https://example.com

    Usage
    -----

    ``sample --help``

    View Slide

  48. LICENSE

    View Slide

  49. Tests
    ./tests
    tox.ini

    View Slide

  50. Docs
    ./docs

    View Slide

  51. CI
    .travis.yml

    View Slide

  52. requirements.txt

    View Slide

  53. Also Common
    (rst | md | txt)
    HISTORY or CHANGES or CHANGELOG
    CONTRIBUTING
    AUTHORS

    View Slide

  54. “Now let's share our code!”

    View Slide

  55. Git init
    cd Example-Package
    git init
    git add .
    git commit -m 'initial commit'

    View Slide

  56. Run tests
    tox

    OK
    ___________________________ summary __________________________
    py27: commands succeeded
    py34: commands succeeded
    py35: commands succeeded
    py36: commands succeeded

    View Slide

  57. Commit
    git add .
    git commit -m "add hello pycon functionality"

    View Slide

  58. Services

    View Slide

  59. GitHub

    View Slide

  60. Travis CI
    https://travis-ci.org/
    or
    travis enable

    View Slide

  61. Git push
    To [email protected]:tylerdave/Example-Package.git
    * [new branch] master -> master
    Branch master set up to track remote branch master
    from origin.

    View Slide

  62. See builds succeeding!

    View Slide

  63. View Slide

  64. PyPI
    https://pypi.python.org/

    View Slide

  65. PyPI
    https://pypi.python.org/
    Test PyPI
    https://testpypi.python.org/

    View Slide

  66. Save PyPI Settings
    $HOME/.pypirc
    [distutils]
    index-servers=pypi
    [pypi]
    repository = https://pypi.python.org/pypi
    username =
    password =

    View Slide

  67. Virtualenv
    pew
    virtualenvwrapper

    View Slide

  68. Packaging Tools
    pip install wheel
    pip install twine

    View Slide

  69. Build dist. files
    ./setup.py sdist
    ./setup.py bdist_wheel
    or
    make dist

    View Slide

  70. Upload
    twine upload dist/*

    View Slide

  71. Install
    pip install example-package

    View Slide

  72. Develop Mode
    ./setup.py develop
    or
    pip install -e .

    View Slide

  73. Rinse, Repeat

    View Slide

  74. Versions
    bumpversion
    versioneer

    View Slide

  75. Recap

    View Slide

  76. Recap
    DIY

    View Slide

  77. Recap
    DIY
    Use the tools

    View Slide

  78. Recap
    DIY
    Use the tools
    Share your code!

    View Slide

  79. Thank you!
    Please leave feedback
    daveops.com/pycon2017
    [email protected]
    @tylerdave

    View Slide