diff --git a/poetry.lock b/poetry.lock index 2bccf3e..63a87e6 100644 --- a/poetry.lock +++ b/poetry.lock @@ -145,6 +145,21 @@ wcwidth = ">=0.1.7" dev = ["pytest (>=4.6)", "codecov", "pytest-cov", "pytest-mock", "flake8", "sphinx", "sphinx-rtd-theme", "sphinx-autobuild", "doc8", "invoke", "twine (>=1.11)", "mock", "nox (==2019.11.9)", "nox"] test = ["codecov", "coverage", "pytest (>=4.6)", "pytest-cov", "pytest-mock", "mock", "gnureadline"] +[[package]] +name = "cmd2-ext-test" +version = "0.2.0" +description = "External test plugin for cmd2. Allows for external invocation of commands as if from a cmd2 pyscript" +category = "dev" +optional = false +python-versions = ">=3.5" + +[package.dependencies] +cmd2 = ">=0.9.4,<=2" + +[package.extras] +dev = ["codecov", "invoke", "pylint", "pytest", "pytest-cov", "setuptools-scm", "twine", "wheel"] +test = ["codecov", "coverage", "pytest", "pytest-cov"] + [[package]] name = "colorama" version = "0.4.4" @@ -1362,7 +1377,7 @@ postgres = ["psycopg2-binary"] [metadata] lock-version = "1.1" python-versions = ">=3.7,<4.0.0" -content-hash = "8d8786dc29411ab6dabaeeb1105cd3a1c96c5549dedb9e7c00acd840c26095d4" +content-hash = "3e215321bf862597e821a9949122dc5c5e2b1f88a0fc2ffcc7eb2f833c37f39e" [metadata.files] appdirs = [ @@ -1457,6 +1472,10 @@ cmd2 = [ {file = "cmd2-1.5.0-py3-none-any.whl", hash = "sha256:31aaeb590ec7bd2cc2cee0172099cc6f0a1396f82ab7bc389dbff23d9b90f6ec"}, {file = "cmd2-1.5.0.tar.gz", hash = "sha256:701a8c9975c4abc45e5d13906ab149f959f812869106347323a3f89ac0e82a62"}, ] +cmd2-ext-test = [ + {file = "cmd2-ext-test-0.2.0.tar.gz", hash = "sha256:76c66fa914b9fdf9f5e9b4adb81783ffca925dc223dd40e8cb7bc01d13c49c47"}, + {file = "cmd2_ext_test-0.2.0-py3-none-any.whl", hash = "sha256:20593396e6b67f1342e8498f61548712bcf6d5d4b03fb3acc2f00b2c15b001b0"}, +] colorama = [ {file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"}, {file = "colorama-0.4.4.tar.gz", hash = "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b"}, diff --git a/pyproject.toml b/pyproject.toml index b65bfca..68d57dd 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -64,6 +64,7 @@ postgres = ["psycopg2-binary"] dev_shell = ">=0.2.2" # https://github.com/jedie/dev-shell poetry-publish = "*" # https://github.com/jedie/poetry-publish python-creole = "*" # https://github.com/jedie/python-creole +cmd2_ext_test = "*" tox = "*" pytest = "*" pytest-randomly = "*" diff --git a/src/inventory_project/dev_shell.py b/src/inventory_project/dev_shell.py index 2bd8bc3..401ffd8 100644 --- a/src/inventory_project/dev_shell.py +++ b/src/inventory_project/dev_shell.py @@ -1,3 +1,4 @@ +import os import sys from pathlib import Path @@ -9,18 +10,44 @@ from dev_shell.command_sets.dev_shell_commands import DevShellCommandSet as Orig from dev_shell.command_sets.dev_shell_commands import run_linters from dev_shell.config import DevShellConfig from dev_shell.utils.assertion import assert_is_dir -from dev_shell.utils.subprocess_utils import verbose_check_call +from dev_shell.utils.colorful import blue, bright_yellow, print_error +from dev_shell.utils.subprocess_utils import argv2str, verbose_check_call from poetry_publish.publish import poetry_publish import inventory +from inventory_project.manage import main PACKAGE_ROOT = Path(inventory.__file__).parent.parent.parent assert_is_dir(PACKAGE_ROOT / 'src' / 'inventory') +class TempCwd: + def __init__(self, cwd: Path): + assert_is_dir(cwd) + self.cwd = cwd + + def __enter__(self): + self.old_cwd = Path().cwd() + os.chdir(self.cwd) + + def __exit__(self, exc_type, exc_val, exc_tb): + os.chdir(self.old_cwd) + + def call_manage_py(*args): - verbose_check_call('python3', '-m', 'inventory_project.manage.main', *args) + print() + print('_' * 100) + print(f'+ src$ {bright_yellow("manage")} {blue(argv2str(args))}') + args = list(args) + args.insert(0, 'manage.py') # Needed for argparse! + with TempCwd(PACKAGE_ROOT / 'src'): + try: + main(argv=args) + except SystemExit as err: + print_error(f'finished with exit code {err}') + except BaseException as err: + print_error(err) @cmd2.with_default_category('PyInventory commands') @@ -46,12 +73,14 @@ class PyInventoryCommandSet(DevShellBaseCommandSet): call_manage_py( 'makemessages', '--all', - '--no-location', '--no-obsolete', - '--ignore=htmlcov', '--ignore=.*' + '--no-location', + '--no-obsolete', + '--ignore=.*', + '--ignore=htmlcov', + '--ignore=volumes', ) call_manage_py( 'compilemessages', - '--ignore=htmlcov', '--ignore=.*' ) def do_update_rst_readme(self, statement: cmd2.Statement): diff --git a/src/inventory_project/manage.py b/src/inventory_project/manage.py index 32e9635..79dda51 100644 --- a/src/inventory_project/manage.py +++ b/src/inventory_project/manage.py @@ -12,10 +12,10 @@ from inventory import __version__ BASE_PATH = Path(inventory.__file__).parent -def main(): +def main(argv): os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'inventory_project.settings.local') - if '--version' not in sys.argv: + if '--version' not in argv: print(f'PyInventory v{__version__} (Django v{django_version})', file=sys.stderr) print(f'DJANGO_SETTINGS_MODULE={os.environ["DJANGO_SETTINGS_MODULE"]!r}', file=sys.stderr) @@ -28,7 +28,7 @@ def main(): 'forget to activate a virtual environment?' ) from exc try: - execute_from_command_line(sys.argv) + execute_from_command_line(argv) except Exception as err: from bx_py_utils.error_handling import print_exc_plus print_exc_plus(err) @@ -39,9 +39,8 @@ def start_test_server(): """ Entrypoint for "[tool.poetry.scripts]" script started by devshell command. """ - sys.argv = [__file__, "run_testserver"] - main() + main(argv=[__file__, "run_testserver"]) if __name__ == '__main__': - main() + main(argv=sys.argv) diff --git a/src/inventory_project/tests/test_inventory_commands.py b/src/inventory_project/tests/test_inventory_commands.py new file mode 100644 index 0000000..ff97b36 --- /dev/null +++ b/src/inventory_project/tests/test_inventory_commands.py @@ -0,0 +1,43 @@ +from cmd2 import CommandResult +from cmd2_ext_test import ExternalTestMixin +from dev_shell.tests.fixtures import CmdAppBaseTestCase +from django import __version__ + +from inventory_project.dev_shell import DevShellApp, get_devshell_app_kwargs + + +class DevShellAppTester(ExternalTestMixin, DevShellApp): + pass + + +class DevShellAppBaseTestCase(CmdAppBaseTestCase): + """ + Base class for dev-shell tests + """ + + def get_app_instance(self): + # Init the test app with the same kwargs as the real app + # see: dev_shell.cmd2app.devshell_cmdloop() + app = DevShellAppTester(**get_devshell_app_kwargs()) + return app + + +class PyInventoryDevShellTestCase(DevShellAppBaseTestCase): + def test_help_raw(self): + out = self.app.app_cmd('help') + + assert isinstance(out, CommandResult) + assert 'Documented commands' in out.stdout + + assert 'Documented commands' in out.stdout + + def test_help_via_execute(self): + stdout, stderr = self.execute('help') + assert stderr == '' + assert 'Documented commands' in stdout + + def test_manage(self): + stdout, stderr = self.execute('manage --version') + assert stderr == '' + assert 'manage --version' in stdout + assert __version__ in stdout