Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,18 @@
MigrationFunction = Callable[[Any, Any | None], None]
WriteToStdOut = Callable[[str], None]


def emit_progress(message: str, stdout: WriteToStdOut | None = None) -> None:
if stdout is not None:
stdout(message)
else:
logger.warning(message)

def log_and_run(funcs: Iterable[MigrationFunction], stdout: WriteToStdOut | None = None) -> None:
for func in funcs:
if stdout is not None:
stdout(f"Running {func.__name__}...")
emit_progress(f"Running {func.__name__}...", stdout)
func(apps)
emit_progress(f"Finished {func.__name__}.", stdout)

def fix_cots(stdout: WriteToStdOut | None = None):
funcs = [
Expand Down Expand Up @@ -206,6 +213,11 @@ def add_arguments(self, parser):
def handle(self, *args, **options):
functions = options.get("functions")
verbose = options.get("verbose", False)
stdout = (
(lambda message: self.stdout.write(self.style.SUCCESS(message)))
if verbose
else None
)

try:
with (transaction.atomic(),
Expand All @@ -220,16 +232,16 @@ def handle(self, *args, **options):
self.style.ERROR(f"Unknown function: {function}")
)
return
self.stdout.write(
self.style.SUCCESS(f"Applying {function}...")
)
ALL_FUNCTIONS[function](self.stdout.write if verbose else None)
emit_progress(f"Applying {function}...", stdout)
ALL_FUNCTIONS[function](stdout)
emit_progress(f"Applied {function}.", stdout)
else:
self.stdout.write(self.style.SUCCESS("Running full pipeline..."))
emit_progress("Running full pipeline...", stdout)
for func_name, func in ALL_FUNCTIONS.items():
self.stdout.write(self.style.SUCCESS(f"Applying {func_name}..."))
func(self.stdout.write if verbose else None)
self.stdout.write(self.style.SUCCESS(f"Applied {func_name}"))
emit_progress(f"Applying {func_name}...", stdout)
func(stdout)
emit_progress(f"Applied {func_name}.", stdout)
emit_progress("Completed full pipeline.", stdout)
except Exception:
logger.exception("An error occurred while running key migrations")
raise
20 changes: 18 additions & 2 deletions specifyweb/specify/management/commands/tests/command_tests.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from io import StringIO
from unittest.mock import Mock, patch, sentinel
from unittest.mock import Mock, call, patch, sentinel

from specifyweb.specify.management.commands import run_key_migration_functions as rkm
from specifyweb.specify.management.commands.tests.test_migration_base import MigrationCommandTestCase
Expand Down Expand Up @@ -63,4 +63,20 @@ def test_unknown_function_writes_error_and_dispatches_nothing(self):
command.handle(functions=["unknown"], verbose=True)

command.funcs["known"].assert_not_called()
self.assertIn("Unknown function: unknown", stderr.getvalue())
self.assertIn("Unknown function: unknown", stderr.getvalue())

def test_non_verbose_run_emits_warning_progress_messages(self):
command = self._command()

with patch.object(rkm, "make_selectseries_false") as make_selectseries_false, patch.object(rkm.logger, "warning") as warning:
command.handle(functions=["fix_misc"], verbose=False)

make_selectseries_false.assert_called_once_with(rkm.apps)
warning.assert_has_calls(
[
call("Applying fix_misc..."),
call("Running make_selectseries_false..."),
call("Finished make_selectseries_false."),
call("Applied fix_misc."),
]
)
Loading