-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add command to run extra tutor commands (#59)
- Loading branch information
Showing
20 changed files
with
468 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
Feature: Run extra commands | ||
@fixture.behave.tutor_root | ||
Scenario: Execute the extra commands from config.yml properly | ||
Given There is a tutor root | ||
And There is a config.yml file | ||
And There are valid commands defined | ||
When I write the command tutor distro run-extra-commands and commands will be properly executed | ||
|
||
@fixture.behave.tutor_root | ||
Scenario: Execute commands that are not valid | ||
Given There is a tutor root | ||
And There is a config.yml file | ||
And There are invalid commands defined | ||
When I write the command tutor distro run-extra-commands and commands execution will fail |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
import os | ||
|
||
import subprocess | ||
|
||
from behave import given, when, then # pylint: disable=no-name-in-module | ||
from click.testing import CliRunner | ||
from tutor import config as tutor_config | ||
|
||
from tutordistro.commands.run_extra_commands import run_extra_commands | ||
|
||
|
||
@given("There are valid commands defined") | ||
def step_impl(context): # pylint: disable=function-redefined,missing-function-docstring | ||
extra_commands = [ | ||
"tutor plugins update", | ||
"tutor plugins install forum", | ||
"tutor plugins enable forum" | ||
] | ||
|
||
config = context.scenario.config | ||
config.update({ | ||
"DISTRO_EXTRA_COMMANDS": extra_commands | ||
}) | ||
|
||
tutor_config.save_config_file(context.scenario.tutor_root, config) | ||
config = tutor_config.load(context.scenario.tutor_root) | ||
context.scenario.config = config | ||
context.scenario.extra_commands = "DISTRO_EXTRA_COMMANDS" | ||
|
||
assert "DISTRO_EXTRA_COMMANDS" in config | ||
|
||
|
||
@given("There are invalid commands defined") | ||
def step_impl(context): # pylint: disable=function-redefined,missing-function-docstring | ||
extra_commands = [ | ||
"pip install application" | ||
] | ||
|
||
config = context.scenario.config | ||
config.update({ | ||
"DISTRO_EXTRA_COMMANDS": extra_commands | ||
}) | ||
|
||
tutor_config.save_config_file(context.scenario.tutor_root, config) | ||
config = tutor_config.load(context.scenario.tutor_root) | ||
context.scenario.config = config | ||
context.scenario.extra_commands = "DISTRO_EXTRA_COMMANDS" | ||
|
||
assert "DISTRO_EXTRA_COMMANDS" in config | ||
|
||
|
||
@when("I write the command tutor distro run-extra-commands and commands will be properly executed") | ||
def step_impl(context): # pylint: disable=function-redefined,missing-function-docstring | ||
runner = CliRunner() | ||
result = runner.invoke(run_extra_commands, obj=context) | ||
assert result.exit_code == 0 | ||
|
||
|
||
@when("I write the command tutor distro run-extra-commands and commands execution will fail") | ||
def step_impl(context): # pylint: disable=function-redefined,missing-function-docstring | ||
runner = CliRunner() | ||
result = runner.invoke(run_extra_commands, obj=context) | ||
assert result.exit_code != 0 | ||
|
Empty file.
Empty file.
109 changes: 109 additions & 0 deletions
109
tests/distro/run_extra_commands/application/test_run_command.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
""" | ||
Test run commands application. | ||
""" | ||
|
||
import pytest | ||
|
||
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(): | ||
""" | ||
Test running valid commands. | ||
This test verifies that are executed all the extra commands successfully. | ||
""" | ||
# Given | ||
valid_tutor_commands = [ | ||
"command with word tutor 1", | ||
"command with word tutor 2", | ||
"command with word tutor 3", | ||
] | ||
|
||
tutor_commands_manager = TestTutorCommandManager() | ||
run_tutor_command = CommandsRunner( | ||
commands_manager=tutor_commands_manager, commands=valid_tutor_commands | ||
) | ||
|
||
# When | ||
for command in valid_tutor_commands: | ||
run_tutor_command(command=command) | ||
|
||
assert tutor_commands_manager.commands_ran == len(valid_tutor_commands) | ||
|
||
|
||
def test_invalid_or_misspelled_tutor_command(): | ||
""" | ||
Test running invalid commands. | ||
This test verifies that the execution fails when is | ||
intended to execute invalid extra commands. | ||
""" | ||
# Given | ||
invalid_tutor_command = [ | ||
"pip command 1", | ||
"tutor command && pip command 2", | ||
"tutor command & pip command 3", | ||
"tutor command || pip command 4", | ||
"tutor command | pip command 5", | ||
"tutor command ; pip command 6", | ||
] | ||
|
||
with pytest.raises(CommandError) as command_error: | ||
tutor_commands_manager = TestTutorCommandManager() | ||
CommandsRunner( | ||
commands_manager=tutor_commands_manager, commands=invalid_tutor_command | ||
) | ||
|
||
assert command_error.type is CommandError | ||
|
||
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") | ||
pip_commands_found = command_error.value.args[0].split(" ").count("pip") | ||
|
||
assert pip_commands_sent == pip_commands_found | ||
|
||
|
||
def test_misspelled_tutor_command(): | ||
""" | ||
Test running misspelled Tutor commands. | ||
This test verifies that is warned the user of trying to execute | ||
a misspelled Tutor command. | ||
""" | ||
# Given | ||
misspelled_commands = [ | ||
"totur command 1", | ||
"totur command 2", | ||
"totur command 3", | ||
"totur command 4", | ||
"totur command 5", | ||
] | ||
|
||
with pytest.raises(CommandError) as command_error: | ||
tutor_commands_manager = TestTutorCommandManager() | ||
CommandsRunner( | ||
commands_manager=tutor_commands_manager, commands=misspelled_commands | ||
) | ||
|
||
assert command_error.type is CommandError | ||
|
||
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") | ||
misspelled_commands_found = command_error.value.args[0].split(" ").count("totur") | ||
|
||
assert misspelled_commands_sent == misspelled_commands_found |
Empty file.
27 changes: 27 additions & 0 deletions
27
tests/distro/run_extra_commands/infrastructure/test_tutor_commands.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
""" | ||
Test tutor commands functions. | ||
""" | ||
|
||
from tutordistro.distro.extra_commands.infrastructure.tutor_commands import TutorCommandManager | ||
|
||
|
||
class TestTutorCommandManager(TutorCommandManager): | ||
""" | ||
Executes a Tutor command for testing. | ||
This class provides functionality to execute extra Tutor commands for testing. | ||
Args: | ||
CommandManager (class): Base command manager class. | ||
""" | ||
commands_ran = 0 | ||
|
||
def run_command(self, command: str): | ||
""" | ||
This method runs an testing command. | ||
Args: | ||
command (str): Testing command. | ||
""" | ||
|
||
self.commands_ran += 1 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
""" | ||
Distro run extra commands command. | ||
""" | ||
|
||
import subprocess | ||
|
||
import click | ||
from tutor import config as tutor_config | ||
|
||
from tutordistro.distro.extra_commands.application.commands_runner import CommandsRunner | ||
from tutordistro.distro.extra_commands.infrastructure.tutor_commands import TutorCommandManager | ||
|
||
|
||
@click.command(name="run-extra-commands", help="Run tutor commands") | ||
def run_extra_commands(): | ||
""" | ||
This command runs tutor commands defined in DISTRO_EXTRA_COMMANDS | ||
""" | ||
directory = ( | ||
subprocess.check_output("tutor config printroot", shell=True) | ||
.decode("utf-8") | ||
.strip() | ||
) | ||
config = tutor_config.load(directory) | ||
distro_extra_commands = config.get("DISTRO_EXTRA_COMMANDS", None) | ||
|
||
tutor_commands_manager = TutorCommandManager() | ||
run_tutor_command = CommandsRunner(commands_manager=tutor_commands_manager, commands=distro_extra_commands) | ||
|
||
if distro_extra_commands: | ||
for command in distro_extra_commands: | ||
run_tutor_command(command=command) |
Empty file.
Empty file.
38 changes: 38 additions & 0 deletions
38
tutordistro/distro/extra_commands/application/commands_runner.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
""" | ||
Distro command runner. | ||
""" | ||
# Was necessary to use this for compatibility with Python 3.8 | ||
from typing import List, Optional | ||
|
||
from tutordistro.distro.extra_commands.domain.command_manager import CommandManager | ||
|
||
|
||
class CommandsRunner: | ||
""" | ||
Command runner. | ||
This class is responsible of executing extra commands by invoking the run_command method | ||
on a commands manager. | ||
Attributes: | ||
commands_manager (ThemeRepository): The command manager to use for executing the extra command. | ||
""" | ||
|
||
def __init__(self, commands_manager: CommandManager, commands: Optional[List[str]]): | ||
self.commands_manager = commands_manager | ||
|
||
if commands is not None: | ||
commands_manager.validate_commands(commands) | ||
|
||
def __call__(self, command: str): | ||
""" | ||
Run the provided command. | ||
This method runs the provided command by invoking the run_command method | ||
from the given command manager | ||
Args: | ||
command (str): Command to execute. | ||
""" | ||
|
||
return self.commands_manager.run_command(command=command) |
Empty file.
12 changes: 12 additions & 0 deletions
12
tutordistro/distro/extra_commands/domain/command_manager.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
"""Command Manager""" | ||
|
||
import abc | ||
from abc import abstractmethod | ||
|
||
|
||
class CommandManager(metaclass=abc.ABCMeta): | ||
"""Command Manager""" | ||
|
||
@abstractmethod | ||
def run_command(self, command: str): | ||
"""Run a command.""" |
Empty file.
Oops, something went wrong.