def test_xfunction_import_error(self): """Test for error on importing a xtrigger function. To prevent the test eventually failing if the test function is added and successfully imported, we use an invalid module name as per Python spec. """ with TemporaryDirectory() as temp_dir: with self.assertRaises(ModuleNotFoundError): get_func("invalid-module-name", temp_dir)
def test_xfunction_attribute_error(self): """Test for error on looking for an attribute in a xtrigger script.""" with TemporaryDirectory() as temp_dir: python_dir = Path(temp_dir, "lib", "python") python_dir.mkdir(parents=True) the_answer_file = python_dir / "the_sword.py" with the_answer_file.open(mode="w") as f: f.write("""the_droid = lambda: 'excalibur'""") f.flush() with self.assertRaises(AttributeError): get_func("the_sword", temp_dir)
def test_xfunction_cache(self): """Test xtrigger function import cache.""" with TemporaryDirectory() as temp_dir: python_dir = Path(temp_dir, "lib", "python") python_dir.mkdir(parents=True) amandita_file = python_dir / "amandita.py" with amandita_file.open(mode="w") as f: f.write("""amandita = lambda: 'chocolate'""") f.flush() fn = get_func("amandita", temp_dir) result = fn() self.assertEqual('chocolate', result) # is in the cache self.assertTrue('amandita' in _XTRIG_FUNCS) # returned from cache self.assertEqual(fn, get_func("amandita", temp_dir)) del _XTRIG_FUNCS['amandita'] # is not in the cache self.assertFalse('amandita' in _XTRIG_FUNCS)
def test_xfunction(self): """Test xtrigger function import.""" with TemporaryDirectory() as temp_dir: python_dir = Path(temp_dir, "lib", "python") python_dir.mkdir(parents=True) the_answer_file = python_dir / "the_answer.py" with the_answer_file.open(mode="w") as f: f.write("""the_answer = lambda: 42""") f.flush() fn = get_func("the_answer", temp_dir) result = fn() self.assertEqual(42, result)
def validate_xtrigger(fname: str, fdir: str): """Validate an Xtrigger function. Args: fname (str): function name fdir(str): function directory Raises: ImportError: if the function module was not found AttributeError: if the function was not found in the xtrigger module ValueError: if the function is not callable """ try: func = get_func(fname, fdir) except ImportError: raise ImportError(f"ERROR: xtrigger module '{fname}' not found") except AttributeError: raise AttributeError( f"ERROR: '{fname}' not found in xtrigger module '{fname}'") if not callable(func): raise ValueError( f"ERROR: '{fname}' not callable in xtrigger module '{fname}'")
def validate_xtrigger(label: str, fctx: SubFuncContext, fdir: str) -> None: """Validate an Xtrigger function. Args: label: xtrigger label fctx: function context fdir: function directory Raises: ImportError: if the function module was not found AttributeError: if the function was not found in the xtrigger module ValueError: if the function is not callable ValueError: if any string template in the function context arguments are not present in the expected template values. """ fname: str = fctx.func_name try: func = get_func(fname, fdir) except ImportError: raise ImportError( f"ERROR: xtrigger module '{fname}' not found") except AttributeError: raise AttributeError( f"ERROR: '{fname}' not found in xtrigger module '{fname}'") if not callable(func): raise ValueError( f"ERROR: '{fname}' not callable in xtrigger module '{fname}'") # Check any string templates in the function arg values (note this # won't catch bad task-specific values - which are added dynamically). for argv in fctx.func_args + list(fctx.func_kwargs.values()): try: for match in RE_STR_TMPL.findall(argv): if match not in ARG_VAL_TEMPLATES: raise ValueError( f"Illegal template in xtrigger {label}: {match}") except TypeError: # Not a string arg. continue
def validate_xtrigger(label: str, fctx: SubFuncContext, fdir: str) -> None: """Validate an Xtrigger function. Args: label: xtrigger label fctx: function context fdir: function directory Raises: XtriggerConfigError: * If the function module was not found. * If the function was not found in the xtrigger module. * If the function is not callable. * If any string template in the function context arguments are not present in the expected template values. """ fname: str = fctx.func_name try: func = get_func(fname, fdir) except ImportError: raise XtriggerConfigError( label, fname, f"xtrigger module '{fname}' not found", ) except AttributeError: raise XtriggerConfigError( label, fname, f"'{fname}' not found in xtrigger module '{fname}'", ) if not callable(func): raise XtriggerConfigError( label, fname, f"'{fname}' not callable in xtrigger module '{fname}'", ) # Check any string templates in the function arg values (note this # won't catch bad task-specific values - which are added dynamically). template_vars = set() for argv in fctx.func_args + list(fctx.func_kwargs.values()): if not isinstance(argv, str): # Not a string arg. continue # check template variables are valid for match in RE_STR_TMPL.findall(argv): try: template_vars.add(TemplateVariables(match)) except ValueError: raise XtriggerConfigError( label, fname, f"Illegal template in xtrigger: {match}", ) # check for deprecated template variables deprecated_variables = template_vars & { TemplateVariables.WorkflowName, TemplateVariables.SuiteName, TemplateVariables.SuiteRunDir, TemplateVariables.SuiteShareDir, } if deprecated_variables: LOG.warning( f'Xtrigger "{label}" uses deprecated template variables:' f' {", ".join(t.value for t in deprecated_variables)}')