From 2baf25fe3f57afa9c68a4bccb51d8349ebfb3e28 Mon Sep 17 00:00:00 2001 From: mattsb42-aws Date: Mon, 12 Mar 2018 20:11:36 -0700 Subject: [PATCH] initial package setup and structure --- .gitignore | 19 +++++ .travis.yml | 40 ++++++++++ CHANGELOG.rst | 0 MANIFEST.in | 6 ++ appveyor.yml | 62 +++++++++++++++ setup.cfg | 41 ++++++++++ setup.py | 65 ++++++++++++++++ tox.ini | 207 ++++++++++++++++++++++++++++++++++++++++++++++++++ 8 files changed, 440 insertions(+) create mode 100644 .gitignore create mode 100644 .travis.yml create mode 100644 CHANGELOG.rst create mode 100644 MANIFEST.in create mode 100644 appveyor.yml create mode 100644 setup.cfg create mode 100644 setup.py create mode 100644 tox.ini diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..993f84e --- /dev/null +++ b/.gitignore @@ -0,0 +1,19 @@ +*.egg-info +*.pyc +*.pyo +*~ +.DS_Store +.tox +/.cache* +/.coverage* +/build +/doc/generated/* +/runpy +__pycache__ +build +dist +docs/build +.python-version +.mypy_cache +.hypothesis +.pytest_cache diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..3fde6e4 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,40 @@ +sudo: false +language: python +matrix: + include: + - python: 2.6 + env: TOXENV=py26 + - python: 2.7 + env: TOXENV=py27 + - python: 3.3 + env: TOXENV=py33 + - python: 3.4 + env: TOXENV=py34 + - python: 3.5 + env: TOXENV=py35 + - python: 3.6 + env: TOXENV=py36 + - python: 3.7 + env: TOXENV=py37 + - python: 3.6 + env: TOXENV=mypy-py2 + - python: 3.6 + env: TOXENV=mypy-py3 + - python: 3.6 + env: TOXENV=bandit + - python: 3.6 + env: TOXENV=doc8 + - python: 3.6 + env: TOXENV=readme + - python: 3.6 + env: TOXENV=docs + - python: 3.6 + env: TOXENV=flake8 + - python: 3.6 + env: TOXENV=pylint + - python: 3.6 + env: TOXENV=flake8-tests + - python: 3.6 + env: TOXENV=pylint-tests +install: pip install tox +script: tox diff --git a/CHANGELOG.rst b/CHANGELOG.rst new file mode 100644 index 0000000..e69de29 diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 0000000..38af3e7 --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1,6 @@ +include README.rst +include CHANGELOG.rst +include LICENSE + +recursive-include doc * +recursive-include test *.py \ No newline at end of file diff --git a/appveyor.yml b/appveyor.yml new file mode 100644 index 0000000..65473c8 --- /dev/null +++ b/appveyor.yml @@ -0,0 +1,62 @@ +# https://packaging.python.org/guides/supporting-windows-using-appveyor/ + +environment: + + matrix: + # The only test we perform on Windows are our actual code tests. All linting, static + # analysis, etc are only run on Linux (via Travis CI). + + # Python 2.6 + - PYTHON: "C:\\Python26" + TOXENV: "py26" + - PYTHON: "C:\\Python26-x64" + TOXENV: "py26" + + # Python 2.7 + - PYTHON: "C:\\Python27" + TOXENV: "py27" + - PYTHON: "C:\\Python27-x64" + TOXENV: "py27" + + # Python 3.3 + - PYTHON: "C:\\Python33" + TOXENV: "py33" + - PYTHON: "C:\\Python33-x64" + TOXENV: "py33" + + # Python 3.4 + - PYTHON: "C:\\Python34" + TOXENV: "py34" + - PYTHON: "C:\\Python34-x64" + DISTUTILS_USE_SDK: "1" + TOXENV: "py34" + + # Python 3.5 + - PYTHON: "C:\\Python35" + TOXENV: "py35" + - PYTHON: "C:\\Python35-x64" + TOXENV: "py35" + + # Python 3.6 + - PYTHON: "C:\\Python36" + TOXENV: "py36" + - PYTHON: "C:\\Python36-x64" + TOXENV: "py36" + + # Python 3.7 + - PYTHON: "C:\\Python37" + TOXENV: "py37" + - PYTHON: "C:\\Python37-x64" + TOXENV: "py37" + +install: + # Prepend newly installed Python to the PATH of this build + - "SET PATH=%PYTHON%;%PYTHON%\\Scripts;%PATH%" + # Check the Python version to verify the correct version was installed + - "python --version" + - "python -m pip install wheel tox" + +build: off + +test_script: + - "tox" diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 0000000..02db1ba --- /dev/null +++ b/setup.cfg @@ -0,0 +1,41 @@ +[wheel] +universal = 1 + +[metadata] +license_file = LICENSE + +[coverage:run] +branch = True + +[coverage:report] +show_missing = True + +[mypy] +ignore_missing_imports = True + +[tool:pytest] +markers = + unit: mark test as a unit test (does not require network access) + functional: mark test as a functional test (does not require network access) + hypothesis: mark a test as using hypothesis (will run many times for each pytest call) +log_level=NOTSET + +# Flake8 Configuration +[flake8] +max_complexity = 10 +max_line_length = 120 +import_order_style = google +application_import_names = base64io +builtins = raw_input +ignore = + # Ignoring D205 and D400 because of false positives + #D205, D400, + # Ignoring D401 pending discussion of imperative mood + #D401, + # Ignoring D202 (no blank lines after function docstring) because mypy confuses flake8 + D202 + + +# Doc8 Configuration +[doc8] +max-line-length = 120 diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..876e7b1 --- /dev/null +++ b/setup.py @@ -0,0 +1,65 @@ +"""Base64IO stream handler.""" +import io +import os +import re + +from setuptools import find_packages, setup + +VERSION_RE = re.compile(r'''__version__ = ['"]([0-9.]+)['"]''') +HERE = os.path.abspath(os.path.dirname(__file__)) + + +def read(*args): + """Read complete file contents.""" + return io.open(os.path.join(HERE, *args), encoding='utf-8').read() + + +def readme(): + """Read and patch README.""" + readme_text = read('README.rst') + # PyPI does not accept :class: references. + return readme_text.replace(':class:`base64io.Base64IO`', '``base64io.Base64IO``') + + +def get_version(): + """Read the version from this module.""" + init = read('src', 'base64io', '__init__.py') + return VERSION_RE.search(init).group(1) + + +setup( + name='base64io', + version=get_version(), + packages=find_packages('src'), + package_dir={'': 'src'}, + url='http://base64io.readthedocs.io/en/latest/', + author='Amazon Web Services', + author_email='aws-cryptools@amazon.com', + maintainer='Amazon Web Services', + long_description=readme(), + keywords='base64 stream', + data_files=[ + 'README.rst', + 'CHANGELOG.rst', + 'LICENSE' + ], + license='Apache License 2.0', + install_requires=[], + classifiers=[ + 'Development Status :: 5 - Production/Stable', + 'Intended Audience :: Developers', + 'Natural Language :: English', + 'License :: OSI Approved :: Apache Software License', + 'Programming Language :: Python', + 'Programming Language :: Python :: 2', + 'Programming Language :: Python :: 2.6', + 'Programming Language :: Python :: 2.7', + 'Programming Language :: Python :: 3', + 'Programming Language :: Python :: 3.3', + 'Programming Language :: Python :: 3.4', + 'Programming Language :: Python :: 3.5', + 'Programming Language :: Python :: 3.6', + 'Programming Language :: Python :: 3.7', + 'Programming Language :: Python :: Implementation :: CPython' + ] +) diff --git a/tox.ini b/tox.ini new file mode 100644 index 0000000..2c027cd --- /dev/null +++ b/tox.ini @@ -0,0 +1,207 @@ +[tox] +envlist = + py{26,27,33,34,35,36,37}, + bandit, doc8, readme, + mypy-py{2,3}, + flake8, pylint, + flake8-tests, pylint-tests, + # prone to false positives + vulture + +# Additional environments: +# linters :: Runs all linters over all source code. +# linters-tests :: Runs all linters over all tests. + +[testenv:default-python] +basepython = python3.6 + +[testenv:base-command] +commands = pytest --basetemp={envtmpdir} -l --cov base64io {posargs} + +[testenv] +sitepackages = False +deps = + py26: -rtest/requirements/legacy + py27: -rtest/requirements/modern + py33: -rtest/requirements/legacy + py34: -rtest/requirements/modern + py35: -rtest/requirements/modern + py36: -rtest/requirements/modern + py37: -rtest/requirements/modern +commands = pytest --basetemp={envtmpdir} -l --cov base64io {posargs} + +# mypy +[testenv:mypy-common] +basepython = {[testenv:default-python]basepython} +deps = + coverage + mypy + mypy_extensions + typing>=3.6.2 +commands = + python -m mypy \ + --linecoverage-report build \ + src/base64io/ + +[testenv:mypy-coverage] +commands = + # Make mypy linecoverage report readable by coverage + python -c \ + "t = open('.coverage', 'w');\ + c = open('build/coverage.json').read();\ + t.write('!coverage.py: This is a private format, don\'t read it directly!\n');\ + t.write(c);\ + t.close()" + coverage report -m + +[testenv:mypy-py3] +basepython = {[testenv:mypy-common]basepython} +deps = {[testenv:mypy-common]deps} +commands = + {[testenv:mypy-common]commands} + {[testenv:mypy-coverage]commands} + +[testenv:mypy-py2] +basepython = {[testenv:mypy-common]basepython} +deps = {[testenv:mypy-common]deps} +commands = + {[testenv:mypy-common]commands} --py2 + {[testenv:mypy-coverage]commands} + +# Linters +[testenv:flake8] +basepython = {[testenv:default-python]basepython} +deps = + flake8 + flake8-docstrings + flake8-import-order + # https://github.com/JBKahn/flake8-print/pull/30 + flake8-print>=3.1.0 +commands = + flake8 \ + src/base64io/ \ + setup.py \ + doc/conf.py + +[testenv:flake8-tests] +basepython = {[testenv:flake8]basepython} +deps = {[testenv:flake8]deps} +commands = + flake8 \ + # Ignore F811 redefinition errors in tests (breaks with pytest-mock use) + # Ignore D103 docstring requirements for tests + --ignore F811,D103 \ + test/ + +[testenv:pylint] +basepython = {[testenv:default-python]basepython} +deps = + -rtest/requirements/modern + pyflakes + pylint +commands = + pylint \ + --rcfile=src/pylintrc \ + src/base64io/ \ + setup.py \ + doc/conf.py + +[testenv:pylint-tests] +basepython = {[testenv:pylint]basepython} +deps = {[testenv:pylint]deps} +commands = + pylint \ + --rcfile=test/pylintrc \ + test/unit/ + +[testenv:doc8] +basepython = {[testenv:default-python]basepython} +deps = + sphinx + doc8 +commands = doc8 doc/index.rst README.rst CHANGELOG.rst + +[testenv:readme] +basepython = {[testenv:default-python]basepython} +deps = readme_renderer +commands = python setup.py check -r -s + +[testenv:bandit] +basepython = {[testenv:default-python]basepython} +deps = bandit +commands = bandit -r src/base64io/ + +# Prone to false positives: only run independently +[testenv:vulture] +basepython = {[testenv:default-python]basepython} +deps = vulture +commands = vulture src/base64io/ + +[testenv:linters] +basepython = {[testenv:default-python]basepython} +deps = + {[testenv:flake8]deps} + {[testenv:pylint]deps} + {[testenv:doc8]deps} + {[testenv:readme]deps} + {[testenv:bandit]deps} +commands = + {[testenv:flake8]commands} + {[testenv:pylint]commands} + {[testenv:doc8]commands} + {[testenv:readme]commands} + {[testenv:bandit]commands} + +[testenv:linters-tests] +basepython = {[testenv:default-python]basepython} +deps = + {[testenv:flake8-tests]deps} + {[testenv:pylint-tests]deps} +commands = + {[testenv:flake8-tests]commands} + {[testenv:pylint-tests]commands} + +# Documentation +[testenv:docs] +basepython = {[testenv:default-python]basepython} +deps = -rdoc/requirements.txt +commands = + sphinx-build -E -c doc/ -b html doc/ doc/build/html + +[testenv:serve-docs] +basepython = {[testenv:default-python]basepython} +skip_install = true +changedir = doc/build/html +deps = +commands = + python -m http.server {posargs} + +# Release tooling +[testenv:build] +basepython = {[testenv:default-python]basepython} +skip_install = true +deps = + wheel + setuptools +commands = + python setup.py sdist bdist_wheel + +[testenv:test-release] +basepython = {[testenv:default-python]basepython} +skip_install = true +deps = + {[testenv:build]deps} + twine +commands = + {[testenv:build]commands} + twine upload --skip-existing --repository testpypi dist/* + +[testenv:release] +basepython = {[testenv:default-python]basepython} +skip_install = true +deps = + {[testenv:build]deps} + twine +commands = + {[testenv:build]commands} + twine upload --skip-existing --repository pypi dist/*