def test_loop_two_control_vars_fails_on_string(self): with pytest.raises(exceptions.YamlSyntaxError): run_section([{ 'for $i, $j in $(echo "foo bar")': [{ 'log_i': '$i' }] }])
def test_for_word_in_string(self): rs = [{'for $i word_in $list': [{'$foo~': '$(echo $i)'}]}] self.assert_run_section_result(run_section(rs, {'list': 'fo'}), [True, 'fo']) self.assert_run_section_result(run_section(rs, {'list': 'fo ba'}), [True, 'ba']) self.assert_run_section_result(run_section(rs, {}), [False, ''])
def test_loop_two_control_vars(self, iter_type): # this should work the same for both iteration types tlh = TestLoggingHandler.create_fresh_handler() run_section([{'for $i, $j {0} $foo'.format(iter_type): [{'log_i': '$i, $j'}]}], {'foo': {'bar': 'barval', 'spam': 'spamval'}}) assert ('INFO', 'bar, barval') in tlh.msgs assert ('INFO', 'spam, spamval') in tlh.msgs
def test_for(self): rs = [{'for $i in $list': [{'$foo~': '$(echo $i)'}]}] self.assert_run_section_result(run_section(rs, {'list': '1'}), [True, '1']) self.assert_run_section_result(run_section(rs, {'list': '1 2'}), [True, '2']) self.assert_run_section_result(run_section(rs, {}), [False, ''])
def _dot_devassistant_run(cls, comm, kwargs): dda_content = cls.__dot_devassistant_read_exact(comm) # TODO: we should really create devassistant.util.expand_path to not use # abspath + expanduser everywhere all the time... dda_fullpath = os.path.join(os.path.abspath(os.path.expanduser(comm)), ".devassistant") kwargs.setdefault("__sourcefiles__", []) kwargs["__sourcefiles__"].append(dda_fullpath) lang.run_section(dda_content.get("run", []), kwargs, runner=kwargs.get("__assistant__")) kwargs["__sourcefiles__"].pop()
def test_assign_existing_nonempty_variable(self): kwargs = {'bar': 'bar'} run_section([{'$foo': '$bar'}], kwargs) assert kwargs['foo'] == 'bar' # both logical result and result run_section([{'$success, $val': '$bar'}], kwargs) assert kwargs['success'] == True assert kwargs['val'] == 'bar'
def test_assign_unsuccessful_command(self): kwargs = {} run_section([{'$foo~': '$(ls spam/spam/spam)'}], kwargs) assert kwargs['foo'] == u'ls: cannot access spam/spam/spam: No such file or directory' # both logical result and result run_section([{'$success, $val~': '$(ls spam/spam/spam)'}], kwargs) assert kwargs['val'] == u'ls: cannot access spam/spam/spam: No such file or directory' assert kwargs['success'] == False
def test_assign_existing_empty_variable(self, exec_flag, lres, res): kwargs = {'bar': ''} run_section([{'$foo{0}'.format(exec_flag): '$bar'}], kwargs) assert kwargs['foo'] == res # both logical result and result run_section([{'$success, $val{0}'.format(exec_flag): '$foo'}], kwargs) assert kwargs['success'] == lres assert kwargs['val'] == res
def test_assign_successful_command(self): kwargs = {} run_section([{'$foo~': '$(basename foo/bar)'}, {'log_i': '$foo'}], kwargs) assert kwargs['foo'] == u'bar' # both logical result and result run_section([{'$success, $val~': '$(basename foo/bar)'}], kwargs) assert kwargs['success'] == True assert kwargs['val'] == 'bar'
def test_loop_two_control_vars_fails_on_string(self, iter_type): # this should work the same for both iteration types with pytest.raises(exceptions.YamlSyntaxError): run_section([{ 'for $i, $j {0} $(echo "foo bar")'.format(iter_type): [{ 'log_i': '$i' }] }])
def test_assign_nonexisting_variable_depending_on_exec_flag(self, exec_flag, lres, res): kwargs = {} run_section([{'$foo{0}'.format(exec_flag): '$bar'}], kwargs) assert kwargs['foo'] == res # both logical result and result run_section([{'$success, $val{0}'.format(exec_flag): '$bar'}], kwargs) assert kwargs['success'] == lres assert kwargs['val'] == res
def test_result(self): assert run_section([], {}) == [False, ''] rs = [{'$foo': '$(echo asd)'}] assert run_section(rs, {}) == [True, 'asd'] rs = [{'if $foo': [{'$foo': '"bar"'}, {'$foo': '"baz"'}]}] assert run_section(rs, {}) == [False, ''] assert run_section(rs, {'foo': 'yes'}) == [True, 'baz']
def _dot_devassistant_run(cls, comm, kwargs): dda_content = cls.__dot_devassistant_read_exact(comm) # TODO: we should really create devassistant.util.expand_path to not use # abspath + expanduser everywhere all the time... dda_fullpath = os.path.join(os.path.abspath(os.path.expanduser(comm)), '.devassistant') kwargs.setdefault('__sourcefiles__', []) kwargs['__sourcefiles__'].append(dda_fullpath) lang.run_section(dda_content.get('run', []), kwargs, runner=kwargs.get('__assistant__')) kwargs['__sourcefiles__'].pop()
def test_assign_unsuccessful_command(self): kwargs = {} run_section([{'$foo~': '$(ls spam/spam/spam)'}], kwargs) assert kwargs[ 'foo'] == u'ls: cannot access spam/spam/spam: No such file or directory' # both logical result and result run_section([{'$success, $val~': '$(ls spam/spam/spam)'}], kwargs) assert kwargs[ 'val'] == u'ls: cannot access spam/spam/spam: No such file or directory' assert kwargs['success'] == False
def test_loop_two_control_vars(self): tlh = TestLoggingHandler.create_fresh_handler() run_section([{ 'for $i, $j in $foo': [{ 'log_i': '$i, $j' }] }], {'foo': { 'bar': 'barval', 'spam': 'spamval' }}) assert ('INFO', 'bar, barval') in tlh.msgs assert ('INFO', 'spam, spamval') in tlh.msgs
def test_assign_successful_command(self): kwargs = {} run_section([{ '$foo~': '$(basename foo/bar)' }, { 'log_i': '$foo' }], kwargs) assert kwargs['foo'] == u'bar' # both logical result and result run_section([{'$success, $val~': '$(basename foo/bar)'}], kwargs) assert kwargs['success'] == True assert kwargs['val'] == 'bar'
def test_loop_two_control_vars(self, iter_type): # this should work the same for both iteration types tlh = TestLoggingHandler.create_fresh_handler() run_section([{ 'for $i, $j {0} $foo'.format(iter_type): [{ 'log_i': '$i, $j' }] }], {'foo': { 'bar': 'barval', 'spam': 'spamval' }}) assert ('INFO', 'bar, barval') in tlh.msgs assert ('INFO', 'spam, spamval') in tlh.msgs
def run(cls, c): assistant = c.kwargs['__assistant__'] kwargs = copy.deepcopy(c.kwargs) try: yaml_name, section_name = c.input_res.rsplit('.', 1) except ValueError: raise exceptions.CommandException('"use" command expects "use: what.which_section".') # Modify kwargs based on command if cls.is_snippet_call(c.input_res): snip = cls.get_snippet(yaml_name) section = cls.get_snippet_section(section_name, snip) kwargs['__files__'].append(snip.get_files_section()) kwargs['__files_dir__'].append(snip.get_files_dir()) kwargs['__sourcefiles__'].append(snip.path) else: assistant = cls.get_assistant(yaml_name, section_name, assistant) section = cls.get_assistant_section(section_name, assistant) kwargs['__assistant__'] = assistant # Get section with modified kwargs if section_name.startswith('dependencies'): result = lang.dependencies_section(section, kwargs, runner=assistant) else: result = lang.run_section(section, kwargs, runner=assistant) return result
def run(cls, c): assistant = c.kwargs['__assistant__'] call_parts = c.input_res.rsplit('.', 1) if len(call_parts) < 2: raise exceptions.CommandException('"use" command expects "use: what.which_section".') section_name = call_parts[1] # TODO: check dependencies/run called = call_parts[0] section, sourcefile = cls.get_section_from_call(called, section_name, assistant) if not section: msg = 'Couldn\'t find {t} section "{n}".'.format(t=section, n=c.input_res) raise exceptions.CommandException(msg) if cls.is_snippet_call(c.input_res): # we're calling a snippet => add files and files_dir to kwargs snippet = yaml_snippet_loader.YamlSnippetLoader.\ get_snippet_by_name(c.input_res.split('.')[0]) c.kwargs['__files__'].append(snippet.get_files_section()) c.kwargs['__files_dir__'].append(snippet.get_files_dir()) c.kwargs['__sourcefiles__'].append(snippet.path) if section_name.startswith('dependencies'): result = lang.dependencies_section(section, copy.deepcopy(c.kwargs), runner=assistant) else: result = lang.run_section(section, copy.deepcopy(c.kwargs), runner=assistant) if cls.is_snippet_call(c.input_res): c.kwargs['__files__'].pop() c.kwargs['__files_dir__'].pop() c.kwargs['__sourcefiles__'].pop() return result
def run(cls, c): sect_type = c.kwargs['__section__'] assistant = c.kwargs['__assistant__'] section, sourcefile = cls.get_section_from_call(c.comm, sect_type, assistant) if not section: msg = 'Couldn\'t find {t} section "{n}".'.format(t=c.kwargs['__section__'], n=c.comm) raise exceptions.CommandException(msg) if cls.is_snippet_call(c.comm): # we're calling a snippet => add files and files_dir to kwargs snippet = yaml_snippet_loader.YamlSnippetLoader.get_snippet_by_name(c.comm.split('.')[0]) c.kwargs['__files__'].append(snippet.get_files_section()) c.kwargs['__files_dir__'].append(snippet.get_files_dir()) c.kwargs['__sourcefiles__'].append(snippet.path) if sect_type == 'dependencies': result = lang.dependencies_section(section, copy.deepcopy(c.kwargs), runner=assistant) else: result = lang.run_section(section, copy.deepcopy(c.kwargs), runner=assistant) if cls.is_snippet_call(c.comm): c.kwargs['__files__'].pop() c.kwargs['__files_dir__'].pop() c.kwargs['__sourcefiles__'].pop() return result
def test_catch(self): kwargs = {} res = run_section( [{'catch $x, $y': [{'cl': 'ls this_doesnt_exist_and_thus_will_raise'}]}], kwargs) assert res[0] == True assert res[1] != ''
def run(cls, c): c.kwargs['__scls__'].append(c.comm_type.split()[1:]) retval = lang.run_section(c.comm, c.kwargs, runner=c.kwargs['__assistant__']) c.kwargs['__scls__'].pop() return retval
def test_catch(self): kwargs = {} res = run_section([{ 'catch $x, $y': [{ 'cl': 'ls this_doesnt_exist_and_thus_will_raise' }] }], kwargs) assert res[0] == True assert res[1] != ''
def run(self, stage='', kwargs=None): # we can't use {} as a default for kwargs, as that initializes the dict only once in Python # and uses the same dict in all subsequent calls of this method if not kwargs: kwargs = {} self.proper_kwargs('run', kwargs) to_run = '_run' if stage: # if we have stage, always use that to_run = '_' + stage + '_run' elif self.role == 'mod': # try to get a section to run from the most specialized one to the least specialized one # e.g. first run_python_django, then run_python and then just run sa_path = kwargs.get('subassistant_path', []) for i in range(len(sa_path), -1, -1): possible_run = '_'.join(['_run'] + sa_path[:i]) if hasattr(self, possible_run): to_run = possible_run break lang.run_section(getattr(self, to_run, {}), kwargs, runner=self)
def run(self, stage='', kwargs=None): # we can't use {} as a default for kwargs, as that initializes the dict only once in Python # and uses the same dict in all subsequent calls of this method if not kwargs: kwargs = {} self.proper_kwargs('run', kwargs) to_run = '_run' if stage: # if we have stage, always use that to_run = '_' + stage + '_run' elif self.role == 'mod': # try to get a section to run from the most specialized one to the least specialized one # e.g. first run_python_django, then run_python and then just run sa_path = kwargs.get('subassistant_path', []) for i in range(len(sa_path), -1, -1): possible_run = '_'.join(['_run'] + sa_path[:i]) if hasattr(self, possible_run): to_run = possible_run break return lang.run_section(getattr(self, to_run, {}), kwargs, runner=self)
def run(cls, c): """SCLCommandRunner adds command processors to ClHelper in order to wrap commands in possibly multiple nested calls of "scl <action> <collection>". Note: Identical calls are ignored.""" # TODO: in 0.10.0, we can actually remove global __scls__, since we don't need them # due to the fact that we're creating closure in _get_scl_command_processor c.kwargs.setdefault("__scls__", []) c.kwargs.setdefault("__assistant__", None) c.kwargs["__scls__"].append(c.comm_type.split()[1:]) # a unique name for command processor comproc_name = c.comm_type # if such a command processor is already there, don't re-push/re-pop pushpop = comproc_name not in ClHelper.command_processors if pushpop: ClHelper.command_processors[comproc_name] = cls._get_scl_command_processor(c.kwargs["__scls__"][-1]) # use "c.comm", not "c.input_res" - we need unformatted input here retval = lang.run_section(c.comm, c.kwargs, runner=c.kwargs["__assistant__"]) if pushpop: ClHelper.command_processors.pop(comproc_name) return retval
def run(cls, c): c.kwargs.setdefault('__scls__', []) c.kwargs.setdefault('__assistant__', None) c.kwargs['__scls__'].append(c.comm_type.split()[1:]) def scl_command_processor(cmd_str): if cmd_str.startswith('cd '): return cmd_str scls = [] scls = functools.reduce(lambda x, y: x + y, c.kwargs['__scls__'], scls) cmd_str = 'scl {scls} - << DA_SCL_EOF\n {cmd_str} \nDA_SCL_EOF'.\ format(cmd_str=cmd_str, scls=' '.join(scls)) return cmd_str ClHelper.command_processors['scl_command_processor'] = scl_command_processor # use "c.comm", not "c.input_res" - we need unformatted input here retval = lang.run_section(c.comm, c.kwargs, runner=c.kwargs['__assistant__']) ClHelper.command_processors.pop('scl_command_processor') return retval
def test_nested_condition(self): rs = [{'if $foo': [{'if $bar': 'bar'}, {'else': [{'log_i': 'baz'}]}]}] self.assert_run_section_result(run_section(rs, {'foo': 'yes'}), [True, 'baz'])
def test_shell_command(self): rs = [{'$foo~': '$(echo asd)'}] self.assert_run_section_result(run_section(rs, {}), [True, 'asd'])
def test_looks_like_shell_command_but_no_exec_flag(self): rs = [{'$foo': '$(echo asd)'}] self.assert_run_section_result(run_section(rs, {}), [True, '$(echo asd)'])
def test_result(self): self.assert_run_section_result(run_section([]), [False, '']) self.assert_run_section_result(run_section([{'log_i': 'foo'}]), [True, 'foo'])
def test_run_unkown_command(self): with pytest.raises(exceptions.CommandException): run_section([{'foo': 'bar'}])
def test_assign_in_condition_modifies_outer_scope(self): kwargs = {'foo': 'foo', 'spam': 'spam'} run_section([{'if $foo': [{'$foo': '$spam'}]}], kwargs) assert kwargs['foo'] == 'spam'
def test_else(self): rs = [{'if $foo': [{'$foo': 'bar'}]}, {'else': [{'$foo': 'baz'}]}] self.assert_run_section_result(run_section(rs, {'foo': 'yes'}), [True, 'bar']) self.assert_run_section_result(run_section(rs, {}), [True, 'baz'])
def test_for_empty_string(self): kwargs = {} run_section([{'for $i in $(echo "")': [{'$foo': '$i'}]}], kwargs) assert 'foo' not in kwargs
def test_assing_string_with_escaped_exec_flag(self): kwargs = {} run_section([{'$foo': '~~/asd'}], kwargs) assert kwargs['foo'] == os.path.expanduser('~/asd')
def test_bool_literal_section(self): kwargs = {} run_section([{'$foo': True}], kwargs) assert kwargs['foo'] == True
def test_result(self): self.assert_run_section_result(run_section([]), [False, '']) self.assert_run_section_result(run_section([{ 'log_i': 'foo' }]), [True, 'foo'])
def test_loop_two_control_vars_fails_on_string(self, iter_type): # this should work the same for both iteration types with pytest.raises(exceptions.YamlSyntaxError): run_section([{'for $i, $j {0} $(echo "foo bar")'.format(iter_type): [{'log_i': '$i'}]}])
def test_assign_in_condition_modifies_outer_scope(self): kwargs={'foo': 'foo', 'spam': 'spam'} run_section([{'if $foo': [{'$foo': '$spam'}]}], kwargs) assert kwargs['foo'] == 'spam'
def test_successful_command_with_no_output_evaluates_to_true(self): kwargs = {} run_section([{'if $(true)': [{'$success': 'success'}]}], kwargs) assert 'success' in kwargs
def run(self): to_run = self.gather_input(self.kwargs['input']) parsed = yaml.load(to_run, Loader=Loader) lang.run_section(parsed.get('run', []), parsed.get('ctxt', {}))
def test_assign_defined_nonexistent_variable(self): kwargs = {} run_section([{'$success, $val~': 'defined $foo'}], kwargs) assert kwargs['success'] == False assert kwargs['val'] == ''
def test_assign_defined_variable(self): kwargs = {'foo': 'foo'} run_section([{'$success, $val~': 'defined $foo'}], kwargs) assert kwargs['success'] == True assert kwargs['val'] == 'foo'
def run(cls, **kwargs): to_run = cls.gather_input(kwargs['input']) parsed = yaml.load(to_run, Loader=Loader) lang.run_section(parsed.get('run', []), parsed.get('ctxt', {}))