def _call_objs(self, contextualized): # Setup pre_body, post_body = Mock(), Mock() t1 = Task(pre_body, contextualized=contextualized) t2 = Task(post_body, contextualized=contextualized) t3 = Task(Mock(), pre=[call(t1, 5, foo='bar')], post=[call(t2, 7, biz='baz')], ) c = Collection(t1=t1, t2=t2, t3=t3) e = Executor(collection=c) e.execute('t3') # Pre-task asserts args, kwargs = pre_body.call_args eq_(kwargs, {'foo': 'bar'}) if contextualized: assert isinstance(args[0], Context) eq_(args[1], 5) else: eq_(args, (5,)) # Post-task asserts args, kwargs = post_body.call_args eq_(kwargs, {'biz': 'baz'}) if contextualized: assert isinstance(args[0], Context) eq_(args[1], 7) else: eq_(args, (7,))
class Executor_(Spec): def setup(self): self.task1 = Task(Mock()) self.task2 = Task(Mock(), pre=['task1']) self.task3 = Task(Mock(), pre=['task1']) coll = Collection() coll.add_task(self.task1, name='task1') coll.add_task(self.task2, name='task2') coll.add_task(self.task3, name='task3') self.executor = Executor(coll) self.coll = coll def base_case(self): self.executor.execute('task1') assert self.task1.body.called def kwargs(self): k = {'foo': 'bar'} self.executor.execute(name='task1', kwargs=k) self.task1.body.assert_called_once_with(**k) def pre_tasks(self): self.executor.execute(name='task2') eq_(self.task1.body.call_count, 1) def enabled_deduping(self): self.executor.execute(name='task2') self.executor.execute(name='task3') eq_(self.task1.body.call_count, 1) def disabled_deduping(self): self.executor.execute(name='task2', dedupe=False) self.executor.execute(name='task3', dedupe=False) eq_(self.task1.body.call_count, 2)
def _call_objs(self, contextualized): # Setup pre_body, post_body = Mock(), Mock() t1 = Task(pre_body, contextualized=contextualized) t2 = Task(post_body, contextualized=contextualized) t3 = Task( Mock(), pre=[call(t1, 5, foo='bar')], post=[call(t2, 7, biz='baz')], ) c = Collection(t1=t1, t2=t2, t3=t3) e = Executor(collection=c) e.execute('t3') # Pre-task asserts args, kwargs = pre_body.call_args eq_(kwargs, {'foo': 'bar'}) if contextualized: assert isinstance(args[0], Context) eq_(args[1], 5) else: eq_(args, (5, )) # Post-task asserts args, kwargs = post_body.call_args eq_(kwargs, {'biz': 'baz'}) if contextualized: assert isinstance(args[0], Context) eq_(args[1], 7) else: eq_(args, (7, ))
def calls_default_to_empty_args_always(self): pre_body, post_body = Mock(), Mock() t1 = Task(pre_body) t2 = Task(post_body) t3 = Task(Mock(), pre=[t1], post=[t2]) e = Executor(collection=Collection(t1=t1, t2=t2, t3=t3)) e.execute(('t3', {'something': 'meh'})) for body in (pre_body, post_body): eq_(body.call_args, tuple())
def default_tasks_called_when_no_tasks_specified(self): # NOTE: when no tasks AND no default, Program will print global # help. We just won't do anything at all, which is fine for now. task = Task(Mock('default-task')) coll = Collection() coll.add_task(task, name='mytask', default=True) executor = Executor(collection=coll) executor.execute() task.body.assert_called_with()
def default_tasks_called_when_no_tasks_specified(self): # NOTE: when no tasks AND no default, Program will print global # help. We just won't do anything at all, which is fine for now. task = Task(Mock('default-task')) coll = Collection() coll.add_task(task, name='mytask', default=True) executor = Executor(collection=coll) executor.execute() task.body.assert_called_with()
def calls_default_to_empty_args_always(self): pre_body, post_body = Mock(), Mock() t1 = Task(pre_body) t2 = Task(post_body) t3 = Task(Mock(), pre=[t1], post=[t2]) e = Executor(collection=Collection(t1=t1, t2=t2, t3=t3)) e.execute(('t3', {'something': 'meh'})) for body in (pre_body, post_body): eq_(body.call_args, tuple())
def deduping_treats_different_calls_to_same_task_differently(self): body = Mock() t1 = Task(body) pre = [call(t1, 5), call(t1, 7), call(t1, 5)] t2 = Task(Mock(), pre=pre) c = Collection(t1=t1, t2=t2) e = Executor(collection=c) e.execute('t2') # Does not call the second t1(5) body.assert_has_calls([mock_call(5), mock_call(7)])
def deduping_treats_different_calls_to_same_task_differently(self): body = Mock() t1 = Task(body) pre = [call(t1, 5), call(t1, 7), call(t1, 5)] t2 = Task(Mock(), pre=pre) c = Collection(t1=t1, t2=t2) e = Executor(collection=c) e.execute('t2') # Does not call the second t1(5) body.assert_has_calls([mock_call(5), mock_call(7)])
def execute_cleanup_tasks(ctx, cleanup_tasks, dry_run=False): """Execute several cleanup tasks as part of the cleanup. :param ctx: Context object for the tasks. :param cleanup_tasks: Collection of cleanup tasks (as Collection). :param dry_run: Indicates dry-run mode (bool) """ executor = Executor(cleanup_tasks, ctx.config) for cleanup_task in cleanup_tasks.tasks: print("CLEANUP TASK: %s" % cleanup_task) executor.execute((cleanup_task, dict(dry_run=dry_run)))
def execute_cleanup_tasks(ctx, cleanup_tasks, dry_run=False): """Execute several cleanup tasks as part of the cleanup. REQUIRES: ``clean(ctx, dry_run=False)`` signature in cleanup tasks. :param ctx: Context object for the tasks. :param cleanup_tasks: Collection of cleanup tasks (as Collection). :param dry_run: Indicates dry-run mode (bool) """ executor = Executor(cleanup_tasks, ctx.config) for cleanup_task in cleanup_tasks.tasks: print("CLEANUP TASK: %s" % cleanup_task) executor.execute((cleanup_task, dict(dry_run=dry_run)))
def execute_cleanup_tasks(ctx, cleanup_tasks, dry_run=False): """Execute several cleanup tasks as part of the cleanup. REQUIRES: ``clean(ctx, dry_run=False)`` signature in cleanup tasks. :param ctx: Context object for the tasks. :param cleanup_tasks: Collection of cleanup tasks (as Collection). :param dry_run: Indicates dry-run mode (bool) """ # pylint: disable=redefined-outer-name executor = Executor(cleanup_tasks, ctx.config) for cleanup_task in cleanup_tasks.tasks: print("CLEANUP TASK: %s" % cleanup_task) executor.execute((cleanup_task, dict(dry_run=dry_run)))
def hands_task_specific_configuration_to_context(self): @ctask def mytask(ctx): eq_(ctx.my_key, 'value') @ctask def othertask(ctx): eq_(ctx.my_key, 'othervalue') inner1 = Collection('inner1', mytask) inner1.configure({'my_key': 'value'}) inner2 = Collection('inner2', othertask) inner2.configure({'my_key': 'othervalue'}) c = Collection(inner1, inner2) e = Executor(collection=c) e.execute('inner1.mytask', 'inner2.othertask')
def hands_task_specific_configuration_to_context(self): @ctask def mytask(ctx): eq_(ctx['my.config.key'], 'value') @ctask def othertask(ctx): eq_(ctx['my.config.key'], 'othervalue') inner1 = Collection('inner1', mytask) inner1.configure({'my.config.key': 'value'}) inner2 = Collection('inner2', othertask) inner2.configure({'my.config.key': 'othervalue'}) c = Collection(inner1, inner2) e = Executor(collection=c, context=Context()) e.execute('inner1.mytask', 'inner2.othertask')
def execute_cleanup_tasks(ctx, cleanup_tasks): """Execute several cleanup tasks as part of the cleanup. :param ctx: Context object for the tasks. :param cleanup_tasks: Collection of cleanup tasks (as Collection). """ # pylint: disable=redefined-outer-name executor = Executor(cleanup_tasks, ctx.config) failure_count = 0 for cleanup_task in cleanup_tasks.tasks: try: print("CLEANUP TASK: %s" % cleanup_task) executor.execute(cleanup_task) except (Exit, Failure, UnexpectedExit) as e: print(e) print("FAILURE in CLEANUP TASK: %s (GRACEFULLY-IGNORED)" % cleanup_task) failure_count += 1 if failure_count: print("CLEANUP TASKS: %d failure(s) occured" % failure_count)
def execute_cleanup_tasks(ctx, cleanup_tasks, dry_run=False): """Execute several cleanup tasks as part of the cleanup. REQUIRES: ``clean(ctx, dry_run=False)`` signature in cleanup tasks. :param ctx: Context object for the tasks. :param cleanup_tasks: Collection of cleanup tasks (as Collection). :param dry_run: Indicates dry-run mode (bool) """ # pylint: disable=redefined-outer-name executor = Executor(cleanup_tasks, ctx.config) failure_count = 0 for cleanup_task in cleanup_tasks.tasks: try: print("CLEANUP TASK: %s" % cleanup_task) executor.execute((cleanup_task, dict(dry_run=dry_run))) except (Exit, Failure, UnexpectedExit) as e: print("FAILURE in CLEANUP TASK: %s (GRACEFULLY-IGNORED)" % cleanup_task) failure_count += 1 if failure_count: print("CLEANUP TASKS: %d failure(s) occured" % failure_count)
def execute_cleanup_tasks(ctx, cleanup_tasks, dry_run=False): """Execute several cleanup tasks as part of the cleanup. REQUIRES: ``clean(ctx, dry_run=False)`` signature in cleanup tasks. :param ctx: Context object for the tasks. :param cleanup_tasks: Collection of cleanup tasks (as Collection). :param dry_run: Indicates dry-run mode (bool) """ # pylint: disable=redefined-outer-name executor = Executor(cleanup_tasks, ctx.config) failure_count = 0 for cleanup_task in cleanup_tasks.tasks: try: print("CLEANUP TASK: %s" % cleanup_task) executor.execute((cleanup_task, dict(dry_run=dry_run))) except (Exit, Failure, UnexpectedExit) as e: print("FAILURE in CLEANUP TASK: %s (GRACEFULLY-IGNORED)" % cleanup_task) failure_count += 1 if failure_count: print("CLEANUP TASKS: %d failure(s) occured" % failure_count)
c.run(f"git stash push -q --keep-index") @task def stage_changes(c): """ Stage the newly changed files only. Only works in a pre-commit context. """ c.run(f"git add -u") # Until invoke has proper support for prgramatic accsess # see https://github.com/pyinvoke/invoke/issues/170 for details namespace = Collection(stash_changes, stage_changes, format, check, test) namespace.configure({"root_namespace": namespace}) executor = Executor(namespace) try: executor.execute("stash_changes") # will be deleted in post-commit on success executor.execute("format") executor.execute("check") executor.execute("test") executor.execute("stage_changes") except UnexpectedExit: print("\n\n[ERROR]] Pre-commit hook failed, commit aborted!") print("[ERROR]] Working directory contains files potentially changed by pre-commit hook") print("[ERROR]] Unaltered changes can be found in latest stash: 'git stash list'") print("[ERROR]] Cleanup of he stashes may be needed after failure") exit(1)