From 601a8e271020ca1b0918deabf70ad0778ded7d4a Mon Sep 17 00:00:00 2001 From: Eric Lin Date: Tue, 7 Jul 2020 15:57:02 -0400 Subject: external test plugin tests and coverage should now run --- plugins/cmd2_ext_test/CHANGELOG.md | 12 -- plugins/cmd2_ext_test/LICENSE | 21 --- plugins/cmd2_ext_test/README.md | 84 --------- plugins/cmd2_ext_test/build-pyenvs.sh | 53 ------ plugins/cmd2_ext_test/cmd2_ext_test/__init__.py | 15 -- .../cmd2_ext_test/cmd2_ext_test/cmd2_ext_test.py | 62 ------- plugins/cmd2_ext_test/cmd2_ext_test/pylintrc | 10 - plugins/cmd2_ext_test/examples/example.py | 38 ---- plugins/cmd2_ext_test/setup.py | 52 ------ plugins/cmd2_ext_test/tasks.py | 197 -------------------- plugins/cmd2_ext_test/tests/__init__.py | 2 - plugins/cmd2_ext_test/tests/pylintrc | 19 -- plugins/cmd2_ext_test/tests/test_ext_test.py | 70 ------- plugins/ext_test/CHANGELOG.md | 12 ++ plugins/ext_test/LICENSE | 21 +++ plugins/ext_test/README.md | 84 +++++++++ plugins/ext_test/build-pyenvs.sh | 53 ++++++ plugins/ext_test/cmd2_ext_test/__init__.py | 20 ++ plugins/ext_test/cmd2_ext_test/cmd2_ext_test.py | 62 +++++++ plugins/ext_test/cmd2_ext_test/pylintrc | 10 + plugins/ext_test/examples/example.py | 38 ++++ plugins/ext_test/setup.py | 63 +++++++ plugins/ext_test/tasks.py | 203 +++++++++++++++++++++ plugins/ext_test/tests/__init__.py | 2 + plugins/ext_test/tests/pylintrc | 19 ++ plugins/ext_test/tests/test_ext_test.py | 70 +++++++ plugins/tasks.py | 86 +++------ 27 files changed, 686 insertions(+), 692 deletions(-) delete mode 100644 plugins/cmd2_ext_test/CHANGELOG.md delete mode 100644 plugins/cmd2_ext_test/LICENSE delete mode 100644 plugins/cmd2_ext_test/README.md delete mode 100644 plugins/cmd2_ext_test/build-pyenvs.sh delete mode 100644 plugins/cmd2_ext_test/cmd2_ext_test/__init__.py delete mode 100644 plugins/cmd2_ext_test/cmd2_ext_test/cmd2_ext_test.py delete mode 100644 plugins/cmd2_ext_test/cmd2_ext_test/pylintrc delete mode 100644 plugins/cmd2_ext_test/examples/example.py delete mode 100644 plugins/cmd2_ext_test/setup.py delete mode 100644 plugins/cmd2_ext_test/tasks.py delete mode 100644 plugins/cmd2_ext_test/tests/__init__.py delete mode 100644 plugins/cmd2_ext_test/tests/pylintrc delete mode 100644 plugins/cmd2_ext_test/tests/test_ext_test.py create mode 100644 plugins/ext_test/CHANGELOG.md create mode 100644 plugins/ext_test/LICENSE create mode 100644 plugins/ext_test/README.md create mode 100644 plugins/ext_test/build-pyenvs.sh create mode 100644 plugins/ext_test/cmd2_ext_test/__init__.py create mode 100644 plugins/ext_test/cmd2_ext_test/cmd2_ext_test.py create mode 100644 plugins/ext_test/cmd2_ext_test/pylintrc create mode 100644 plugins/ext_test/examples/example.py create mode 100644 plugins/ext_test/setup.py create mode 100644 plugins/ext_test/tasks.py create mode 100644 plugins/ext_test/tests/__init__.py create mode 100644 plugins/ext_test/tests/pylintrc create mode 100644 plugins/ext_test/tests/test_ext_test.py (limited to 'plugins') diff --git a/plugins/cmd2_ext_test/CHANGELOG.md b/plugins/cmd2_ext_test/CHANGELOG.md deleted file mode 100644 index c6eae3f7..00000000 --- a/plugins/cmd2_ext_test/CHANGELOG.md +++ /dev/null @@ -1,12 +0,0 @@ -# Changelog -All notable changes to this project will be documented in this file. - -The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) -and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). - -## 1.0.0 (2020-03-09) - -### Added -- Initial contribution - - diff --git a/plugins/cmd2_ext_test/LICENSE b/plugins/cmd2_ext_test/LICENSE deleted file mode 100644 index b1784d5d..00000000 --- a/plugins/cmd2_ext_test/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2018 Jared Crapo - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/plugins/cmd2_ext_test/README.md b/plugins/cmd2_ext_test/README.md deleted file mode 100644 index 6f8a2b8c..00000000 --- a/plugins/cmd2_ext_test/README.md +++ /dev/null @@ -1,84 +0,0 @@ -# cmd2 External Test Plugin - -## Table of Contents - -- [Overview](#overview) -- [Example cmd2 Application](#example-cmd2-application) -- [Defining the test fixture](#defining-the-test-fixture) -- [Writing Tests](#writing-tests) -- [License](#license) - - -## Overview - -This plugin supports testing of a cmd2 application by exposing access cmd2 commands with the same context -as from within a cmd2 pyscript. This allows for verification of an application's support for pyscripts. - - -## Example cmd2 Application - -The following short example shows how to mix in the external test plugin to create a fixture for testing -your cmd2 application. - -Define your cmd2 application - -```python -import cmd2 -class ExampleApp(cmd2.Cmd): - """An class to show how to use a plugin""" - def __init__(self, *args, **kwargs): - # gotta have this or neither the plugin or cmd2 will initialize - super().__init__(*args, **kwargs) - - def do_something(self, arg): - self.last_result = 5 - self.poutput('this is the something command') -``` - -## Defining the test fixture - -In your test, define a fixture for your cmd2 application - -```python -import cmd2_ext_test -import pytest - -class ExampleAppTester(cmd2_ext_test.ExternalTestMixin, ExampleApp): - def __init__(self, *args, **kwargs): - # gotta have this or neither the plugin or cmd2 will initialize - super().__init__(*args, **kwargs) - -@pytest.fixture -def example_app(): - app = ExampleAppTester() - app.fixture_setup() - yield app - app.fixture_teardown() - -``` - -## Writing Tests - -Now write your tests that validate your application using the `app_cmd` function to access -the cmd2 application's commands. This allows invocation of the application's commands in the -same format as a user would type. The results from calling a command matches what is returned -from running an python script with cmd2's pyscript command, which provides stdout, stderr, and -the command's result data. - -```python -from cmd2 import CommandResult - -def test_something(example_app): - # execute a command - out = example_app.app_cmd("something") - - # validate the command output and result data - assert isinstance(out, CommandResult) - assert str(out.stdout).strip() == 'this is the something command' - assert out.data == 5 -``` - -## License - -cmd2 [uses the very liberal MIT license](https://github.com/python-cmd2/cmd2/blob/master/LICENSE). -We invite plugin authors to consider doing the same. diff --git a/plugins/cmd2_ext_test/build-pyenvs.sh b/plugins/cmd2_ext_test/build-pyenvs.sh deleted file mode 100644 index 39c28aa1..00000000 --- a/plugins/cmd2_ext_test/build-pyenvs.sh +++ /dev/null @@ -1,53 +0,0 @@ -#!/usr/bin/env bash -# - -# create pyenv environments for each minor version of python -# supported by this project -# -# this script uses terms from Semantic Versioning https://semver.org/ -# version numbers are: major.minor.patch -# -# this script will delete and recreate existing virtualenvs named -# cmd2-3.7, etc. It will also create a .python-version -# -# Prerequisites: -# - *nix-ish environment like macOS or Linux -# - pyenv installed -# - pyenv-virtualenv installed -# - readline and openssl libraries installed so pyenv can -# build pythons -# - -# Make a array of the python minor versions we want to install. -# Order matters in this list, because it's the order that the -# virtualenvs will be added to '.python-version'. Feel free to modify -# this list, but note that this script intentionally won't install -# dev, rc, or beta python releases -declare -a pythons=("3.7" "3.6" "3.5" "3.4") - -# function to find the latest patch of a minor version of python -function find_latest_version { - pyenv install -l | \ - sed -En -e "s/^ *//g" -e "/(dev|b|rc)/d" -e "/^$1/p" | \ - tail -1 -} - -# empty out '.python-version' -> .python-version - -# loop through the pythons -for minor_version in "${pythons[@]}" -do - patch_version=$( find_latest_version "$minor_version" ) - # use pyenv to install the latest versions of python - # if it's already installed don't install it again - pyenv install -s "$patch_version" - - envname="cmd2-$minor_version" - # remove the associated virtualenv - pyenv uninstall -f "$envname" - # create a new virtualenv - pyenv virtualenv -p "python$minor_version" "$patch_version" "$envname" - # append the virtualenv to .python-version - echo "$envname" >> .python-version -done diff --git a/plugins/cmd2_ext_test/cmd2_ext_test/__init__.py b/plugins/cmd2_ext_test/cmd2_ext_test/__init__.py deleted file mode 100644 index da3fae9a..00000000 --- a/plugins/cmd2_ext_test/cmd2_ext_test/__init__.py +++ /dev/null @@ -1,15 +0,0 @@ -# -# coding=utf-8 -"""Description of myplugin - -An overview of what myplugin does. -""" - -from pkg_resources import get_distribution, DistributionNotFound - -from .cmd2_ext_test import ExternalTestMixin - -try: - __version__ = get_distribution(__name__).version -except DistributionNotFound: - __version__ = 'unknown' diff --git a/plugins/cmd2_ext_test/cmd2_ext_test/cmd2_ext_test.py b/plugins/cmd2_ext_test/cmd2_ext_test/cmd2_ext_test.py deleted file mode 100644 index 02fd29b1..00000000 --- a/plugins/cmd2_ext_test/cmd2_ext_test/cmd2_ext_test.py +++ /dev/null @@ -1,62 +0,0 @@ -# -# coding=utf-8 -"""External test interface plugin""" - -from typing import Optional - -import cmd2 - - -class ExternalTestMixin: - """A cmd2 plugin (mixin class) that exposes an interface to execute application commands from python""" - - def __init__(self, *args, **kwargs): - """ - - :type self: cmd2.Cmd - :param args: - :param kwargs: - """ - # code placed here runs before cmd2 initializes - super().__init__(*args, **kwargs) - assert isinstance(self, cmd2.Cmd) - # code placed here runs after cmd2 initializes - self._pybridge = cmd2.py_bridge.PyBridge(self) - - def app_cmd(self, command: str, echo: Optional[bool] = None) -> cmd2.CommandResult: - """ - Run the application command - - :param command: The application command as it would be written on the cmd2 application prompt - :param echo: Flag whether the command's output should be echoed to stdout/stderr - :return: A CommandResult object that captures stdout, stderr, and the command's result object - """ - assert isinstance(self, cmd2.Cmd) and isinstance(self, ExternalTestMixin) - try: - self._in_py = True - - return self._pybridge(command, echo=echo) - - finally: - self._in_py = False - - def fixture_setup(self): - """ - Replicates the behavior of `cmdloop()` preparing the state of the application - :type self: cmd2.Cmd - """ - - for func in self._preloop_hooks: - func() - self.preloop() - - def fixture_teardown(self): - """ - Replicates the behavior of `cmdloop()` tearing down the application - - :type self: cmd2.Cmd - """ - # assert isinstance(self, cmd2.Cmd) and isinstance(self, ExternalTestMixin) - for func in self._postloop_hooks: - func() - self.postloop() diff --git a/plugins/cmd2_ext_test/cmd2_ext_test/pylintrc b/plugins/cmd2_ext_test/cmd2_ext_test/pylintrc deleted file mode 100644 index 2f6d3de2..00000000 --- a/plugins/cmd2_ext_test/cmd2_ext_test/pylintrc +++ /dev/null @@ -1,10 +0,0 @@ -# -# pylint configuration -# -# $ pylint --rcfile=cmd2_myplugin/pylintrc cmd2_myplugin -# - -[messages control] -# too-few-public-methods pylint expects a class to have at -# least two public methods -disable=too-few-public-methods diff --git a/plugins/cmd2_ext_test/examples/example.py b/plugins/cmd2_ext_test/examples/example.py deleted file mode 100644 index 649f8627..00000000 --- a/plugins/cmd2_ext_test/examples/example.py +++ /dev/null @@ -1,38 +0,0 @@ -# -# coding=utf-8 -# import cmd2 -import cmd2 -import cmd2_ext_test -import cmd2.py_bridge - - -class Example(cmd2.Cmd): - """An class to show how to use a plugin""" - def __init__(self, *args, **kwargs): - # gotta have this or neither the plugin or cmd2 will initialize - super().__init__(*args, **kwargs) - - def do_something(self, arg): - self.last_result = 5 - self.poutput('this is the something command') - - -class ExampleTester(cmd2_ext_test.ExternalTestMixin, Example): - def __init__(self, *args, **kwargs): - # gotta have this or neither the plugin or cmd2 will initialize - super().__init__(*args, **kwargs) - - -if __name__ == '__main__': - app = ExampleTester() - - try: - app.fixture_setup() - - out = app.app_cmd("something") - assert isinstance(out, cmd2.CommandResult) - - assert out.data == 5 - - finally: - app.fixture_teardown() diff --git a/plugins/cmd2_ext_test/setup.py b/plugins/cmd2_ext_test/setup.py deleted file mode 100644 index cb55c16a..00000000 --- a/plugins/cmd2_ext_test/setup.py +++ /dev/null @@ -1,52 +0,0 @@ -# -# coding=utf-8 - -import os -import setuptools - -# -# get the long description from the README file -here = os.path.abspath(os.path.dirname(__file__)) -with open(os.path.join(here, 'README.md'), encoding='utf-8') as f: - long_description = f.read() - -setuptools.setup( - name='cmd2-ext-test', - use_scm_version=True, - - description='External test plugin for cmd2. Allows for external invocation of commands as if from a cmd2 pyscript', - long_description=long_description, - long_description_content_type='text/markdown', - keywords='cmd2 test plugin', - - author='Eric Lin', - author_email='anselor@gmail.com', - url='https://github.com/python-cmd2/cmd2-ext-test', - license='MIT', - - packages=['cmd2_ext_test'], - - python_requires='>=3.4', - install_requires=['cmd2 >= 0.9.4, <=2'], - setup_requires=['setuptools_scm'], - - classifiers=[ - 'Development Status :: 4 - Beta', - 'Environment :: Console', - 'Operating System :: OS Independent', - 'Topic :: Software Development :: Libraries :: Python Modules', - 'Intended Audience :: Developers', - 'License :: OSI Approved :: MIT License', - 'Programming Language :: Python :: 3.4', - 'Programming Language :: Python :: 3.5', - 'Programming Language :: Python :: 3.6', - 'Programming Language :: Python :: 3.7', - ], - - # dependencies for development and testing - # $ pip install -e .[dev] - extras_require={ - 'dev': ['setuptools_scm', 'pytest', 'codecov', 'pytest-cov', - 'pylint', 'invoke', 'wheel', 'twine'] - }, -) diff --git a/plugins/cmd2_ext_test/tasks.py b/plugins/cmd2_ext_test/tasks.py deleted file mode 100644 index 6bb8d307..00000000 --- a/plugins/cmd2_ext_test/tasks.py +++ /dev/null @@ -1,197 +0,0 @@ -# -# coding=utf-8 -# flake8: noqa E302 -"""Development related tasks to be run with 'invoke'. - -Make sure you satisfy the following Python module requirements if you are trying to publish a release to PyPI: - - twine >= 1.11.0 - - wheel >= 0.31.0 - - setuptools >= 39.1.0 -""" -import os -import pathlib -import re -import shutil -import sys - -import invoke - - -TASK_ROOT = pathlib.Path(__file__).resolve().parent -TASK_ROOT_STR = str(TASK_ROOT) - -# shared function -def rmrf(items, verbose=True): - "Silently remove a list of directories or files" - if isinstance(items, str): - items = [items] - - for item in items: - if verbose: - print("Removing {}".format(item)) - shutil.rmtree(item, ignore_errors=True) - # rmtree doesn't remove bare files - try: - os.remove(item) - except FileNotFoundError: - pass - - -# create namespaces -namespace = invoke.Collection() -namespace_clean = invoke.Collection('clean') -namespace.add_collection(namespace_clean, 'clean') - -##### -# -# pytest, tox, pylint, and codecov -# -##### -@invoke.task -def pytest(context): - "Run tests and code coverage using pytest" - with context.cd(TASK_ROOT_STR): - context.run("pytest --cov=cmd2_ext_test --cov-report=term --cov-report=html", pty=True) -namespace.add_task(pytest) - -@invoke.task -def pytest_junit(context): - "Run tests and code coverage using pytest" - with context.cd(TASK_ROOT_STR): - context.run("pytest --cov --junitxml=junit/test-results.xml", pty=True) -namespace.add_task(pytest_junit) - -@invoke.task -def pytest_clean(context): - "Remove pytest cache and code coverage files and directories" - #pylint: disable=unused-argument - with context.cd(TASK_ROOT_STR): - dirs = ['.pytest_cache', '.cache', 'htmlcov', '.coverage'] - rmrf(dirs) -namespace_clean.add_task(pytest_clean, 'pytest') - -@invoke.task -def mypy(context): - "Run mypy optional static type checker" - with context.cd(TASK_ROOT_STR): - context.run("mypy main.py") - namespace.add_task(mypy) -namespace.add_task(mypy) - -@invoke.task -def mypy_clean(context): - "Remove mypy cache directory" - #pylint: disable=unused-argument - with context.cd(TASK_ROOT_STR): - dirs = ['.mypy_cache', 'dmypy.json', 'dmypy.sock'] - rmrf(dirs) -namespace_clean.add_task(mypy_clean, 'mypy') - - -##### -# -# documentation -# -##### - - -##### -# -# build and distribute -# -##### -BUILDDIR = 'build' -DISTDIR = 'dist' - -@invoke.task -def build_clean(context): - "Remove the build directory" - #pylint: disable=unused-argument - with context.cd(TASK_ROOT_STR): - rmrf(BUILDDIR) - -namespace_clean.add_task(build_clean, 'build') - -@invoke.task -def dist_clean(context): - "Remove the dist directory" - #pylint: disable=unused-argument - with context.cd(TASK_ROOT_STR): - rmrf(DISTDIR) -namespace_clean.add_task(dist_clean, 'dist') - -@invoke.task -def eggs_clean(context): - "Remove egg directories" - #pylint: disable=unused-argument - with context.cd(TASK_ROOT_STR): - dirs = set() - dirs.add('.eggs') - for name in os.listdir(os.curdir): - if name.endswith('.egg-info'): - dirs.add(name) - if name.endswith('.egg'): - dirs.add(name) - rmrf(dirs) -namespace_clean.add_task(eggs_clean, 'eggs') - -@invoke.task -def pycache_clean(context): - "Remove __pycache__ directories" - #pylint: disable=unused-argument - with context.cd(TASK_ROOT_STR): - dirs = set() - for root, dirnames, _ in os.walk(os.curdir): - if '__pycache__' in dirnames: - dirs.add(os.path.join(root, '__pycache__')) - print("Removing __pycache__ directories") - rmrf(dirs, verbose=False) -namespace_clean.add_task(pycache_clean, 'pycache') - -# -# make a dummy clean task which runs all the tasks in the clean namespace -clean_tasks = list(namespace_clean.tasks.values()) -@invoke.task(pre=list(namespace_clean.tasks.values()), default=True) -def clean_all(context): - "Run all clean tasks" - #pylint: disable=unused-argument - pass -namespace_clean.add_task(clean_all, 'all') - - -@invoke.task(pre=[clean_all]) -def sdist(context): - "Create a source distribution" - with context.cd(TASK_ROOT_STR): - context.run('python setup.py sdist') -namespace.add_task(sdist) - -@invoke.task(pre=[clean_all]) -def wheel(context): - "Build a wheel distribution" - with context.cd(TASK_ROOT_STR): - context.run('python setup.py bdist_wheel') -namespace.add_task(wheel) - -@invoke.task(pre=[sdist, wheel]) -def pypi(context): - "Build and upload a distribution to pypi" - with context.cd(TASK_ROOT_STR): - context.run('twine upload dist/*') -namespace.add_task(pypi) - -@invoke.task(pre=[sdist, wheel]) -def pypi_test(context): - "Build and upload a distribution to https://test.pypi.org" - with context.cd(TASK_ROOT_STR): - context.run('twine upload --repository-url https://test.pypi.org/legacy/ dist/*') -namespace.add_task(pypi_test) - - -# Flake8 - linter and tool for style guide enforcement and linting -@invoke.task -def flake8(context): - "Run flake8 linter and tool for style guide enforcement" - with context.cd(TASK_ROOT_STR): - context.run("flake8 --ignore=E252,W503 --max-complexity=26 --max-line-length=127 --show-source --statistics --exclude=.git,__pycache__,.tox,.eggs,*.egg,.venv,.idea,.pytest_cache,.vscode,build,dist,htmlcov") -namespace.add_task(flake8) diff --git a/plugins/cmd2_ext_test/tests/__init__.py b/plugins/cmd2_ext_test/tests/__init__.py deleted file mode 100644 index eb198dc0..00000000 --- a/plugins/cmd2_ext_test/tests/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -# -# empty file to create a package diff --git a/plugins/cmd2_ext_test/tests/pylintrc b/plugins/cmd2_ext_test/tests/pylintrc deleted file mode 100644 index 1dd17c1c..00000000 --- a/plugins/cmd2_ext_test/tests/pylintrc +++ /dev/null @@ -1,19 +0,0 @@ -# -# pylint configuration for tests package -# -# $ pylint --rcfile=tests/pylintrc tests -# - -[basic] -# allow for longer method and function names -method-rgx=(([a-z][a-z0-9_]{2,50})|(_[a-z0-9_]*))$ -function-rgx=(([a-z][a-z0-9_]{2,50})|(_[a-z0-9_]*))$ - -[messages control] -# too-many-public-methods -> test classes can have lots of methods, so let's ignore those -# missing-docstring -> prefer method names instead of docstrings -# no-self-use -> test methods part of a class hardly ever use self -# unused-variable -> sometimes we are expecting exceptions -# redefined-outer-name -> pylint fixtures cause these -# protected-access -> we want to test private methods -disable=too-many-public-methods,missing-docstring,no-self-use,unused-variable,redefined-outer-name,protected-access diff --git a/plugins/cmd2_ext_test/tests/test_ext_test.py b/plugins/cmd2_ext_test/tests/test_ext_test.py deleted file mode 100644 index cf5429b8..00000000 --- a/plugins/cmd2_ext_test/tests/test_ext_test.py +++ /dev/null @@ -1,70 +0,0 @@ -# -# coding=utf-8 - -import pytest - -from cmd2 import cmd2, CommandResult -import cmd2_ext_test - -###### -# -# define a class which implements a simple cmd2 application -# -###### - -OUT_MSG = 'this is the something command' - - -class ExampleApp(cmd2.Cmd): - """An class to show how to use a plugin""" - def __init__(self, *args, **kwargs): - # gotta have this or neither the plugin or cmd2 will initialize - super().__init__(*args, **kwargs) - - def do_something(self, _): - self.last_result = 5 - self.poutput(OUT_MSG) - - -# Define a tester class that brings in the external test mixin - -class ExampleTester(cmd2_ext_test.ExternalTestMixin, ExampleApp): - def __init__(self, *args, **kwargs): - # gotta have this or neither the plugin or cmd2 will initialize - super().__init__(*args, **kwargs) - -# -# You can't use a fixture to instantiate your app if you want to use -# to use the capsys fixture to capture the output. cmd2.Cmd sets -# internal variables to sys.stdout and sys.stderr on initialization -# and then uses those internal variables instead of sys.stdout. It does -# this so you can redirect output from within the app. The capsys fixture -# can't capture the output properly in this scenario. -# -# If you have extensive initialization needs, create a function -# to initialize your cmd2 application. - - -@pytest.fixture -def example_app(): - app = ExampleTester() - app.fixture_setup() - yield app - app.fixture_teardown() - - -##### -# -# unit tests -# -##### - -def test_something(example_app): - # load our fixture - # execute a command - out = example_app.app_cmd("something") - - # validate the command output and result data - assert isinstance(out, CommandResult) - assert str(out.stdout).strip() == OUT_MSG - assert out.data == 5 diff --git a/plugins/ext_test/CHANGELOG.md b/plugins/ext_test/CHANGELOG.md new file mode 100644 index 00000000..c6eae3f7 --- /dev/null +++ b/plugins/ext_test/CHANGELOG.md @@ -0,0 +1,12 @@ +# Changelog +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) +and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). + +## 1.0.0 (2020-03-09) + +### Added +- Initial contribution + + diff --git a/plugins/ext_test/LICENSE b/plugins/ext_test/LICENSE new file mode 100644 index 00000000..b1784d5d --- /dev/null +++ b/plugins/ext_test/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2018 Jared Crapo + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/plugins/ext_test/README.md b/plugins/ext_test/README.md new file mode 100644 index 00000000..6f8a2b8c --- /dev/null +++ b/plugins/ext_test/README.md @@ -0,0 +1,84 @@ +# cmd2 External Test Plugin + +## Table of Contents + +- [Overview](#overview) +- [Example cmd2 Application](#example-cmd2-application) +- [Defining the test fixture](#defining-the-test-fixture) +- [Writing Tests](#writing-tests) +- [License](#license) + + +## Overview + +This plugin supports testing of a cmd2 application by exposing access cmd2 commands with the same context +as from within a cmd2 pyscript. This allows for verification of an application's support for pyscripts. + + +## Example cmd2 Application + +The following short example shows how to mix in the external test plugin to create a fixture for testing +your cmd2 application. + +Define your cmd2 application + +```python +import cmd2 +class ExampleApp(cmd2.Cmd): + """An class to show how to use a plugin""" + def __init__(self, *args, **kwargs): + # gotta have this or neither the plugin or cmd2 will initialize + super().__init__(*args, **kwargs) + + def do_something(self, arg): + self.last_result = 5 + self.poutput('this is the something command') +``` + +## Defining the test fixture + +In your test, define a fixture for your cmd2 application + +```python +import cmd2_ext_test +import pytest + +class ExampleAppTester(cmd2_ext_test.ExternalTestMixin, ExampleApp): + def __init__(self, *args, **kwargs): + # gotta have this or neither the plugin or cmd2 will initialize + super().__init__(*args, **kwargs) + +@pytest.fixture +def example_app(): + app = ExampleAppTester() + app.fixture_setup() + yield app + app.fixture_teardown() + +``` + +## Writing Tests + +Now write your tests that validate your application using the `app_cmd` function to access +the cmd2 application's commands. This allows invocation of the application's commands in the +same format as a user would type. The results from calling a command matches what is returned +from running an python script with cmd2's pyscript command, which provides stdout, stderr, and +the command's result data. + +```python +from cmd2 import CommandResult + +def test_something(example_app): + # execute a command + out = example_app.app_cmd("something") + + # validate the command output and result data + assert isinstance(out, CommandResult) + assert str(out.stdout).strip() == 'this is the something command' + assert out.data == 5 +``` + +## License + +cmd2 [uses the very liberal MIT license](https://github.com/python-cmd2/cmd2/blob/master/LICENSE). +We invite plugin authors to consider doing the same. diff --git a/plugins/ext_test/build-pyenvs.sh b/plugins/ext_test/build-pyenvs.sh new file mode 100644 index 00000000..39c28aa1 --- /dev/null +++ b/plugins/ext_test/build-pyenvs.sh @@ -0,0 +1,53 @@ +#!/usr/bin/env bash +# + +# create pyenv environments for each minor version of python +# supported by this project +# +# this script uses terms from Semantic Versioning https://semver.org/ +# version numbers are: major.minor.patch +# +# this script will delete and recreate existing virtualenvs named +# cmd2-3.7, etc. It will also create a .python-version +# +# Prerequisites: +# - *nix-ish environment like macOS or Linux +# - pyenv installed +# - pyenv-virtualenv installed +# - readline and openssl libraries installed so pyenv can +# build pythons +# + +# Make a array of the python minor versions we want to install. +# Order matters in this list, because it's the order that the +# virtualenvs will be added to '.python-version'. Feel free to modify +# this list, but note that this script intentionally won't install +# dev, rc, or beta python releases +declare -a pythons=("3.7" "3.6" "3.5" "3.4") + +# function to find the latest patch of a minor version of python +function find_latest_version { + pyenv install -l | \ + sed -En -e "s/^ *//g" -e "/(dev|b|rc)/d" -e "/^$1/p" | \ + tail -1 +} + +# empty out '.python-version' +> .python-version + +# loop through the pythons +for minor_version in "${pythons[@]}" +do + patch_version=$( find_latest_version "$minor_version" ) + # use pyenv to install the latest versions of python + # if it's already installed don't install it again + pyenv install -s "$patch_version" + + envname="cmd2-$minor_version" + # remove the associated virtualenv + pyenv uninstall -f "$envname" + # create a new virtualenv + pyenv virtualenv -p "python$minor_version" "$patch_version" "$envname" + # append the virtualenv to .python-version + echo "$envname" >> .python-version +done diff --git a/plugins/ext_test/cmd2_ext_test/__init__.py b/plugins/ext_test/cmd2_ext_test/__init__.py new file mode 100644 index 00000000..50a3f5a5 --- /dev/null +++ b/plugins/ext_test/cmd2_ext_test/__init__.py @@ -0,0 +1,20 @@ +# +# coding=utf-8 +"""Description of myplugin + +An overview of what myplugin does. +""" + +from pkg_resources import get_distribution, DistributionNotFound + +from .cmd2_ext_test import ExternalTestMixin + +__all__ = [ + 'ExternalTestMixin' +] + + +try: + __version__ = get_distribution(__name__).version +except DistributionNotFound: + __version__ = 'unknown' diff --git a/plugins/ext_test/cmd2_ext_test/cmd2_ext_test.py b/plugins/ext_test/cmd2_ext_test/cmd2_ext_test.py new file mode 100644 index 00000000..02fd29b1 --- /dev/null +++ b/plugins/ext_test/cmd2_ext_test/cmd2_ext_test.py @@ -0,0 +1,62 @@ +# +# coding=utf-8 +"""External test interface plugin""" + +from typing import Optional + +import cmd2 + + +class ExternalTestMixin: + """A cmd2 plugin (mixin class) that exposes an interface to execute application commands from python""" + + def __init__(self, *args, **kwargs): + """ + + :type self: cmd2.Cmd + :param args: + :param kwargs: + """ + # code placed here runs before cmd2 initializes + super().__init__(*args, **kwargs) + assert isinstance(self, cmd2.Cmd) + # code placed here runs after cmd2 initializes + self._pybridge = cmd2.py_bridge.PyBridge(self) + + def app_cmd(self, command: str, echo: Optional[bool] = None) -> cmd2.CommandResult: + """ + Run the application command + + :param command: The application command as it would be written on the cmd2 application prompt + :param echo: Flag whether the command's output should be echoed to stdout/stderr + :return: A CommandResult object that captures stdout, stderr, and the command's result object + """ + assert isinstance(self, cmd2.Cmd) and isinstance(self, ExternalTestMixin) + try: + self._in_py = True + + return self._pybridge(command, echo=echo) + + finally: + self._in_py = False + + def fixture_setup(self): + """ + Replicates the behavior of `cmdloop()` preparing the state of the application + :type self: cmd2.Cmd + """ + + for func in self._preloop_hooks: + func() + self.preloop() + + def fixture_teardown(self): + """ + Replicates the behavior of `cmdloop()` tearing down the application + + :type self: cmd2.Cmd + """ + # assert isinstance(self, cmd2.Cmd) and isinstance(self, ExternalTestMixin) + for func in self._postloop_hooks: + func() + self.postloop() diff --git a/plugins/ext_test/cmd2_ext_test/pylintrc b/plugins/ext_test/cmd2_ext_test/pylintrc new file mode 100644 index 00000000..2f6d3de2 --- /dev/null +++ b/plugins/ext_test/cmd2_ext_test/pylintrc @@ -0,0 +1,10 @@ +# +# pylint configuration +# +# $ pylint --rcfile=cmd2_myplugin/pylintrc cmd2_myplugin +# + +[messages control] +# too-few-public-methods pylint expects a class to have at +# least two public methods +disable=too-few-public-methods diff --git a/plugins/ext_test/examples/example.py b/plugins/ext_test/examples/example.py new file mode 100644 index 00000000..649f8627 --- /dev/null +++ b/plugins/ext_test/examples/example.py @@ -0,0 +1,38 @@ +# +# coding=utf-8 +# import cmd2 +import cmd2 +import cmd2_ext_test +import cmd2.py_bridge + + +class Example(cmd2.Cmd): + """An class to show how to use a plugin""" + def __init__(self, *args, **kwargs): + # gotta have this or neither the plugin or cmd2 will initialize + super().__init__(*args, **kwargs) + + def do_something(self, arg): + self.last_result = 5 + self.poutput('this is the something command') + + +class ExampleTester(cmd2_ext_test.ExternalTestMixin, Example): + def __init__(self, *args, **kwargs): + # gotta have this or neither the plugin or cmd2 will initialize + super().__init__(*args, **kwargs) + + +if __name__ == '__main__': + app = ExampleTester() + + try: + app.fixture_setup() + + out = app.app_cmd("something") + assert isinstance(out, cmd2.CommandResult) + + assert out.data == 5 + + finally: + app.fixture_teardown() diff --git a/plugins/ext_test/setup.py b/plugins/ext_test/setup.py new file mode 100644 index 00000000..41d97316 --- /dev/null +++ b/plugins/ext_test/setup.py @@ -0,0 +1,63 @@ +# +# coding=utf-8 + +import os +import setuptools + +# +# get the long description from the README file +here = os.path.abspath(os.path.dirname(__file__)) +with open(os.path.join(here, 'README.md'), encoding='utf-8') as f: + long_description = f.read() + +setuptools.setup( + name='cmd2-ext-test', + version='0.2.0', + # use_scm_version={ + # 'root': '../..', + # 'relative_to': __file__, + # 'git_describe_command': 'git describe --dirty --tags --long --match plugin-ext-test*' + # }, + + description='External test plugin for cmd2. Allows for external invocation of commands as if from a cmd2 pyscript', + long_description=long_description, + long_description_content_type='text/markdown', + keywords='cmd2 test plugin', + + author='Eric Lin', + author_email='anselor@gmail.com', + url='https://github.com/python-cmd2/cmd2-ext-test', + license='MIT', + + packages=['cmd2_ext_test'], + + python_requires='>=3.4', + install_requires=['cmd2 >= 0.9.4, <=2'], + setup_requires=['setuptools_scm >= 3.0'], + + classifiers=[ + 'Development Status :: 4 - Beta', + 'Environment :: Console', + 'Operating System :: OS Independent', + 'Topic :: Software Development :: Libraries :: Python Modules', + 'Intended Audience :: Developers', + 'License :: OSI Approved :: MIT License', + 'Programming Language :: Python :: 3.4', + 'Programming Language :: Python :: 3.5', + 'Programming Language :: Python :: 3.6', + 'Programming Language :: Python :: 3.7', + ], + + # dependencies for development and testing + # $ pip install -e .[dev] + extras_require={ + 'test': [ + 'codecov', + 'coverage', + 'pytest', + 'pytest-cov', + ], + 'dev': ['setuptools_scm', 'pytest', 'codecov', 'pytest-cov', + 'pylint', 'invoke', 'wheel', 'twine'] + }, +) diff --git a/plugins/ext_test/tasks.py b/plugins/ext_test/tasks.py new file mode 100644 index 00000000..2f5955ae --- /dev/null +++ b/plugins/ext_test/tasks.py @@ -0,0 +1,203 @@ +# +# coding=utf-8 +# flake8: noqa E302 +"""Development related tasks to be run with 'invoke'. + +Make sure you satisfy the following Python module requirements if you are trying to publish a release to PyPI: + - twine >= 1.11.0 + - wheel >= 0.31.0 + - setuptools >= 39.1.0 +""" +import os +import pathlib +import shutil + +import invoke + + +TASK_ROOT = pathlib.Path(__file__).resolve().parent +TASK_ROOT_STR = str(TASK_ROOT) + +# shared function +def rmrf(items, verbose=True): + """Silently remove a list of directories or files""" + if isinstance(items, str): + items = [items] + + for item in items: + if verbose: + print("Removing {}".format(item)) + shutil.rmtree(item, ignore_errors=True) + # rmtree doesn't remove bare files + try: + os.remove(item) + except FileNotFoundError: + pass + + +# create namespaces +namespace = invoke.Collection() +namespace_clean = invoke.Collection('clean') +namespace.add_collection(namespace_clean, 'clean') + +##### +# +# pytest, tox, pylint, and codecov +# +##### + + +@invoke.task +def pytest(context, junit=False, pty=True, append_cov=False): + """Run tests and code coverage using pytest""" + ROOT_PATH = TASK_ROOT.parent.parent + + with context.cd(str(ROOT_PATH)): + command_str = 'pytest --cov=cmd2_ext_test --cov-report=term --cov-report=html' + if append_cov: + command_str += ' --cov-append' + if junit: + command_str += ' --junitxml=junit/test-results.xml' + command_str += ' ' + str((TASK_ROOT/'tests').relative_to(ROOT_PATH)) + context.run(command_str, pty=pty) + + +namespace.add_task(pytest) + + +@invoke.task +def pytest_clean(context): + """Remove pytest cache and code coverage files and directories""" + # pylint: disable=unused-argument + with context.cd(TASK_ROOT_STR): + dirs = ['.pytest_cache', '.cache', 'htmlcov', '.coverage'] + rmrf(dirs) + + +namespace_clean.add_task(pytest_clean, 'pytest') + + +@invoke.task +def mypy(context): + """Run mypy optional static type checker""" + with context.cd(TASK_ROOT_STR): + context.run("mypy cmd2_ext_test") + namespace.add_task(mypy) + + +namespace.add_task(mypy) + + +@invoke.task +def mypy_clean(context): + """Remove mypy cache directory""" + # pylint: disable=unused-argument + with context.cd(TASK_ROOT_STR): + dirs = ['.mypy_cache', 'dmypy.json', 'dmypy.sock'] + rmrf(dirs) + + +namespace_clean.add_task(mypy_clean, 'mypy') + + +##### +# +# documentation +# +##### + + +##### +# +# build and distribute +# +##### +BUILDDIR = 'build' +DISTDIR = 'dist' + + +@invoke.task +def build_clean(context): + """Remove the build directory""" + # pylint: disable=unused-argument + with context.cd(TASK_ROOT_STR): + rmrf(BUILDDIR) + + +namespace_clean.add_task(build_clean, 'build') + + +@invoke.task +def dist_clean(context): + """Remove the dist directory""" + # pylint: disable=unused-argument + with context.cd(TASK_ROOT_STR): + rmrf(DISTDIR) + + +namespace_clean.add_task(dist_clean, 'dist') + + +# +# make a dummy clean task which runs all the tasks in the clean namespace +clean_tasks = list(namespace_clean.tasks.values()) +@invoke.task(pre=list(namespace_clean.tasks.values()), default=True) +def clean_all(context): + """Run all clean tasks""" + # pylint: disable=unused-argument + pass + + +namespace_clean.add_task(clean_all, 'all') + + +@invoke.task(pre=[clean_all]) +def sdist(context): + """Create a source distribution""" + with context.cd(TASK_ROOT_STR): + context.run('python setup.py sdist') + + +namespace.add_task(sdist) + + +@invoke.task(pre=[clean_all]) +def wheel(context): + """Build a wheel distribution""" + with context.cd(TASK_ROOT_STR): + context.run('python setup.py bdist_wheel') + + +namespace.add_task(wheel) + + +@invoke.task(pre=[sdist, wheel]) +def pypi(context): + """Build and upload a distribution to pypi""" + with context.cd(TASK_ROOT_STR): + context.run('twine upload dist/*') + + +namespace.add_task(pypi) + + +@invoke.task(pre=[sdist, wheel]) +def pypi_test(context): + """Build and upload a distribution to https://test.pypi.org""" + with context.cd(TASK_ROOT_STR): + context.run('twine upload --repository-url https://test.pypi.org/legacy/ dist/*') + + +namespace.add_task(pypi_test) + + +# Flake8 - linter and tool for style guide enforcement and linting +@invoke.task +def flake8(context): + """Run flake8 linter and tool for style guide enforcement""" + with context.cd(TASK_ROOT_STR): + context.run("flake8 --ignore=E252,W503 --max-complexity=26 --max-line-length=127 --show-source --statistics " + "--exclude=.git,__pycache__,.tox,.nox,.eggs,*.egg,.venv,.idea,.pytest_cache,.vscode,build,dist,htmlcov") + + +namespace.add_task(flake8) diff --git a/plugins/ext_test/tests/__init__.py b/plugins/ext_test/tests/__init__.py new file mode 100644 index 00000000..eb198dc0 --- /dev/null +++ b/plugins/ext_test/tests/__init__.py @@ -0,0 +1,2 @@ +# +# empty file to create a package diff --git a/plugins/ext_test/tests/pylintrc b/plugins/ext_test/tests/pylintrc new file mode 100644 index 00000000..1dd17c1c --- /dev/null +++ b/plugins/ext_test/tests/pylintrc @@ -0,0 +1,19 @@ +# +# pylint configuration for tests package +# +# $ pylint --rcfile=tests/pylintrc tests +# + +[basic] +# allow for longer method and function names +method-rgx=(([a-z][a-z0-9_]{2,50})|(_[a-z0-9_]*))$ +function-rgx=(([a-z][a-z0-9_]{2,50})|(_[a-z0-9_]*))$ + +[messages control] +# too-many-public-methods -> test classes can have lots of methods, so let's ignore those +# missing-docstring -> prefer method names instead of docstrings +# no-self-use -> test methods part of a class hardly ever use self +# unused-variable -> sometimes we are expecting exceptions +# redefined-outer-name -> pylint fixtures cause these +# protected-access -> we want to test private methods +disable=too-many-public-methods,missing-docstring,no-self-use,unused-variable,redefined-outer-name,protected-access diff --git a/plugins/ext_test/tests/test_ext_test.py b/plugins/ext_test/tests/test_ext_test.py new file mode 100644 index 00000000..cf5429b8 --- /dev/null +++ b/plugins/ext_test/tests/test_ext_test.py @@ -0,0 +1,70 @@ +# +# coding=utf-8 + +import pytest + +from cmd2 import cmd2, CommandResult +import cmd2_ext_test + +###### +# +# define a class which implements a simple cmd2 application +# +###### + +OUT_MSG = 'this is the something command' + + +class ExampleApp(cmd2.Cmd): + """An class to show how to use a plugin""" + def __init__(self, *args, **kwargs): + # gotta have this or neither the plugin or cmd2 will initialize + super().__init__(*args, **kwargs) + + def do_something(self, _): + self.last_result = 5 + self.poutput(OUT_MSG) + + +# Define a tester class that brings in the external test mixin + +class ExampleTester(cmd2_ext_test.ExternalTestMixin, ExampleApp): + def __init__(self, *args, **kwargs): + # gotta have this or neither the plugin or cmd2 will initialize + super().__init__(*args, **kwargs) + +# +# You can't use a fixture to instantiate your app if you want to use +# to use the capsys fixture to capture the output. cmd2.Cmd sets +# internal variables to sys.stdout and sys.stderr on initialization +# and then uses those internal variables instead of sys.stdout. It does +# this so you can redirect output from within the app. The capsys fixture +# can't capture the output properly in this scenario. +# +# If you have extensive initialization needs, create a function +# to initialize your cmd2 application. + + +@pytest.fixture +def example_app(): + app = ExampleTester() + app.fixture_setup() + yield app + app.fixture_teardown() + + +##### +# +# unit tests +# +##### + +def test_something(example_app): + # load our fixture + # execute a command + out = example_app.app_cmd("something") + + # validate the command output and result data + assert isinstance(out, CommandResult) + assert str(out.stdout).strip() == OUT_MSG + assert out.data == 5 diff --git a/plugins/tasks.py b/plugins/tasks.py index 4aac4f77..7edcc08d 100644 --- a/plugins/tasks.py +++ b/plugins/tasks.py @@ -14,7 +14,7 @@ import shutil import sys import invoke -from plugins.cmd2_ext_test import tasks as ext_test_tasks +from plugins.ext_test import tasks as ext_test_tasks # create namespaces namespace = invoke.Collection() @@ -26,22 +26,19 @@ namespace.add_collection(namespace_clean, 'clean') # pytest, tox, pylint, and codecov # ##### -@invoke.task(pre=[ext_test_tasks.pytest]) -def pytest(_): - """Run tests and code coverage using pytest""" - pass - - -namespace.add_task(pytest) -@invoke.task(pre=[ext_test_tasks.pytest_junit]) -def pytest_junit(_): +@invoke.task() +def pytest(_, junit=False, pty=True): """Run tests and code coverage using pytest""" - pass + iexec = invoke.Executor([]) + iexec.execute([ + invoke.call(ext_test_tasks.pytest, junit=junit, pty=pty, append_cov=True) + ]) -namespace.add_task(pytest_junit) + +namespace.add_task(pytest) @invoke.task(pre=[ext_test_tasks.pytest_clean]) @@ -54,17 +51,18 @@ namespace_clean.add_task(pytest_clean, 'pytest') @invoke.task(pre=[ext_test_tasks.mypy]) -def mypy(context): +def mypy(_): """Run mypy optional static type checker""" pass namespace.add_task(mypy) + @invoke.task(pre=[ext_test_tasks.mypy_clean]) -def mypy_clean(context): +def mypy_clean(_): """Remove mypy cache directory""" - #pylint: disable=unused-argument + # pylint: disable=unused-argument pass @@ -79,9 +77,11 @@ namespace_clean.add_task(mypy_clean, 'mypy') BUILDDIR = 'build' DISTDIR = 'dist' + @invoke.task(pre=[ext_test_tasks.build_clean]) def build_clean(_): """Remove the build directory""" + pass namespace_clean.add_task(build_clean, 'build') @@ -96,32 +96,14 @@ def dist_clean(_): namespace_clean.add_task(dist_clean, 'dist') -@invoke.task(pre=[ext_test_tasks.eggs_clean]) -def eggs_clean(context): - """Remove egg directories""" - pass - - -namespace_clean.add_task(eggs_clean, 'eggs') - - -@invoke.task(pre=[ext_test_tasks.pycache_clean]) -def pycache_clean(context): - """Remove __pycache__ directories""" - pass - - -namespace_clean.add_task(pycache_clean, 'pycache') - - # make a dummy clean task which runs all the tasks in the clean namespace clean_tasks = list(namespace_clean.tasks.values()) @invoke.task(pre=list(namespace_clean.tasks.values()), default=True) -def clean_all(context): +def clean_all(_): """Run all clean tasks""" - #pylint: disable=unused-argument + # pylint: disable=unused-argument pass @@ -129,38 +111,28 @@ namespace_clean.add_task(clean_all, 'all') @invoke.task(pre=[clean_all], post=[ext_test_tasks.sdist]) -def sdist(context): - "Create a source distribution" - context.run('python setup.py sdist') +def sdist(_): + """Create a source distribution""" + pass namespace.add_task(sdist) @invoke.task(pre=[clean_all], post=[ext_test_tasks.wheel]) -def wheel(context): - "Build a wheel distribution" - context.run('python setup.py bdist_wheel') -namespace.add_task(wheel) - - -@invoke.task(pre=[sdist, wheel]) -def pypi(context): - "Build and upload a distribution to pypi" - context.run('twine upload dist/*') -namespace.add_task(pypi) +def wheel(_): + """Build a wheel distribution""" + pass -@invoke.task(pre=[sdist, wheel]) -def pypi_test(context): - "Build and upload a distribution to https://test.pypi.org" - context.run('twine upload --repository-url https://test.pypi.org/legacy/ dist/*') -namespace.add_task(pypi_test) +namespace.add_task(wheel) # Flake8 - linter and tool for style guide enforcement and linting @invoke.task(pre=[ext_test_tasks.flake8]) -def flake8(context): - "Run flake8 linter and tool for style guide enforcement" - context.run("flake8 --ignore=E252,W503 --max-complexity=26 --max-line-length=127 --show-source --statistics --exclude=.git,__pycache__,.tox,.eggs,*.egg,.venv,.idea,.pytest_cache,.vscode,build,dist,htmlcov") +def flake8(_): + """Run flake8 linter and tool for style guide enforcement""" + pass + + namespace.add_task(flake8) -- cgit v1.2.1