From 2f329536500fb13e0d81ef40c3fa949e24373d99 Mon Sep 17 00:00:00 2001 From: bra-i-am Date: Tue, 2 Apr 2024 10:21:57 -0500 Subject: [PATCH] refactor: improve order restructuring function & folders * fix: solve tests failing because using a class method directly in tests --- .../application/test_run_command.py | 24 +++++++-- .../application/commands_runner.py | 6 ++- .../infrastructure/tutor_commands.py | 29 +++++------ tutordistro/utils/common.py | 52 +++++++++++++++++++ tutordistro/utils/constants.py | 30 ----------- 5 files changed, 88 insertions(+), 53 deletions(-) create mode 100644 tutordistro/utils/common.py diff --git a/tests/distro/run_extra_commands/application/test_run_command.py b/tests/distro/run_extra_commands/application/test_run_command.py index dfd0b63..3708cbd 100644 --- a/tests/distro/run_extra_commands/application/test_run_command.py +++ b/tests/distro/run_extra_commands/application/test_run_command.py @@ -7,6 +7,8 @@ from tests.distro.run_extra_commands.infrastructure.test_tutor_commands import TestTutorCommandManager from tutordistro.distro.extra_commands.application.commands_runner import CommandsRunner from tutordistro.distro.share.domain.command_error import CommandError +from tutordistro.utils.common import split_string +from tutordistro.utils.constants import COMMAND_CHAINING_OPERATORS def test_valid_tutor_command(): @@ -23,7 +25,9 @@ def test_valid_tutor_command(): ] tutor_commands_manager = TestTutorCommandManager() - run_tutor_command = CommandsRunner(commands_manager=tutor_commands_manager, commands=valid_tutor_commands) + run_tutor_command = CommandsRunner( + commands_manager=tutor_commands_manager, commands=valid_tutor_commands + ) # When for command in valid_tutor_commands: @@ -51,11 +55,16 @@ def test_invalid_or_misspelled_tutor_command(): with pytest.raises(CommandError) as command_error: tutor_commands_manager = TestTutorCommandManager() - CommandsRunner(commands_manager=tutor_commands_manager, commands=invalid_tutor_command) + CommandsRunner( + commands_manager=tutor_commands_manager, commands=invalid_tutor_command + ) assert command_error.type is CommandError - splitted_commands = [tutor_commands_manager.split_command(command) for command in invalid_tutor_command] + splitted_commands = [ + split_string(command, COMMAND_CHAINING_OPERATORS) + for command in invalid_tutor_command + ] commands_word_by_word = " ".join(sum(splitted_commands, [])).split(" ") pip_commands_sent = commands_word_by_word.count("pip") @@ -82,11 +91,16 @@ def test_misspelled_tutor_command(): with pytest.raises(CommandError) as command_error: tutor_commands_manager = TestTutorCommandManager() - CommandsRunner(commands_manager=tutor_commands_manager, commands=misspelled_commands) + CommandsRunner( + commands_manager=tutor_commands_manager, commands=misspelled_commands + ) assert command_error.type is CommandError - splitted_commands = [tutor_commands_manager.split_command(command) for command in misspelled_commands] + splitted_commands = [ + split_string(command, COMMAND_CHAINING_OPERATORS) + for command in misspelled_commands + ] commands_word_by_word = " ".join(sum(splitted_commands, [])).split(" ") misspelled_commands_sent = commands_word_by_word.count("totur") diff --git a/tutordistro/distro/extra_commands/application/commands_runner.py b/tutordistro/distro/extra_commands/application/commands_runner.py index b2cf730..bd3d228 100644 --- a/tutordistro/distro/extra_commands/application/commands_runner.py +++ b/tutordistro/distro/extra_commands/application/commands_runner.py @@ -1,6 +1,10 @@ """ Distro command runner. """ +# Was necessary to use List from typing because of failing tests in Python 3.8 +# https://stackoverflow.com/questions/75202610/typeerror-type-object-is-not-subscriptable-python +from typing import List + from tutordistro.distro.extra_commands.domain.command_manager import CommandManager @@ -15,7 +19,7 @@ class CommandsRunner: commands_manager (ThemeRepository): The command manager to use for executing the extra command. """ - def __init__(self, commands_manager: CommandManager, commands: list[str]): + def __init__(self, commands_manager: CommandManager, commands: List[str]): self.commands_manager = commands_manager commands_manager.validate_commands(commands) diff --git a/tutordistro/distro/extra_commands/infrastructure/tutor_commands.py b/tutordistro/distro/extra_commands/infrastructure/tutor_commands.py index 41bafff..024c97d 100644 --- a/tutordistro/distro/extra_commands/infrastructure/tutor_commands.py +++ b/tutordistro/distro/extra_commands/infrastructure/tutor_commands.py @@ -2,12 +2,15 @@ Distro tutor command functions. """ -import re import subprocess +# Was necessary to use List from typing because of failing tests in Python 3.8 +# https://stackoverflow.com/questions/75202610/typeerror-type-object-is-not-subscriptable-python +from typing import List, Optional from tutordistro.distro.extra_commands.domain.command_manager import CommandManager from tutordistro.distro.share.domain.command_error import CommandError -from tutordistro.utils.constants import COMMAND_CHAINING_OPERATORS, create_regex_from_array, find_tutor_misspelled +from tutordistro.utils.common import find_tutor_misspelled, split_string +from tutordistro.utils.constants import COMMAND_CHAINING_OPERATORS class TutorCommandManager(CommandManager): @@ -19,20 +22,8 @@ class TutorCommandManager(CommandManager): Args: CommandManager (class): Base command manager class. """ - def split_command(self, command: str): - """ - Takes a command that is wanted to be split according to some - bash command chaining operators - - Args: - command (str): Command with command chaining operator - Return: - The command split into an array - """ - return re.split(create_regex_from_array(COMMAND_CHAINING_OPERATORS), command) - - def validate_commands(self, commands: list[str] | None): + def validate_commands(self, commands: Optional[List[str]]): """ Takes all the extra commands sent through config.yml and verifies that all the commands are correct before executing them @@ -45,7 +36,9 @@ def validate_commands(self, commands: list[str] | None): "No commands found in the DISTRO_EXTRA_COMMANDS attribute of the config.yml file." ) - splitted_commands = [self.split_command(command) for command in commands] + splitted_commands = [ + split_string(command, COMMAND_CHAINING_OPERATORS) for command in commands + ] flat_commands_array = sum(splitted_commands, []) invalid_commands = [] @@ -93,4 +86,6 @@ def run_command(self, command: str): print(process.stdout.decode()) except subprocess.CalledProcessError as error: - raise CommandError(f"Error running command '{error.cmd}':\n{error.stderr.decode()}") from error + raise CommandError( + f"Error running command '{error.cmd}':\n{error.stderr.decode()}" + ) from error diff --git a/tutordistro/utils/common.py b/tutordistro/utils/common.py new file mode 100644 index 0000000..54a9440 --- /dev/null +++ b/tutordistro/utils/common.py @@ -0,0 +1,52 @@ +""" +Global utils +""" + +import re +# Was necessary to use List from typing because of failing tests in Python 3.8 +# https://stackoverflow.com/questions/75202610/typeerror-type-object-is-not-subscriptable-python +from typing import List + + +def find_tutor_misspelled(command: str): + """ + This function takes a command and looks if it has the word 'tutor' misspelled + + Args: + command (str): Command to be reviewed + + Return: + If its found the word 'tutor' misspelled is returned True + """ + return re.match(r"[tT](?:[oru]{3}|[oru]{2}[rR]|[oru]u?)", command) + + +def create_regex_from_array(arr: List[str]): + """ + This functions compiles a new regex turning taking care of + escaping special characters + + Args: + arr (list[str]): String that would be used to create a new regex + + Return: + A new compiled regex pattern that can be used for comparisons + """ + escaped_arr = [re.escape(item) for item in arr] + regex_pattern = "|".join(escaped_arr) + return re.compile(regex_pattern) + + +def split_string(string: str, split_by: List[str]): + """ + Takes a string that is wanted to be split according to some + other strings received in a list + + Args: + string (str): String that will be split + split_by (list[str]): Array of strings which will be used to split the string + + Return: + The string split into an array + """ + return re.split(create_regex_from_array(split_by), string) diff --git a/tutordistro/utils/constants.py b/tutordistro/utils/constants.py index f366767..897fe8a 100644 --- a/tutordistro/utils/constants.py +++ b/tutordistro/utils/constants.py @@ -1,35 +1,5 @@ """ File of constant variables """ -import re COMMAND_CHAINING_OPERATORS = ["&&", "&", "||", "|", ";"] - - -def find_tutor_misspelled(command: str): - """ - This function takes a command and looks if it has the word 'tutor' misspelled - - Args: - command (str): Command to be reviewed - - Return: - If its found the word 'tutor' misspelled is returned True - """ - return re.match(r'[tT](?:[oru]{3}|[oru]{2}[rR]|[oru]u?)', command) - - -def create_regex_from_array(arr: list[str]): - """ - This functions compiles a new regex turning taking care of - escaping special characters - - Args: - arr (list[str]): String that would be used to create a new regex - - Return: - A new compiled regex pattern that can be used for comparisons - """ - escaped_arr = [re.escape(item) for item in arr] - regex_pattern = "|".join(escaped_arr) - return re.compile(regex_pattern)