From 93ac9d270d1aac5d112d4930142b1ff12c58042e Mon Sep 17 00:00:00 2001 From: Mateusz Masiarz Date: Fri, 8 Mar 2024 23:22:35 +0100 Subject: [PATCH] Command chaining (#211) * Allow chaining of commands * Add tests * Update readme --- README.md | 6 +++++ src/sinol_make/__init__.py | 38 +++++++++++++++++++++++--------- src/sinol_make/util.py | 14 ++++++++++++ tests/test_multiple_arguments.py | 31 ++++++++++++++++++++++++++ 4 files changed, 78 insertions(+), 11 deletions(-) create mode 100644 tests/test_multiple_arguments.py diff --git a/README.md b/README.md index b22d583a..17a432ab 100644 --- a/README.md +++ b/README.md @@ -85,6 +85,12 @@ program to use, what tests to check and how many CPUs to use. Run `sinol-make in - `sinol-make doc` -- Compiles all LaTeX files in doc/ directory to PDF. Run `sinol-make doc --help` to see all available flags. - `sinol-make init [id]` -- Creates package from template [on github](https://github.com/sio2project/sinol-make/tree/main/example_package) and sets task id to provided `[id]`. Requires an internet connection to run. +You can also run multiple commands at once, for example: + +```shell +sinol-make gen prog/abcingen2.cpp inwer --cpus 4 run --tests abc1*.in doc export --no-statement +``` + ### Reporting bugs and contributing code - Want to report a bug or request a feature? [Open an issue](https://github.com/sio2project/sinol-make/issues). diff --git a/src/sinol_make/__init__.py b/src/sinol_make/__init__.py index 8f53bac6..70502443 100644 --- a/src/sinol_make/__init__.py +++ b/src/sinol_make/__init__.py @@ -1,7 +1,7 @@ # PYTHON_ARGCOMPLETE_OK +import sys import argparse import traceback - import argcomplete from sinol_make import util, oiejq @@ -43,21 +43,37 @@ def check_oiejq(): 'unpack it to `~/.local/bin/` and rename oiejq.sh to oiejq.\n' 'You can also use --oiejq-path to specify path to your oiejq.') except Exception as err: - util.exit_with_error('`oiejq` could not be installed.\n' + err) + util.exit_with_error('`oiejq` could not be installed.\n' + str(err)) def main_exn(): parser = configure_parsers() - args = parser.parse_args() + arguments = [] + curr_args = [] + for arg in sys.argv[1:]: + if arg in util.get_command_names() and not (len(curr_args) > 0 and curr_args[0] == 'init'): + if curr_args: + arguments.append(curr_args) + curr_args = [arg] + else: + curr_args.append(arg) + if curr_args: + arguments.append(curr_args) commands = util.get_commands() - - for command in commands: - if command.get_name() == args.command: - check_oiejq() - command.run(args) - exit(0) - - parser.print_help() + check_oiejq() + + for curr_args in arguments: + args = parser.parse_args(curr_args) + command_found = False + for command in commands: + if command.get_name() == args.command: + command_found = True + if len(arguments) > 1: + print(f' {command.get_name()} command '.center(util.get_terminal_size()[1], '=')) + command.run(args) + if not command_found: + parser.print_help() + exit(1) def main(): diff --git a/src/sinol_make/util.py b/src/sinol_make/util.py index df699de2..a8714b52 100644 --- a/src/sinol_make/util.py +++ b/src/sinol_make/util.py @@ -13,10 +13,16 @@ from sinol_make.structs.status_structs import Status +__cache = {} + + def get_commands(): """ Function to get an array of all available commands. """ + global __cache + if 'commands' in __cache: + return __cache['commands'] commands_path = glob.glob( os.path.join( os.path.dirname(os.path.realpath(__file__)), @@ -28,9 +34,17 @@ def get_commands(): temp = importlib.import_module('sinol_make.commands.' + os.path.basename(path), 'Command') commands.append(temp.Command()) + __cache['commands'] = commands return commands +def get_command_names(): + """ + Function to get an array of all available command names. + """ + return [command.get_name() for command in get_commands()] + + def find_and_chdir_package(): """ Checks if current directory or parent directory is a package directory. diff --git a/tests/test_multiple_arguments.py b/tests/test_multiple_arguments.py new file mode 100644 index 00000000..4a508c70 --- /dev/null +++ b/tests/test_multiple_arguments.py @@ -0,0 +1,31 @@ +import pytest +import subprocess + +from tests.fixtures import create_package +from tests import util + + +def run(args): + print("Running with args:", args) + p = subprocess.run(args, shell=True) + assert p.returncode == 0 + + +@pytest.mark.parametrize("create_package", [util.get_simple_package_path()], indirect=True) +def test_simple_package(create_package): + run("sinol-make gen run") + run("sinol-make gen prog/abcingen.cpp run --tests abc1a.in") + run("sinol-make run --tests abc1a.in run --tests abc1a.in abc2a.in ingen prog/abcingen.cpp") + run("sinol-make gen run export --no-statement") + + +@pytest.mark.parametrize("create_package", [util.get_inwer_package_path()], indirect=True) +def test_inwer_package(create_package): + run("sinol-make ingen inwer run") + run("sinol-make ingen prog/weringen.cpp inwer prog/werinwer.cpp --tests wer1a.in run --tests wer2a.in") + run("sinol-make ingen inwer run export --no-statement") + + +@pytest.mark.parametrize("create_package", [util.get_doc_package_path()], indirect=True) +def test_doc_package(create_package): + run("sinol-make doc doc/doczad.tex export")