167 lines
		
	
	
		
			5.6 KiB
		
	
	
	
		
			Python
		
	
	
	
			
		
		
	
	
			167 lines
		
	
	
		
			5.6 KiB
		
	
	
	
		
			Python
		
	
	
	
| """
 | |
| managing loading and interacting with pytest plugins. 
 | |
| """
 | |
| import py
 | |
| from py.__.test.plugin import api
 | |
| 
 | |
| def check_old_use(mod, modname):
 | |
|     clsname = modname[len('pytest_'):].capitalize() + "Plugin" 
 | |
|     assert not hasattr(mod, clsname), (mod, clsname)
 | |
| 
 | |
| class PluginManager(object):
 | |
|     def __init__(self, comregistry=None):
 | |
|         if comregistry is None: 
 | |
|             comregistry = py._com.Registry()
 | |
|         self.comregistry = comregistry 
 | |
|         self.MultiCall = self.comregistry.MultiCall
 | |
|         self.impname2plugin = {}
 | |
| 
 | |
|         self.hook = py._com.Hooks(
 | |
|             hookspecs=api.PluginHooks, 
 | |
|             registry=self.comregistry) 
 | |
| 
 | |
|     def register(self, plugin, name=None):
 | |
|         if name is None:
 | |
|             name = getattr(plugin, '__name__', id(plugin))
 | |
|         if name not in self.impname2plugin:
 | |
|             self.impname2plugin[name] = plugin
 | |
|             self.hook.pytest_plugin_registered(plugin=plugin)
 | |
|             self.comregistry.register(plugin)
 | |
|             return True
 | |
| 
 | |
|     def unregister(self, plugin):
 | |
|         self.hook.pytest_plugin_unregistered(plugin=plugin)
 | |
|         self.comregistry.unregister(plugin)
 | |
|         for name, value in self.impname2plugin.items():
 | |
|             if value == plugin:
 | |
|                 del self.impname2plugin[name]
 | |
| 
 | |
|     def isregistered(self, plugin):
 | |
|         return self.comregistry.isregistered(plugin)
 | |
| 
 | |
|     def getplugins(self):
 | |
|         return list(self.comregistry)
 | |
| 
 | |
|     # API for bootstrapping 
 | |
|     #
 | |
|     def getplugin(self, importname):
 | |
|         impname = canonical_importname(importname)
 | |
|         return self.impname2plugin[impname]
 | |
| 
 | |
|     def _envlist(self, varname):
 | |
|         val = py.std.os.environ.get(varname, None)
 | |
|         if val is not None:
 | |
|             return val.split(',')
 | |
|         return ()
 | |
|     
 | |
|     def consider_env(self):
 | |
|         for spec in self._envlist("PYTEST_PLUGINS"):
 | |
|             self.import_plugin(spec)
 | |
| 
 | |
|     def consider_preparse(self, args):
 | |
|         for opt1,opt2 in zip(args, args[1:]):
 | |
|             if opt1 == "-p": 
 | |
|                 self.import_plugin(opt2)
 | |
| 
 | |
|     def consider_conftest(self, conftestmodule):
 | |
|         cls = getattr(conftestmodule, 'ConftestPlugin', None)
 | |
|         if cls is not None:
 | |
|             raise ValueError("%r: 'ConftestPlugins' only existed till 1.0.0b1, "
 | |
|                 "were removed in 1.0.0b2" % (cls,))
 | |
|         if self.register(conftestmodule, name=conftestmodule.__file__):
 | |
|             self.consider_module(conftestmodule)
 | |
| 
 | |
|     def consider_module(self, mod):
 | |
|         attr = getattr(mod, "pytest_plugins", ())
 | |
|         if attr:
 | |
|             if not isinstance(attr, (list, tuple)):
 | |
|                 attr = (attr,)
 | |
|             for spec in attr:
 | |
|                 self.import_plugin(spec) 
 | |
| 
 | |
|     def import_plugin(self, spec):
 | |
