class WebView(object): def __init__(self, driver, timeout, pm=None): self.driver = driver self.driver_adapter = IDriver(driver) self.timeout = timeout self.pm = pm if self.pm is None: self.pm = PluginManager("pypom", implprefix="pypom_") self.pm.add_hookspecs(hooks) self.pm.load_setuptools_entrypoints("pypom.plugin") self.pm.check_pending() self.wait = self.driver_adapter.wait_factory(self.timeout) @property def selenium(self): """Backwards compatibility attribute""" warn("use driver instead", DeprecationWarning, stacklevel=2) return self.driver def find_element(self, strategy, locator): return self.driver_adapter.find_element(strategy, locator) def find_elements(self, strategy, locator): """Finds elements on the page. :param strategy: Location strategy to use. See :py:class:`~selenium.webdriver.common.by.By` or :py:attr:`~pypom.splinter_driver.ALLOWED_STRATEGIES`. :param locator: Location of target elements. :type strategy: str :type locator: str :return: List of :py:class:`~selenium.webdriver.remote.webelement.WebElement` or :py:class:`~splinter.element_list.ElementList` :rtype: list """ return self.driver_adapter.find_elements(strategy, locator) def is_element_present(self, strategy, locator): """Checks whether an element is present. :param strategy: Location strategy to use. See :py:class:`~selenium.webdriver.common.by.By` or :py:attr:`~pypom.splinter_driver.ALLOWED_STRATEGIES`. :param locator: Location of target element. :type strategy: str :type locator: str :return: ``True`` if element is present, else ``False``. :rtype: bool """ return self.driver_adapter.is_element_present(strategy, locator) def is_element_displayed(self, strategy, locator): """Checks whether an element is displayed. :param strategy: Location strategy to use. See :py:class:`~selenium.webdriver.common.by.By` or :py:attr:`~pypom.splinter_driver.ALLOWED_STRATEGIES`. :param locator: Location of target element. :type strategy: str :type locator: str :return: ``True`` if element is displayed, else ``False``. :rtype: bool """ return self.driver_adapter.is_element_displayed(strategy, locator)
def test_load_setuptools_instantiation(monkeypatch, pm: PluginManager) -> None: class EntryPoint: name = "myname" group = "hello" value = "myname:foo" def load(self): class PseudoPlugin: x = 42 return PseudoPlugin() class Distribution: entry_points = (EntryPoint(), ) dist = Distribution() def my_distributions(): return (dist, ) monkeypatch.setattr(importlib_metadata, "distributions", my_distributions) num = pm.load_setuptools_entrypoints("hello") assert num == 1 plugin = pm.get_plugin("myname") assert plugin is not None assert plugin.x == 42 ret = pm.list_plugin_distinfo() # poor man's `assert ret == [(plugin, mock.ANY)]` assert len(ret) == 1 assert len(ret[0]) == 2 assert ret[0][0] == plugin assert ret[0][1]._dist == dist # type: ignore[comparison-overlap] num = pm.load_setuptools_entrypoints("hello") assert num == 0 # no plugin loaded by this call
def get_pluginmanager(): pm = PluginManager("devpiserver", implprefix="devpiserver_") pm.add_hookspecs(hookspecs) # XXX load internal plugins here pm.load_setuptools_entrypoints("devpi_server") pm.check_pending() return pm
def get_pluginmanager(load_entry_points=True): pm = PluginManager("devpiclient", implprefix="devpiclient_") pm.add_hookspecs(hookspecs) if load_entry_points: pm.load_setuptools_entrypoints("devpi_client") pm.check_pending() return pm
def get_pluginmanager(load_entry_points=True): pm = PluginManager("devpipasswdreset", implprefix="devpipasswdreset_") pm.add_hookspecs(hookspecs) if load_entry_points: pm.load_setuptools_entrypoints("devpi_passwd_reset") pm.check_pending() return pm
def get_pluggin_manager(load_entrypoints=True): pm = PluginManager('banana', implprefix='banana_') pm.add_hookspecs(hookspecs) if load_entrypoints: pm.load_setuptools_entrypoints('banana') pm.check_pending() return pm
def get_serializers(refresh_cache=False): """Discover and return Serializer classes from all installed plugins Serializers are cached and are not repeatedly loaded in future calls Args: refresh_cache (bool): If True, ignore any existing serializer cache and discover serializers as normal Returns: dict: Keys are the formats provided by and pointing to their respective Serializers """ global _serializer_cache if _serializer_cache is None or refresh_cache: from pluggy import PluginManager package_name = __name__.split('.')[0] pm = PluginManager(package_name) pm.load_setuptools_entrypoints(package_name + '.serializers') for mod in pm.get_plugins(): import_submodules(mod) _serializer_cache = {} for serializer_class in get_recursive_subclasses(Serializer): if not serializer_class.format: logger.warning( 'Serializer "{}" does not provide a format, will not be auto-discovered' .format(get_full_qualname(serializer_class))) continue _serializer_cache[serializer_class.format] = serializer_class return _serializer_cache
def get_pluginmanager(load_entrypoints=True): pm = PluginManager("devpiserver", implprefix="devpiserver_") pm.add_hookspecs(hookspecs) # XXX load internal plugins here if load_entrypoints: pm.load_setuptools_entrypoints("devpi_server") pm.check_pending() return pm
def get_pluginmanager(config, load_entry_points=True): pm = PluginManager("devpiweb") # support old plugins, but emit deprecation warnings pm._implprefix = "devpiweb_" pm.add_hookspecs(hookspecs) if load_entry_points: pm.load_setuptools_entrypoints("devpi_web") pm.check_pending() return pm
def get_plugin_manager() -> PluginManager: """ Get a plugin manager that the entry points and the default implementation are already loaded. """ manager = PluginManager("preacher") manager.add_hookspecs(hookspec) manager.load_setuptools_entrypoints("preacher") return manager
def get_pluginmanager(load_entrypoints=True): pm = PluginManager("devpiserver") # support old plugins, but emit deprecation warnings pm._implprefix = "devpiserver_" pm.add_hookspecs(hookspecs) # XXX load internal plugins here if load_entrypoints: pm.load_setuptools_entrypoints("devpi_server") pm.check_pending() return pm
class SimplePluginManager(object): """ A PluginManager class for simple, non-scanning related plugins. """ def __init__(self, project_name, entrypoint, plugin_base_class): """ Initialize this plugin manager for the fully qualified Python module name `module_qname` with plugins loaded from the setuptools `entrypoint` that must subclass `plugin_base_class`. """ self.manager = PluggyPluginManager(project_name=project_name) self.entrypoint = entrypoint self.plugin_base_class = plugin_base_class self.manager.add_hookspecs(sys.modules[project_name]) # set to True once this manager is initialized by running its setup() self.initialized = False # mapping of {plugin.name: plugin_class} for all the loaded plugins of # this manager self.plugin_classes = OrderedDict() def setup(self): """ Load and validate available plugins for this PluginManager from its assigned `entrypoint`. Raise an Exception if a plugin is not valid such that when it does not subcclass the manager `plugin_base_class`. Must be called once to initialize the plugins if this manager. Return a list of all plugin classes for this manager. """ if self.initialized: return self.plugin_classes.values() entrypoint = self.entrypoint self.manager.load_setuptools_entrypoints(entrypoint) plugin_classes = [] for name, plugin_class in self.manager.list_name_plugin(): if not issubclass(plugin_class, self.plugin_base_class): plugin_base_class = self.plugin_base_class raise Exception( 'Invalid plugin: %(name)r: %(plugin_class)r ' 'must extend %(plugin_base_class)r.' % locals()) plugin_class.name = name plugin_classes.append(plugin_class) self.plugin_classes = OrderedDict([(cls.name, cls) for cls in plugin_classes]) self.initialized = True return self.plugin_classes.values()
def get_pluginmanager(config, load_entry_points=True): # lookup cached value pm = getattr(config, 'devpiweb_pluginmanager', None) if pm is not None: return pm pm = PluginManager("devpiweb") # support old plugins, but emit deprecation warnings pm._implprefix = "devpiweb_" pm.add_hookspecs(hookspecs) if load_entry_points: pm.load_setuptools_entrypoints("devpi_web") pm.check_pending() # cache the expensive setup config.devpiweb_pluginmanager = pm return pm
def create_app(): pm = PluginManager('fp') pm.add_hookspecs(hooks) pm.register(impl) pm.load_setuptools_entrypoints('flaskplug') app = Flask(__name__) for bp in pm.hook.fp_load_blueprints(): if isinstance(bp, dict): app.register_blueprint(**bp) elif isinstance(bp, tuple): app.register_blueprint(bp[0], **bp[1]) else: app.register_blueprint(bp) return app
def _register_hooks_setuptools( hook_manager: PluginManager, disabled_plugins: Iterable[str] ) -> None: """Register pluggy hooks from setuptools entrypoints. Args: hook_manager: Hook manager instance to register the hooks with. disabled_plugins: An iterable returning the names of plugins which hooks must not be registered; any already registered hooks will be unregistered. """ already_registered = hook_manager.get_plugins() hook_manager.load_setuptools_entrypoints(_PLUGIN_HOOKS) disabled_plugins = set(disabled_plugins) # Get list of plugin/distinfo tuples for all setuptools registered plugins. plugininfo = hook_manager.list_plugin_distinfo() plugin_names = set() disabled_plugin_names = set() for plugin, dist in plugininfo: if dist.project_name in disabled_plugins: # `unregister()` is used instead of `set_blocked()` because # we want to disable hooks for specific plugin based on project # name and not `entry_point` name. Also, we log project names with # version for which hooks were registered. hook_manager.unregister(plugin=plugin) disabled_plugin_names.add(f"{dist.project_name}-{dist.version}") elif plugin not in already_registered: plugin_names.add(f"{dist.project_name}-{dist.version}") if disabled_plugin_names: logger.info( "Hooks are disabled for plugin(s): %s", ", ".join(sorted(disabled_plugin_names)), ) if plugin_names: logger.info( "Registered hooks from %d installed plugin(s): %s", len(plugin_names), ", ".join(sorted(plugin_names)), )
from pluggy import PluginManager from . import hookspec, PROJECT_NAME # TODO: move to main? manager = PluginManager(PROJECT_NAME) manager.add_hookspecs(hookspec) manager.load_setuptools_entrypoints('gumby.plugin')
class PluginManager(object): """ A PluginManager class for scanning-related plugins. """ # a global managers cache as a mapping of {stage: manager instance} managers = {} def __init__(self, stage, module_qname, entrypoint, plugin_base_class): """ Initialize this plugin manager for the `stage` specified in the fully qualified Python module name `module_qname` with plugins loaded from the setuptools `entrypoint` that must subclass `plugin_base_class`. """ self.manager = PluggyPluginManager(project_name=stage) self.managers[stage] = self self.stage = stage self.entrypoint = entrypoint self.plugin_base_class = plugin_base_class self.manager.add_hookspecs(sys.modules[module_qname]) # set to True once this manager is initialized by running its setup() self.initialized = False # list of plugin_class for all the plugins of this manager self.plugin_classes = [] @classmethod def load_plugins(cls): """ Setup the plugins enviroment. Must be called once to initialize all the plugins of all managers. """ plugin_classes = [] plugin_options = [] for stage, manager in cls.managers.items(): mgr_setup = manager.setup() if not mgr_setup: msg = 'Cannot load plugins for stage: %(stage)s' % locals() raise PlugincodeError(msg) mplugin_classes, mplugin_options = mgr_setup plugin_classes.extend(mplugin_classes) plugin_options.extend(mplugin_options) return plugin_classes, plugin_options def setup(self): """ Return a tuple of (list of all plugin classes, list of all options of all plugin classes). Load and validate available plugins for this PluginManager from its assigned `entrypoint`. Raise a PlugincodeError if a plugin is not valid such that when it does not subcclass the manager `plugin_base_class`. Must be called once to setup the plugins of this manager. """ if self.initialized: return entrypoint = self.entrypoint try: self.manager.load_setuptools_entrypoints(entrypoint) except ImportError as e: raise e stage = self.stage plugin_options = [] plugin_classes = [] required_plugins = set() for name, plugin_class in self.manager.list_name_plugin(): if not issubclass(plugin_class, self.plugin_base_class): qname = '%(stage)s:%(name)s' % locals() plugin_base_class = self.plugin_base_class raise PlugincodeError( 'Invalid plugin: %(qname)r: %(plugin_class)r ' 'must extend %(plugin_base_class)r.' % locals()) for option in plugin_class.options: if not isinstance(option, cliutils.PluggableCommandLineOption): qname = '%(stage)s:%(name)s' % locals() oname = option.name clin = cliutils.PluggableCommandLineOption raise PlugincodeError( 'Invalid plugin: %(qname)r: option %(oname)r ' 'must extend %(clin)r.' % locals()) plugin_options.append(option) plugin_class.stage = stage plugin_class.name = name plugin_classes.append(plugin_class) self.plugin_classes = sorted(plugin_classes, key=lambda c: (c.sort_order, c.name)) self.initialized = True return self.plugin_classes, plugin_options
def load_all_plugins(plugin_manager: PluginManager): plugin_manager.load_setuptools_entrypoints( "cfripper") # Dynamically load plugins using entry points plugin_manager.register(rules) # Register default rules