Skip to content

Commit

Permalink
refactor: improve order restructuring function & folders
Browse files Browse the repository at this point in the history
* fix: solve tests failing because using a class method directly in tests
  • Loading branch information
bra-i-am committed Apr 2, 2024
1 parent 9d7cc1b commit 2f32953
Show file tree
Hide file tree
Showing 5 changed files with 88 additions and 53 deletions.
24 changes: 19 additions & 5 deletions tests/distro/run_extra_commands/application/test_run_command.py
Original file line number Diff line number Diff line change
Expand Up @@ -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():
Expand All @@ -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:
Expand Down Expand Up @@ -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")
Expand All @@ -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")
Expand Down
Original file line number Diff line number Diff line change
@@ -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


Expand All @@ -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)

Expand Down
29 changes: 12 additions & 17 deletions tutordistro/distro/extra_commands/infrastructure/tutor_commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand All @@ -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
Expand All @@ -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 = []
Expand Down Expand Up @@ -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
52 changes: 52 additions & 0 deletions tutordistro/utils/common.py
Original file line number Diff line number Diff line change
@@ -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)
30 changes: 0 additions & 30 deletions tutordistro/utils/constants.py
Original file line number Diff line number Diff line change
@@ -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)

0 comments on commit 2f32953

Please sign in to comment.