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 test(ctx, pytest_args='', which='adhoc', quiet=False): """ Run the test suite against ad-hoc created infrastructure. """ testenv = getattr(ctx.qabel.testing, which) start_servers = testenv.get('start_servers', False) pallin = Executor(namespace, ctx.config) if start_servers: # For correct resolution of pre/post tasks this is needed, a bit ugly but oh well. result = pallin.execute( ('start', {'background': True, 'quiet': quiet}) ) start_servers = result[start] # only stop them if we actually had to start them command_line = ['py.test'] for app in APPS: *_, app = app.split('/') app_url = '--{app}-url {url}'.format(app=app, url=testenv[app]) command_line.append(app_url) command_line.append(pytest_args) command_line = ' '.join(command_line) print_bold(command_line) try: ctx.run(command_line, pty=True) finally: if start_servers: pallin.execute(('stop', {}))
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 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 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): args = body.call_args[0] eq_(len(args), 1) ok_(isinstance(args[0], Context))
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): args = body.call_args[0] assert len(args) == 1 assert isinstance(args[0], Context)
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() args = task.body.call_args[0] assert isinstance(args[0], Context) assert len(args) == 1
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) param_list = [] for body_call in body.call_args_list: assert isinstance(body_call[0][0], Context) param_list.append(body_call[0][1]) assert set(param_list) == {5, 7}
def graph_treats_different_calls_to_same_task_differently(self): body = Mock() t1 = Task(body) dep = [call(t1, 5), call(t1, 7), call(t1, 5)] t2 = Task(Mock(), depends_on=dep) c = Collection(t1=t1, t2=t2) e = Executor(collection=c) e.execute('t2') # Does not call the second t1(5) param_list = [] for body_call in body.call_args_list: ok_(isinstance(body_call[0][0], Context)) param_list.append(body_call[0][1]) ok_(set(param_list) == set((5, 7)))
def hands_task_specific_configuration_to_context(self): @task def mytask(ctx): eq_(ctx.my_key, 'value') @task 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 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) param_list = [] for body_call in body.call_args_list: assert isinstance(body_call[0][0], Context) param_list.append(body_call[0][1]) assert set(param_list) == {5, 7}
def hands_collection_configuration_to_context(self): @task def mytask(ctx): eq_(ctx.my_key, 'value') c = Collection(mytask) c.configure({'my_key': 'value'}) Executor(collection=c).execute('mytask')
def hands_task_specific_configuration_to_context(self): @task def mytask(c): assert c.my_key == "value" @task def othertask(c): assert c.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_collection_configuration_to_context(self): @task def mytask(c): assert c.my_key == "value" c = Collection(mytask) c.configure({"my_key": "value"}) Executor(collection=c).execute("mytask")
def hands_collection_configuration_to_context(self): @task def mytask(c): assert c.my_key == 'value' c = Collection(mytask) c.configure({'my_key': 'value'}) Executor(collection=c).execute('mytask')
def can_grant_access_to_core_arg_parse_result(self): c = ParseResult([ParserContext(name="mytask")]) e = Executor(collection=Collection(), core=c) assert e.core is c # Sanity test of real-world access/usage assert len(e.core) == 1 assert e.core[0].name == "mytask" assert len(e.core[0].args) == 0
def subcollection_config_works_with_default_tasks(self): @task(default=True) def mytask(ctx): eq_(ctx.my_key, 'value') # Sets up a task "known as" sub.mytask which may be called as # just 'sub' due to being default. sub = Collection('sub', mytask=mytask) sub.configure({'my_key': 'value'}) main = Collection(sub=sub) # Execute via collection default 'task' name. Executor(collection=main).execute('sub')
def subcollection_config_works_with_default_tasks(self): @task(default=True) def mytask(c): assert c.my_key == "value" # Sets up a task "known as" sub.mytask which may be called as # just 'sub' due to being default. sub = Collection("sub", mytask=mytask) sub.configure({"my_key": "value"}) main = Collection(sub=sub) # Execute via collection default 'task' name. Executor(collection=main).execute("sub")
def call_objs_play_well_with_context_args(self): # Setup dep_body, followup_body = Mock(), Mock() t1 = Task(dep_body) t2 = Task(followup_body) t3 = Task(Mock(), depends_on=[call(t1, 5, foo='bar')], afterwards=[call(t2, 7, biz='baz')], ) c = Collection(t1=t1, t2=t2, t3=t3) e = Executor(collection=c) e.execute('t3') # Dependency asserts args, kwargs = dep_body.call_args eq_(kwargs, {'foo': 'bar'}) assert isinstance(args[0], Context) eq_(args[1], 5) # Followup asserts args, kwargs = followup_body.call_args eq_(kwargs, {'biz': 'baz'}) assert isinstance(args[0], Context) eq_(args[1], 7)
def _call_objs(self): # Setup pre_body, post_body = Mock(), Mock() t1 = Task(pre_body) t2 = Task(post_body) 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'}) assert isinstance(args[0], Context) eq_(args[1], 5) # Post-task asserts args, kwargs = post_body.call_args eq_(kwargs, {'biz': 'baz'}) assert isinstance(args[0], Context) eq_(args[1], 7)
def _call_objs(self): # Setup pre_body, post_body = Mock(), Mock() t1 = Task(pre_body) t2 = Task(post_body) 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 assert kwargs == {'foo': 'bar'} assert isinstance(args[0], Context) assert args[1] == 5 # Post-task asserts args, kwargs = post_body.call_args assert kwargs == {'biz': 'baz'} assert isinstance(args[0], Context) assert args[1] == 7
def setup(self): self.task1 = Task(Mock(return_value=7)) self.task2 = Task(Mock(return_value=10), pre=[self.task1]) self.task3 = Task(Mock(), pre=[self.task1]) self.task4 = Task(Mock(return_value=15), post=[self.task1]) self.contextualized = Task(Mock()) coll = Collection() coll.add_task(self.task1, name='task1') coll.add_task(self.task2, name='task2') coll.add_task(self.task3, name='task3') coll.add_task(self.task4, name='task4') coll.add_task(self.contextualized, name='contextualized') self.executor = Executor(collection=coll)
def _call_objs(self): # Setup pre_body, post_body = Mock(), Mock() t1 = Task(pre_body) t2 = Task(post_body) 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 assert kwargs == {"foo": "bar"} assert isinstance(args[0], Context) assert args[1] == 5 # Post-task asserts args, kwargs = post_body.call_args assert kwargs == {"biz": "baz"} assert isinstance(args[0], Context) assert args[1] == 7
def config_mutation_is_preserved_between_tasks(self): @task def task1(c): c.config.run.echo = True # NOTE: returned for test inspection, not as mechanism of # sharing data! return c @task def task2(c): return c coll = Collection(task1, task2) ret = Executor(collection=coll).execute('task1', 'task2') c2 = ret[task2] eq_(c2.config.run.echo, True)
def config_deletion_is_preserved_between_tasks(self): @task def task1(c): del c.config.run.echo # NOTE: returned for test inspection, not as mechanism of # sharing data! return c @task def task2(c): return c coll = Collection(task1, task2) ret = Executor(collection=coll).execute('task1', 'task2') c2 = ret[task2] ok_('echo' not in c2.config.run)
def new_config_data_is_preserved_between_tasks(self): @task def task1(c): c.foo = 'bar' # NOTE: returned for test inspection, not as mechanism of # sharing data! return c @task def task2(c): return c coll = Collection(task1, task2) ret = Executor(collection=coll).execute('task1', 'task2') c2 = ret[task2] ok_('foo' in c2.config) eq_(c2.foo, 'bar')
def context_is_new_but_config_is_same(self): @task def task1(c): return c @task def task2(c): return c coll = Collection(task1, task2) ret = Executor(collection=coll).execute('task1', 'task2') c1 = ret[task1] c2 = ret[task2] ok_(c1 is not c2) # TODO: eventually we may want to change this again, as long as the # effective values within the config are still matching...? Ehh ok_(c1.config is c2.config)
def setup(self): s = super(Executor_, self) s.setup() self.task1 = Task(Mock(return_value=7)) self.task2 = Task(Mock(return_value=10), depends_on=[self.task1]) self.task3 = Task(Mock(), requires=[self.task1]) self.task4 = Task(Mock(return_value=15), afterwards=[self.task1]) self.contextualized = Task(Mock()) coll = Collection() coll.add_task(self.task1, name='task1') coll.add_task(self.task2, name='task2') coll.add_task(self.task3, name='task3') coll.add_task(self.task4, name='task4') coll.add_task(self.contextualized, name='contextualized') self.executor = Executor(collection=coll)
def new_config_data_is_preserved_between_tasks(self): @task def task1(c): c.foo = "bar" # NOTE: returned for test inspection, not as mechanism of # sharing data! return c @task def task2(c): return c coll = Collection(task1, task2) ret = Executor(collection=coll).execute("task1", "task2") c2 = ret[task2] assert "foo" in c2.config assert c2.foo == "bar"
def core_arg_parse_result_defaults_to_None(self): ok_(Executor(collection=Collection()).core is None)
def can_grant_access_to_core_arg_parse_result(self): c = ParserContext() ok_(Executor(collection=Collection(), core=c).core is c)
def uses_blank_config_by_default(self): e = Executor(collection=Collection()) assert isinstance(e.config, Config)
def allows_collection_and_config(self): coll = Collection() conf = Config() e = Executor(collection=coll, config=conf) assert e.collection is coll assert e.config is conf
def invoke_execute(c, command, **kwargs): results = Executor(c.root_namespace, config=c.config, core=program.core).execute((command, kwargs)) target_task = c.root_namespace[command] return results[target_task]