├── setup.cfg ├── src └── overload │ ├── __init__.py │ └── overload.py ├── README.md ├── docs ├── source │ ├── index.rst │ └── conf.py ├── Makefile └── make.bat ├── tests └── test_overload.py ├── LICENSE ├── Makefile ├── setup.py ├── .gitignore ├── .travis.yml └── tox.ini /setup.cfg: -------------------------------------------------------------------------------- 1 | [metadata] 2 | description-file = README.md 3 | -------------------------------------------------------------------------------- /src/overload/__init__.py: -------------------------------------------------------------------------------- 1 | # encoding=utf-8 2 | from .overload import OverloadException, overload # noqa: F401 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Build Status](https://travis-ci.org/arpitbbhayani/overload.svg?branch=master)](https://travis-ci.org/arpitbbhayani/overload) 2 | [![Codacy Badge](https://api.codacy.com/project/badge/Grade/2f20647a28534955828d897776821efe)](https://www.codacy.com/manual/arpitbbhayani/overload?utm_source=github.com&utm_medium=referral&utm_content=arpitbbhayani/overload&utm_campaign=Badge_Grade) 3 | 4 | overload 5 | --- 6 | -------------------------------------------------------------------------------- /docs/source/index.rst: -------------------------------------------------------------------------------- 1 | .. overload documentation master file, created by 2 | sphinx-quickstart on Fri Feb 21 23:18:39 2020. 3 | You can adapt this file completely to your liking, but it should at least 4 | contain the root `toctree` directive. 5 | 6 | Welcome to overload's documentation! 7 | ==================================== 8 | 9 | .. toctree:: 10 | :maxdepth: 2 11 | :caption: Contents: 12 | 13 | 14 | 15 | Indices and tables 16 | ================== 17 | 18 | * :ref:`genindex` 19 | * :ref:`modindex` 20 | * :ref:`search` 21 | -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # Minimal makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line, and also 5 | # from the environment for the first two. 6 | SPHINXOPTS ?= 7 | SPHINXBUILD ?= sphinx-build 8 | SOURCEDIR = source 9 | BUILDDIR = build 10 | 11 | # Put it first so that "make" without argument is like "make help". 12 | help: 13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 14 | 15 | .PHONY: help Makefile 16 | 17 | # Catch-all target: route all unknown targets to Sphinx using the new 18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 19 | %: Makefile 20 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 21 | -------------------------------------------------------------------------------- /docs/make.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | pushd %~dp0 4 | 5 | REM Command file for Sphinx documentation 6 | 7 | if "%SPHINXBUILD%" == "" ( 8 | set SPHINXBUILD=sphinx-build 9 | ) 10 | set SOURCEDIR=source 11 | set BUILDDIR=build 12 | 13 | if "%1" == "" goto help 14 | 15 | %SPHINXBUILD% >NUL 2>NUL 16 | if errorlevel 9009 ( 17 | echo. 18 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx 19 | echo.installed, then set the SPHINXBUILD environment variable to point 20 | echo.to the full path of the 'sphinx-build' executable. Alternatively you 21 | echo.may add the Sphinx directory to PATH. 22 | echo. 23 | echo.If you don't have Sphinx installed, grab it from 24 | echo.http://sphinx-doc.org/ 25 | exit /b 1 26 | ) 27 | 28 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% 29 | goto end 30 | 31 | :help 32 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% 33 | 34 | :end 35 | popd 36 | -------------------------------------------------------------------------------- /tests/test_overload.py: -------------------------------------------------------------------------------- 1 | # encoding=utf-8 2 | import logging 3 | 4 | import pytest 5 | from hamcrest import assert_that, close_to 6 | from overload import OverloadException, overload 7 | 8 | logger = logging.getLogger(__name__) 9 | 10 | 11 | @overload 12 | def area(length, breadth): 13 | return length * breadth 14 | 15 | 16 | @overload 17 | def area(radius): # noqa: F811 18 | import math 19 | 20 | return math.pi * radius ** 2 21 | 22 | 23 | @overload 24 | def area(length, breadth, height): # noqa: F811 25 | return 2 * (length * breadth + breadth * height + height * length) 26 | 27 | 28 | def test_overload_functions(): 29 | assert area(4, 3, 6) == 108 30 | assert area(4, 3) == 12 31 | assert_that(area(4), close_to(50.26, 0.01)) 32 | 33 | 34 | def test_no_such_function(): 35 | with pytest.raises(OverloadException): 36 | area(1, 2, 3, 4) 37 | 38 | 39 | def test_namespace_re_instantiation_attempt(): 40 | from overload.overload import Namespace 41 | 42 | with pytest.raises(OverloadException): 43 | Namespace() # should raise exception 44 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Arpit Bhayani 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | SHELL = /bin/bash 2 | 3 | default: help 4 | .PHONY: help 5 | 6 | test: ## Run tests 7 | tox -e py35,py38 8 | 9 | coverage: ## Test coverage report 10 | tox -e coverage 11 | 12 | lint: check-format flake8 bandit ## Lint code 13 | 14 | flake8: 15 | tox -e flake8 16 | 17 | bandit: 18 | tox -e bandit 19 | 20 | extra-lint: pylint mypy ## Extra, optional linting. 21 | 22 | pylint: 23 | tox -e pylint 24 | 25 | mypy: 26 | tox -e mypy 27 | 28 | check-format: 29 | tox -e check-format 30 | 31 | format: ## Format code 32 | tox -e format 33 | 34 | piprot: ## Check for outdated dependencies 35 | tox -e piprot 36 | 37 | .PHONY: docs 38 | docs: ## Generate documentation 39 | tox -e docs 40 | 41 | precommit: test lint coverage docs ## Pre-commit targets 42 | @ python -m this 43 | 44 | recreate: ## Recreate tox environments 45 | tox --recreate --notest -e py35,py36,py37,format,flake8,bandit,piprot,pylint 46 | 47 | clean: ## Clean generated files 48 | find . -name '*.pyc' -delete 49 | find . -name '*.pyo' -delete 50 | rm -rf build/ dist/ *.egg-info/ .cache .coverage .pytest_cache 51 | find . -name "__pycache__" -type d -print | xargs -t rm -r 52 | find . -name "test-output" -type d -print | xargs -t rm -r 53 | 54 | repl: ## Python REPL 55 | tox -e py38 -- python 56 | 57 | outdated: ## List outdated dependancies 58 | tox -e py38 -- pip list --outdated 59 | 60 | help: ## Show this help 61 | @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1,$$2}' 62 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | import logging 2 | import os 3 | 4 | from setuptools import find_packages, setup 5 | 6 | logger = logging.getLogger(__name__) 7 | 8 | # Get the base directory 9 | here = os.path.dirname(__file__) 10 | if not here: 11 | here = os.path.curdir 12 | here = os.path.abspath(here) 13 | 14 | try: 15 | readme = os.path.join(here, "README.md") 16 | long_description = open(readme, "r").read() 17 | except IOError: 18 | logger.warning("README file not found or unreadable.") 19 | long_description = "See https://github.com/arpitbbhayani/overload" 20 | 21 | setup( 22 | name="overload", 23 | zip_safe=False, 24 | version="0.1.0", 25 | description="Overload Functions in Python.", 26 | long_description=long_description, 27 | long_description_content_type="text/markdown", 28 | author="Arpit Bhayani", 29 | author_email="arpit.b.bhayani@gmail.com", 30 | url="https://github.com/arpitbbhayani/overload", 31 | packages=find_packages(where="src"), 32 | package_dir={"": "src"}, 33 | package_data={"": ["README.md"]}, 34 | include_package_data=True, 35 | classifiers=[ 36 | "Development Status :: 5 - Production/Stable", 37 | "Intended Audience :: Developers", 38 | "License :: OSI Approved :: MIT License", 39 | "Operating System :: OS Independent", 40 | "Programming Language :: Python", 41 | "Programming Language :: Python :: 3", 42 | "Programming Language :: Python :: 3.5", 43 | "Programming Language :: Python :: 3.6", 44 | "Programming Language :: Python :: 3.7", 45 | "Programming Language :: Python :: 3.8", 46 | "Programming Language :: Python :: Implementation :: PyPy", 47 | "Topic :: Software Development :: Testing", 48 | ], 49 | python_requires=">=3.4", 50 | install_requires=[], 51 | ) 52 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | build_docs/ 13 | develop-eggs/ 14 | dist/ 15 | downloads/ 16 | eggs/ 17 | .eggs/ 18 | lib/ 19 | lib64/ 20 | parts/ 21 | sdist/ 22 | var/ 23 | wheels/ 24 | *.egg-info/ 25 | .installed.cfg 26 | *.egg 27 | MANIFEST 28 | 29 | # PyInstaller 30 | # Usually these files are written by a python script from a template 31 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 32 | *.manifest 33 | *.spec 34 | 35 | # Installer logs 36 | pip-log.txt 37 | pip-delete-this-directory.txt 38 | 39 | # Unit test / coverage reports 40 | htmlcov/ 41 | .tox/ 42 | .coverage 43 | .coverage.* 44 | .cache 45 | nosetests.xml 46 | coverage.xml 47 | *.cover 48 | .hypothesis/ 49 | .pytest_cache/ 50 | 51 | # Translations 52 | *.mo 53 | *.pot 54 | 55 | # Django stuff: 56 | *.log 57 | local_settings.py 58 | db.sqlite3 59 | 60 | # Flask stuff: 61 | instance/ 62 | .webassets-cache 63 | 64 | # Scrapy stuff: 65 | .scrapy 66 | 67 | # Sphinx documentation 68 | docs/_build/ 69 | 70 | # PyBuilder 71 | target/ 72 | 73 | # Jupyter Notebook 74 | .ipynb_checkpoints 75 | 76 | # pyenv 77 | .python-version 78 | 79 | # celery beat schedule file 80 | celerybeat-schedule 81 | 82 | # SageMath parsed files 83 | *.sage.py 84 | 85 | # Environments 86 | .env 87 | .venv 88 | env/ 89 | venv/ 90 | ENV/ 91 | env.bak/ 92 | venv.bak/ 93 | 94 | # Spyder project settings 95 | .spyderproject 96 | .spyproject 97 | 98 | # Rope project settings 99 | .ropeproject 100 | 101 | # mkdocs documentation 102 | /site 103 | 104 | # mypy 105 | .mypy_cache/ 106 | 107 | 108 | # Editor cruft 109 | .idea/ 110 | *~ 111 | 112 | # Node modules 113 | node_modules/ 114 | package-lock.json 115 | 116 | # Mac cruft 117 | .DS_Store 118 | 119 | .vscode 120 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: python 2 | dist: xenial 3 | matrix: 4 | allow_failures: 5 | - os: windows 6 | - os: osx 7 | include: 8 | - python: 3.7 9 | env: 10 | - TOX_ENV=py37 11 | - os: osx 12 | language: generic 13 | python: 3.7 14 | env: 15 | - TOX_ENV=py37 16 | - os: windows 17 | language: sh 18 | python: 3.7 19 | before_install: 20 | - choco install python --version=3.7.5 21 | - export PATH="/c/Python37:/c/Python37/Scripts:$PATH" 22 | - python -m pip install --upgrade pip wheel tox 23 | env: 24 | - TOX_ENV=py37 25 | - python: 3.5 26 | env: 27 | - TOX_ENV=py35 28 | - python: 3.6 29 | env: 30 | - TOX_ENV=py36 31 | - python: 3.8 32 | env: 33 | - TOX_ENV=py38 34 | - python: 3.6 35 | env: 36 | - TOX_ENV=pypy3.6 37 | - python: 3.6 38 | env: 39 | - TOX_ENV=check-format 40 | - python: 3.6 41 | env: 42 | - TOX_ENV=flake8 43 | - python: 3.6 44 | env: 45 | - TOX_ENV=bandit 46 | - python: 3.6 47 | env: 48 | - TOX_ENV=publish-coverage 49 | - secure: "AHqwDFNNRqwXipvdK/qsQlQxeSws/5wzXg6zYCLL68tLr47dSeCGEiBzDHaZTmPnD3EuRe2o3g3EoB9L+6kElpzd9UfgiXKaKafQqMI12qNRkhgPURAvHmepSfu4qRSUZa3qYE18tCtcD3QJRwBlETQT5czucCM9VF3wWHg3DDWQ/lGlBgpLN/nTMY9xjsWNKjkz6A8JElWokAkKzcdF1zYC5lmyBMe6QiTJIY1b5UAz2/kFO0TS+wl9hNebnIYWucubY8NzuIxpRwpri2/wtIBGYUbwkU0zbgUurTcknZGnGnpkxgLWUs/c4+JjMSHCprzaxwBt9cj/aY1jPZ3Y2SiI8ssQxFAdxeG4xo8gv1E+hCwq90LcpDuyNeMmssIwA7xiOX7fncyj0tI1Ndtfy1Obiz/Mk3MWZEgXLwPozoXIhszu3JskOyK1B1Pv6WyO9Miyk0s1liTpqwPIi7xQhdSo5ExBKp4IxhtsC+x5WR3CkxRVgXyOVCKdfwEID3uDZle/NqrpKnDU9BQtYSUlLbqajpH/R3uogF4Ll8FZUEnH6re1fkCY7fbOrxqveIbtOmzQyyO4eU3uSa8SodUOKhGNxNqd3fAZz+STMN7m74vrZ55qYQ0C0jndEZihTGv5SPu2ui3T8JzN5XPlZw9FUOiIGs8hrMR8Ua772zvfrfA=" 50 | - python: 3.6 51 | env: 52 | - TOX_ENV=docs 53 | install: 54 | - pip install --upgrade tox 55 | script: 56 | - tox -e $TOX_ENV 57 | -------------------------------------------------------------------------------- /docs/source/conf.py: -------------------------------------------------------------------------------- 1 | # Configuration file for the Sphinx documentation builder. 2 | # 3 | # This file only contains a selection of the most common options. For a full 4 | # list see the documentation: 5 | # https://www.sphinx-doc.org/en/master/usage/configuration.html 6 | 7 | # -- Path setup -------------------------------------------------------------- 8 | 9 | # If extensions (or modules to document with autodoc) are in another directory, 10 | # add these directories to sys.path here. If the directory is relative to the 11 | # documentation root, use os.path.abspath to make it absolute, like shown here. 12 | # 13 | # import os 14 | # import sys 15 | # sys.path.insert(0, os.path.abspath('.')) 16 | 17 | 18 | # -- Project information ----------------------------------------------------- 19 | 20 | project = 'overload' 21 | copyright = '2020, Arpit Bhayani, Simon Burnninng' 22 | author = 'Arpit Bhayani, Simon Burnninng' 23 | 24 | 25 | # -- General configuration --------------------------------------------------- 26 | 27 | # Add any Sphinx extension module names here, as strings. They can be 28 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom 29 | # ones. 30 | extensions = [ 31 | ] 32 | 33 | # Add any paths that contain templates here, relative to this directory. 34 | templates_path = ['_templates'] 35 | 36 | # List of patterns, relative to source directory, that match files and 37 | # directories to ignore when looking for source files. 38 | # This pattern also affects html_static_path and html_extra_path. 39 | exclude_patterns = [] 40 | 41 | 42 | # -- Options for HTML output ------------------------------------------------- 43 | 44 | # The theme to use for HTML and HTML Help pages. See the documentation for 45 | # a list of builtin themes. 46 | # 47 | html_theme = 'alabaster' 48 | 49 | # Add any paths that contain custom static files (such as style sheets) here, 50 | # relative to this directory. They are copied after the builtin static files, 51 | # so a file named "default.css" will overwrite the builtin "default.css". 52 | html_static_path = [] 53 | -------------------------------------------------------------------------------- /src/overload/overload.py: -------------------------------------------------------------------------------- 1 | # encoding=utf-8 2 | import logging 3 | from inspect import getfullargspec 4 | 5 | logger = logging.getLogger(__name__) 6 | 7 | 8 | class Function(object): 9 | """Function is a wrap over standard python function 10 | 11 | An instance of this Function class is also callable 12 | just like the python function that it wrapped. 13 | When the instance is "called" like a function it fetches 14 | the function to be invoked from the virtual namespace and then 15 | invokes the same. 16 | """ 17 | 18 | def __init__(self, fn): 19 | self.fn = fn 20 | 21 | def __call__(self, *args, **kwargs): 22 | """Overriding the __call__ function which makes the 23 | instance callable. 24 | """ 25 | # fetching the function to be invoked from the virtual namespace 26 | # through the arguments. 27 | fn = Namespace.get_instance().get(self.fn, *args) 28 | if not fn: 29 | raise OverloadException("no matching function found.") 30 | 31 | # invoking the wrapped function and returning the value. 32 | return fn(*args, **kwargs) 33 | 34 | def key(self, args=None): 35 | """Returns the key that will uniquely identifies 36 | a function (even when it is overloaded). 37 | """ 38 | if args is None: 39 | args = getfullargspec(self.fn).args 40 | 41 | return ( 42 | self.fn.__module__, 43 | self.fn.__class__, 44 | self.fn.__name__, 45 | len(args or []), 46 | ) 47 | 48 | 49 | class Namespace(object): 50 | """Namespace is the singleton class that is responsible 51 | for holding all the functions. 52 | """ 53 | 54 | __instance = None 55 | 56 | def __init__(self): 57 | if self.__instance is None: 58 | self.function_map = {} 59 | Namespace.__instance = self 60 | else: 61 | raise OverloadException("cannot instantiate Namespace again.") 62 | 63 | @staticmethod 64 | def get_instance(): 65 | if Namespace.__instance is None: 66 | Namespace() 67 | return Namespace.__instance 68 | 69 | def register(self, fn): 70 | """registers the function in the virtual namespace and returns 71 | an instance of callable Function that wraps the 72 | function fn. 73 | """ 74 | func = Function(fn) 75 | # getfullargspec(fn) 76 | self.function_map[func.key()] = fn 77 | return func 78 | 79 | def get(self, fn, *args): 80 | """get returns the matching function from the virtual namespace. 81 | 82 | return None if it did not fund any matching function. 83 | """ 84 | func = Function(fn) 85 | return self.function_map.get(func.key(args=args)) 86 | 87 | 88 | class OverloadException(Exception): 89 | pass 90 | 91 | 92 | def overload(fn): 93 | """overload is the decorator that wraps the function 94 | and returns a callable object of type Function. 95 | """ 96 | return Namespace.get_instance().register(fn) 97 | -------------------------------------------------------------------------------- /tox.ini: -------------------------------------------------------------------------------- 1 | [tox] 2 | envlist = py35,py36,py37,py38,pypy3.6 3 | 4 | [testenv] 5 | whitelist_externals = 6 | find 7 | sed 8 | cat 9 | bash 10 | echo 11 | deps = 12 | pytest~=5.0 13 | pyhamcrest~=2.0 14 | commands = 15 | {posargs:py.test} 16 | {[cleanup]commands} 17 | 18 | [testenv:coverage] 19 | envlist = py38 20 | deps = 21 | {[testenv]deps} 22 | pytest-cov~=2.5 23 | commands = 24 | echo {envsitepackagesdir} 25 | pytest --cov {envsitepackagesdir}/overload/ --durations=10 --cov-report term-missing --cov-fail-under 100 --basetemp={envtmpdir} {posargs} 26 | {[cleanup]commands} 27 | 28 | [testenv:publish-coverage] 29 | envlist = py38 30 | passenv = TRAVIS TRAVIS_* CODACY_* 31 | deps = 32 | {[testenv:coverage]deps} 33 | codacy-coverage~=1.0 34 | commands = 35 | pytest --cov {envsitepackagesdir}/overload/ --cov-report xml --basetemp={envtmpdir} {posargs} 36 | sed -i 's/\/home\/travis\/build\/arpitbbhayani\/overload\/.tox\/publish-coverage\/lib\/python3..\/site-packages/src/g' coverage.xml 37 | python-codacy-coverage -r coverage.xml 38 | 39 | [coverage:run] 40 | branch = True 41 | 42 | [testenv:flake8] 43 | basepython = python3 44 | skip_install = true 45 | deps = 46 | flake8~=3.0 47 | flake8-bugbear~=18.0 48 | flake8-comprehensions~=1.0 49 | flake8-mutable~=1.0 50 | mccabe~=0.6 51 | flake8-blind-except~=0.1 52 | flake8-builtins~=1.0 53 | flake8-pep3101~=1.0 54 | flake8-print~=3.0 55 | flake8-string-format~=0.2 56 | flake8-logging-format~=0.5 57 | flake8-colors~=0.1 58 | # flake8-tidy-imports~=1.0 59 | 60 | commands = 61 | flake8 --version 62 | flake8 src/ tests/ setup.py --ignore=F811 63 | 64 | [flake8] 65 | max-complexity = 5 66 | max-line-length = 100 67 | show-source = True 68 | enable-extensions = M,B,C,T,P 69 | ignore = C812,W503,P103,E1,E2,E3,E5 70 | statistics = True 71 | 72 | [base] ; Needs to match as setup.py's install_requires. TODO - DRY. 73 | deps = 74 | 75 | [testenv:pylint] 76 | basepython = python3 77 | skip_install = true 78 | deps = 79 | pylint~=2.2 80 | {[testenv]deps} 81 | {[base]deps} 82 | commands = 83 | pylint --disable=C src/ 84 | 85 | [testenv:mypy] 86 | basepython = python3 87 | skip_install = true 88 | deps = 89 | mypy~=0.7 90 | {[testenv]deps} 91 | {[base]deps} 92 | commands = 93 | mypy src/ {posargs} 94 | 95 | [testenv:bandit] 96 | basepython = python3 97 | skip_install = true 98 | deps = 99 | bandit~=1.4 100 | commands = 101 | bandit -r src/ 102 | 103 | [testenv:piprot] 104 | basepython = python3 105 | skip_install = true 106 | deps = 107 | piprot~=0.9 108 | commands = 109 | pip freeze | piprot 110 | 111 | [testenv:format] 112 | basepython = python3 113 | skip_install = true 114 | deps = 115 | black 116 | isort 117 | commands = 118 | isort {toxinidir}/setup.py 119 | isort -rc {toxinidir}/src/ 120 | isort -rc {toxinidir}/tests/ 121 | black -l100 -tpy35 src/ tests/ setup.py 122 | 123 | [testenv:check-format] 124 | basepython = python3 125 | skip_install = true 126 | deps = {[testenv:format]deps} 127 | commands = 128 | isort --check-only {toxinidir}/setup.py 129 | isort --check-only -rc {toxinidir}/src/ 130 | isort --check-only -rc {toxinidir}/tests/ 131 | black --check -l100 -tpy35 src/ tests/ setup.py 132 | 133 | [tool:isort] 134 | multi_line_output=3 135 | include_trailing_comma=True 136 | force_grid_wrap=0 137 | use_parentheses=True 138 | line_length=100 139 | 140 | [testenv:docs] 141 | description = invoke sphinx-build to build the HTML docs 142 | basepython = python3 143 | deps = 144 | sphinx~=2.4.2 145 | sphinx-autodoc-typehints~=1.10.3 146 | commands = sphinx-build docs/source "{toxinidir}/build_docs" --color -W -bhtml {posargs} 147 | python -c 'import pathlib; print("documentation available under file://\{0\}".format(pathlib.Path(r"{toxinidir}") / "docs_out" / "index.html"))' 148 | 149 | [cleanup] 150 | commands = 151 | find {toxinidir}/tests -type f -name "*.pyc" -delete 152 | find {toxinidir}/tests -type d -name "__pycache__" -delete 153 | find {toxinidir}/src -type f -name "*.pyc" -delete 154 | find {toxinidir}/src -type d -name "__pycache__" -delete 155 | find {toxinidir}/src -type f -path "*.egg-info*" -delete 156 | find {toxinidir}/src -type d -path "*.egg-info" -delete 157 | --------------------------------------------------------------------------------