Skip to content

Instantly share code, notes, and snippets.

@uilianries
Last active August 19, 2019 12:05
Show Gist options
  • Save uilianries/ec470e9f181507c7abcb6eb349d2812c to your computer and use it in GitHub Desktop.
Save uilianries/ec470e9f181507c7abcb6eb349d2812c to your computer and use it in GitHub Desktop.
Upload PyPi package
matrix:
fast_finish: true
include:
- os: linux
dist: xenial
sudo: false
language: python
python: '2.7'
- os: linux
dist: xenial
sudo: false
language: python
python: '3.7'
- os: osx
language: generic
osx_image: xcode9
install:
- ".travis/install.sh"
script:
- ".travis/run.sh"
after_success:
- codecov
deploy:
- provider: pypi
user: ${PYPI_LOGIN_USERNAME}
password: ${PYPI_PASSWORD}
on:
branch: master
python: 2.7

How to build, test and upload a Python package, using Travis CI

  • First all, you need a Travis account, and a Pypi account:

    • pypi.org
    • travis.com
  • If you have unit tests, you can put them in tests/ or where you want

How Travis works in this case:

  • It will run your package 2x on Linux, one running Python 2.7 and another one, running Python 3.7. If your project does not support Python 2, remove the lines 4 - 8. For MacOS, it will install Python 3 and virtualenv, since we don't have permission to install directly on system

  • The first step is install, which is composed by install.sh. It will run pip install -r to install requirements, before testing you project. For MacOS it will also install Python3

  • The next step is build.sh, which will run all unit tests. You strongly recommend pytest, which easier and powerful than nose.

  • The last step is the deploy. Travis offers a plugin to upload python package in pypi. Internally it has all package already installer, as twine. The condition on: in Travis yaml indicates that your package ONLY will be uploaded when the current branch is master AND the current python version is 2.7. This condition avoids duplicated uploads. You only need to pass your username and password from pypi.org. Use env vars from settings and don't forge to make them private.

#!/bin/bash
set -e
set -x
if [[ "$(uname -s)" == 'Darwin' ]]; then
brew update || brew update
brew outdated pyenv || brew upgrade pyenv
brew install pyenv-virtualenv
if which pyenv > /dev/null; then
eval "$(pyenv init -)"
fi
pyenv install 2.7.10
pyenv virtualenv 2.7.10 conan
pyenv rehash
pyenv activate conan
fi
pip install codecov
# If your are using setup.py to install all packages:
# pip install -e .[test]
#
# Otherwise:
pip install -r requirements.txt
# If you have a specific requirements file for test or development, just update the line above with all files names
#!/bin/bash
set -e
set -x
if [[ "$(uname -s)" == 'Darwin' ]]; then
if which pyenv > /dev/null; then
eval "$(pyenv init -)"
fi
pyenv activate conan
fi
python setup.py sdist
# If you are using pytest:
#
# pushd tests/
# pytest -v
# popd
#
# For basic unittest using Noise2:
nosetest -v tests/
"""A setuptools based setup module.
See:
https://packaging.python.org/en/latest/distributing.html
https://github.com/pypa/sampleproject
"""
# Always prefer setuptools over distutils
import re
import os
from setuptools import setup, find_packages
# To use a consistent encoding
from codecs import open
here = os.path.abspath(os.path.dirname(__file__))
# Get the long description from the README file
with open(os.path.join(here, 'README.md'), encoding='utf-8') as f:
long_description = f.read()
def get_requires(filename):
requirements = []
with open(filename) as req_file:
for line in req_file.read().splitlines():
if not line.strip().startswith("#"):
requirements.append(line)
return requirements
def load_version():
"""Loads a file content"""
filename = os.path.abspath(os.path.join(os.path.dirname(os.path.abspath(__file__)),
"conan_deploy_tool", "__init__.py"))
with open(filename, "rt") as version_file:
conan_init = version_file.read()
version = re.search("__version__ = '([0-9a-z.-]+)'", conan_init).group(1)
return version
setup(
name='conan-deploy-tool',
# Versions should comply with PEP440. For a discussion on single-sourcing
# the version across setup.py and the project code, see
# https://packaging.python.org/en/latest/single_source_version.html
version=load_version(),
# This is an optional longer description of your project that represents
# the body of text which users will see when they visit PyPI.
#
# Often, this is the same as your README, so you can just read it in from
# that file directly (as we have already done above)
#
# This field corresponds to the "Description" metadata field:
# https://packaging.python.org/specifications/core-metadata/#description-optional
long_description=long_description, # Optional
description='Conan Deploy Tool',
# The project's main homepage.
url='https://github.com/SSE3/conan-deploy-tool',
# Author details
author='<author>',
author_email='<[email protected]>',
# Choose your license
license='MIT',
# See https://pypi.python.org/pypi?%3Aaction=list_classifiers
classifiers=[
'Development Status :: 4 - Beta',
'Intended Audience :: Developers',
'Topic :: Software Development :: Build Tools',
'License :: OSI Approved :: MIT License',
'Programming Language :: Python :: 2',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3',
],
# What does your project relate to?
keywords=['conan', 'C/C++', 'package', 'libraries', 'developer', 'manager',
'dependency', 'tool', 'c', 'c++', 'cpp', 'deploy'],
# You can just specify the packages manually here if your project is
# simple. Or you can use find_packages().
packages=find_packages(exclude=['tests']),
# Alternatively, if you want to distribute just a my_module.py, uncomment
# this:
# py_modules=["my_module"],
# List run-time dependencies here. These will be installed by pip when
# your project is installed. For an analysis of "install_requires" vs pip's
# requirements files see:
# https://packaging.python.org/en/latest/requirements.html
install_requires=get_requires(os.path.join('conan_deploy_tool', 'requirements.txt')),
# List additional groups of dependencies here (e.g. development
# dependencies). You can install these using the following syntax,
# for example:
# $ pip install -e .[dev,test]
extras_require={
'test': get_requires(os.path.join('conan_deploy_tool', 'requirements_test.txt'))
},
# If there are data files included in your packages that need to be
# installed, specify them here. If using Python 2.6 or less, then these
# have to be included in MANIFEST.in as well.
package_data={
'': ['*.md'],
'conan_deploy_tool' : ['*.txt'],
},
# Although 'package_data' is the preferred approach, in some case you may
# need to place data files outside of your packages. See:
# http://docs.python.org/3.4/distutils/setupscript.html#installing-additional-files # noqa
# In this case, 'data_file' will be installed into '<sys.prefix>/my_data'
# data_files=[('my_data', ['data/data_file'])],
# To provide executable scripts, use entry points in preference to the
# "scripts" keyword. Entry points provide cross-platform support and allow
# pip to create the appropriate form of executable for the target platform.
entry_points={
'console_scripts': [
'conan-deploy-tool=conan_deploy_tool.main:run',
],
},
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment