boromir674/so-magic

View on GitHub
tox-dev.ini

Summary

Maintainability
Test Coverage
[tox]
skip_missing_interpreters = true
requires =
    tox >= 3.20.0


[testenv]
basepython = {spell,clean,report,codecov,graphs,quickstart,apidoc,deploy,check,uml}: {env:TOXPYTHON:python3}
passenv =
    *
    # See https://github.com/codecov/codecov-python/blob/5b9d539a6a09bc84501b381b563956295478651a/README.md#using-tox
    codecov: TOXENV
    codecov: CI
    codecov: TRAVIS TRAVIS_*
setenv =
    PYTHONPATH={toxinidir}/tests
    PYTHOUNBUFFERED=yes
    PIP_DISABLE_PIP_VERSION_CHECK=1
    VIRTUALENV_NO_DOWNLOAD=0
    DOCS_BUILD_LOCATION=dist/docs
deps =
    setuptools >= 40.0.0
    -rrequirements/docs.txt
skip_install = true


## DOCUMENTATION OPERATIONS

[testenv:apidoc]
description = Populate rst files with directives to process docstrings. To force re-creation of
    files that already exist, you can use the -f flag; eg command: tox -c tox-dev.ini -e apidocs -- -f. To override the
    default filename 'modules', of the table of contents, you can use the --tocfile flag (takes 1 argument); eg command:
    tox -c tox-dev.ini -e apidoc -v -- --tocfile my_contents_filename
commands = sphinx-apidoc -o docs src/so_magic {posargs}


[testenv:spell]
description = Check the documentation spelling. Checks spelling both for the .rst files in 'docs' directory and for the
    code docstrings. Writes the errors in separate .spelling files, in the {env:DOCS_BUILD_LOCATION:dist/docs}
    directory. Requires as external dependency the "pyenchant C library", which you should install manually (eg
    command on Linux: sudo apt install python-pyenchant).
setenv =
    {[testenv]setenv}
    SPELLCHECK=1
deps =
    {[testenv]deps}
    pyenchant
commands = sphinx-build -E -b spelling docs {env:DOCS_BUILD_LOCATION:dist/docs}

## PACKAGING

[testenv:check]
description = Check the code for compliance with best practises of Python packaging ecosystem (PyPI, pip, Distribute, etc).
deps =
    docutils
    readme-renderer
    pygments
    check-manifest
    pyroma
commands =
    check-manifest
    pyroma -d {toxinidir}


[testenv:build]
description = Create/build the python package/distribution.
    Creates .tar.gz and .whl files in the dist folder, that can be upload to a pypi index server.
basepython = {env:TOXPYTHON:python3}
deps =
    setuptools >= 40.0.0
commands_pre =
    python -c 'import os; import shutil; exec("if os.path.exists(os.path.join(\"{toxinidir}\", \"dist\")):\n    shutil.rmtree(os.path.join(\"{toxinidir}\", \"dist\"))")'
commands =
    python setup.py sdist bdist_wheel
; commands_post =
;     twine check dist/so-magic-*.tar.gz
;     twine check dist/so_magic-*.whl


############## DEPLOY ##############

# usage 1
# deploy to testpypi while ignoring collisions (case where the version already exists on remote)
# python -m tox -c tox-dev.ini -e deploy

# usage 2
# deploy to pypi
# PYPI_SERVER=pypi python -m tox -c tox-dev.ini -e deploy

[testenv:deploy]
description = Deploy the python package to be hosted in a pypi server. Requires the SO_MAGIC_RELEASE_VERSION
    environment variable to contain the string that represents the semantic version (eg 0.5.3 or 1.0.0) under which
    to release the so_magic package to pypi. By default, deploys to the official test-pypi server.
    If you want to deploy to the "production" pypi then you have to set the PYPI_SERVER environment
    variable like `export PYPI_SERVER=pypi`. Also runs certain checks on the packaged distribution (.tar.gz and .whl)
deps =
    keyring==21.3.0
    twine==3.4.0
commands_pre =
    python -m twine check dist/so[\-_]magic-{env:SO_MAGIC_RELEASE_VERSION:PLEASE_INDICATE_THE_SEM_VER_FOR_RELEASE}*
commands =
    python -m twine {posargs:upload --non-interactive} --repository {env:PYPI_SERVER:testpypi --skip-existing} dist/so[\-_]magic-{env:SO_MAGIC_RELEASE_VERSION:PLEASE_INDICATE_THE_SEM_VER_FOR_RELEASE}* --verbose


## COVERAGE
[testenv:clean]
description = Clean the working directory from any previously computed code coverage results.
    Removes any data resulted from measuring code coverage. Useful before running the test suite
    with code coverage enabled.
deps = coverage
commands = coverage erase

[testenv:report]
description = Show the most recently computed codecoverage results.
deps = coverage
commands = {posargs:coverage report}

[testenv:format-report]
description = Generate xml and html formatted files out of previously computed code coverage results.
deps = coverage
commands =
    coverage xml
    coverage html


## CODECOV
[testenv:codecov]
description = Send code coverage data to codecov.io
passenv = TOXENV CI TRAVIS TRAVIS_* CODECOV_*
deps = codecov
commands = codecov


## STATIC ANALYSIS OF CODE

[testenv:prospector]
description = Analyse Python code and output information about errors, potential problems, convention violations and complexity.
    Runs the prospector tool which brings together the functionality of other Python analysis tools such as Pyflakes and McCabe complexity.
    We run tools: Pyflakes, Pyroma, McCabe and Dodgy
basepython = {env:TOXPYTHON:python3.6}
deps = prospector[with_pyroma]
commands_pre =
    # We do not run pylint, since we have a dedicated pylint env for it.
    # Prospector still tries to read .pylintrc, which causes a crash (bevause .pylintrc was generated with a pylint version higher than the one supported by prospector)
    # So we temporarily "hide" .pylintrc from prospector
    python -c 'import os; exec("if os.path.exists(os.path.join(\"{toxinidir}\", \".pylintrc\")):\n    os.rename(os.path.join(\"{toxinidir}\", \".pylintrc\"), os.path.join(\"{toxinidir}\", \".pylintrc-bak\"))")'
commands =
    prospector
    ; prospector {posargs: -t pyflakes -t pyroma -t mccabe -t dodgy -s medium --max-line-length 120 -T -A}
commands_post =
    # We "restore" .pylintrc (to be available to the pylint env command)
    python -c 'import os; exec("if os.path.exists(os.path.join(\"{toxinidir}\", \".pylintrc-bak\")):\n    os.rename(os.path.join(\"{toxinidir}\", \".pylintrc-bak\"), os.path.join(\"{toxinidir}\", \".pylintrc\"))")'

[testenv:pylint]
description = Run the Pylint tool to analyse the Python code and output information about errors,
    potential problems and convention violations
basepython = {env:TOXPYTHON:python3.8}
deps =
    attrs
    pandas
    numpy
    scikit-learn
    pylint==2.7.4
skip_install = false
use_develop = true
commands = python -m pylint {posargs:{toxinidir}/src/so_magic}


## GENERATE ARCHITECTURE GRAPHS

[testenv:graphs]
description = Visualise the dependency graphs (roughly which module imports which), by examining the
    Python code. The dependency graph(s) are rendered in .svg file(s) and saved on the disk. You can
    use the SO_MAGIC_DEPS_GRAPHS environment variable to determine the directory location to store the visualisation(s). If
    the variable is not supplied then the default folder 'so-magic-dependency-graphs', inside the project's root folder, is used. If the directory does not exist it gets created.
    Requires that the 'dot' executable is in your PATH. Installing the graphviz library should make the dot executable available
    in PATH. Installing 'graphviz':
    * For Linux users using Debian-based distributions (ie Ubuntu, Debian, Mint), please run "sudo apt install graphviz"
    * For MacOS users Homebrew, please run "brew install graphviz"
basepython = {env:TOXPYTHON:python3.8}
passenv =
    HOME
    SO_MAGIC_DEPS_GRAPHS
setenv =
    {[testenv]setenv}
    DEPS_DEFAULT_LOCATION = so-magic-dependency-graphs
deps =
    attrs
    pandas
    numpy
    scikit-learn
    pydeps==1.9.13
skip_install = false
use_develop = true
commands_pre =
    - python -c 'import os; my_dir = os.getcwd(); os.mkdir(os.path.join(my_dir, "{env:SO_MAGIC_DEPS_GRAPHS:{env:DEPS_DEFAULT_LOCATION}}"))'
