示例#1
0
文件: Plugins.py 项目: txf626/Nuitka
def loadUserPlugin(plugin_filename):
    """Load of a user plugins and store them in list of active plugins.

    Notes:
        A plugin is accepted only if it has a non-empty variable plugin_name, which
        does not equal that of a disabled (standard) plugin.
        Supports plugin option specifications.
    Returns:
        None
    """
    if not os.path.exists(plugin_filename):
        plugins_logger.sysexit("Error, cannot find '%s'." % plugin_filename)

    user_plugin_module = importFileAsModule(plugin_filename)

    valid_file = False
    plugin_class = None
    for key in dir(user_plugin_module):
        obj = getattr(user_plugin_module, key)
        if not isObjectAUserPluginBaseClass(obj):
            continue

        plugin_name = getattr(obj, "plugin_name", None)
        if plugin_name and plugin_name not in Options.getPluginsDisabled():
            plugin_class = obj

            valid_file = True
            break  # do not look for more in that module

    if not valid_file:  # this is not a plugin file ...
        plugins_logger.sysexit("Error, '%s' is not a plugin file." %
                               plugin_filename)

    return plugin_class
示例#2
0
def getPluginOptions(plugin_name):
    """Return the options values for the specified plugin.

    Args:
        plugin_name: plugin identifier
    Returns:
        dict with key, value of options given, potentially from default values.
    """
    result = plugin_values.get(plugin_name, {})

    for option in plugin_options.get(plugin_name, {}):
        option_name = option._long_opts[0]  # pylint: disable=protected-access

        arg_value = getattr(Options.options, option.dest)

        if "[REQUIRED]" in option.help:
            if not arg_value:
                plugins_logger.sysexit(
                    "Error, required plugin argument %r of Nuitka plugin %s not given."
                    % (option_name, plugin_name)
                )

        result[option.dest] = arg_value

    return result
示例#3
0
def getPluginClass(plugin_name):
    # First, load plugin classes, to know what we are talking about.
    loadPlugins()

    if plugin_name not in plugin_name2plugin_classes:
        plugins_logger.sysexit("Error, unknown plug-in '%s' referenced." % plugin_name)

    return plugin_name2plugin_classes[plugin_name][0]
示例#4
0
文件: Plugins.py 项目: txf626/Nuitka
def _loadPluginClassesFromPath(scan_path):
    for loader, name, is_pkg in pkgutil.iter_modules(scan_path):
        if is_pkg:
            continue

        module_loader = loader.find_module(name)

        # Ignore bytecode only left overs.
        try:
            if module_loader.get_filename().endswith(".pyc"):
                continue
        except AttributeError:
            # Not a bytecode loader, but e.g. extension module, which is OK in case
            # it was compiled with Nuitka.
            pass

        try:
            plugin_module = module_loader.load_module(name)
        except Exception:
            if Options.is_nondebug:
                plugins_logger.warning(
                    "Problem loading plugin %r (%s), ignored. Use --debug to make it visible."
                    % (name, module_loader.get_filename()))
                continue

            raise

        plugin_classes = set(obj for obj in plugin_module.__dict__.values()
                             if isObjectAUserPluginBaseClass(obj))

        detectors = [
            plugin_class for plugin_class in plugin_classes
            if hasattr(plugin_class, "detector_for")
        ]

        for detector in detectors:
            plugin_class = detector.detector_for
            assert detector.plugin_name is None, detector
            detector.plugin_name = plugin_class.plugin_name

            if plugin_class not in plugin_classes:
                plugins_logger.sysexit(
                    "Plugin detector %r references unknown plugin %r" %
                    (detector, plugin_class))

            plugin_classes.remove(detector)
            plugin_classes.remove(plugin_class)

            plugin_name2plugin_classes[plugin_class.plugin_name] = (
                plugin_class,
                detector,
            )

        for plugin_class in plugin_classes:
            plugin_name2plugin_classes[
                plugin_class.plugin_name] = plugin_class, None
