summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIonel Cristian Mărieș <contact@ionelmc.ro>2015-10-02 22:42:08 +0300
committerIonel Cristian Mărieș <contact@ionelmc.ro>2015-10-02 22:42:08 +0300
commit8d04e68fdac7ddf9f34f3d2f11f5f305815ef789 (patch)
tree8ada746468eb93994e805c0b893f43517f1592f0
parent7331663ecd68cee8f0310f87aaf257fb24a9e976 (diff)
Upgrade skel.
-rw-r--r--.bumpversion.cfg8
-rw-r--r--.cookiecutterrc34
-rw-r--r--.coveragerc12
-rw-r--r--.gitignore69
-rw-r--r--.travis.yml84
-rw-r--r--AUTHORS.rst5
-rw-r--r--CHANGELOG.rst8
-rw-r--r--CONTRIBUTING.rst89
-rw-r--r--LICENSE38
-rw-r--r--MANIFEST.in31
-rw-r--r--README.rst101
-rw-r--r--appveyor.yml104
-rw-r--r--ci/appveyor-bootstrap.py117
-rw-r--r--ci/appveyor-download.py108
-rw-r--r--ci/appveyor-with-compiler.cmd46
-rw-r--r--coverage.ini1
-rw-r--r--python-tblib.komodoproject4
-rw-r--r--setup.cfg40
-rw-r--r--setup.py57
-rw-r--r--tox.ini143
20 files changed, 938 insertions, 161 deletions
diff --git a/.bumpversion.cfg b/.bumpversion.cfg
new file mode 100644
index 0000000..b0ec9c5
--- /dev/null
+++ b/.bumpversion.cfg
@@ -0,0 +1,8 @@
+[bumpversion]
+current_version = 1.1.0
+commit = True
+tag = True
+
+[bumpversion:file:setup.py]
+[bumpversion:file:docs/conf.py]
+[bumpversion:file:src/tblib/__init__.py]
diff --git a/.cookiecutterrc b/.cookiecutterrc
new file mode 100644
index 0000000..50db3bb
--- /dev/null
+++ b/.cookiecutterrc
@@ -0,0 +1,34 @@
+# This file exists so you can easily regenerate your project.
+#
+# Unfortunately cookiecutter can't use this right away so
+# you have to copy this file to ~/.cookiecutterrc
+
+default_context:
+
+ appveyor: 'yes'
+ c_extension_optional: 'no'
+ c_extension_support: 'no'
+ codacy: 'yes'
+ codeclimate: 'yes'
+ codecov: 'yes'
+ command_line_interface: 'no'
+ coveralls: 'yes'
+ distribution_name: 'tblib'
+ email: 'contact@ionelmc.ro'
+ full_name: 'Ionel Cristian Mărieș'
+ github_username: 'ionelmc'
+ landscape: 'yes'
+ package_name: 'tblib'
+ project_name: 'tblib'
+ project_short_description: 'Traceback fiddling library. For now allows you to pickle tracebacks and raise exceptions with pickled tracebacks in different processes. This allows better error handling when running code over multiple processes (imagine multiprocessing, billiard, futures, celery etc).'
+ release_date: '2015-07-27'
+ repo_name: 'python-tblib'
+ requiresio: 'yes'
+ scrutinizer: 'yes'
+ sphinx_theme: 'sphinx-py3doc-enhanced-theme'
+ test_matrix_configurator: 'no'
+ test_runner: 'no'
+ travis: 'yes'
+ version: '1.1.0'
+ website: 'http://blog.ionelmc.ro'
+ year: '2013-2015'
diff --git a/.coveragerc b/.coveragerc
new file mode 100644
index 0000000..772866d
--- /dev/null
+++ b/.coveragerc
@@ -0,0 +1,12 @@
+[paths]
+source = src
+
+[run]
+branch = True
+source = src
+parallel = true
+
+[report]
+show_missing = true
+precision = 2
+omit = *migrations*
diff --git a/.gitignore b/.gitignore
index d122979..9e8fc16 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,12 +1,63 @@
+*.py[cod]
+
+# C extensions
+*.so
+
+# Packages
+*.egg
+*.egg-info
+dist
+build
+eggs
+.eggs
+parts
+bin
+var
+sdist
+develop-eggs
+.installed.cfg
+lib
+lib64
+venv*/
+pyvenv*/
+
+# Installer logs
+pip-log.txt
+
+# Unit test / coverage reports
+.coverage
+.tox
+.coverage.*
+nosetests.xml
+coverage.xml
+htmlcov
+
+# Translations
+*.mo
+
+# Mr Developer
+.mr.developer.cfg
+.project
+.pydevproject
+.idea
+*.iml
+*.komodoproject
+
+# Complexity
+output/*.html
+output/*/index.html
+
+# Sphinx
+docs/_build
+
.DS_Store
-*.pyc
*~
.*.sw[po]
-dist/
-*.egg-info
-build/
-.build/
-pip-log.txt
-.tox/
-.coverage*
-.ve/
+.build
+.ve
+.env
+.cache
+.pytest
+.bootstrap
+.appveyor.token
+*.bak
diff --git a/.travis.yml b/.travis.yml
index e23c8a5..ebdd015 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,57 +1,47 @@
language: python
-
-python:
- - "2.6"
- - "2.7"
- - "3.2"
- - "3.3"
- - "pypy"
-
+python: '3.5'
+sudo: false
env:
global:
- PYTHONPATH=src:tests
- PYTHONUNBUFFERED=yes
- MANHOLE_TEST_TIMEOUT=30
+ LD_PRELOAD=/lib/x86_64-linux-gnu/libSegFault.so
matrix:
- - WITH_COVERAGE=no
- - WITH_COVERAGE=yes
+ - TOXENV=check
-before_install:
- - |
- if python --version |& grep PyPy; then
- deactivate
- sudo apt-add-repository --yes ppa:pypy/ppa
- sudo apt-get update
- sudo apt-get install pypy
- source ~/virtualenv/pypy/bin/activate
- fi
- python --version
- uname -a
- lsb_release -a
- sudo apt-get install strace
+ - TOXENV=2.6-cover,coveralls,codecov
+ - TOXENV=2.6-nocov
-install:
- - if [[ $WITH_COVERAGE == yes ]]; then pip install coverage coveralls; fi
- - python setup.py develop
+ - TOXENV=2.7-cover,coveralls,codecov
+ - TOXENV=2.7-nocov
-script:
- - python --version
- - rm .coverage* || true
- - stat /lib/x86_64-linux-gnu/libgcc_s.so.1
- - export LOG_NAME="$TRAVIS_PYTHON_VERSION-$TRAVIS_JOB_NUMBER-$TRAVIS_BUILD_ID.log"
- - |
- if [[ $WITH_COVERAGE == yes ]]; then
- #strace -f -s 8000 -o "$LOG_NAME"
- coverage run --source=src --parallel-mode tests/test_tblib.py
- else
- #strace -f -s 8000 -o "$LOG_NAME"
- python tests/test_tblib.py
- fi
+ - TOXENV=3.3-cover,coveralls,codecov
+ - TOXENV=3.3-nocov
+
+ - TOXENV=3.4-cover,coveralls,codecov
+ - TOXENV=3.4-nocov
+ - TOXENV=3.5-cover,coveralls,codecov
+ - TOXENV=3.5-nocov
+
+ - TOXENV=pypy-cover,coveralls,codecov
+ - TOXENV=pypy-nocov
+
+before_install:
+ - python --version
+ - uname -a
+ - lsb_release -a
+install:
+ - pip install tox
+ - virtualenv --version
+ - easy_install --version
+ - pip --version
+ - tox --version
+script:
+ - tox -v
after_failure:
- - curl -i -F "upfile=@$LOG_NAME" http://home.ionelmc.ro/
+ - more .tox/log/* | cat
+ - more .tox/*/log/* | cat
+notifications:
+ email:
+ on_success: never
+ on_failure: always
-after_success:
- - coverage combine || true
- - coverage report --show-missing --include='src/*' || true
- - coveralls || true
diff --git a/AUTHORS.rst b/AUTHORS.rst
new file mode 100644
index 0000000..0e54887
--- /dev/null
+++ b/AUTHORS.rst
@@ -0,0 +1,5 @@
+
+Authors
+=======
+
+* Ionel Cristian Mărieș - http://blog.ionelmc.ro
diff --git a/CHANGELOG.rst b/CHANGELOG.rst
new file mode 100644
index 0000000..04ccf94
--- /dev/null
+++ b/CHANGELOG.rst
@@ -0,0 +1,8 @@
+
+Changelog
+=========
+
+1.1.0 (2015-07-27)
+-----------------------------------------
+
+* First release on PyPI.
diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst
new file mode 100644
index 0000000..4eb5bdd
--- /dev/null
+++ b/CONTRIBUTING.rst
@@ -0,0 +1,89 @@
+============
+Contributing
+============
+
+Contributions are welcome, and they are greatly appreciated! Every
+little bit helps, and credit will always be given.
+
+Bug reports
+===========
+
+When `reporting a bug <https://github.com/ionelmc/python-tblib/issues>`_ please include:
+
+ * Your operating system name and version.
+ * Any details about your local setup that might be helpful in troubleshooting.
+ * Detailed steps to reproduce the bug.
+
+Documentation improvements
+==========================
+
+tblib could always use more documentation, whether as part of the
+official tblib docs, in docstrings, or even on the web in blog posts,
+articles, and such.
+
+Feature requests and feedback
+=============================
+
+The best way to send feedback is to file an issue at https://github.com/ionelmc/python-tblib/issues.
+
+If you are proposing a feature:
+
+* Explain in detail how it would work.
+* Keep the scope as narrow as possible, to make it easier to implement.
+* Remember that this is a volunteer-driven project, and that contributions are welcome :)
+
+Development
+===========
+
+To set up `python-tblib` for local development:
+
+1. `Fork python-tblib on GitHub <https://github.com/ionelmc/python-tblib/fork>`_.
+2. Clone your fork locally::
+
+ git clone git@github.com:your_name_here/python-tblib.git
+
+3. Create a branch for local development::
+
+ git checkout -b name-of-your-bugfix-or-feature
+
+ Now you can make your changes locally.
+
+4. When you're done making changes, run all the checks, doc builder and spell checker with `tox <http://tox.readthedocs.org/en/latest/install.html>`_ one command::
+
+ tox
+
+5. Commit your changes and push your branch to GitHub::
+
+ git add .
+ git commit -m "Your detailed description of your changes."
+ git push origin name-of-your-bugfix-or-feature
+
+6. Submit a pull request through the GitHub website.
+
+Pull Request Guidelines
+-----------------------
+
+If you need some code review or feedback while you're developing the code just make the pull request.
+
+For merging, you should:
+
+1. Include passing tests (run ``tox``) [1]_.
+2. Update documentation when there's new API, functionality etc.
+3. Add a note to ``CHANGELOG.rst`` about the changes.
+4. Add yourself to ``AUTHORS.rst``.
+
+.. [1] If you don't have all the necessary python versions available locally you can rely on Travis - it will
+ `run the tests <https://travis-ci.org/ionelmc/python-tblib/pull_requests>`_ for each change you add in the pull request.
+
+ It will be slower though ...
+
+Tips
+----
+
+To run a subset of tests::
+
+ tox -e envname -- py.test -k test_myfeature
+
+To run all the test environments in *parallel* (you need to ``pip install detox``)::
+
+ detox \ No newline at end of file
diff --git a/LICENSE b/LICENSE
index 5b0b07e..7959354 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,19 +1,19 @@
-Copyright (c) 2013-2014, Ionel Cristian Mărieș
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
-following conditions are met:
-
-1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
-disclaimer.
-
-2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
-disclaimer in the documentation and/or other materials provided with the distribution.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
-INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+Copyright (c) 2013-2015, Ionel Cristian Mărieș
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
+following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
+disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
+disclaimer in the documentation and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/MANIFEST.in b/MANIFEST.in
index 57cdec0..49b230a 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -1,14 +1,21 @@
-include README.rst
-include LICENSE
-include AUTHORS
-include tox.ini
-include .coveragerc
-include .travis.yml
-include .pylintrc
-include coverage.ini
-include *.komodoproject
-graft tests
+graft docs
graft examples
graft src
-graft docs
-global-exclude *.pyc *.pyo
+graft ci
+graft tests
+
+include .bumpversion.cfg
+include .coveragerc
+include .cookiecutterrc
+include .isort.cfg
+include .pylintrc
+
+include AUTHORS.rst
+include CHANGELOG.rst
+include CONTRIBUTING.rst
+include LICENSE
+include README.rst
+
+include tox.ini .travis.yml appveyor.yml
+
+global-exclude *.py[cod] __pycache__ *.so *.dylib
diff --git a/README.rst b/README.rst
index c80cc80..94bfd8e 100644
--- a/README.rst
+++ b/README.rst
@@ -1,30 +1,95 @@
-==========================
- python-tblib
-==========================
-
-.. image:: https://secure.travis-ci.org/ionelmc/python-tblib.png?branch=master
- :alt: Build Status
- :target: http://travis-ci.org/ionelmc/python-tblib
-
-.. image:: https://coveralls.io/repos/ionelmc/python-tblib/badge.png?branch=master
+=====
+tblib
+=====
+
+.. list-table::
+ :stub-columns: 1
+
+ * - docs
+ - |docs|
+ * - tests
+ - | |travis| |appveyor| |requires|
+ | |coveralls| |codecov|
+ | |landscape| |scrutinizer| |codacy| |codeclimate|
+ * - package
+ - |version| |downloads| |wheel| |supported-versions| |supported-implementations|
+
+.. |docs| image:: https://readthedocs.org/projects/python-tblib/badge/?style=flat
+ :target: https://readthedocs.org/projects/python-tblib
+ :alt: Documentation Status
+
+.. |travis| image:: https://travis-ci.org/ionelmc/python-tblib.svg?branch=master
+ :alt: Travis-CI Build Status
+ :target: https://travis-ci.org/ionelmc/python-tblib
+
+.. |appveyor| image:: https://ci.appveyor.com/api/projects/status/github/ionelmc/python-tblib?branch=master&svg=true
+ :alt: AppVeyor Build Status
+ :target: https://ci.appveyor.com/project/ionelmc/python-tblib
+
+.. |requires| image:: https://requires.io/github/ionelmc/python-tblib/requirements.svg?branch=master
+ :alt: Requirements Status
+ :target: https://requires.io/github/ionelmc/python-tblib/requirements/?branch=master
+
+.. |coveralls| image:: https://coveralls.io/repos/ionelmc/python-tblib/badge.svg?branch=master&service=github
:alt: Coverage Status
:target: https://coveralls.io/r/ionelmc/python-tblib
-.. image:: https://badge.fury.io/py/tblib.png
- :alt: PYPI Package
+.. |codecov| image:: https://codecov.io/github/ionelmc/python-tblib/coverage.svg?branch=master
+ :alt: Coverage Status
+ :target: https://codecov.io/github/ionelmc/python-tblib
+
+.. |landscape| image:: https://landscape.io/github/ionelmc/python-tblib/master/landscape.svg?style=flat
+ :target: https://landscape.io/github/ionelmc/python-tblib/master
+ :alt: Code Quality Status
+
+.. |codacy| image:: https://img.shields.io/codacy/REPLACE_WITH_PROJECT_ID.svg?style=flat
+ :target: https://www.codacy.com/app/ionelmc/python-tblib
+ :alt: Codacy Code Quality Status
+
+.. |codeclimate| image:: https://codeclimate.com/github/ionelmc/python-tblib/badges/gpa.svg
+ :target: https://codeclimate.com/github/ionelmc/python-tblib
+ :alt: CodeClimate Quality Status
+.. |version| image:: https://img.shields.io/pypi/v/tblib.svg?style=flat
+ :alt: PyPI Package latest release
+ :target: https://pypi.python.org/pypi/tblib
+
+.. |downloads| image:: https://img.shields.io/pypi/dm/tblib.svg?style=flat
+ :alt: PyPI Package monthly downloads
+ :target: https://pypi.python.org/pypi/tblib
+
+.. |wheel| image:: https://img.shields.io/pypi/wheel/tblib.svg?style=flat
+ :alt: PyPI Wheel
:target: https://pypi.python.org/pypi/tblib
+.. |supported-versions| image:: https://img.shields.io/pypi/pyversions/tblib.svg?style=flat
+ :alt: Supported versions
+ :target: https://pypi.python.org/pypi/tblib
+
+.. |supported-implementations| image:: https://img.shields.io/pypi/implementation/tblib.svg?style=flat
+ :alt: Supported implementations
+ :target: https://pypi.python.org/pypi/tblib
+
+.. |scrutinizer| image:: https://img.shields.io/scrutinizer/g/ionelmc/python-tblib/master.svg?style=flat
+ :alt: Scrutinizer Status
+ :target: https://scrutinizer-ci.com/g/ionelmc/python-tblib/
+
Traceback fiddling library. For now allows you to pickle tracebacks and raise exceptions with pickled tracebacks in different processes.
This allows better error handling when running code over multiple processes (imagine multiprocessing, billiard, futures, celery etc).
-Requirements
+* Free software: BSD license
+
+Installation
============
-:OS: Any
-:Runtime: Python 2.6, 2.7, 3.2, 3.3, 3.4 and PyPy.
+::
+
+ pip install tblib
+
+Documentation
+=============
Pickling tracebacks
-===================
+-------------------
**Note**: The traceback objects that come out are stripped of some attributes (like variables). But you'll be able to raise exceptions with
those tracebacks or print them - that should cover 99% of the usecases.
@@ -173,7 +238,7 @@ Yes it does::
The tblib.Traceback object
-==========================
+--------------------------
It is used by the ``pickling_support``. You can use it too if you want more flexibility::
@@ -247,7 +312,7 @@ json.JSONDecoder::
'f_globals': {'__name__': '__main__'}},
'tb_lineno': 2,
'tb_next': None}}}}
- >>> tb_json = json.dumps(tb_dict)
+ >>> tb_json = json.dumps(tb_dict)
>>> tb = Traceback.from_dict(json.loads(tb_json))
>>> reraise(et, ev, tb.as_traceback())
Traceback (most recent call last):
@@ -268,7 +333,7 @@ json.JSONDecoder::
Decorators
-==========
+----------
return_error
------------
diff --git a/appveyor.yml b/appveyor.yml
new file mode 100644
index 0000000..889906b
--- /dev/null
+++ b/appveyor.yml
@@ -0,0 +1,104 @@
+version: '{branch}-{build}'
+build: off
+cache:
+ - '%LOCALAPPDATA%\pip\Cache'
+environment:
+ global:
+ WITH_COMPILER: 'cmd /E:ON /V:ON /C .\ci\appveyor-with-compiler.cmd'
+ matrix:
+ - TOXENV: check
+ PYTHON_HOME: C:\Python27
+ PYTHON_VERSION: '2.7'
+ PYTHON_ARCH: '32'
+
+ - TOXENV: '2.7-cover,codecov'
+ TOXPYTHON: C:\Python27\python.exe
+ PYTHON_HOME: C:\Python27
+ PYTHON_VERSION: '2.7'
+ PYTHON_ARCH: '32'
+ - TOXENV: '2.7-nocov'
+ TOXPYTHON: C:\Python27\python.exe
+ PYTHON_HOME: C:\Python27
+ PYTHON_VERSION: '2.7'
+ PYTHON_ARCH: '32'
+
+ - TOXENV: '2.7-cover,codecov'
+ TOXPYTHON: C:\Python27-x64\python.exe
+ WINDOWS_SDK_VERSION: v7.0
+ PYTHON_HOME: C:\Python27-x64
+ PYTHON_VERSION: '2.7'
+ PYTHON_ARCH: '64'
+ - TOXENV: '2.7-nocov'
+ TOXPYTHON: C:\Python27-x64\python.exe
+ WINDOWS_SDK_VERSION: v7.0
+ PYTHON_HOME: C:\Python27-x64
+ PYTHON_VERSION: '2.7'
+ PYTHON_ARCH: '64'
+
+ - TOXENV: '3.4-cover,codecov'
+ TOXPYTHON: C:\Python34\python.exe
+ PYTHON_HOME: C:\Python34
+ PYTHON_VERSION: '3.4'
+ PYTHON_ARCH: '32'
+ - TOXENV: '3.4-nocov'
+ TOXPYTHON: C:\Python34\python.exe
+ PYTHON_HOME: C:\Python34
+ PYTHON_VERSION: '3.4'
+ PYTHON_ARCH: '32'
+
+ - TOXENV: '3.4-cover,codecov'
+ TOXPYTHON: C:\Python34-x64\python.exe
+ WINDOWS_SDK_VERSION: v7.1
+ PYTHON_HOME: C:\Python34-x64
+ PYTHON_VERSION: '3.4'
+ PYTHON_ARCH: '64'
+ - TOXENV: '3.4-nocov'
+ TOXPYTHON: C:\Python34-x64\python.exe
+ WINDOWS_SDK_VERSION: v7.1
+ PYTHON_HOME: C:\Python34-x64
+ PYTHON_VERSION: '3.4'
+ PYTHON_ARCH: '64'
+
+ - TOXENV: '3.5-cover,codecov'
+ TOXPYTHON: C:\Python35\python.exe
+ PYTHON_HOME: C:\Python35
+ PYTHON_VERSION: '3.5'
+ PYTHON_ARCH: '32'
+ - TOXENV: '3.5-nocov'
+ TOXPYTHON: C:\Python35\python.exe
+ PYTHON_HOME: C:\Python35
+ PYTHON_VERSION: '3.5'
+ PYTHON_ARCH: '32'
+
+ - TOXENV: '3.5-cover,codecov'
+ TOXPYTHON: C:\Python35-x64\python.exe
+ WINDOWS_SDK_VERSION: v7.1
+ PYTHON_HOME: C:\Python35-x64
+ PYTHON_VERSION: '3.5'
+ PYTHON_ARCH: '64'
+ - TOXENV: '3.5-nocov'
+ TOXPYTHON: C:\Python35-x64\python.exe
+ WINDOWS_SDK_VERSION: v7.1
+ PYTHON_HOME: C:\Python35-x64
+ PYTHON_VERSION: '3.5'
+ PYTHON_ARCH: '64'
+
+init:
+ - ps: echo $env:TOXENV
+ - ps: ls C:\Python*
+install:
+ - python -u ci\appveyor-bootstrap.py
+ - '%PYTHON_HOME%\Scripts\virtualenv --version'
+ - '%PYTHON_HOME%\Scripts\easy_install --version'
+ - '%PYTHON_HOME%\Scripts\pip --version'
+ - '%PYTHON_HOME%\Scripts\tox --version'
+test_script:
+ - '%WITH_COMPILER% %PYTHON_HOME%\Scripts\tox'
+
+on_failure:
+ - ps: dir "env:"
+ - ps: get-content .tox\*\log\*
+artifacts:
+ - path: dist\*
+### To enable remote debugging uncomment this:
+# - ps: $blockRdp = $true; iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
diff --git a/ci/appveyor-bootstrap.py b/ci/appveyor-bootstrap.py
new file mode 100644
index 0000000..bc351bc
--- /dev/null
+++ b/ci/appveyor-bootstrap.py
@@ -0,0 +1,117 @@
+"""
+AppVeyor will at least have few Pythons around so there's no point of implementing a bootstrapper in PowerShell.
+
+This is a port of https://github.com/pypa/python-packaging-user-guide/blob/master/source/code/install.ps1
+with various fixes and improvements that just weren't feasible to implement in PowerShell.
+"""
+from __future__ import print_function
+from os import environ
+from os.path import exists
+from subprocess import check_call
+
+try:
+ from urllib.request import urlretrieve
+except ImportError:
+ from urllib import urlretrieve
+
+BASE_URL = "https://www.python.org/ftp/python/"
+GET_PIP_URL = "https://bootstrap.pypa.io/get-pip.py"
+GET_PIP_PATH = "C:\get-pip.py"
+URLS = {
+ ("2.6", "64"): BASE_URL + "2.6.6/python-2.6.6.amd64.msi",
+ ("2.6", "32"): BASE_URL + "2.6.6/python-2.6.6.msi",
+ ("2.7", "64"): BASE_URL + "2.7.10/python-2.7.10.amd64.msi",
+ ("2.7", "32"): BASE_URL + "2.7.10/python-2.7.10.msi",
+ # NOTE: no .msi installer for 3.3.6
+ ("3.3", "64"): BASE_URL + "3.3.3/python-3.3.3.amd64.msi",
+ ("3.3", "32"): BASE_URL + "3.3.3/python-3.3.3.msi",
+ ("3.4", "64"): BASE_URL + "3.4.3/python-3.4.3.amd64.msi",
+ ("3.4", "32"): BASE_URL + "3.4.3/python-3.4.3.msi",
+ ("3.5", "64"): BASE_URL + "3.5.0/python-3.5.0-amd64.exe",
+ ("3.5", "32"): BASE_URL + "3.5.0/python-3.5.0.exe",
+}
+INSTALL_CMD = {
+ # Commands are allowed to fail only if they are not the last command. Eg: uninstall (/x) allowed to fail.
+ "2.6": [["msiexec.exe", "/L*+!", "install.log", "/qn", "/x", "{path}"],
+ ["msiexec.exe", "/L*+!", "install.log", "/qn", "/i", "{path}", "TARGETDIR={home}"]],
+ "2.7": [["msiexec.exe", "/L*+!", "install.log", "/qn", "/x", "{path}"],
+ ["msiexec.exe", "/L*+!", "install.log", "/qn", "/i", "{path}", "TARGETDIR={home}"]],
+ "3.3": [["msiexec.exe", "/L*+!", "install.log", "/qn", "/x", "{path}"],
+ ["msiexec.exe", "/L*+!", "install.log", "/qn", "/i", "{path}", "TARGETDIR={home}"]],
+ "3.4": [["msiexec.exe", "/L*+!", "install.log", "/qn", "/x", "{path}"],
+ ["msiexec.exe", "/L*+!", "install.log", "/qn", "/i", "{path}", "TARGETDIR={home}"]],
+ "3.5": [["{path}", "/quiet", "TargetDir={home}"]],
+}
+
+
+def download_file(url, path):
+ print("Downloading: {} (into {})".format(url, path))
+ progress = [0, 0]
+
+ def report(count, size, total):
+ progress[0] = count * size
+ if progress[0] - progress[1] > 1000000:
+ progress[1] = progress[0]
+ print("Downloaded {:,}/{:,} ...".format(progress[1], total))
+
+ dest, _ = urlretrieve(url, path, reporthook=report)
+ return dest
+
+
+def install_python(version, arch, home):
+ print("Installing Python", version, "for", arch, "bit architecture to", home)
+ if exists(home):
+ return
+
+ path = download_python(version, arch)
+ print("Installing", path, "to", home)
+ success = False
+ for cmd in INSTALL_CMD[version]:
+ cmd = [part.format(home=home, path=path) for part in cmd]
+ print("Running:", " ".join(cmd))
+ try:
+ check_call(cmd)
+ except Exception as exc:
+ print("Failed command", cmd, "with:", exc)
+ if exists("install.log"):
+ with open("install.log") as fh:
+ print(fh.read())
+ else:
+ success = True
+ if success:
+ print("Installation complete!")
+ else:
+ print("Installation failed")
+
+
+def download_python(version, arch):
+ for _ in range(3):
+ try:
+ return download_file(URLS[version, arch], "installer.exe")
+ except Exception as exc:
+ print("Failed to download:", exc)
+ print("Retrying ...")
+
+
+def install_pip(home):
+ pip_path = home + "/Scripts/pip.exe"
+ python_path = home + "/python.exe"
+ if exists(pip_path):
+ print("pip already installed.")
+ else:
+ print("Installing pip...")
+ download_file(GET_PIP_URL, GET_PIP_PATH)
+ print("Executing:", python_path, GET_PIP_PATH)
+ check_call([python_path, GET_PIP_PATH])
+
+
+def install_packages(home, *packages):
+ cmd = [home + "/Scripts/pip.exe", "install"]
+ cmd.extend(packages)
+ check_call(cmd)
+
+
+if __name__ == "__main__":
+ install_python(environ['PYTHON_VERSION'], environ['PYTHON_ARCH'], environ['PYTHON_HOME'])
+ install_pip(environ['PYTHON_HOME'])
+ install_packages(environ['PYTHON_HOME'], "setuptools>=18.0.1", "wheel", "tox", "virtualenv>=13.1.0")
diff --git a/ci/appveyor-download.py b/ci/appveyor-download.py
new file mode 100644
index 0000000..fa5e80d
--- /dev/null
+++ b/ci/appveyor-download.py
@@ -0,0 +1,108 @@
+"""
+Use the AppVeyor API to download Windows artifacts.
+
+Taken from: https://bitbucket.org/ned/coveragepy/src/tip/ci/download_appveyor.py
+# Licensed under the Apache License: http://www.apache.org/licenses/LICENSE-2.0
+# For details: https://bitbucket.org/ned/coveragepy/src/default/NOTICE.txt
+"""
+import argparse
+import os
+import zipfile
+
+import requests
+
+
+def make_auth_headers():
+ """Make the authentication headers needed to use the Appveyor API."""
+ if not os.path.exists(".appveyor.token"):
+ raise RuntimeError(
+ "Please create a file named `.appveyor.token` in the current directory. "
+ "You can get the token from https://ci.appveyor.com/api-token"
+ )
+ with open(".appveyor.token") as f:
+ token = f.read().strip()
+
+ headers = {
+ 'Authorization': 'Bearer {}'.format(token),
+ }
+ return headers
+
+
+def make_url(url, **kwargs):
+ """Build an Appveyor API url."""
+ return "https://ci.appveyor.com/api" + url.format(**kwargs)
+
+
+def get_project_build(account_project):
+ """Get the details of the latest Appveyor build."""
+ url = make_url("/projects/{account_project}", account_project=account_project)
+ response = requests.get(url, headers=make_auth_headers())
+ return response.json()
+
+
+def download_latest_artifacts(account_project):
+ """Download all the artifacts from the latest build."""
+ build = get_project_build(account_project)
+ jobs = build['build']['jobs']
+ print("Build {0[build][version]}, {1} jobs: {0[build][message]}".format(build, len(jobs)))
+ for job in jobs:
+ name = job['name'].partition(':')[2].split(',')[0].strip()
+ print(" {0}: {1[status]}, {1[artifactsCount]} artifacts".format(name, job))
+
+ url = make_url("/buildjobs/{jobid}/artifacts", jobid=job['jobId'])
+ response = requests.get(url, headers=make_auth_headers())
+ artifacts = response.json()
+
+ for artifact in artifacts:
+ is_zip = artifact['type'] == "Zip"
+ filename = artifact['fileName']
+ print(" {0}, {1} bytes".format(filename, artifact['size']))
+
+ url = make_url(
+ "/buildjobs/{jobid}/artifacts/{filename}",
+ jobid=job['jobId'],
+ filename=filename
+ )
+ download_url(url, filename, make_auth_headers())
+
+ if is_zip:
+ unpack_zipfile(filename)
+ os.remove(filename)
+
+
+def ensure_dirs(filename):
+ """Make sure the directories exist for `filename`."""
+ dirname, _ = os.path.split(filename)
+ if dirname and not os.path.exists(dirname):
+ os.makedirs(dirname)
+
+
+def download_url(url, filename, headers):
+ """Download a file from `url` to `filename`."""
+ ensure_dirs(filename)
+ response = requests.get(url, headers=headers, stream=True)
+ if response.status_code == 200:
+ with open(filename, 'wb') as f:
+ for chunk in response.iter_content(16 * 1024):
+ f.write(chunk)
+
+
+def unpack_zipfile(filename):
+ """Unpack a zipfile, using the names in the zip."""
+ with open(filename, 'rb') as fzip:
+ z = zipfile.ZipFile(fzip)
+ for name in z.namelist():
+ print(" extracting {}".format(name))
+ ensure_dirs(name)
+ z.extract(name)
+
+parser = argparse.ArgumentParser(description='Download artifacts from AppVeyor.')
+parser.add_argument('name',
+ metavar='ID',
+ help='Project ID in AppVeyor. Example: ionelmc/python-nameless')
+
+if __name__ == "__main__":
+ # import logging
+ # logging.basicConfig(level="DEBUG")
+ args = parser.parse_args()
+ download_latest_artifacts(args.name)
diff --git a/ci/appveyor-with-compiler.cmd b/ci/appveyor-with-compiler.cmd
new file mode 100644
index 0000000..7f82a02
--- /dev/null
+++ b/ci/appveyor-with-compiler.cmd
@@ -0,0 +1,46 @@
+:: To build extensions for 64 bit Python 3, we need to configure environment
+:: variables to use the MSVC 2010 C++ compilers from GRMSDKX_EN_DVD.iso of:
+:: MS Windows SDK for Windows 7 and .NET Framework 4 (SDK v7.1)
+::
+:: To build extensions for 64 bit Python 2, we need to configure environment
+:: variables to use the MSVC 2008 C++ compilers from GRMSDKX_EN_DVD.iso of:
+:: MS Windows SDK for Windows 7 and .NET Framework 3.5 (SDK v7.0)
+::
+:: 32 bit builds do not require specific environment configurations.
+::
+:: Note: this script needs to be run with the /E:ON and /V:ON flags for the
+:: cmd interpreter, at least for (SDK v7.0)
+::
+:: More details at:
+:: https://github.com/cython/cython/wiki/64BitCythonExtensionsOnWindows
+:: http://stackoverflow.com/a/13751649/163740
+::
+:: Author: Olivier Grisel
+:: License: CC0 1.0 Universal: http://creativecommons.org/publicdomain/zero/1.0/
+SET COMMAND_TO_RUN=%*
+SET WIN_SDK_ROOT=C:\Program Files\Microsoft SDKs\Windows
+SET WIN_WDK="c:\Program Files (x86)\Windows Kits\10\Include\wdf"
+ECHO SDK: %WINDOWS_SDK_VERSION% ARCH: %PYTHON_ARCH%
+
+
+IF "%PYTHON_VERSION%"=="3.5" (
+ IF EXIST %WIN_WDK% (
+ REM See: https://connect.microsoft.com/VisualStudio/feedback/details/1610302/
+ REN %WIN_WDK% 0wdf
+ )
+ GOTO main
+)
+
+IF "%PYTHON_ARCH%"=="32" (
+ GOTO main
+)
+
+SET DISTUTILS_USE_SDK=1
+SET MSSdk=1
+"%WIN_SDK_ROOT%\%WINDOWS_SDK_VERSION%\Setup\WindowsSdkVer.exe" -q -version:%WINDOWS_SDK_VERSION%
+CALL "%WIN_SDK_ROOT%\%WINDOWS_SDK_VERSION%\Bin\SetEnv.cmd" /x64 /release
+
+:main
+
+ECHO Executing: %COMMAND_TO_RUN%
+CALL %COMMAND_TO_RUN% || EXIT 1
diff --git a/coverage.ini b/coverage.ini
deleted file mode 100644
index 8b13789..0000000
--- a/coverage.ini
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/python-tblib.komodoproject b/python-tblib.komodoproject
deleted file mode 100644
index 326bd66..0000000
--- a/python-tblib.komodoproject
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Komodo Project File - DO NOT EDIT -->
-<project id="7ba245b2-6970-4ccb-8dcd-074295eae6bb" kpf_version="5" name="python-tblib.komodoproject">
-</project>
diff --git a/setup.cfg b/setup.cfg
new file mode 100644
index 0000000..a935c0f
--- /dev/null
+++ b/setup.cfg
@@ -0,0 +1,40 @@
+[bdist_wheel]
+universal = 1
+
+[aliases]
+release = register clean --all sdist bdist_wheel
+
+[flake8]
+max-line-length = 140
+exclude = tests/*,*/migrations/*,*/south_migrations/*
+
+[pytest]
+norecursedirs =
+ .git
+ .tox
+ .env
+ dist
+ build
+ south_migrations
+ migrations
+python_files =
+ test_*.py
+ *_test.py
+ tests.py
+addopts =
+ -rxEfsw
+ --strict
+ --ignore=docs/conf.py
+ --ignore=setup.py
+ --ignore=ci
+ --ignore=.eggs
+ --doctest-modules
+ --doctest-glob=\*.rst
+ --tb=short
+
+[isort]
+force_single_line=True
+line_length=120
+known_first_party=tblib
+default_section=THIRDPARTY
+forced_separate=test_tblib
diff --git a/setup.py b/setup.py
index 91498dc..9faebef 100644
--- a/setup.py
+++ b/setup.py
@@ -1,37 +1,70 @@
-# -*- encoding: utf8 -*-
-from setuptools import setup, find_packages
+#!/usr/bin/env python
+# -*- encoding: utf-8 -*-
+from __future__ import absolute_import, print_function
+import io
import os
+import re
+from glob import glob
+from os.path import basename
+from os.path import dirname
+from os.path import join
+from os.path import relpath
+from os.path import splitext
+
+from setuptools import find_packages
+from setuptools import setup
+
+
+def read(*names, **kwargs):
+ return io.open(
+ join(dirname(__file__), *names),
+ encoding=kwargs.get('encoding', 'utf8')
+ ).read()
+
+
setup(
- name="tblib",
- version="1.1.0",
- url='https://github.com/ionelmc/python-tblib',
- download_url='',
+ name='tblib',
+ version='1.1.0',
license='BSD',
- description="Traceback fiddling library.",
- long_description=open(os.path.join(os.path.dirname(__file__), 'README.rst')).read(),
+ description='Traceback fiddling library. For now allows you to pickle tracebacks and raise exceptions with pickled tracebacks in different processes. This allows better error handling when running code over multiple processes (imagine multiprocessing, billiard, futures, celery etc).',
+ long_description='%s\n%s' % (read('README.rst'), re.sub(':[a-z]+:`~?(.*?)`', r'``\1``', read('CHANGELOG.rst'))),
author='Ionel Cristian Mărieș',
author_email='contact@ionelmc.ro',
+ url='https://github.com/ionelmc/python-tblib',
packages=find_packages('src'),
package_dir={'': 'src'},
+ py_modules=[splitext(basename(path))[0] for path in glob('src/*.py')],
include_package_data=True,
zip_safe=False,
classifiers=[
+ # complete classifier list: http://pypi.python.org/pypi?%3Aaction=list_classifiers
'Development Status :: 5 - Production/Stable',
'Intended Audience :: Developers',
'License :: OSI Approved :: BSD License',
'Operating System :: Unix',
'Operating System :: POSIX',
+ 'Operating System :: Microsoft :: Windows',
'Programming Language :: Python',
- 'Topic :: Software Development :: Debuggers',
- 'Topic :: Utilities',
+ '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 :: Implementation :: CPython',
'Programming Language :: Python :: Implementation :: PyPy',
+ 'Topic :: Utilities',
+ ],
+ keywords=[
+ # eg: 'keyword1', 'keyword2', 'keyword3',
],
install_requires=[
- 'six',
- ]
+ # eg: 'aspectlib==1.1.1', 'six>=1.7',
+ ],
+ extras_require={
+ # eg:
+ # 'rst': ['docutils>=0.11'],
+ # ':python_version=="2.6"': ['argparse'],
+ },
)
diff --git a/tox.ini b/tox.ini
index 81b6a64..7b46a80 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,52 +1,117 @@
+; a generative tox configuration, see: https://testrun.org/tox/latest/config.html#generative-envlist
+
[tox]
envlist =
- py,
- py2.7,
- py3,
- py3.2,
- py3.3,
- py3.4,
- pypy
+ clean,
+ check,
+ {2.6,2.7,3.3,3.4,pypy}-{cover,nocov},
+ report,
+ docs
[testenv]
+basepython =
+ pypy: {env:TOXPYTHON:pypy}
+ 2.6: {env:TOXPYTHON:python2.6}
+ {2.7,docs,spell}: {env:TOXPYTHON:python2.7}
+ 3.3: {env:TOXPYTHON:python3.3}
+ 3.4: {env:TOXPYTHON:python3.4}
+ {clean,check,report,extension-coveralls,coveralls,codecov}: python3.4
setenv =
- PYTHONPATH = {toxinidir}/src:{toxinidir}/tests
- WITH_COVERAGE = x
- PYTHONUNBUFFERED = x
-commands = {envpython} {toxinidir}/tests/test_tblib.py
-
-[base]
+ PYTHONPATH={toxinidir}/tests
+ PYTHONUNBUFFERED=yes
+passenv =
+ *
deps =
- coverage
- ;nose
- ;yanc
- ;nose-timelimit
+ six
+ cover: coverage
+commands =
+ cover: {posargs:coverage run {toxinidir}/tests/test_tblib.py}
+ nocov: {posargs:{envpython} {toxinidir}/tests/test_tblib.py}
+usedevelop = true
-[testenv:py]
-basepython = python
+[testenv:spell]
+setenv =
+ SPELLCHECK=1
+commands =
+ sphinx-build -b spelling docs dist/docs
+skip_install = true
+usedevelop = true
deps =
- {[base]deps}
-[testenv:py2.7]
-basepython = python2.7
+ -r{toxinidir}/docs/requirements.txt
+ sphinxcontrib-spelling
+ pyenchant
+
+[testenv:docs]
deps =
- {[base]deps}
-[testenv:py3]
-basepython = python3
+ -r{toxinidir}/docs/requirements.txt
+commands =
+ sphinx-build {posargs:-E} -b html docs dist/docs
+ sphinx-build -b linkcheck docs dist/docs
+
+[testenv:check]
+basepython = python3.4
deps =
- {[base]deps}
-[testenv:py3.2]
-basepython = python3.2
+ docutils
+ check-manifest
+ flake8
+ readme
+ pygments
+skip_install = true
+usedevelop = false
+commands =
+ python setup.py check --strict --metadata --restructuredtext
+ check-manifest {toxinidir}
+ flake8 src tests
+
+[testenv:coveralls]
deps =
- {[base]deps}
-[testenv:py3.3]
-basepython = python3.3
+ coveralls
+skip_install = true
+usedevelop = false
+commands =
+ coverage combine
+ coverage report
+ coveralls []
+
+[testenv:codecov]
deps =
- {[base]deps}
-[testenv:py3.4]
+ codecov
+skip_install = true
+usedevelop = false
+commands =
+ coverage combine
+ coverage report
+ coverage xml --ignore-errors
+ codecov []
+
+
+[testenv:report]
basepython = python3.4
-deps =
- {[base]deps}
-[testenv:pypy]
-basepython = pypy
-deps =
- {[base]deps}
+deps = coverage
+skip_install = true
+usedevelop = false
+commands =
+ coverage combine
+ coverage report
+
+[testenv:clean]
+commands = coverage erase
+skip_install = true
+usedevelop = false
+deps = coverage
+
+[testenv:2.6-nocov]
+usedevelop = false
+
+[testenv:2.7-nocov]
+usedevelop = false
+
+[testenv:3.3-nocov]
+usedevelop = false
+
+[testenv:3.4-nocov]
+usedevelop = false
+
+[testenv:pypy-nocov]
+usedevelop = false
+