def collect_test_references(root, included_files, filter_package, filter_module, filter_testname, test_prefix): """ Finds the test references based on the expression provided and the excludes for this class. The `find_test_references` method is intended to be called multiple times, once with each include expression provided by the users. :param expression: An include expression to process and collect references for. """ test_references = {} import_errors = {} root_pkgname = os.path.basename(root) # Go through the files and import them, then go through the classes and find the TestPack and # TestContainer objects that match the specified include expression criteria rootlen = len(root) for ifile in included_files: modname = None try: ifilebase, _ = os.path.splitext(ifile) ifileleaf = ifilebase[rootlen:].strip("/") modname = "{}.{}".format(root_pkgname, ifileleaf.replace("/", ".")) # Import the module for the file being processed mod = import_by_name(modname) # Go through all of the members of the candidate_function_coll = inspect.getmembers( mod, inspect.isfunction) for function_name, function_obj in candidate_function_coll: cand_module_name = function_obj.__module__ # We only want to include the classes that are from the target module if cand_module_name != modname: continue if function_name.startswith(test_prefix): if filter_testname is not None: # If we have a testname expression only add a reference to the test function # if the function_name matches the filter expression if fnmatch.fnmatch(function_name, filter_testname): tref = TestRef(function_obj) test_references[tref.test_name] = tref else: tref = TestRef(function_obj) test_references[tref.test_name] = tref except ImportError: errmsg = traceback.format_exc() print(errmsg) import_errors[ifile] = (modname, ifile, errmsg) import_errors.update(import_errors) for modname, ifile, errmsg in import_errors.values(): logger.error("TestCase: Import error filename=%r" % ifile) return test_references, import_errors
def collect_extensions_under_code_container(container: ModuleType, ext_base_type: type) -> List[type]: """ Scans the code `container` provide and all descendant containers for classes that inherit from the type passed as `ext_base_type` :param container: A python package or module to scan for extension types. :param ext_base_type: A python class type that serves as a base class to identify other types that are a type of extension. :returns: A list of types found that inherit from `ext_base_type` """ ext_collection = [] # This is declare here so it can be used as a closure nxtmod = None def is_extension_class(obj): result = False if inspect.isclass(obj): obj_container = obj.__module__ if obj_container == nxtmod.__name__ and LoadableExtension in obj.__bases__: result = issubclass(obj, ext_base_type) and obj is not ext_base_type return result container_name = container.__name__ container_dir = get_directory_for_code_container(container) container_parts = container_name.split(".") container_root = os.sep.join( container_dir.split(os.sep)[:-len(container_parts)]) rootlen = len(container_root) for dirpath, _, filenames in os.walk(container_dir): leafdir = dirpath[rootlen:].lstrip(os.sep) leafcontainer = leafdir.replace(os.sep, ".") for nxtfile in filenames: nfbase, nfext = os.path.splitext(nxtfile) if nfext != ".py": continue if nfbase == "__init__": nxtmodname = "%s" % (leafcontainer) else: nxtmodname = "%s.%s" % (leafcontainer, nfbase) nxtmod = import_by_name(nxtmodname) if nxtmod is None: continue ext_collection.extend( inspect.getmembers(nxtmod, predicate=is_extension_class)) return ext_collection
def execute_workflow(logger, *, environment: dict, parameters: dict, tasklist: list, **kwargs): # Publish the environment variables so they will take effect in the current # process and any sub-processes lauched from this process for key, val in environment.items(): os.environ[key] = val result_code = 0 task_ordinal = 1 for task_info in tasklist: task_label = task_info["label"] tasktype = task_info["tasktype"] task_module_name, task_module_class = tasktype.split("@") task_module = import_by_name(task_module_name) failure_section = None if hasattr(task_module, task_module_class): task_class = getattr(task_module, task_module_class) task_instance = task_class(task_ordinal, task_label, task_info, logger) if failure_section is not None: section = task_instance.section if failure_section == section: failure_section = None else: # Skip ahead until we file the failure section continue task_result = task_instance.execute(parameters=parameters, **kwargs) if task_result != 0: result_code = 1 if task_instance.onfailure is not None: failure_section = task_instance.onfailure else: error_msg = "The specified task module %r does not contain a class %r" % ( task_module_name, task_module_class) raise AKitConfigurationError(error_msg) from None return result_code
def __init__(self): """ Initializes the Singleton initializer class """ thisType = type(self) if not thisType._initialized: thisType._initialized = True self._dyn_embedded_device_registry = {} self._dyn_root_device_registry = {} self._dyn_service_registry = {} self._std_embedded_device_registry = {} self._std_root_device_registry = {} self._std_service_registry = {} dyn_ext_module = None dyn_ext_module_name = AKIT_VARIABLES.AKIT_UPNP_DYN_EXTENSIONS_MODULE if dyn_ext_module_name is not None: dyn_ext_module = import_by_name(dyn_ext_module_name) dyn_ext_folder = AKIT_VARIABLES.AKIT_UPNP_EXTENSIONS_INTEGRATION_BASE if dyn_ext_module is not None: self._scan_for_device_extensions_under_code_container( dyn_ext_module, self._dyn_root_device_registry) self._scan_for_service_extensions_under_code_container( dyn_ext_module, self._dyn_service_registry) elif dyn_ext_folder is not None: self._scan_for_device_extensions_under_folder( dyn_ext_folder, self._dyn_root_device_registry) self._scan_for_service_extensions_under_folder( dyn_ext_folder, self._dyn_service_registry) self._scan_for_device_extensions_under_code_container( standard_extensions, self._std_root_device_registry) self._scan_for_service_extensions_under_code_container( standard_extensions, self._std_service_registry) return
def is_subclass_of_extension_points(cand_type): """ Returns a boolean value indicating if the candidate type is a subclass of :class:`Landscape`. """ is_scoep = False if inspect.isclass(cand_type) and issubclass(cand_type, AKitExtensionPoints): is_scoep = True return is_scoep def load_and_set_extension_points_type(lscape_module): """ Scans the module provided for :class:`Landscape` derived classes and will take the first one and assign it as the current runtime landscape type. """ class_items = inspect.getmembers(lscape_module, is_subclass_of_extension_points) for _, cls_type in class_items: type_module_name = cls_type.__module__ if type_module_name == lscape_module.__name__: AKitExtensionPoints._extension_points_type = cls_type # pylint: disable=protected-access break return if AKIT_VARIABLES.AKIT_CONFIG_EXTENSION_POINTS_MODULE != "akit.extensionpoints": ep_module_override = import_by_name( AKIT_VARIABLES.AKIT_CONFIG_EXTENSION_POINTS_MODULE) load_and_set_extension_points_type(ep_module_override)
def command_akit_jobs_run(root, job, output, start, branch, build, flavor, console_level, logfile_level): # pylint: disable=unused-import,import-outside-toplevel # We do the imports of the automation framework code inside the action functions because # we don't want to startup loggin and the processing of inputs and environment variables # until we have entered an action method. Thats way we know how to setup the environment. # IMPORTANT: We need to load the context first because it will trigger the loading # of the default user configuration from akit.environment.context import Context from akit.compat import import_by_name from akit.environment.variables import extend_path try: ctx = Context() ctx.insert("/environment/jobtype", 'testrun') test_root = os.path.abspath(os.path.expandvars(os.path.expanduser(root))) if not os.path.isdir(test_root): errmsg = "The specified root folder does not exist. root=%s" % root if test_root != root: errmsg += " expanded=%s" % test_root raise argparse.ArgumentError("--root", errmsg) # Make sure we extend PATH to include the test root extend_path(test_root) # We perform activation a little later in the testrunner.py file so we can # handle exceptions in the context of testrunner_main function import akit.activation.testrun from akit.xlogging.foundations import logging_initialize, getAutomatonKitLogger # Initialize logging logging_initialize() logger = getAutomatonKitLogger() from akit.extensionpoints import AKitExtensionPoints akep = AKitExtensionPoints() # At this point in the code, we either lookup an existing test job or we create a test job # from the includes, excludes or test_module TestJobType = akep.get_testplus_default_job_type() if job is not None: job_parts = job.split("@") if len(job_parts) != 2: errmsg = "A --job parameter must be of the form 'package.module@JobClass'" raise click.UsageError(errmsg) job_package, job_class = job_parts try: job_mod = import_by_name(job_package) except ImportError as imperr: errmsg = "Failure while importing job package %r" % job_package raise argparse.ArgumentError("--job", errmsg) from imperr if not hasattr(job_mod, job_class): errmsg = "The job package %r does not have a job type %r." % (job_package, job_class) raise argparse.ArgumentError("--job", errmsg) TestJobType = getattr(job_mod, job_class) result_code = 0 with TestJobType(logger, test_root) as tjob: result_code = tjob.execute() sys.exit(result_code) finally: pass return
def load_and_set_landscape_type(lscape_module): """ Scans the module provided for :class:`Landscape` derived classes and will take the first one and assign it as the current runtime landscape type. """ class_items = inspect.getmembers(lscape_module, is_subclass_of_landscape) for _, cls_type in class_items: type_module_name = cls_type.__module__ if type_module_name == lscape_module.__name__: Landscape._landscape_type = cls_type # pylint: disable=protected-access break return if AKIT_VARIABLES.AKIT_CONFIG_LANDSCAPE_MODULE is not None: lscape_module_override = import_by_name( AKIT_VARIABLES.AKIT_CONFIG_LANDSCAPE_MODULE) load_and_set_landscape_type(lscape_module_override) # We need to ensure that the first time this module is loaded that we trigger # the initialization of the landscape and that we activate the configuration first_landscape = Landscape() first_landscape.activate_configuration() def startup_landscape(include_ssh: bool = True, include_upnp: bool = True, allow_missing_devices: bool = False, allow_unknown_devices: bool = False, validate_topology: bool = True, interactive: Optional[bool] = None) -> Landscape: """