From ba51922ed2866acda9f88f0350d784fcdd924a78 Mon Sep 17 00:00:00 2001 From: Jasha <8935917+Jasha10@users.noreply.github.com> Date: Sat, 10 Apr 2021 12:02:33 -0500 Subject: [PATCH 1/7] implement CmdAction.title() --- doit/action.py | 13 +++++++++++++ tests/test_action.py | 5 +++++ 2 files changed, 18 insertions(+) diff --git a/doit/action.py b/doit/action.py index e7b0e2fa..6b28b288 100644 --- a/doit/action.py +++ b/doit/action.py @@ -7,6 +7,7 @@ import inspect from pathlib import PurePath from threading import Thread +from typing import Union import pdb from .exceptions import InvalidTask, TaskFailed, TaskError @@ -27,6 +28,9 @@ class BaseAction(object): # must implement: # def execute(self, out=None, err=None) + # must implement: + # def title(self) + @staticmethod def _prepare_kwargs(task, func, args, kwargs): """ @@ -153,6 +157,15 @@ def action(self): kwargs = self._prepare_kwargs(self.task, ref, args, kw) return ref(*args, **kwargs) + def title(self) -> Union[str, TaskError]: + try: + action = self.expand_action() + except Exception as exc: + return TaskError( + "CmdAction Error creating command string", exc) + assert isinstance(action, str) + return "+ " + action + def _print_process_output(self, process, input_, capture, realtime): """Reads 'input_' until process is terminated. diff --git a/tests/test_action.py b/tests/test_action.py index fdbfc191..f0164c9d 100644 --- a/tests/test_action.py +++ b/tests/test_action.py @@ -85,6 +85,11 @@ def test_values(self): my_action.execute() assert {} == my_action.values + def test_title(self): + cmd = "%s 1 2" % PROGRAM + my_action = action.CmdAction(cmd) + assert "+ " + cmd == my_action.title() + class TestCmdActionParams(object): def test_invalid_param_stdout(self): From 53f46369dd6c3335895d0f0009f5cebb32b169ed Mon Sep 17 00:00:00 2001 From: Jasha <8935917+Jasha10@users.noreply.github.com> Date: Sat, 10 Apr 2021 12:13:07 -0500 Subject: [PATCH 2/7] implement PythonAction.title() --- doit/action.py | 3 +++ tests/test_action.py | 5 +++++ 2 files changed, 8 insertions(+) diff --git a/doit/action.py b/doit/action.py index 6b28b288..257c084c 100644 --- a/doit/action.py +++ b/doit/action.py @@ -409,6 +409,9 @@ def __init__(self, py_callable, args=None, kwargs=None, task=None): msg = "%r kwargs must be a 'dict'. got '%s'" raise InvalidTask(msg % (self.task, self.kwargs)) + def title(self) -> str: + return f"+ {self.py_callable.__name__}(*{self.args}, **{self._prepare_kwargs()})" + def _prepare_kwargs(self): return BaseAction._prepare_kwargs(self.task, self.py_callable, diff --git a/tests/test_action.py b/tests/test_action.py index f0164c9d..f8b29767 100644 --- a/tests/test_action.py +++ b/tests/test_action.py @@ -601,6 +601,11 @@ def vvv(): return {'x': 5, 'y':10} my_action.execute() assert {'x': 5, 'y':10} == my_action.values + def test_title(self): + my_action = action.PythonAction(self._func_par,args=(2,2), + kwargs={'par3':25}) + assert "+ _func_par(*(2, 2), **{'par3': 25})" == my_action.title() + class TestPythonVerbosity(object): def write_stderr(self): From 39ecba759aaca141fcfdc3d7c28590aaf89aee63 Mon Sep 17 00:00:00 2001 From: Jasha <8935917+Jasha10@users.noreply.github.com> Date: Sun, 18 Apr 2021 16:09:19 -0500 Subject: [PATCH 3/7] remove `+ ` prefix from {CmdAction,PythonAction}.title --- doit/action.py | 4 ++-- tests/test_action.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/doit/action.py b/doit/action.py index 257c084c..f4d99353 100644 --- a/doit/action.py +++ b/doit/action.py @@ -164,7 +164,7 @@ def title(self) -> Union[str, TaskError]: return TaskError( "CmdAction Error creating command string", exc) assert isinstance(action, str) - return "+ " + action + return action def _print_process_output(self, process, input_, capture, realtime): @@ -410,7 +410,7 @@ def __init__(self, py_callable, args=None, kwargs=None, task=None): raise InvalidTask(msg % (self.task, self.kwargs)) def title(self) -> str: - return f"+ {self.py_callable.__name__}(*{self.args}, **{self._prepare_kwargs()})" + return f"{self.py_callable.__name__}(*{self.args}, **{self._prepare_kwargs()})" def _prepare_kwargs(self): diff --git a/tests/test_action.py b/tests/test_action.py index f8b29767..7a5fcc97 100644 --- a/tests/test_action.py +++ b/tests/test_action.py @@ -88,7 +88,7 @@ def test_values(self): def test_title(self): cmd = "%s 1 2" % PROGRAM my_action = action.CmdAction(cmd) - assert "+ " + cmd == my_action.title() + assert cmd == my_action.title() class TestCmdActionParams(object): @@ -604,7 +604,7 @@ def vvv(): return {'x': 5, 'y':10} def test_title(self): my_action = action.PythonAction(self._func_par,args=(2,2), kwargs={'par3':25}) - assert "+ _func_par(*(2, 2), **{'par3': 25})" == my_action.title() + assert "_func_par(*(2, 2), **{'par3': 25})" == my_action.title() class TestPythonVerbosity(object): From c49123611abe96fd94b02de0d031f0e79e32db14 Mon Sep 17 00:00:00 2001 From: Jasha <8935917+Jasha10@users.noreply.github.com> Date: Sun, 18 Apr 2021 16:19:07 -0500 Subject: [PATCH 4/7] implement ConsoleReporter.execute_action --- doit/reporter.py | 4 ++++ tests/test_reporter.py | 8 ++++++++ 2 files changed, 12 insertions(+) diff --git a/doit/reporter.py b/doit/reporter.py index 6ac59f69..9ad70b62 100644 --- a/doit/reporter.py +++ b/doit/reporter.py @@ -42,6 +42,10 @@ def execute_task(self, task): if task.actions and (task.name[0] != '_'): self.write('. %s\n' % task.title()) + def execute_action(self, action): + """called before executing each action""" + self.write(' + %s\n' % action.title()) + def add_failure(self, task, exception): """called when execution finishes with a failure""" result = {'task': task, 'exception':exception} diff --git a/tests/test_reporter.py b/tests/test_reporter.py index 85ae3296..48444b05 100644 --- a/tests/test_reporter.py +++ b/tests/test_reporter.py @@ -3,6 +3,7 @@ from io import StringIO from doit import reporter +from doit.action import BaseAction from doit.task import Stream, Task from doit.exceptions import CatchedException @@ -28,6 +29,13 @@ def do_nothing():pass rep.execute_task(t1) assert ". with_action\n" == rep.outstream.getvalue() + def test_executeAction(self): + rep = reporter.ConsoleReporter(StringIO(), {}) + a1 = BaseAction() + a1.title = lambda: "action_title" + rep.execute_action(a1) + assert " + action_title\n" == rep.outstream.getvalue() + def test_executeTask_unicode(self): rep = reporter.ConsoleReporter(StringIO(), {}) def do_nothing():pass From a3747d59819647f4677733dd7979d6a30fa52df3 Mon Sep 17 00:00:00 2001 From: Jasha <8935917+Jasha10@users.noreply.github.com> Date: Sun, 18 Apr 2021 17:00:53 -0500 Subject: [PATCH 5/7] add "show_action" option to ConsoleReporter (default False) --- doit/reporter.py | 4 +++- tests/test_reporter.py | 16 +++++++++++++--- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/doit/reporter.py b/doit/reporter.py index 9ad70b62..21754901 100644 --- a/doit/reporter.py +++ b/doit/reporter.py @@ -21,6 +21,7 @@ def __init__(self, outstream, options): self.failures = [] self.runtime_errors = [] self.failure_verbosity = options.get('failure_verbosity', 0) + self.show_action = options.get('show_action', False) self.outstream = outstream def write(self, text): @@ -44,7 +45,8 @@ def execute_task(self, task): def execute_action(self, action): """called before executing each action""" - self.write(' + %s\n' % action.title()) + if self.show_action: + self.write(' + %s\n' % action.title()) def add_failure(self, task, exception): """called when execution finishes with a failure""" diff --git a/tests/test_reporter.py b/tests/test_reporter.py index 48444b05..4f20625b 100644 --- a/tests/test_reporter.py +++ b/tests/test_reporter.py @@ -7,6 +7,8 @@ from doit.task import Stream, Task from doit.exceptions import CatchedException +import pytest + class TestConsoleReporter(object): @@ -29,12 +31,20 @@ def do_nothing():pass rep.execute_task(t1) assert ". with_action\n" == rep.outstream.getvalue() - def test_executeAction(self): - rep = reporter.ConsoleReporter(StringIO(), {}) + @pytest.mark.parametrize( + "options,expected", + [ + ({}, ""), + ({"show_action": True}, " + action_title\n"), + ({"show_action": False}, ""), + ], + ) + def test_executeAction(self, options, expected): + rep = reporter.ConsoleReporter(StringIO(), options) a1 = BaseAction() a1.title = lambda: "action_title" rep.execute_action(a1) - assert " + action_title\n" == rep.outstream.getvalue() + assert expected == rep.outstream.getvalue() def test_executeTask_unicode(self): rep = reporter.ConsoleReporter(StringIO(), {}) From 6ab85fdcaae87710d3d7160dbf7ca91120139381 Mon Sep 17 00:00:00 2001 From: Jasha <8935917+Jasha10@users.noreply.github.com> Date: Sun, 18 Apr 2021 19:00:49 -0500 Subject: [PATCH 6/7] add `reporter` arg to `Task.execute` and `Task.execute_teardown` --- doit/reporter.py | 2 +- doit/runner.py | 4 ++-- doit/task.py | 11 ++++++++--- tests/test_task.py | 28 ++++++++++++++++++++++++++++ 4 files changed, 39 insertions(+), 6 deletions(-) diff --git a/doit/reporter.py b/doit/reporter.py index 21754901..c723aa29 100644 --- a/doit/reporter.py +++ b/doit/reporter.py @@ -143,7 +143,7 @@ def _just_pass(self, *args): """over-write base to do nothing""" pass - get_status = execute_task = add_failure = add_success \ + get_status = execute_task = execute_action = add_failure = add_success \ = skip_uptodate = skip_ignore = teardown_task = complete_run \ = _just_pass diff --git a/doit/runner.py b/doit/runner.py index 572058f2..662ac988 100644 --- a/doit/runner.py +++ b/doit/runner.py @@ -174,7 +174,7 @@ def execute_task(self, task): # finally execute it! self.reporter.execute_task(task) - return task.execute(self.stream) + return task.execute(self.stream, self.reporter) def process_task_result(self, node, catched_excp): @@ -227,7 +227,7 @@ def teardown(self): """run teardown from all tasks""" for task in reversed(self.teardown_list): self.reporter.teardown_task(task) - catched = task.execute_teardown(self.stream) + catched = task.execute_teardown(self.stream, self.reporter) if catched: msg = "ERROR: task '%s' teardown action" % task.name error = SetupError(msg, catched) diff --git a/doit/task.py b/doit/task.py index 2ad04f83..d9e7b9a5 100644 --- a/doit/task.py +++ b/doit/task.py @@ -10,8 +10,9 @@ from .cmdparse import CmdOption, TaskParse from .exceptions import CatchedException, InvalidTask -from .action import create_action, PythonAction +from .action import create_action, BaseAction, PythonAction from .dependency import UptodateCalculator +from .reporter import ConsoleReporter def first_line(doc): @@ -449,7 +450,7 @@ def save_extra_values(self): def overwrite_verbosity(self, stream): self.verbosity = stream.effective_verbosity(self.verbosity) - def execute(self, stream): + def execute(self, stream, reporter=None): """Executes the task. @return failure: see CmdAction.execute """ @@ -457,6 +458,8 @@ def execute(self, stream): self.init_options() task_stdout, task_stderr = stream._get_out_err(self.verbosity) for action in self.actions: + if isinstance(action, BaseAction) and isinstance(reporter, ConsoleReporter): + reporter.execute_action(action) action_return = action.execute(task_stdout, task_stderr) if isinstance(action_return, CatchedException): return action_return @@ -464,12 +467,14 @@ def execute(self, stream): self.values.update(action.values) - def execute_teardown(self, stream): + def execute_teardown(self, stream, reporter=None): """Executes task's teardown @return failure: see CmdAction.execute """ task_stdout, task_stderr = stream._get_out_err(self.verbosity) for action in self.teardown: + if isinstance(action, BaseAction) and isinstance(reporter, ConsoleReporter): + reporter.execute_action(action) action_return = action.execute(task_stdout, task_stderr) if isinstance(action_return, CatchedException): return action_return diff --git a/tests/test_task.py b/tests/test_task.py index 678b1bba..75096efc 100644 --- a/tests/test_task.py +++ b/tests/test_task.py @@ -10,6 +10,7 @@ from doit.exceptions import TaskError from doit.exceptions import CatchedException from doit import action +from doit import reporter from doit import task from doit.task import Stream @@ -391,6 +392,33 @@ def my_raise(): got = t.execute_teardown(Stream(0)) assert isinstance(got, CatchedException) +@pytest.mark.parametrize( + "show_action,expected", + [ + (False, ""), + (True, " + put(*[1], **{})\n + put(*[2], **{})\n"), + ], +) +class TestTaskCallsShowAction(object): + def test_show_action(self, show_action, expected): + rep = reporter.ConsoleReporter(StringIO(), {"show_action": show_action}) + got = [] + def put(x): + got.append(x) + t = task.Task("t1", [(put, [1]), (put, [2])]) + t.execute(Stream(0), rep) + t.execute_teardown(Stream(0), rep) + assert expected == rep.outstream.getvalue() + + def test_teardown_show_action(self, show_action, expected): + rep = reporter.ConsoleReporter(StringIO(), {"show_action": show_action}) + got = [] + def put(x): + got.append(x) + t = task.Task("t1", [], teardown=[(put, [1]), (put, [2])]) + t.execute(Stream(0), rep) + t.execute_teardown(Stream(0), rep) + assert expected == rep.outstream.getvalue() class TestTaskClean(object): From c19288270b0b423df6f0ae08d5862f745eddf6f0 Mon Sep 17 00:00:00 2001 From: Jasha <8935917+Jasha10@users.noreply.github.com> Date: Sun, 18 Apr 2021 19:24:47 -0500 Subject: [PATCH 7/7] simplify test_task.py:test_show_action --- tests/test_task.py | 39 ++++++++++++++++----------------------- 1 file changed, 16 insertions(+), 23 deletions(-) diff --git a/tests/test_task.py b/tests/test_task.py index 75096efc..00ab8d78 100644 --- a/tests/test_task.py +++ b/tests/test_task.py @@ -392,33 +392,26 @@ def my_raise(): got = t.execute_teardown(Stream(0)) assert isinstance(got, CatchedException) + +def py_fn(x): + pass + @pytest.mark.parametrize( - "show_action,expected", + "t", [ - (False, ""), - (True, " + put(*[1], **{})\n + put(*[2], **{})\n"), + task.Task("t1", [(py_fn, [1]), (py_fn, [2])]), + task.Task("t1", [], teardown=[(py_fn, [1]), (py_fn, [2])]), ], ) -class TestTaskCallsShowAction(object): - def test_show_action(self, show_action, expected): - rep = reporter.ConsoleReporter(StringIO(), {"show_action": show_action}) - got = [] - def put(x): - got.append(x) - t = task.Task("t1", [(put, [1]), (put, [2])]) - t.execute(Stream(0), rep) - t.execute_teardown(Stream(0), rep) - assert expected == rep.outstream.getvalue() - - def test_teardown_show_action(self, show_action, expected): - rep = reporter.ConsoleReporter(StringIO(), {"show_action": show_action}) - got = [] - def put(x): - got.append(x) - t = task.Task("t1", [], teardown=[(put, [1]), (put, [2])]) - t.execute(Stream(0), rep) - t.execute_teardown(Stream(0), rep) - assert expected == rep.outstream.getvalue() +@pytest.mark.parametrize( + "show_action,expected", + [(False, ""), (True, " + py_fn(*[1], **{})\n + py_fn(*[2], **{})\n")], +) +def test_show_action(t, show_action, expected): + rep = reporter.ConsoleReporter(StringIO(), {"show_action": show_action}) + t.execute(Stream(0), rep) + t.execute_teardown(Stream(0), rep) + assert expected == rep.outstream.getvalue() class TestTaskClean(object):