|         assert isinstance(spec, str)
 | |
|         modname = canonical_importname(spec)
 | |
|         if modname in self.impname2plugin:
 | |
|             return
 | |
|         mod = importplugin(modname)
 | |
|         check_old_use(mod, modname) 
 | |
|         self.register(mod) 
 | |
|         self.consider_module(mod)
 | |
|     # 
 | |
|     #
 | |
|     # API for interacting with registered and instantiated plugin objects 
 | |
|     #
 | |
|     # 
 | |
|     def getfirst(self, attrname):
 | |
|         for x in self.comregistry.listattr(attrname):
 | |
|             return x
 | |
| 
 | |
|     def listattr(self, attrname, plugins=None, extra=()):
 | |
|         return self.comregistry.listattr(attrname, plugins=plugins, extra=extra)
 | |
| 
 | |
|     def call_firstresult(self, *args, **kwargs):
 | |
|         return self.comregistry.call_firstresult(*args, **kwargs)
 | |
| 
 | |
|     def notify_exception(self, excinfo=None):
 | |
|         if excinfo is None:
 | |
|             excinfo = py.code.ExceptionInfo()
 | |
|         excrepr = excinfo.getrepr(funcargs=True, showlocals=True)
 | |
|         return self.hook.pytest_internalerror(excrepr=excrepr)
 | |
| 
 | |
|     def do_addoption(self, parser):
 | |
|         methods = self.comregistry.listattr("pytest_addoption", reverse=True)
 | |
|         mc = py._com.MultiCall(methods, parser=parser)
 | |
|         mc.execute()
 | |
| 
 | |
|     def pytest_plugin_registered(self, plugin):
 | |
|         if hasattr(self, '_config'):
 | |
|             self.call_plugin(plugin, "pytest_addoption", parser=self._config._parser)
 | |
|             self.call_plugin(plugin, "pytest_configure", config=self._config)
 | |
| 
 | |
|     def call_plugin(self, plugin, methname, **kwargs):
 | |
|         return self.MultiCall(self.listattr(methname, plugins=[plugin]), 
 | |
|                 **kwargs).execute(firstresult=True)
 | |
| 
 | |
|     def do_configure(self, config):
 | |
|         assert not hasattr(self, '_config')
 | |
|         config.pluginmanager.register(self)
 | |
|         self._config = config
 | |
|         config.hook.pytest_configure(config=self._config)
 | |
| 
 | |
|     def do_unconfigure(self, config):
 | |
|         config = self._config 
 | |
|         del self._config 
 | |
|         config.hook.pytest_unconfigure(config=config)
 | |
|         config.pluginmanager.unregister(self)
 | |
| 
 | |
|     def do_itemrun(self, item, pdb=None):
 | |
|         res = self.comregistry.call_firstresult("pytest_itemrun", item=item, pdb=pdb)
 | |
|         if res is None:
 | |
|             raise ValueError("could not run %r" %(item,))
 | |
| 
 | |
| # 
 | |
| #  XXX old code to automatically load classes
 | |
| #
 | |
| def canonical_importname(name):
 | |
|     name = name.lower()
 | |
|     modprefix = "pytest_"
 | |
|     if not name.startswith(modprefix):
 | |
|         name = modprefix + name 
 | |
|     return name 
 | |
| 
 | |
| def importplugin(importspec):
 | |
|     try:
 | |
|         return __import__(importspec) 
 | |
|     except ImportError, e:
 | |
|         if str(e).find(importspec) == -1:
 | |
|             raise
 | |
|         try:
 | |
|             return __import__("py.__.test.plugin.%s" %(importspec), None, None, '__doc__')
 | |
|         except ImportError, e:
 | |
|             if str(e).find(importspec) == -1:
 | |
|                 raise
 | |
|             #print "syspath:", py.std.sys.path
 | |
|             #print "curdir:", py.std.os.getcwd()
 | |
|             return __import__(importspec)  # show the original exception
 |