From 9b2fc87e33b991b06b12dc042b48a384b45145a8 Mon Sep 17 00:00:00 2001 From: kolo Date: Fri, 25 Apr 2025 02:29:44 +0300 Subject: [PATCH] release v1.0.0a1 --- mock/default_mock_app/main.py | 1 - mock/local_test.py | 22 ++- mock/mock_app/handlers/routers.py | 3 - pyproject.toml | 2 +- src/argenta/command/flag/defaults.py | 10 +- src/argenta/router/__init__.py | 2 +- src/argenta/router/entity.py | 9 +- src/argenta/router/exceptions.py | 10 +- .../test_system_handling_normal_behavior.py | 6 +- tests/unit_tests/test_command.py | 11 +- tests/unit_tests/test_flag.py | 40 +++++- tests/unit_tests/test_flagsgroup.py | 26 ---- tests/unit_tests/test_router.py | 133 ++++++++++++++++-- 13 files changed, 194 insertions(+), 81 deletions(-) delete mode 100644 tests/unit_tests/test_flagsgroup.py diff --git a/mock/default_mock_app/main.py b/mock/default_mock_app/main.py index 9470996..7df8f66 100644 --- a/mock/default_mock_app/main.py +++ b/mock/default_mock_app/main.py @@ -1,5 +1,4 @@ from argenta.app import App -from argenta.app.defaults import PredefinedMessages from argenta.orchestrator import Orchestrator app = App(repeat_command_groups=True) diff --git a/mock/local_test.py b/mock/local_test.py index 4ab2ed7..d61b2e8 100644 --- a/mock/local_test.py +++ b/mock/local_test.py @@ -1,15 +1,13 @@ -import argparse +from argenta.command.flag.defaults import PredefinedFlags +router = Router() +flag = PredefinedFlags.SHORT_HELP -parser = argparse.ArgumentParser(prog='ProgramName', - description='What the program does', - epilog='Text at the bottom of help') +@router.command(Command('test', flags=flag)) +def test(args: InputFlags): + print(f'help for {args.get_flag('h').get_name()} flag') -parser.add_argument('filename') # positional argument -parser.add_argument('-c', '--count') # option that takes a value -parser.add_argument('-v', - action='store_const') - -args = parser.parse_args() -print(args) -print(args.filename, args.count, args.verbose) +app = App(override_system_messages=True, + print_func=print) +app.include_router(router) +app.run_polling() \ No newline at end of file diff --git a/mock/mock_app/handlers/routers.py b/mock/mock_app/handlers/routers.py index 307a2f3..679a36c 100644 --- a/mock/mock_app/handlers/routers.py +++ b/mock/mock_app/handlers/routers.py @@ -1,10 +1,7 @@ from rich.console import Console from argenta.command import Command -from argenta.command.flag import Flags, InputFlags -from argenta.command.flag.defaults import PredefinedFlags from argenta.router import Router -from .handlers_implementation.help_command import help_command work_router: Router = Router(title='Work points:') diff --git a/pyproject.toml b/pyproject.toml index 04d2473..eca33d9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "argenta" -version = "1.0.0-alpha" +version = "1.0.0-alpha1" description = "Python library for creating TUI" authors = [{ name = "kolo", email = "kolo.is.main@gmail.com" }] requires-python = ">=3.11, <4.0" diff --git a/src/argenta/command/flag/defaults.py b/src/argenta/command/flag/defaults.py index f2aa0ba..fda42d6 100644 --- a/src/argenta/command/flag/defaults.py +++ b/src/argenta/command/flag/defaults.py @@ -9,16 +9,16 @@ class PredefinedFlags: Public. A dataclass with predefined flags and most frequently used flags for quick use """ HELP = Flag(name='help', possible_values=False) - SHORT_HELP = Flag(name='h', prefix='-', possible_values=False) + SHORT_HELP = Flag(name='H', prefix='-', possible_values=False) INFO = Flag(name='info', possible_values=False) - SHORT_INFO = Flag(name='i', prefix='-', possible_values=False) + SHORT_INFO = Flag(name='I', prefix='-', possible_values=False) ALL = Flag(name='all', possible_values=False) - SHORT_ALL = Flag(name='a', prefix='-', possible_values=False) + SHORT_ALL = Flag(name='A', prefix='-', possible_values=False) HOST = Flag(name='host', possible_values=re.compile(r'^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$')) - SHORT_HOST = Flag(name='h', prefix='-', possible_values=re.compile(r'^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$')) + SHORT_HOST = Flag(name='H', prefix='-', possible_values=re.compile(r'^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$')) PORT = Flag(name='port', possible_values=re.compile(r'^\d{1,5}$')) - SHORT_PORT = Flag(name='p', prefix='-', possible_values=re.compile(r'^\d{1,5}$')) + SHORT_PORT = Flag(name='P', prefix='-', possible_values=re.compile(r'^\d{1,5}$')) diff --git a/src/argenta/router/__init__.py b/src/argenta/router/__init__.py index 75d05bc..cb253db 100644 --- a/src/argenta/router/__init__.py +++ b/src/argenta/router/__init__.py @@ -1,4 +1,4 @@ __all__ = ["Router"] -from argenta.router.entity import Router \ No newline at end of file +from src.argenta.router.entity import Router \ No newline at end of file diff --git a/src/argenta/router/entity.py b/src/argenta/router/entity.py index 50c6088..7cb3e23 100644 --- a/src/argenta/router/entity.py +++ b/src/argenta/router/entity.py @@ -7,7 +7,6 @@ from src.argenta.command.flag.models import Flag, Flags, InputFlags from src.argenta.router.exceptions import (RepeatedFlagNameException, TooManyTransferredArgsException, RequiredArgumentNotPassedException, - IncorrectNumberOfHandlerArgsException, TriggerContainSpacesException) @@ -45,17 +44,13 @@ class Router: return command_decorator - def set_invalid_input_flag_handler(self, func) -> None: + def set_invalid_input_flag_handler(self, func: Callable[[Flag], None]) -> None: """ Public. Registers handler for invalid input flag :param func: registered handler :return: None """ - processed_args = getfullargspec(func).args - if len(processed_args) != 1: - raise IncorrectNumberOfHandlerArgsException() - else: - self._not_valid_flag_handler = func + self._not_valid_flag_handler = func def finds_appropriate_handler(self, input_command: InputCommand) -> None: diff --git a/src/argenta/router/exceptions.py b/src/argenta/router/exceptions.py index 201415e..d9e876c 100644 --- a/src/argenta/router/exceptions.py +++ b/src/argenta/router/exceptions.py @@ -3,7 +3,7 @@ class RepeatedFlagNameException(Exception): Private. Raised when a repeated flag name is registered """ def __str__(self): - return "Repeated registered_flag name in register command" + return "Repeated registered flag names in register command" class TooManyTransferredArgsException(Exception): @@ -22,14 +22,6 @@ class RequiredArgumentNotPassedException(Exception): return "Required argument not passed" -class IncorrectNumberOfHandlerArgsException(Exception): - """ - Private. Raised when incorrect number of arguments are passed - """ - def __str__(self): - return "Handler has incorrect number of arguments" - - class TriggerContainSpacesException(Exception): """ Private. Raised when there is a space in the trigger being registered diff --git a/tests/system_tests/test_system_handling_normal_behavior.py b/tests/system_tests/test_system_handling_normal_behavior.py index 8f87950..01aa9d7 100644 --- a/tests/system_tests/test_system_handling_normal_behavior.py +++ b/tests/system_tests/test_system_handling_normal_behavior.py @@ -91,7 +91,7 @@ class TestSystemHandlerNormalWork(unittest.TestCase): self.assertIn('\nflag value for port flag : 22\n', output) - @patch("builtins.input", side_effect=["test -h", "q"]) + @patch("builtins.input", side_effect=["test -H", "q"]) @patch("sys.stdout", new_callable=io.StringIO) def test_input_correct_command_with_default_flag(self, mock_stdout: _io.StringIO, magick_mock: MagicMock): router = Router() @@ -99,7 +99,7 @@ class TestSystemHandlerNormalWork(unittest.TestCase): @router.command(Command('test', flags=flag)) def test(args: InputFlags): - print(f'help for {args.get_flag('h').get_name()} flag') + print(f'help for {args.get_flag('H').get_name()} flag') app = App(override_system_messages=True, print_func=print) @@ -108,7 +108,7 @@ class TestSystemHandlerNormalWork(unittest.TestCase): output = mock_stdout.getvalue() - self.assertIn('\nhelp for h flag\n', output) + self.assertIn('\nhelp for H flag\n', output) @patch("builtins.input", side_effect=["test --info", "q"]) diff --git a/tests/unit_tests/test_command.py b/tests/unit_tests/test_command.py index 39f3a0d..4bde140 100644 --- a/tests/unit_tests/test_command.py +++ b/tests/unit_tests/test_command.py @@ -1,4 +1,5 @@ -from argenta.command.models import InputCommand +from argenta.command.flag import Flag, InputFlag, Flags +from argenta.command.models import InputCommand, Command from argenta.command.exceptions import (UnprocessedInputFlagException, RepeatedInputFlagsException, EmptyInputCommandException) @@ -22,3 +23,11 @@ class TestInputCommand(unittest.TestCase): with self.assertRaises(EmptyInputCommandException): InputCommand.parse('') + def test_validate_correct_input_flag1(self): + command = Command('some', flags=Flag('test')) + self.assertEqual(command.validate_input_flag(InputFlag('test')), True) + + def test_validate_correct_input_flag2(self): + command = Command('some', flags=Flags(Flag('test'), Flag('more'))) + self.assertEqual(command.validate_input_flag(InputFlag('more')), True) + diff --git a/tests/unit_tests/test_flag.py b/tests/unit_tests/test_flag.py index 414a30d..c83bb95 100644 --- a/tests/unit_tests/test_flag.py +++ b/tests/unit_tests/test_flag.py @@ -1,4 +1,4 @@ -from argenta.command.flag.models import Flag, InputFlag +from argenta.command.flag.models import Flag, InputFlag, InputFlags, Flags import unittest import re @@ -68,6 +68,44 @@ class TestFlag(unittest.TestCase): flag = Flag(name='test', possible_values=True) self.assertEqual(flag.validate_input_flag_value('random value'), True) + def test_get_input_flag1(self): + flag = InputFlag(name='test') + input_flags = InputFlags(flag) + self.assertEqual(input_flags.get_flag('test'), flag) + + def test_get_input_flag2(self): + flag = InputFlag(name='test') + flag2 = InputFlag(name='some') + input_flags = InputFlags(flag, flag2) + self.assertEqual(input_flags.get_flag('some'), flag2) + + def test_get_undefined_input_flag(self): + flag = InputFlag(name='test') + flag2 = InputFlag(name='some') + input_flags = InputFlags(flag, flag2) + self.assertEqual(input_flags.get_flag('case'), None) + + def test_get_flags(self): + flags = Flags() + list_of_flags = [ + Flag('test1'), + Flag('test2'), + Flag('test3'), + ] + flags.add_flags(list_of_flags) + self.assertEqual(flags.get_flags(), + list_of_flags) + + def test_add_flag(self): + flags = Flags() + flags.add_flag(Flag('test')) + self.assertEqual(len(flags.get_flags()), 1) + + def test_add_flags(self): + flags = Flags() + flags.add_flags([Flag('test'), Flag('test2')]) + self.assertEqual(len(flags.get_flags()), 2) + diff --git a/tests/unit_tests/test_flagsgroup.py b/tests/unit_tests/test_flagsgroup.py deleted file mode 100644 index aeb2f81..0000000 --- a/tests/unit_tests/test_flagsgroup.py +++ /dev/null @@ -1,26 +0,0 @@ -from argenta.command.flag.models import Flag, Flags - -import unittest - - -class TestFlags(unittest.TestCase): - def test_get_flags(self): - flags = Flags() - list_of_flags = [ - Flag('test1'), - Flag('test2'), - Flag('test3'), - ] - flags.add_flags(list_of_flags) - self.assertEqual(flags.get_flags(), - list_of_flags) - - def test_add_flag(self): - flags = Flags() - flags.add_flag(Flag('test')) - self.assertEqual(len(flags.get_flags()), 1) - - def test_add_flags(self): - flags = Flags() - flags.add_flags([Flag('test'), Flag('test2')]) - self.assertEqual(len(flags.get_flags()), 2) diff --git a/tests/unit_tests/test_router.py b/tests/unit_tests/test_router.py index 4e9bc9c..e1a22aa 100644 --- a/tests/unit_tests/test_router.py +++ b/tests/unit_tests/test_router.py @@ -1,8 +1,13 @@ +from argenta.command.flag import InputFlags, InputFlag, Flag, Flags from src.argenta.router import Router from src.argenta.command import Command -from src.argenta.router import TriggerContainSpacesException +from src.argenta.router.exceptions import (TriggerContainSpacesException, + RepeatedFlagNameException, + TooManyTransferredArgsException, + RequiredArgumentNotPassedException) import unittest +import re class TestRouter(unittest.TestCase): @@ -12,16 +17,122 @@ class TestRouter(unittest.TestCase): def test_register_command_with_spaces_in_trigger(self): router = Router() with self.assertRaises(TriggerContainSpacesException): - @router.command(Command(trigger='command with spaces')) - def test(): - return 'correct result' - - - - - - - + router._validate_command(Command(trigger='command with spaces')) + + def test_register_command_with_repeated_flags(self): + router = Router() + with self.assertRaises(RepeatedFlagNameException): + router._validate_command(Command(trigger='command', flags=Flags(Flag('test'), Flag('test')))) + + def test_validate_incorrect_input_flag1(self): + router = Router() + router.set_invalid_input_flag_handler(lambda flag: None) + self.assertEqual(router._validate_input_flags(Command('cmd'), InputFlags(InputFlag('ssh'))), False) + + def test_validate_incorrect_input_flag2(self): + router = Router() + router.set_invalid_input_flag_handler(lambda flag: None) + self.assertEqual(router._validate_input_flags(Command('cmd'), InputFlags(InputFlag('ssh', value='some'))), False) + + def test_validate_incorrect_input_flag3(self): + router = Router() + router.set_invalid_input_flag_handler(lambda flag: None) + command = Command('cmd', flags=Flag('port')) + input_flags = InputFlags(InputFlag('ssh', value='some2')) + self.assertEqual(router._validate_input_flags(command, input_flags), False) + + def test_validate_incorrect_input_flag4(self): + router = Router() + router.set_invalid_input_flag_handler(lambda flag: None) + command = Command('cmd', flags=Flag('ssh', possible_values=False)) + input_flags = InputFlags(InputFlag('ssh', value='some3')) + self.assertEqual(router._validate_input_flags(command, input_flags), False) + + def test_validate_incorrect_input_flag5(self): + router = Router() + router.set_invalid_input_flag_handler(lambda flag: None) + command = Command('cmd', flags=Flag('ssh', possible_values=re.compile(r'some[1-5]$'))) + input_flags = InputFlags(InputFlag('ssh', value='some40')) + self.assertEqual(router._validate_input_flags(command, input_flags), False) + + def test_validate_incorrect_input_flag6(self): + router = Router() + router.set_invalid_input_flag_handler(lambda flag: None) + command = Command('cmd', flags=Flag('ssh', possible_values=['example'])) + input_flags = InputFlags(InputFlag('ssh', value='example2')) + self.assertEqual(router._validate_input_flags(command, input_flags), False) + + def test_validate_incorrect_input_flag7(self): + router = Router() + router.set_invalid_input_flag_handler(lambda flag: None) + command = Command('cmd', flags=Flag('ssh', possible_values=['example'])) + input_flags = InputFlags(InputFlag('ssh')) + self.assertEqual(router._validate_input_flags(command, input_flags), False) + + def test_validate_correct_input_flag1(self): + command = Command('cmd', flags=Flag('port')) + input_flags = InputFlags(InputFlag('port', value='some2')) + self.assertEqual(Router()._validate_input_flags(command, input_flags), True) + + def test_validate_correct_input_flag2(self): + command = Command('cmd', flags=Flag('port', possible_values=['some2', 'some3'])) + input_flags = InputFlags(InputFlag('port', value='some2')) + self.assertEqual(Router()._validate_input_flags(command, input_flags), True) + + def test_validate_correct_input_flag3(self): + command = Command('cmd', flags=Flag('ssh', possible_values=re.compile(r'more[1-5]$'))) + input_flags = InputFlags(InputFlag('ssh', value='more5')) + self.assertEqual(Router()._validate_input_flags(command, input_flags), True) + + def test_validate_correct_input_flag4(self): + command = Command('cmd', flags=Flag('ssh', possible_values=False)) + input_flags = InputFlags(InputFlag('ssh')) + self.assertEqual(Router()._validate_input_flags(command, input_flags), True) + + def test_validate_incorrect_func_args1(self): + command = Command('cmd', flags=Flag('port')) + def handler(): + pass + with self.assertRaises(RequiredArgumentNotPassedException): + Router()._validate_func_args(command, handler) + + def test_validate_incorrect_func_args2(self): + command = Command('cmd', flags=Flag('port')) + def handler(args, kwargs): + pass + with self.assertRaises(TooManyTransferredArgsException): + Router()._validate_func_args(command, handler) + + def test_validate_incorrect_func_args3(self): + command = Command('cmd') + def handler(args): + pass + with self.assertRaises(TooManyTransferredArgsException): + Router()._validate_func_args(command, handler) + + def test_get_router_aliases(self): + router = Router() + @router.command(Command('some', aliases=['test', 'case'])) + def handler(): + pass + self.assertListEqual(router.get_aliases(), ['test', 'case']) + + def test_get_router_aliases2(self): + router = Router() + @router.command(Command('some', aliases=['test', 'case'])) + def handler(): + pass + @router.command(Command('ext', aliases=['more', 'foo'])) + def handler2(): + pass + self.assertListEqual(router.get_aliases(), ['test', 'case', 'more', 'foo']) + + def test_get_router_aliases3(self): + router = Router() + @router.command(Command('some')) + def handler(): + pass + self.assertListEqual(router.get_aliases(), [])