示例#5
0
def activatePlugins():
    """Activate selected plugin classes

    Args:
        None

    Notes:
        This creates actual plugin instances, before only class objects were
        used.

        User plugins are activated as a first step, because they themselves may
        enable standard plugins.

    Returns:
        None
    """
    loadPlugins()

    # ensure plugin is known and not both, enabled and disabled
    for plugin_name in Options.getPluginsEnabled() + Options.getPluginsDisabled():
        if plugin_name not in plugin_name2plugin_classes:
            plugins_logger.sysexit(
                "Error, unknown plug-in '%s' referenced." % plugin_name
            )

        if (
            plugin_name in Options.getPluginsEnabled()
            and plugin_name in Options.getPluginsDisabled()
        ):
            plugins_logger.sysexit(
                "Error, conflicting enable/disable of plug-in '%s'." % plugin_name
            )

    for (plugin_name, (plugin_class, plugin_detector)) in sorted(
        plugin_name2plugin_classes.items()
    ):
        if plugin_name in Options.getPluginsEnabled():
            if plugin_class.isRelevant():
                _addActivePlugin(plugin_class, args=True)
            else:
                plugin_class.warning(
                    "Not relevant with this OS, or Nuitka arguments given, not activated."
                )
        elif plugin_name in Options.getPluginsDisabled():
            pass
        elif plugin_class.isAlwaysEnabled() and plugin_class.isRelevant():
            _addActivePlugin(plugin_class, args=True)
        elif (
            plugin_detector is not None
            and Options.shallDetectMissingPlugins()
            and plugin_detector.isRelevant()
        ):
            _addActivePlugin(plugin_detector, args=False)

    for plugin_class in user_plugins:
        _addActivePlugin(plugin_class, args=True)
示例#6
0
文件: Plugins.py 项目: psydox/Nuitka
def _addPluginClass(plugin_class, detector):
    plugin_name = plugin_class.plugin_name

    if plugin_name in plugin_name2plugin_classes:
        plugins_logger.sysexit("Error, plugins collide by name %s: %s <-> %s" %
                               (plugin_name, plugin_class,
                                plugin_name2plugin_classes[plugin_name]))

    plugin_name2plugin_classes[plugin_name] = (
        plugin_class,
        detector,
    )
示例#7
0
文件: Plugins.py 项目: psydox/Nuitka
def getPluginClass(plugin_name):
    # First, load plugin classes, to know what we are talking about.
    loadPlugins()

    # Backward compatibility.
    plugin_name = Options.getPluginNameConsideringRenames(plugin_name)

    if plugin_name not in plugin_name2plugin_classes:
        plugins_logger.sysexit("Error, unknown plug-in '%s' referenced." %
                               plugin_name)

    return plugin_name2plugin_classes[plugin_name][0]
示例#8
0
    def onModuleDiscovered(self, module):
        """Called with a module to be loaded.

        Notes:
            We may specify code to be prepended and/or appended to this module.
            This code is stored in the appropriate dict.
            For every imported module and each of these two options, only one plugin may do this.
            We check this condition here.

        Args:
            module: the module object
        Returns:
            None
        """

        full_name = module.getFullName()

        pre_code, reason = self.createPreModuleLoadCode(module)

        if pre_code:
            # Note: We could find a way to handle this if needed.
            if full_name in pre_modules:
                plugins_logger.sysexit(
                    "Error, conflicting pre module code from plug-ins for %s"
                    % full_name
                )

            self.info("Injecting pre-module load code for module '%s':" % full_name)
            for line in reason.split("\n"):
                self.info("    " + line)

            pre_modules[full_name] = self._createTriggerLoadedModule(
                module=module, trigger_name="-preLoad", code=pre_code
            )

        post_code, reason = self.createPostModuleLoadCode(module)

        if post_code:
            # Note: We could find a way to handle this if needed.
            if full_name is post_modules:
                plugins_logger.sysexit(
                    "Error, conflicting post module code from plug-ins for %s"
                    % full_name
                )

            self.info("Injecting post-module load code for module '%s':" % full_name)
            for line in reason.split("\n"):
                self.info("    " + line)

            post_modules[full_name] = self._createTriggerLoadedModule(
                module=module, trigger_name="-postLoad", code=post_code
            )
示例#9
0
文件: Plugins.py 项目: psydox/Nuitka
    def _createTriggerLoadedModule(cls, module, trigger_name, code, flags):
        """Create a "trigger" for a module to be imported.

        Notes:
            The trigger will incorporate the code to be prepended / appended.
            Called by @onModuleDiscovered.

        Args:
            module: the module object (serves as dict key)
            trigger_name: string ("preload"/"postload")
            code: the code string

        Returns
            trigger_module
        """

        from nuitka.tree.Building import buildModule

        module_name = makeTriggerModuleName(module.getFullName(), trigger_name)

        # In debug mode, put the files in the build folder, so they can be looked up easily.
        if Options.is_debug and "HIDE_SOURCE" not in flags:
            source_path = os.path.join(
                OutputDirectories.getSourceDirectoryPath(),
                module_name + ".py")

            putTextFileContents(filename=source_path, contents=code)

        try:
            trigger_module, _added = buildModule(
                module_filename=os.path.join(
                    os.path.dirname(module.getCompileTimeFilename()),
                    module_name.asPath() + ".py",
                ),
                module_name=module_name,
                source_code=code,
                is_top=False,
                is_main=False,
                is_extension=False,
                is_fake=module_name,
                hide_syntax_error=False,
            )
        except SyntaxError:
            plugins_logger.sysexit(
                "SyntaxError in plugin provided source code for '%s'." %
                module_name)

        if trigger_module.getCompilationMode() == "bytecode":
            trigger_module.setSourceCode(code)

        return trigger_module
