pip - Releasing a Package
Decide library name; I'll use magillan
here as an example.
# venv shortcut functions, but I'm just making and activating a venv here
vmk magillan 3
v magillan
Create setup.py
; note that, contrary to what requirements.txt
does, all dependencies are listed without versions. This is important because you won't know what exact versions of libraries will be installed alongside of this libraries so you must be flexible and fix any problems that might raise.
import ast
import os
import re
import setuptools
# read library version from the main package so it's in one place
with open(os.path.join(os.path.dirname(__file__), 'magillan', '__init__.py')) as infp:
version = ast.literal_eval(re.search('__version__ = (.+?)$', infp.read(), re.M).group(1))
# read full page library descrption shown on PyPI website from README like GitHub
with open('README.md', 'r') as fp:
long_description = fp.read()
dev_dependencies = [
'flake8',
'isort',
'pydocstyle',
'pytest',
'pytest-cov',
'pytest-mock',
'tox',
]
if __name__ == '__main__':
setuptools.setup(
name='magillan',
description='Awesome library for Python',
long_description=long_description,
long_description_content_type='text/markdown',
version=version,
author='Ruksi',
author_email='me@ruk.si',
url='https://github.com/ruksi/magillan',
license='MIT',
packages=setuptools.find_packages(
'.', exclude=('magillan_tests', 'magillan_tests.*',)
),
install_requires=[],
tests_require=dev_dependencies,
extras_require={'dev': dev_dependencies},
classifiers=[
"Programming Language :: Python :: 3",
"License :: OSI Approved :: MIT License",
"Operating System :: OS Independent",
],
)
After the setup.py
, you can install development version to current virtual enviroment:
pip install -e .[dev] # where . can be a path to the library source root
Based on the above configuration, you have a single module called magillan
. This should look something like this:
magillan/
magillan/
__init__.py
magillan_tests/
__init__.py
setup.py
README.md
Where magillan/__init__.py
contains something like:
__version__ = '0.0.1'
And magillan_tests/__ini__.py
something like:
import magillan
def test_for_smoke():
assert magillan.__version__
Readme
Add README.md
. Shown on GitHub and PyPI project home pages.
License
Add LICENSE
. For example MIT from https://opensource.org/licenses/MIT
Development Tools
Create setup.cfg
:
[flake8]
ignore = E741
max-line-length = 79
max-complexity = 10
[pydocstyle]
ignore = D100,D104,D203,D212
[tool:pytest]
norecursedirs = .git .tox
[isort]
atomic = true
combine_as_imports = false
indent = 4
length_sort = false
line_length = 79
multi_line_output = 5
not_skip = __init__.py
order_by_type = false
wrap_length = 79
Create tox.ini
:
[tox]
envlist = {py35,py36,py37,py38}
[testenv]
commands = pytest -v {posargs}
deps =
pytest
Create .coveragerc
:
[run]
branch = True
omit =
*site-packages*
setup.py
Running the various tools:
isort -y # automatically enforce import style rules
flake8 # run code style checker
pydocstyle # run documentation style checker
tox # run tests with multiple Python versions
pytest --cov # run unit tests and print test coverage
If you are doing open source, create .travis.yml
for free Travis CI and Codecov:
sudo: false
dist: xenial
language: python
python:
- "3.5"
- "3.6"
- "3.7"
- "3.8"
install:
- pip install -U pip
- "pip install -e .[dev]"
script:
- flake8
- pydocstyle
- pytest -vvv --cov .
after_success:
- bash <(curl -s https://codecov.io/bash)
Release
Create .gitignore
, here is a good starting point:
*.egg-info
*.py[cod]
.cache
.coverage
.eggs
.pytest_cache
.tox
.venv
.idea
__pycache__
build
dist
sdist
venv
env
htmlcov
pip-delete-this-directory.txt
pip-log.txt
coverage.xml
# check that the tar archive looks good after source distribution build
python setup.py sdist
tar tzvf dist/magillan-0.1.tar.gz
# create local git repository
git init
git status
git add -A
git commit -m "Initial commit"
git clean -ndx -e .idea/ # lists which files would be deleted by clean
git clean -fdx -e .idea/ # deletes them
# create project in GitHub and then...
git remote add origin git@github.com:ruksi/magillan.git
git push -u origin master
Create PyPI account at PyPI registration page. You will use this to upload and manage your pip
packages.
# create a build distribution and upload it to PyPI
python setup.py sdist bdist_wheel
pip install twine
twine upload dist/*
# ... add your username and password
# and how you should have your library visible on https://pypi.org/
Now the following should work anywhere with Python and pip
installed:
pip install magillan
python
>> import magillan; print(magillan.__version__)