Example #1
0
 def get_ui(self, version):
     actual_version = "1.0.0"
     if Utility.compare_versions(version, actual_version) > 0:
         raise NotImplementedError(
             "API requested version %s is greater than %s." %
             (version, actual_version))
     return Declarative.DeclarativeUI()
Example #2
0
 def get_interactive(self, version=None):
     actual_version = "1.0.0"
     if Utility.compare_versions(version, actual_version) > 0:
         raise NotImplementedError(
             "API requested version %s is greater than %s." %
             (version, actual_version))
     return interactive_session
    def get_api(self, version):
        actual_version = "1.0.0"
        if Utility.compare_versions(version, actual_version) > 0:
            raise NotImplementedError("Camera API requested version %s is greater than %s." % (version, actual_version))

        class CameraFacade:

            def __init__(self):
                pass

        return CameraFacade()
Example #4
0
def load_plug_ins(document_location: str, data_location: str, root_dir: typing.Optional[str]) -> None:
    """Load plug-ins."""
    global extensions

    # a list of directories in which sub-directories PlugIns will be searched.
    subdirectories = []

    # the default location is where the directory main packages are located.
    if root_dir:
        subdirectories.append(root_dir)

    # also search the default data location; create directory there if it doesn't exist to make it easier for user.
    # default data location will be application specific.
    if data_location is not None:
        subdirectories.append(data_location)
        # create directories here if they don't exist
        plugins_dir = os.path.abspath(os.path.join(data_location, "PlugIns"))
        if not os.path.exists(plugins_dir):
            logging.info("Creating plug-ins directory %s", plugins_dir)
            os.makedirs(plugins_dir)

    # search the Nion/Swift subdirectory of the default document location too,
    # but don't create directories here - avoid polluting user visible directories.
    if document_location is not None:
        subdirectories.append(os.path.join(document_location, "Nion", "Swift"))
        # do not create them in documents if they don't exist. this location is optional.

    # build a list of directories that will be loaded as plug-ins.
    PlugInDir = collections.namedtuple("PlugInDir", ["directory", "relative_path"])
    plugin_dirs = list()

    # track directories that have already been searched.
    seen_plugin_dirs = list()

    # for each subdirectory, look in PlugIns for sub-directories that represent the plug-ins.
    for subdirectory in subdirectories:
        plugins_dir = os.path.abspath(os.path.join(subdirectory, "PlugIns"))

        if os.path.exists(plugins_dir) and not plugins_dir in seen_plugin_dirs:
            logging.info("Loading plug-ins from %s", plugins_dir)

            # add the PlugIns directory to the system import path.
            sys.path.append(plugins_dir)

            # now build a list of sub-directories representing plug-ins within plugins_dir.
            sorted_relative_paths = sorted([d for d in os.listdir(plugins_dir) if os.path.isdir(os.path.join(plugins_dir, d))])
            plugin_dirs.extend([PlugInDir(plugins_dir, sorted_relative_path) for sorted_relative_path in sorted_relative_paths])

            # mark plugins_dir as 'seen' to avoid search it twice.
            seen_plugin_dirs.append(plugins_dir)
        else:
            logging.info("NOT Loading plug-ins from %s (missing)", plugins_dir)

    version_map: PersistentDictType = dict()
    module_exists_map: typing.Dict[str, bool] = dict()

    plugin_adapters: typing.List[typing.Union[ModuleAdapter, PlugInAdapter]] = list()

    import nionswift_plugin
    for module_info in pkgutil.iter_modules(getattr(nionswift_plugin, "__path__")):
        plugin_adapters.append(ModuleAdapter(getattr(nionswift_plugin, "__name__"), module_info))

    for directory, relative_path in plugin_dirs:
        plugin_adapters.append(PlugInAdapter(directory, relative_path))

    progress = True
    while progress:
        progress = False
        plugin_adapters_copy = copy.deepcopy(plugin_adapters)
        plugin_adapters = list()
        for plugin_adapter in plugin_adapters_copy:
            manifest_path = plugin_adapter.manifest_path
            manifest = plugin_adapter.manifest
            if manifest:
                manifest_valid = True
                if not "name" in manifest:
                    logging.info("Invalid manifest (missing 'name'): %s", manifest_path)
                    manifest_valid = False
                if not "identifier" in manifest:
                    logging.info("Invalid manifest (missing 'identifier'): %s", manifest_path)
                    manifest_valid = False
                if "identifier" in manifest and not re.match("[_\-a-zA-Z][_\-a-zA-Z0-9.]*$", manifest["identifier"]):
                    logging.info("Invalid manifest (invalid 'identifier': '%s'): %s", manifest["identifier"], manifest_path)
                    manifest_valid = False
                if not "version" in manifest:
                    logging.info("Invalid manifest (missing 'version'): %s", manifest_path)
                    manifest_valid = False
                if "requires" in manifest and not isinstance(manifest["requires"], list):
                    logging.info("Invalid manifest ('requires' not a list): %s", manifest_path)
                    manifest_valid = False
                if not manifest_valid:
                    continue
                for module in manifest.get("modules", list()):
                    if module in module_exists_map:
                        module_exists = module_exists_map.get(module)
                    else:
                        module_exists = importlib.util.find_spec(module) is not None
                        module_exists_map[module] = module_exists
                    if not module_exists:
                        logging.info("Plug-in '" + plugin_adapter.module_name + "' NOT loaded (" + plugin_adapter.module_path + ").")
                        logging.info("Cannot satisfy requirement (%s): %s", module, manifest_path)
                        manifest_valid = False
                        break
                for requirement in manifest.get("requires", list()):
                    # TODO: see https://packaging.pypa.io/en/latest/
                    requirement_components = requirement.split()
                    if len(requirement_components) != 3 or requirement_components[1] != "~=":
                        logging.info("Invalid manifest (requirement '%s' invalid): %s", requirement, manifest_path)
                        manifest_valid = False
                        break
                    identifier, operator, version_specifier = requirement_components[0], requirement_components[1], requirement_components[2]
                    if identifier in version_map:
                        if Utility.compare_versions("~" + version_specifier, version_map[identifier]) != 0:
                            logging.info("Plug-in '" + plugin_adapter.module_name + "' NOT loaded (" + plugin_adapter.module_path + ").")
                            logging.info("Cannot satisfy requirement (%s): %s", requirement, manifest_path)
                            manifest_valid = False
                            break
                    else:
                        # requirements not loaded yet; add back to plugin_adapters, but don't mark progress since nothing was loaded.
                        logging.info("Plug-in '" + plugin_adapter.module_name + "' delayed (%s) (" + plugin_adapter.module_path + ").", requirement)
                        plugin_adapters.append(plugin_adapter)
                        manifest_valid = False
                        break
                if not manifest_valid:
                    continue
                version_map[manifest["identifier"]] = manifest["version"]
            # read the manifests, if any
            # repeat loop of plug-ins until no plug-ins left in the list
            #   if all dependencies satisfied for a plug-in, load it
            #   otherwise defer until next round
            #   stop if no plug-ins loaded in the round
            #   count on the user to have correct dependencies
            module = plugin_adapter.load()
            if module:
                __modules.append(module)
            progress = True
    for plugin_adapter in plugin_adapters:
        logging.info("Plug-in '" + plugin_adapter.module_name + "' NOT loaded (requirements) (" + plugin_adapter.module_path + ").")

    notify_modules("run")
Example #5
0
 def get_interactive(self, version: typing.Optional[str] = None) -> typing.Any:
     actual_version = "1.0.0"
     if Utility.compare_versions(version or str(), actual_version) > 0:
         raise NotImplementedError("API requested version %s is greater than %s." % (version, actual_version))
     return interactive_session