def get_plugins(interface, package): """ Lazily find objects in a package which implement a given interface. The objects must also implement ``twisted.plugin.IPlugin``. This is a rewrite of Twisted's ``twisted.plugin.getPlugins`` which uses Exocet instead of Twisted to find the plugins. :param interface interface: the interface to match against :param str package: the name of the package to search """ p = getModule(package) for pm in p.iterModules(): try: m = load(pm, bravoMapper) for obj in vars(m).itervalues(): try: adapted = IPlugin(obj, None) adapted = interface(adapted, None) except: log.err() else: if adapted is not None: yield adapted except ImportError, ie: log.msg(ie)
def get_plugins(interface, package, parameters=None): """ Lazily find objects in a package which implement a given interface. If the optional dictionary of parameters is provided, it will be passed into each plugin module as the "bravo.parameters" module. An example access from inside the plugin: >>> from bravo.parameters import foo, bar Since the parameters are available as a real module, the parameters may be imported and used like any other module: >>> from bravo import parameters as params This is a rewrite of Twisted's ``twisted.plugin.getPlugins`` which uses Exocet instead of Twisted to find the plugins. :param interface interface: the interface to match against :param str package: the name of the package to search :param dict parameters: parameters to pass into the plugins """ mapper = bravoMapper # If parameters are provided, add them to the mapper in a synthetic # module. if parameters: mapper = mapper.withOverrides( {"bravo.parameters": synthesize_parameters(parameters)}) # This stack will let us iteratively recurse into packages during the # module search. stack = [getModule(package)] # While there are packages left to search... while stack: # For each package/module in the package... for pm in stack.pop().iterModules(): # If it's a package, append it to the list of packages to search. if pm.isPackage(): stack.append(pm) try: # Load the module. m = load(pm, mapper) # Make a good attempt to iterate through the module's # contents, and see what matches our interface. for obj in vars(m).itervalues(): try: adapted = interface(obj, None) except: log.err() else: if adapted is not None: yield adapted except ImportError, ie: log.msg(ie)
def test_loadd(self): """ Modules can be loaded independent of global state. """ maker = getModule("exocet.test.testpackage.util") m1 = load(maker, emptyMapper) m1.testAttribute = "a value" m2 = load(maker, emptyMapper) m2.testAttribute = "a different value" self.assertFalse(m1 is m2) self.assertNotEqual(m1.testAttribute, m2.testAttribute) self.assertFalse(m1 in sys.modules.values()) self.assertFalse(m2 in sys.modules.values()) self.assertEqual(m1.utilName, "hooray") self.assertEqual(m2.utilName, "hooray")
def get_plugins(interface, package, parameters=None): """ Lazily find objects in a package which implement a given interface. The objects must also implement ``twisted.plugin.IPlugin``. If the optional dictionary of parameters is provided, it will be passed into each plugin module as the "bravo.parameters" module. An example access from inside the plugin: >>> from bravo.parameters import foo, bar Since the parameters are available as a real module, the parameters may be imported and used like any other module: >>> from bravo import parameters as params This is a rewrite of Twisted's ``twisted.plugin.getPlugins`` which uses Exocet instead of Twisted to find the plugins. :param interface interface: the interface to match against :param str package: the name of the package to search :param dict parameters: parameters to pass into the plugins """ mapper = bravoMapper if parameters: mapper = mapper.withOverrides( {"bravo.parameters": synthesize_parameters(parameters)}) p = getModule(package) for pm in p.iterModules(): try: m = load(pm, mapper) for obj in vars(m).itervalues(): try: adapted = IPlugin(obj, None) adapted = interface(adapted, None) except: log.err() else: if adapted is not None: yield adapted except ImportError, ie: log.msg(ie)
def load(self): "direct translation of bukkit equivalent" submodules = set(exocet.getModule(self.module).iterModules()) processed = set() self._clear() allfailed = False finalpass = False # TODO FIXME should map all non-loaded plugins away so they're not importable # and should map loaded plugins so they're not loaded twice mapper = ModuleChecker(self, submodules) while (not allfailed) or finalpass: allfailed = True for submodule in submodules - processed: plugin = None try: plugin = exocet.load(submodule, mapper) except ImportError as e: if finalpass: print_exc() # TODO FIXME LOGGING VERY IMPORTANT processed.add(submodule) else: pass # ignore it except: print_exc() # TODO FIXME LOGGING VERY IMPORTANT processed.add(submodule) if plugin: self.plugins.append(plugin) self.plugmap[plugin.__name__] = plugin allfailed = False finalpass = False processed.add(submodule) if finalpass: break elif allfailed: finalpass = True self.loaded = True