示例#10
0
文件: Plugins.py 项目: psydox/Nuitka
def _addPluginCommandLineOptions(parser, plugin_class, data_files_tags):
    plugin_name = plugin_class.plugin_name

    if plugin_name not in plugin_options:
        option_group = OptionGroup(parser, "Plugin %s" % plugin_name)
        try:
            plugin_class.addPluginCommandLineOptions(option_group)
        except OptionConflictError as e:
            for other_plugin_name, other_plugin_option_list in plugin_options.items(
            ):
                for other_plugin_option in other_plugin_option_list:
                    # no public interface for that, pylint: disable=protected-access
                    if (e.option_id in other_plugin_option._long_opts
                            or other_plugin_option._short_opts):
                        plugins_logger.sysexit(
                            "Plugin '%s' failed to add options due to conflict with '%s' from plugin '%s."
                            % (plugin_name, e.option_id, other_plugin_name))

        if option_group.option_list:
            parser.add_option_group(option_group)
            plugin_options[plugin_name] = option_group.option_list
        else:
            plugin_options[plugin_name] = ()

        plugin_data_files_tags = plugin_class.getTagDataFileTagOptions()

        if plugin_data_files_tags:
            for tag_name, tag_desc in plugin_data_files_tags:
                if tag_name in (tag for tag, _desc in data_files_tags):
                    plugins_logger.sysexit(
                        "Plugin '%s' provides data files tag handling '%s' already provided."
                        % (plugin_name, tag_name))

                data_files_tags.append((tag_name, tag_desc))

                plugin_datatag2pluginclasses[tag_name] = plugin_class
示例#11
0
 def sysexit(cls, message):
     plugins_logger.sysexit(cls.plugin_name + ": " + message)
示例#12
0
文件: Plugins.py 项目: psydox/Nuitka
def _loadPluginClassesFromPackage(scan_package):
    scan_path = scan_package.__path__

    for item in iter_modules(scan_path):
        if item.ispkg:
            continue

        module_loader = item.module_finder.find_module(item.name)

        # Ignore bytecode only left overs.
        try:
            if module_loader.get_filename().endswith(".pyc"):
                continue
        except AttributeError:
            # Not a bytecode loader, but e.g. extension module, which is OK in case
            # it was compiled with Nuitka.
            pass

        try:
            plugin_module = module_loader.load_module(item.name)
        except Exception:
            if Options.is_nondebug:
                plugins_logger.warning(
                    "Problem loading plugin %r (%s), ignored. Use --debug to make it visible."
                    % (item.name, module_loader.get_filename()))
                continue

            raise

        # At least for Python2, this is not set properly, but we use it for package
        # data loading.
        plugin_module.__package__ = scan_package.__name__

        plugin_classes = set(obj for obj in plugin_module.__dict__.values()
                             if isObjectAUserPluginBaseClass(obj))

        detectors = [
            plugin_class for plugin_class in plugin_classes
            if hasattr(plugin_class, "detector_for")
        ]

        # First the ones with detectors.
        for detector in detectors:
            plugin_class = detector.detector_for

            if detector.__name__.replace("NuitkaPluginDetector",
                                         "") != plugin_class.__name__.replace(
                                             "NuitkaPlugin", ""):
                plugins_logger.warning(
                    "Class names %r and %r do not match NuitkaPlugin* and NuitkaPluginDetector* naming convention."
                    % (plugin_class.__name__, detector.__name__))

            assert detector.plugin_name is None, detector
            detector.plugin_name = plugin_class.plugin_name

            if plugin_class not in plugin_classes:
                plugins_logger.sysexit(
                    "Plugin detector %r references unknown plugin %r" %
                    (detector, plugin_class))

            plugin_classes.remove(detector)
            plugin_classes.remove(plugin_class)

            _addPluginClass(
                plugin_class=plugin_class,
                detector=detector,
            )

        # Remaining ones have no detector.
        for plugin_class in plugin_classes:
            _addPluginClass(plugin_class=plugin_class, detector=None)