commands =
    pydeps --version

    # --max-bacon : exclude nodes that are more than n hops away
    # (default=2, 0 -> infinite)

    # --min-cluster-size : the minimum number of nodes a dependency must have before being clustered (default=0)

    # --max-cluster-size : the maximum number of nodes a dependency can have before the cluster is collapsed to a single node (default=0)
    # --keep-target-cluster : draw target module as a cluster

    # Draw only the source code package inner dependencies
    pydeps src/so_magic --only so_magic --noshow -o {env:SO_MAGIC_DEPS_GRAPHS:{env:DEPS_DEFAULT_LOCATION}}/so_magic_inner_deps.svg
    # Draw the source code package inner and external dependencies
    pydeps src/so_magic --cluster --noshow -o {env:SO_MAGIC_DEPS_GRAPHS:{env:DEPS_DEFAULT_LOCATION}}/so_magic_deps.svg

    # Visualize the package inner dependencies and abstract the external (eg with numpy, pandas, etc) ones
    # Draw the source code package inner and minimum external dependencies
    pydeps src/so_magic --max-cluster-size=2 --keep-target-cluster --noshow -o {env:SO_MAGIC_DEPS_GRAPHS:{env:DEPS_DEFAULT_LOCATION}}/so_magic_target_cluster_deps_one_arrow.svg

    # Draw the source code package inner and all external dependencies
    pydeps src/so_magic --keep-target-cluster --noshow -o {env:SO_MAGIC_DEPS_GRAPHS:{env:DEPS_DEFAULT_LOCATION}}/so_magic_target_cluster_deps_all_arrows.svg

    # increasing max-bacon reveales the dependencies of the dependencies..
    ; pydeps src/so_magic --max-bacon=8 --max-cluster-size=2 --keep-target-cluster --noshow -o {env:SO_MAGIC_DEPS_GRAPHS:{env:DEPS_DEFAULT_LOCATION}}/so_magic-n4.svg

    # increasing max-cluster-size reveales more modules inside the external dependencies and their dependencies..
    ; pydeps src/so_magic --max-bacon=8 --max-cluster-size=5 --keep-target-cluster --noshow -o {env:SO_MAGIC_DEPS_GRAPHS:{env:DEPS_DEFAULT_LOCATION}}/so_magic-n5.svg

    python -c 'import os; my_dir = os.getcwd(); print("\nGenerated dependency graph(s), as .svg files."); print("The graph(s) reside in the \"" + os.path.join(my_dir, "{env:SO_MAGIC_DEPS_GRAPHS:{env:DEPS_DEFAULT_LOCATION}}") + "\" directory and you can now view them ie in your browser.\n")'


[testenv:uml]
description = Generate UML (class and package) diagrams by inspecting the code. The diagrams are stored in the
    $SO_MAGIC_UML_DIAGRAMS dir. Runs the pyreverse tool to parse the code and generate the files. This is a pretty legacy tool currently integrated in pylint (not available through pip).
setenv =
    {[testenv]setenv}
    # include dirs to pythonpath to solve issue of inspect lib failing with for some relative imports
    PYTHONPATH={toxinidir}/src/so_magic:{toxinidir}/src/so_magic/data
    SO_MAGIC_UML_DIAGRAMS=uml-diagrams
deps =
    attrs
    pandas
    numpy
    scikit-learn
    pylint==2.7.4
skip_install = false
use_develop = true
commands_pre =
    - python -c 'import os; my_dir = os.getcwd(); os.mkdir(os.path.join(my_dir, "{env:SO_MAGIC_UML_DIAGRAMS}"))'
commands =
    python -c 'import sys; print(sys.path)'
    # so_magic.utils
    pyreverse -o {posargs:png} -A -p utils src/so_magic/utils

    # so_magic.som
    pyreverse -o {posargs:png} -A -p som src/so_magic/som

    # so_magic.data.datapoints
    pyreverse -o {posargs:png} -A -p data.datapoints src/so_magic/data/datapoints
    # so_magic.data.features
    pyreverse -o {posargs:png} -A -p data.features src/so_magic/data/features
    # so_magic.data.backend
    pyreverse -o {posargs:png} -A -p data.backend src/so_magic/data/backend
    pyreverse -o {posargs:png} -k -A -p data.backend-only-class-names src/so_magic/data/backend
    # so_magic.data.variables
    pyreverse -o {posargs:png} -A -p data.variables src/so_magic/data/variables

    # so_magic.data
    pyreverse -o {posargs:png} -A -p data src/so_magic/data
    pyreverse -o {posargs:png} -k -A -p data-only-class-names src/so_magic/data

    # so_magic
    pyreverse -o {posargs:png} -A -p so_magic src/so_magic
    pyreverse -o {posargs:png} -k -A -p so_magic-only-class-names src/so_magic

    # so_magic.so_master
    pyreverse -o {posargs:png} -A -p so_magic.so_master src/so_magic/so_master.py

    pyreverse -o {posargs:png} -A -p data.data_manager src/so_magic/data/data_manager.py
    pyreverse -o {posargs:png} -A -p data.magic_datapoints_factory src/so_magic/data/magic_datapoints_factory.py

    # MOVE uml diagram files manually into $SO_MAGIC_UML_DIAGRAMS directory (the pyreverse -p flag does not fully work when invoked with tox)
    python -c 'import shutil, glob; uml_diagrams = glob.glob("classes_*.{posargs:png}", recursive=False); print(uml_diagrams); exec("for file in uml_diagrams:\n    shutil.move(file, \"{env:SO_MAGIC_UML_DIAGRAMS}\")")'
    python -c 'import shutil, glob; uml_diagrams = glob.glob("packages_*.{posargs:png}", recursive=False); print(uml_diagrams); exec("for file in uml_diagrams:\n    shutil.move(file, \"{env:SO_MAGIC_UML_DIAGRAMS}\")")'

    # PRINT message
    python -c 'import os; my_dir = os.getcwd(); print("\nGenerated uml diagram(s), as svg/png files."); print("The diagram(s) reside in the \"" + os.path.join(my_dir, "{env:SO_MAGIC_UML_DIAGRAMS}") + "\" directory.\n")'