From 50b2b7a3da4fb7b98b4d042d3f14df277ea70d75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teppo=20Per=C3=A4?= Date: Thu, 9 Apr 2015 12:43:22 +0300 Subject: [PATCH] Project update --- .coveragerc | 12 +++ .gitignore | 74 +++++++++--------- .travis.yml | 29 +++++++ AUTHORS.rst | 5 ++ CHANGELOG.rst | 60 +++++++++++++++ CONTRIBUTING.rst | 88 ++++++++++++++++++++++ MANIFEST.in | 21 ++++++ README.md | 2 - README.rst | 138 ++++++++++++++++++++++++++++++++++ appveyor.yml | 68 +++++++++++++++++ ci/appveyor-bootstrap.ps1 | 88 ++++++++++++++++++++++ ci/appveyor-with-compiler.cmd | 37 +++++++++ ci/bootstrap.py | 60 +++++++++++++++ ci/templates/.travis.yml | 27 +++++++ ci/templates/appveyor.yml | 39 ++++++++++ ci/templates/tox.ini | 116 ++++++++++++++++++++++++++++ docs/authors.rst | 1 + docs/changelog.rst | 1 + docs/conf.py | 44 +++++++++++ docs/contributing.rst | 1 + docs/index.rst | 23 ++++++ docs/installation.rst | 7 ++ docs/readme.rst | 5 ++ docs/reference/index.rst | 7 ++ docs/reference/pytraits.rst | 5 ++ docs/requirements.txt | 4 + docs/spelling_wordlist.txt | 11 +++ docs/usage.rst | 9 +++ setup.cfg | 84 ++++++++++++++++++++- setup.py | 55 ++++++++++++++ src/pytraits/__init__.py | 2 + src/pytraits/core/magic.py | 8 +- tests/test_pytraits.py | 5 ++ tox.ini | 94 +++++++++++++++++++++++ 34 files changed, 1186 insertions(+), 44 deletions(-) create mode 100644 .coveragerc create mode 100644 .travis.yml create mode 100644 AUTHORS.rst create mode 100644 CHANGELOG.rst create mode 100644 CONTRIBUTING.rst create mode 100644 MANIFEST.in delete mode 100644 README.md create mode 100644 README.rst create mode 100644 appveyor.yml create mode 100644 ci/appveyor-bootstrap.ps1 create mode 100644 ci/appveyor-with-compiler.cmd create mode 100644 ci/bootstrap.py create mode 100644 ci/templates/.travis.yml create mode 100644 ci/templates/appveyor.yml create mode 100644 ci/templates/tox.ini create mode 100644 docs/authors.rst create mode 100644 docs/changelog.rst create mode 100644 docs/conf.py create mode 100644 docs/contributing.rst create mode 100644 docs/index.rst create mode 100644 docs/installation.rst create mode 100644 docs/readme.rst create mode 100644 docs/reference/index.rst create mode 100644 docs/reference/pytraits.rst create mode 100644 docs/requirements.txt create mode 100644 docs/spelling_wordlist.txt create mode 100644 docs/usage.rst create mode 100644 setup.py create mode 100644 tests/test_pytraits.py create mode 100644 tox.ini 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 db4561e..fc6d847 100644 --- a/.gitignore +++ b/.gitignore @@ -1,54 +1,54 @@ -# Byte-compiled / optimized / DLL files -__pycache__/ *.py[cod] # C extensions *.so -# Distribution / packaging -.Python -env/ -build/ -develop-eggs/ -dist/ -downloads/ -eggs/ -lib/ -lib64/ -parts/ -sdist/ -var/ -*.egg-info/ -.installed.cfg +# Packages *.egg - -# PyInstaller -# Usually these files are written by a python script from a template -# before PyInstaller builds the exe, so as to inject date/other infos into it. -*.manifest -*.spec +*.egg-info +dist +build +eggs +parts +bin +var +sdist +develop-eggs +.installed.cfg +lib +lib64 # Installer logs pip-log.txt -pip-delete-this-directory.txt # Unit test / coverage reports -htmlcov/ -.tox/ .coverage -.cache +.tox +.coverage +.coverage.* nosetests.xml -coverage.xml +htmlcov # Translations *.mo -*.pot - -# Django stuff: -*.log - -# Sphinx documentation -docs/_build/ -# PyBuilder -target/ +# Mr Developer +.mr.developer.cfg +.project +.pydevproject +.idea + +# Complexity +output/*.html +output/*/index.html + +# Sphinx +docs/_build + +.DS_Store +*~ +.*.sw[po] +.build +.ve +.bootstrap +*.bak diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..2126272 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,29 @@ +language: python +python: 3.4 +sudo: false +env: + global: + LD_PRELOAD=/lib/x86_64-linux-gnu/libSegFault.so + matrix: + - TOXENV=check + - TOXENV=3.3,coveralls + - TOXENV=3.3-nocover + - TOXENV=3.4,coveralls + - TOXENV=3.4-nocover + - TOXENV=pypy,coveralls + - TOXENV=pypy-nocover +before_install: + - python --version + - virtualenv --version + - pip --version + - uname -a + - lsb_release -a +install: + - pip install tox +script: + - tox -v +notifications: + email: + on_success: never + on_failure: always + diff --git a/AUTHORS.rst b/AUTHORS.rst new file mode 100644 index 0000000..c7a3b48 --- /dev/null +++ b/AUTHORS.rst @@ -0,0 +1,5 @@ + +Authors +======= + +* Teppo Perä - https://github.com/Debith/py3traits diff --git a/CHANGELOG.rst b/CHANGELOG.rst new file mode 100644 index 0000000..046bd08 --- /dev/null +++ b/CHANGELOG.rst @@ -0,0 +1,60 @@ + +Changelog +========= + +0.10.0 (2014-01-01) +----------------------------------------- + - Splitting into two projects: py2traits and py3traits + - Taking new project template to use from cookiecutter. + +0.9.0 Bringing back compatibility to Python 2.x +----------------------------------------- + - Some small clean up too + +0.8.0 Adding support to private class and instance attributes +----------------------------------------- + - Redone function binding to include recompilation of the function + - Leaving Python 2.x into unsupported state temporarily. + +0.7.0 Improving usability of the library +----------------------------------------- + - Introduced new extendable decorator, which adds function to add traits to object + - Introduced new function combine_class to create new classes out of traits + - Fixed module imports through out the library + - Improved documentation in examples + +0.6.0 Restructuring into library +----------------------------------------- + - Added support for py.test + - Preparing to support tox + - Improved multiple examples and renamed them to make more sense + - Removed the need of having two separate code branches for different Python versions + +0.5.0 Instances can now be extended with traits in Python 3.x +----------------------------------------- + - Instance support now similar to classes + - Added more examples + +0.4.0 Completed function binding with examples in Python 2.x +----------------------------------------- + - Separate functions can now be bound to classes + - Functions with 'self' as a first parameter will be acting as a method + - Functions with 'cls' as a first parameter will be acting as classmethod + - Other functions will be static methods. + - Fixed an issue with binding functions + +0.3.0 Trait extension support without conflicts for Python 2.x +----------------------------------------- + - Classes can be extended + - Instances can be extended + - Python 2.x supported + +0.2.0 Apache License Updated +----------------------------------------- + - Added apache 2.0 license to all files + - Set the character set as utf-8 for all files + +0.1.0 Initial Version +----------------------------------------- + - prepared files for Python 2.x + - prepared files for Python 3.x diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst new file mode 100644 index 0000000..cdcf68f --- /dev/null +++ b/CONTRIBUTING.rst @@ -0,0 +1,88 @@ +============ +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 `_ please include: + + * Your operating system name, version and python version. + * Failing test case created similar manner as in py3traits/examples. + +Documentation improvements +========================== + +py3traits could always use more documentation, whether as part of the +official py3traits 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/Debith/py3traits/issues. + +If you are proposing a feature: + +* Explain in detail how it would work or even better, create a failing test case similar manner as in py3traits/examples +* 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 `py3traits` for local development: + +1. `Fork py3traits on GitHub `_. +2. Clone your fork locally:: + + git clone git@github.com:your_name_here/py3traits.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 `_ 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 `_ 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/MANIFEST.in b/MANIFEST.in new file mode 100644 index 0000000..cf8dcba --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1,21 @@ +graft docs +graft examples +graft src +graft ci +graft tests + +include *.komodoproject +include .bumpversion.cfg +include .coveragerc +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[co] __pycache__ *.so *.pyd diff --git a/README.md b/README.md deleted file mode 100644 index 635b47f..0000000 --- a/README.md +++ /dev/null @@ -1,2 +0,0 @@ -# py3traits -Trait support for Python 3 diff --git a/README.rst b/README.rst new file mode 100644 index 0000000..9fbe2df --- /dev/null +++ b/README.rst @@ -0,0 +1,138 @@ +=============================== +py3traits +=============================== + +| |docs| |travis| |appveyor| |coveralls| |landscape| |scrutinizer| +| |version| |downloads| |wheel| |supported-versions| |supported-implementations| + +.. |docs| image:: https://readthedocs.org/projects/pytraits/badge/?style=flat + :target: https://readthedocs.org/projects/pytraits + :alt: Documentation Status + +.. |travis| image:: http://img.shields.io/travis/Debith/pytraits/master.png?style=flat + :alt: Travis-CI Build Status + :target: https://travis-ci.org/Debith/pytraits + +.. |appveyor| image:: https://ci.appveyor.com/api/projects/status/github/Debith/pytraits?branch=master + :alt: AppVeyor Build Status + :target: https://ci.appveyor.com/project/Debith/pytraits + +.. |coveralls| image:: http://img.shields.io/coveralls/Debith/pytraits/master.png?style=flat + :alt: Coverage Status + :target: https://coveralls.io/r/Debith/pytraits + +.. |landscape| image:: https://landscape.io/github/Debith/pytraits/master/landscape.svg?style=flat + :target: https://landscape.io/github/Debith/pytraits/master + :alt: Code Quality Status + +.. |version| image:: http://img.shields.io/pypi/v/py3traits.png?style=flat + :alt: PyPI Package latest release + :target: https://pypi.python.org/pypi/py3traits + +.. |downloads| image:: http://img.shields.io/pypi/dm/py3traits.png?style=flat + :alt: PyPI Package monthly downloads + :target: https://pypi.python.org/pypi/py3traits + +.. |wheel| image:: https://pypip.in/wheel/py3traits/badge.png?style=flat + :alt: PyPI Wheel + :target: https://pypi.python.org/pypi/py3traits + +.. |supported-versions| image:: https://pypip.in/py_versions/py3traits/badge.png?style=flat + :alt: Supported versions + :target: https://pypi.python.org/pypi/py3traits + +.. |supported-implementations| image:: https://pypip.in/implementation/py3traits/badge.png?style=flat + :alt: Supported imlementations + :target: https://pypi.python.org/pypi/py3traits + +.. |scrutinizer| image:: https://img.shields.io/scrutinizer/g/Debith/pytraits/master.png?style=flat + :alt: Scrutinizer Status + :target: https://scrutinizer-ci.com/g/Debith/pytraits/ + +Trait support for Python 3 + +* Free software: Apache license + +Installation +============ + +:: + + pip install py3traits + +Documentation +============= + +https://pytraits.readthedocs.org/ + +Development +=========== + +To run the all tests run:: + + tox + +About Traits +============ + +Traits are classes which contain methods that can be used to extend +other classes, similar to mixins, with exception that traits do not use +inheritance. Instead, traits are composed into other classes. That is; +methods, properties and internal state is copied to master object. + +The point is to improve code reusability by dividing code into simple +building blocks that can be then combined into actual classes. + +Read more from wikipedia: http://en.wikipedia.org/wiki/Traits_class + +---------------------------------------------------------------- + +Features +======== + - Composition of Traits + - [X] No conflicts + - [X] Cherry-picking + - [ ] Symmertric Sum + - [ ] Override + - [ ] Alias + - [ ] Exclusion + - Supported Trait Targets + - [X] Classes + - [X] Instances + - Supported Trait Types + - [X] Classes + - [X] Instances + - [X] Methods + - [X] Functions + - [X] as instance methods + - [X] as classmethods + - [X] as staticmethods + - [X] Properties + - Supported trait access level + - [X] Private class attributes + - [X] Hidden class attributes + - [X] Public class attributes + - [X] Private instance attributes + - [X] Hidden instance attributes + - [X] Public instance attributes + - [X] Singleton + + +Composition of Traits +--------------------- + +Traits are classes that are not supposed to run stand alone (nothing stops to make them work +like that though). Traits are classes that are composed (by copying functions and properties) +into other classes. Advantage is that there is no inheritance happening and so there are no +typical problems occurring with normal inheritance. For instance, diamond inheritance is not +possible as everything is copied to target class and all conflicting methods and properties +needs to be resolved during composition. + +In Python, this kind of approach is handy with metaclasses, since metaclasses have very strict +requirements for inheritance. + +This library goes bit further than extending just classes. It's possible to also compose traits +into instances of classes, in which case, composition only affects single instance, not whole +class. Also, this library allows cherrypicking methods and properties from other classes and +composing them to target objects. If anything, it at least enables possibility for highly +creative ways to reuse your code. \ No newline at end of file diff --git a/appveyor.yml b/appveyor.yml new file mode 100644 index 0000000..6ccfff7 --- /dev/null +++ b/appveyor.yml @@ -0,0 +1,68 @@ +version: '{build}' +build: off +environment: + global: + WITH_COMPILER: "cmd /E:ON /V:ON /C .\\ci\\appveyor-with-compiler.cmd" + matrix: + - TOXENV: "3.3" + TOXPYTHON: "C:\\Python33\\python.exe" + WINDOWS_SDK_VERSION: "v7.1" + PYTHON_HOME: "C:\\Python33" + PYTHON_VERSION: "3.3" + PYTHON_ARCH: "32" + - TOXENV: "3.3" + TOXPYTHON: "C:\\Python33-x64\\python.exe" + WINDOWS_SDK_VERSION: "v7.1" + PYTHON_HOME: "C:\\Python33-x64" + PYTHON_VERSION: "3.3" + PYTHON_ARCH: "64" + - TOXENV: "3.3-nocover" + TOXPYTHON: "C:\\Python33\\python.exe" + WINDOWS_SDK_VERSION: "v7.1" + PYTHON_HOME: "C:\\Python33" + PYTHON_VERSION: "3.3" + PYTHON_ARCH: "32" + - TOXENV: "3.3-nocover" + TOXPYTHON: "C:\\Python33-x64\\python.exe" + WINDOWS_SDK_VERSION: "v7.1" + PYTHON_HOME: "C:\\Python33-x64" + PYTHON_VERSION: "3.3" + PYTHON_ARCH: "64" + - TOXENV: "3.4" + TOXPYTHON: "C:\\Python34\\python.exe" + WINDOWS_SDK_VERSION: "v7.1" + PYTHON_HOME: "C:\\Python34" + PYTHON_VERSION: "3.4" + PYTHON_ARCH: "32" + - TOXENV: "3.4" + 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-nocover" + TOXPYTHON: "C:\\Python34\\python.exe" + WINDOWS_SDK_VERSION: "v7.1" + PYTHON_HOME: "C:\\Python34" + PYTHON_VERSION: "3.4" + PYTHON_ARCH: "32" + - TOXENV: "3.4-nocover" + TOXPYTHON: "C:\\Python34-x64\\python.exe" + WINDOWS_SDK_VERSION: "v7.1" + PYTHON_HOME: "C:\\Python34-x64" + PYTHON_VERSION: "3.4" + PYTHON_ARCH: "64" +init: + - "ECHO %TOXENV%" + - ps: "ls C:\\Python*" +install: + - "powershell ci\\appveyor-bootstrap.ps1" +test_script: + - "%PYTHON_HOME%\\Scripts\\tox --version" + - "%PYTHON_HOME%\\Scripts\\virtualenv --version" + - "%PYTHON_HOME%\\Scripts\\pip --version" + - "%WITH_COMPILER% %PYTHON_HOME%\\Scripts\\tox" +after_test: + - "IF \"%TOXENV:~-8,8%\" == \"-nocover\" %WITH_COMPILER% %TOXPYTHON% setup.py bdist_wheel" +artifacts: + - path: dist\* diff --git a/ci/appveyor-bootstrap.ps1 b/ci/appveyor-bootstrap.ps1 new file mode 100644 index 0000000..1dd5342 --- /dev/null +++ b/ci/appveyor-bootstrap.ps1 @@ -0,0 +1,88 @@ +# Source: https://github.com/pypa/python-packaging-user-guide/blob/master/source/code/install.ps1 +# Sample script to install Python and pip under Windows +# Authors: Olivier Grisel and Kyle Kastner +# License: CC0 1.0 Universal: http://creativecommons.org/publicdomain/zero/1.0/ + +$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" + + +function DownloadPython ($python_version, $platform_suffix) { + $webclient = New-Object System.Net.WebClient + $filename = "python-" + $python_version + $platform_suffix + ".msi" + $url = $BASE_URL + $python_version + "/" + $filename + + $basedir = $pwd.Path + "\" + $filepath = $basedir + $filename + if (Test-Path $filename) { + Write-Host "Reusing" $filepath + return $filepath + } + + # Download and retry up to 5 times in case of network transient errors. + Write-Host "Downloading" $filename "from" $url + $retry_attempts = 3 + for($i=0; $i -lt $retry_attempts; $i++){ + try { + $webclient.DownloadFile($url, $filepath) + break + } + Catch [Exception]{ + Start-Sleep 1 + } + } + Write-Host "File saved at" $filepath + return $filepath +} + + +function InstallPython ($python_version, $architecture, $python_home) { + Write-Host "Installing Python" $python_version "for" $architecture "bit architecture to" $python_home + if (Test-Path $python_home) { + Write-Host $python_home "already exists, skipping." + return $false + } + if ($architecture -eq "32") { + $platform_suffix = "" + } else { + $platform_suffix = ".amd64" + } + $filepath = DownloadPython $python_version $platform_suffix + Write-Host "Installing" $filepath "to" $python_home + $args = "/qn /i $filepath TARGETDIR=$python_home" + Write-Host "msiexec.exe" $args + Start-Process -FilePath "msiexec.exe" -ArgumentList $args -Wait -Passthru + Write-Host "Python $python_version ($architecture) installation complete" + return $true +} + + +function InstallPip ($python_home) { + $pip_path = $python_home + "/Scripts/pip.exe" + $python_path = $python_home + "/python.exe" + if (-not(Test-Path $pip_path)) { + Write-Host "Installing pip..." + $webclient = New-Object System.Net.WebClient + $webclient.DownloadFile($GET_PIP_URL, $GET_PIP_PATH) + Write-Host "Executing:" $python_path $GET_PIP_PATH + Start-Process -FilePath "$python_path" -ArgumentList "$GET_PIP_PATH" -Wait -Passthru + } else { + Write-Host "pip already installed." + } +} + +function InstallPackage ($python_home, $pkg) { + $pip_path = $python_home + "/Scripts/pip.exe" + & $pip_path install $pkg +} + +function main () { + InstallPython $env:PYTHON_VERSION $env:PYTHON_ARCH $env:PYTHON_HOME + InstallPip $env:PYTHON_HOME + InstallPackage $env:PYTHON_HOME setuptools + InstallPackage $env:PYTHON_HOME wheel + InstallPackage $env:PYTHON_HOME tox +} + +main diff --git a/ci/appveyor-with-compiler.cmd b/ci/appveyor-with-compiler.cmd new file mode 100644 index 0000000..3619733 --- /dev/null +++ b/ci/appveyor-with-compiler.cmd @@ -0,0 +1,37 @@ +:: 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/ +@ECHO OFF + +SET COMMAND_TO_RUN=%* +SET WIN_SDK_ROOT=C:\Program Files\Microsoft SDKs\Windows + +IF "%PYTHON_ARCH%"=="64" ( + ECHO SDK: %WINDOWS_SDK_VERSION% ARCH: %PYTHON_ARCH% + SET DISTUTILS_USE_SDK=1 + SET MSSdk=1 + "%WIN_SDK_ROOT%\%WINDOWS_SDK_VERSION%\Setup\WindowsSdkVer.exe" -q -version:%WINDOWS_SDK_VERSION% + "%WIN_SDK_ROOT%\%WINDOWS_SDK_VERSION%\Bin\SetEnv.cmd" /x64 /release + ECHO Executing: %COMMAND_TO_RUN% + call %COMMAND_TO_RUN% || EXIT 1 +) ELSE ( + ECHO SDK: %WINDOWS_SDK_VERSION% ARCH: %PYTHON_ARCH% + ECHO Executing: %COMMAND_TO_RUN% + call %COMMAND_TO_RUN% || EXIT 1 +) diff --git a/ci/bootstrap.py b/ci/bootstrap.py new file mode 100644 index 0000000..cf93a54 --- /dev/null +++ b/ci/bootstrap.py @@ -0,0 +1,60 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +from __future__ import absolute_import, print_function, unicode_literals + +import os +import sys +from os.path import exists +from os.path import join + + +if __name__ == "__main__": + base_path = join(".tox", "configure") + if sys.platform == "win32": + bin_path = join(base_path, "Scripts") + else: + bin_path = join(base_path, "bin") + if not exists(base_path): + import subprocess + print("Bootstrapping ...") + try: + subprocess.check_call(["virtualenv", base_path]) + except Exception: + subprocess.check_call([sys.executable, "-m", "virtualenv", base_path]) + print("Installing `jinja2` and `matrix` into bootstrap environment ...") + subprocess.check_call([join(bin_path, "pip"), "install", "jinja2", "matrix"]) + activate = join(bin_path, "activate_this.py") + exec(compile(open(activate, "rb").read(), activate, "exec"), dict(__file__=activate)) + + import jinja2 + import matrix + + jinja = jinja2.Environment( + loader=jinja2.FileSystemLoader(join("ci", "templates")), + trim_blocks=True, + lstrip_blocks=True, + keep_trailing_newline=True + ) + tox_environments = {} + for (alias, conf) in matrix.from_file("setup.cfg").items(): + python = conf["python_versions"] + deps = conf["dependencies"] + if "coverage_flags" in conf: + cover = {"false": False, "true": True}[conf["coverage_flags"].lower()] + if "environment_variables" in conf: + env_vars = conf["environment_variables"] + + tox_environments[alias] = { + "python": "python" + python if "py" not in python else python, + "deps": deps.split(), + } + if "coverage_flags" in conf: + tox_environments[alias].update(cover=cover) + if "environment_variables" in conf: + tox_environments[alias].update(env_vars=env_vars.split()) + + for name in os.listdir(join("ci", "templates")): + with open(name, "w") as fh: + fh.write(jinja.get_template(name).render(tox_environments=tox_environments)) + print("Wrote {}".format(name)) + print("DONE.") diff --git a/ci/templates/.travis.yml b/ci/templates/.travis.yml new file mode 100644 index 0000000..b1d89b3 --- /dev/null +++ b/ci/templates/.travis.yml @@ -0,0 +1,27 @@ +language: python +python: 2.7 +sudo: false +env: + global: + LD_PRELOAD=/lib/x86_64-linux-gnu/libSegFault.so + matrix: + - TOXENV=check +{% for env, config in tox_environments|dictsort %} + - TOXENV={{ env }}{% if config.cover %},coveralls{% endif %} + +{% endfor %} +before_install: + - python --version + - virtualenv --version + - pip --version + - uname -a + - lsb_release -a +install: + - pip install tox +script: + - tox -v +notifications: + email: + on_success: never + on_failure: always + diff --git a/ci/templates/appveyor.yml b/ci/templates/appveyor.yml new file mode 100644 index 0000000..fb1deac --- /dev/null +++ b/ci/templates/appveyor.yml @@ -0,0 +1,39 @@ +version: '{build}' +build: off +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" +{% for env, config in tox_environments|dictsort %}{% if env.startswith('2.7') or env.startswith('3.4') or env.startswith('3.3') %} + - TOXENV: "{{ env }}" + TOXPYTHON: "C:\\Python{{ env[:3].replace('.', '') }}\\python.exe" + WINDOWS_SDK_VERSION: "v7.{{ '1' if env[0] == '3' else '0' }}" + PYTHON_HOME: "C:\\Python{{ env[:3].replace('.', '') }}" + PYTHON_VERSION: "{{ env[:3] }}" + PYTHON_ARCH: "32" + - TOXENV: "{{ env }}" + TOXPYTHON: "C:\\Python{{ env[:3].replace('.', '') }}-x64\\python.exe" + WINDOWS_SDK_VERSION: "v7.{{ '1' if env[0] == '3' else '0' }}" + PYTHON_HOME: "C:\\Python{{ env[:3].replace('.', '') }}-x64" + PYTHON_VERSION: "{{ env[:3] }}" + PYTHON_ARCH: "64" +{% endif %}{% endfor %} +init: + - "ECHO %TOXENV%" + - ps: "ls C:\\Python*" +install: + - "powershell ci\\appveyor-bootstrap.ps1" +test_script: + - "%PYTHON_HOME%\\Scripts\\tox --version" + - "%PYTHON_HOME%\\Scripts\\virtualenv --version" + - "%PYTHON_HOME%\\Scripts\\pip --version" + - "%WITH_COMPILER% %PYTHON_HOME%\\Scripts\\tox" +after_test: + - "IF \"%TOXENV:~-8,8%\" == \"-nocover\" %WITH_COMPILER% %TOXPYTHON% setup.py bdist_wheel" +artifacts: + - path: dist\* + diff --git a/ci/templates/tox.ini b/ci/templates/tox.ini new file mode 100644 index 0000000..1f48bed --- /dev/null +++ b/ci/templates/tox.ini @@ -0,0 +1,116 @@ +[tox] +envlist = + clean, + check, +{% for env in tox_environments|sort %} + {{ env }}, +{% endfor %} + report, + docs + +[testenv] +setenv = + PYTHONPATH={toxinidir}/tests + PYTHONUNBUFFERED=yes +deps = + pytest + pytest-capturelog +commands = + {posargs:py.test -vv --ignore=src} + +[testenv:spell] +setenv = + SPELLCHECK = 1 +commands = + sphinx-build -b spelling docs dist/docs +usedevelop = true +deps = + -r{toxinidir}/docs/requirements.txt + sphinxcontrib-spelling + pyenchant + +[testenv:docs] +whitelist_externals = + rm +commands = + rm -rf dist/docs || rmdir /S /Q dist\docs + sphinx-build -b html docs dist/docs + sphinx-build -b linkcheck docs dist/docs +usedevelop = true +deps = + -r{toxinidir}/docs/requirements.txt + +[testenv:configure] +deps = + jinja2 + matrix +usedevelop = true +commands = + python bootstrap.py + +[testenv:check] +basepython = python3.4 +deps = + docutils + check-manifest + flake8 + readme + pygments +usedevelop = true +commands = + python setup.py check --strict --metadata --restructuredtext + check-manifest {toxinidir} + flake8 src + +[testenv:coveralls] +deps = + coveralls +usedevelop = true +commands = + coverage combine + coverage report + coveralls + +[testenv:report] +basepython = python3.4 +commands = + coverage combine + coverage report +usedevelop = true +deps = coverage + +[testenv:clean] +commands = coverage erase +usedevelop = true +deps = coverage + +{% for env, config in tox_environments|dictsort %} +[testenv:{{ env }}] +basepython = {{ config.python }} +{% if config.cover or config.env_vars %} +setenv = + {[testenv]setenv} +{% endif %} +{% for var in config.env_vars %} + {{ var }} +{% endfor %} +{% if config.cover %} + WITH_COVERAGE=yes +usedevelop = true +commands = + {posargs:py.test --cov=src --cov-report=term-missing -vv} +{% endif %} +{% if config.cover or config.deps %} +deps = + {[testenv]deps} +{% endif %} +{% if config.cover %} + pytest-cov +{% endif %} +{% for dep in config.deps %} + {{ dep }} +{% endfor %} + +{% endfor %} + + diff --git a/docs/authors.rst b/docs/authors.rst new file mode 100644 index 0000000..e122f91 --- /dev/null +++ b/docs/authors.rst @@ -0,0 +1 @@ +.. include:: ../AUTHORS.rst diff --git a/docs/changelog.rst b/docs/changelog.rst new file mode 100644 index 0000000..565b052 --- /dev/null +++ b/docs/changelog.rst @@ -0,0 +1 @@ +.. include:: ../CHANGELOG.rst diff --git a/docs/conf.py b/docs/conf.py new file mode 100644 index 0000000..ac05a73 --- /dev/null +++ b/docs/conf.py @@ -0,0 +1,44 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +import os + + +extensions = [ + 'sphinx.ext.autodoc', + 'sphinx.ext.autosummary', + 'sphinx.ext.todo', + 'sphinx.ext.coverage', + 'sphinx.ext.ifconfig', + 'sphinx.ext.viewcode', + 'sphinxcontrib.napoleon' +] +if os.getenv('SPELLCHECK'): + extensions += 'sphinxcontrib.spelling', + spelling_show_suggestions = True + spelling_lang = 'en_US' + +source_suffix = '.rst' +master_doc = 'index' +project = 'py3traits' +year = '2015' +author = 'Teppo Perä' +copyright = '{0}, {1}'.format(year, author) +version = release = '0.10.0' + +import sphinx_py3doc_enhanced_theme +html_theme = "sphinx_py3doc_enhanced_theme" +html_theme_path = [sphinx_py3doc_enhanced_theme.get_html_theme_path()] + +pygments_style = 'trac' +templates_path = ['.'] +html_use_smartypants = True +html_last_updated_fmt = '%b %d, %Y' +html_split_index = True +html_sidebars = { + '**': ['searchbox.html', 'globaltoc.html', 'sourcelink.html'], +} +html_short_title = '%s-%s' % (project, version) +html_theme_options = { + 'githuburl': 'https://github.com/Debith/py3traits/' +} diff --git a/docs/contributing.rst b/docs/contributing.rst new file mode 100644 index 0000000..e582053 --- /dev/null +++ b/docs/contributing.rst @@ -0,0 +1 @@ +.. include:: ../CONTRIBUTING.rst diff --git a/docs/index.rst b/docs/index.rst new file mode 100644 index 0000000..d394a54 --- /dev/null +++ b/docs/index.rst @@ -0,0 +1,23 @@ +Welcome to py3traits's documentation! +====================================== + +Contents: + +.. toctree:: + :maxdepth: 2 + + readme + installation + usage + reference/index + contributing + authors + changelog + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` + diff --git a/docs/installation.rst b/docs/installation.rst new file mode 100644 index 0000000..b6ade81 --- /dev/null +++ b/docs/installation.rst @@ -0,0 +1,7 @@ +============ +Installation +============ + +At the command line:: + + pip install py3traits diff --git a/docs/readme.rst b/docs/readme.rst new file mode 100644 index 0000000..6be290b --- /dev/null +++ b/docs/readme.rst @@ -0,0 +1,5 @@ +######## +Overview +######## + +.. include:: ../README.rst diff --git a/docs/reference/index.rst b/docs/reference/index.rst new file mode 100644 index 0000000..1e5fbc4 --- /dev/null +++ b/docs/reference/index.rst @@ -0,0 +1,7 @@ +Reference +========= + +.. toctree:: + :glob: + + pytraits* diff --git a/docs/reference/pytraits.rst b/docs/reference/pytraits.rst new file mode 100644 index 0000000..47f79ad --- /dev/null +++ b/docs/reference/pytraits.rst @@ -0,0 +1,5 @@ +pytraits +============================= + +.. automodule:: pytraits + :members: diff --git a/docs/requirements.txt b/docs/requirements.txt new file mode 100644 index 0000000..1632a96 --- /dev/null +++ b/docs/requirements.txt @@ -0,0 +1,4 @@ +sphinx +sphinxcontrib-napoleon +sphinx-py3doc-enhanced-theme +-e . diff --git a/docs/spelling_wordlist.txt b/docs/spelling_wordlist.txt new file mode 100644 index 0000000..f95eb78 --- /dev/null +++ b/docs/spelling_wordlist.txt @@ -0,0 +1,11 @@ +builtin +builtins +classmethod +staticmethod +classmethods +staticmethods +args +kwargs +callstack +Changelog +Indices diff --git a/docs/usage.rst b/docs/usage.rst new file mode 100644 index 0000000..3a320cc --- /dev/null +++ b/docs/usage.rst @@ -0,0 +1,9 @@ +===== +Usage +===== + +To use py3traits in a project:: + + import pytraits + +See more details from py3traits/examples \ No newline at end of file diff --git a/setup.cfg b/setup.cfg index 9448504..106c6f3 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,2 +1,84 @@ +[bdist_wheel] +universal = 1 + +[aliases] +release = register clean --all sdist bdist_wheel upload + +[flake8] +max-line-length = 140 +exclude = tests/*,*/migrations/*,*/south_migrations/* + +[bumpversion] +current_version = 0.1.0 +files = setup.py docs/conf.py src/pytraits/__init__.py +commit = True +tag = True + [pytest] -python_files=examples/*.py \ No newline at end of file +norecursedirs = + .git + .tox + dist + build + south_migrations + migrations +python_files = + examples/*.py +addopts = + -rxEfs + --strict + --ignore=docs/conf.py + --ignore=setup.py + --ignore=ci + --doctest-modules + --doctest-glob=\*.rst + --tb=short + +[isort] +force_single_line=True +line_length=120 +known_first_party=pytraits +default_section=THIRDPARTY +forced_separate=test_pytraits + +[matrix] +# This is the configuration for the `./bootstrap.py` script. +# It generates `.travis.yml`, `tox.ini` and `appveyor.yml`. +# +# Syntax: [alias:] value [!variable[glob]] [&variable[glob]] +# +# alias: +# - is used to generate the tox environment +# - it's optional +# - if not present the alias will be computed from the `value` +# value: +# - a value of "-" means empty +# !variable[glob]: +# - exclude the combination of the current `value` with +# any value matching the `glob` in `variable` +# - can use as many you want +# &variable[glob]: +# - only include the combination of the current `value` +# when there's a value matching `glob` in `variable` +# - can use as many you want + +python_versions = + 2.6 + 2.7 + 3.3 + 3.4 + pypy + +dependencies = +# 1.4: Django==1.4.16 !python_versions[3.*] +# 1.5: Django==1.5.11 +# 1.6: Django==1.6.8 +# 1.7: Django==1.7.1 !python_versions[2.6] +# Deps commented above are provided as examples. That's what you would use in a Django project. + +coverage_flags = + : true + nocover: false + +environment_variables = + - diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..588ae6d --- /dev/null +++ b/setup.py @@ -0,0 +1,55 @@ +#!/usr/bin/env python +# -*- encoding: utf-8 -*- +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='py3traits', + version='0.10.0', + license='Apache License 2', + description='Trait support for Python 3', + long_description='%s\n%s' % (read('README.rst'), re.sub(':obj:`~?(.*?)`', r'``\1``', read('CHANGELOG.rst'))), + author='Teppo Per\xc3\xa4', + author_email='debith-dev@outlook.com', + url='https://github.com/Debith/pytraits', + 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', + 'Programming Language :: Python :: 3', + 'Programming Language :: Python :: 3.3', + 'Programming Language :: Python :: 3.4', + 'Topic :: Utilities', + ], + keywords=['traits'], + install_requires=[], + extras_require={}, + entry_points={}, +) diff --git a/src/pytraits/__init__.py b/src/pytraits/__init__.py index 500cf45..984c6a7 100644 --- a/src/pytraits/__init__.py +++ b/src/pytraits/__init__.py @@ -16,6 +16,8 @@ limitations under the License. ''' +__version__ = "0.1.0" + from pytraits.core import Singleton from pytraits.combiner import combine_class from pytraits.extendable import extendable diff --git a/src/pytraits/core/magic.py b/src/pytraits/core/magic.py index 9d4c603..ec05b10 100644 --- a/src/pytraits/core/magic.py +++ b/src/pytraits/core/magic.py @@ -77,15 +77,15 @@ def boolean_conversion(self, value): return value elif isinstance(value, str): - if value.lower() == "true": + if value.lower() == "true": return True if value.lower() == "false": return False elif isinstance(value, int): - if not value: + if not value: return False - if value == 1: + if value == 1: return True raise TypeError() @@ -143,4 +143,4 @@ def __call__(self, *args, **kwargs): if __name__ == "__main__": import doctest - doctest.testmod() \ No newline at end of file + doctest.testmod() diff --git a/tests/test_pytraits.py b/tests/test_pytraits.py new file mode 100644 index 0000000..a33b9f7 --- /dev/null +++ b/tests/test_pytraits.py @@ -0,0 +1,5 @@ +from pytraits.__main__ import main + + +def test_main(): + assert main([]) == 0 diff --git a/tox.ini b/tox.ini new file mode 100644 index 0000000..7d62885 --- /dev/null +++ b/tox.ini @@ -0,0 +1,94 @@ +; a generative tox configuration, see: https://testrun.org/tox/latest/config.html#generative-envlist + +[tox] +envlist = + clean, + check, + {3.3,3.4,pypy}, + {3.3,3.4,pypy}-nocover, + report, + docs + +[testenv] +basepython = + 3.3: python3.3 + 3.4: python3.4 + {clean,check,report,extension-coveralls,coveralls}: python3.4 +setenv = + PYTHONPATH={toxinidir}/tests + PYTHONUNBUFFERED=yes +deps = + pytest + pytest-capturelog + pytest-cov +commands = + {posargs:py.test --cov=src --cov-report=term-missing -vv} +usedevelop = true + +[testenv:spell] +setenv = + SPELLCHECK=1 +commands = + sphinx-build -b spelling docs dist/docs +usedevelop = true +deps = + -r{toxinidir}/docs/requirements.txt + sphinxcontrib-spelling + pyenchant + +[testenv:docs] +whitelist_externals = + rm +commands = + rm -rf dist/docs || rmdir /S /Q dist\docs + sphinx-build -b html docs dist/docs + sphinx-build -b linkcheck docs dist/docs +usedevelop = true +deps = + -r{toxinidir}/docs/requirements.txt + +[testenv:check] +basepython = python3.4 +deps = + docutils + check-manifest + flake8 + readme + pygments +usedevelop = true +commands = + python setup.py check --strict --metadata --restructuredtext + check-manifest {toxinidir} + flake8 src + +[testenv:coveralls] +deps = + coveralls +usedevelop = true +commands = + coverage combine + coverage report + coveralls +[testenv:report] +basepython = python3.4 +commands = + coverage combine + coverage report +usedevelop = true +deps = coverage + +[testenv:clean] +commands = coverage erase +usedevelop = true +deps = coverage + +[testenv:3.3-nocover] +commands = + {posargs:py.test -vv --ignore=src} +usedevelop = false + +[testenv:3.4-nocover] +commands = + {posargs:py.test -vv --ignore=src} +usedevelop = false +