U e<@sdZddlZddlZddlZddlZddlmZddlm Z ddl Z ddl m Z ddlmZddlmZz ddlZWnddlZYnXzddlmZWnddlmZYnXd d d d d gZeeZGdddeZGdddeZGdd d eZGdddZGdd d eZGdd d eZzddl Z Gdd d eeZ!Wn&e"k rnGdd d eZ!YnXGdd d e!Z#dS)a Plugin Manager -------------- A plugin manager class is used to load plugins, manage the list of loaded plugins, and proxy calls to those plugins. The plugin managers provided with nose are: :class:`PluginManager` This manager doesn't implement loadPlugins, so it can only work with a static list of plugins. :class:`BuiltinPluginManager` This manager loads plugins referenced in ``nose.plugins.builtin``. :class:`EntryPointPluginManager` This manager uses setuptools entrypoints to load plugins. :class:`ExtraPluginsPluginManager` This manager loads extra plugins specified with the keyword `addplugins`. :class:`DefaultPluginMananger` This is the manager class that will be used by default. If setuptools is installed, it is a subclass of :class:`EntryPointPluginManager` and :class:`BuiltinPluginManager`; otherwise, an alias to :class:`BuiltinPluginManager`. :class:`RestrictedPluginManager` This manager is for use in test runs where some plugin calls are not available, such as runs started with ``python setup.py test``, where the test runner is the default unittest :class:`TextTestRunner`. It is a subclass of :class:`DefaultPluginManager`. Writing a plugin manager ======================== If you want to load plugins via some other means, you can write a plugin manager and pass an instance of your plugin manager class when instantiating the :class:`nose.config.Config` instance that you pass to :class:`TestProgram` (or :func:`main` or :func:`run`). To implement your plugin loading scheme, implement ``loadPlugins()``, and in that method, call ``addPlugin()`` with an instance of each plugin you wish to make available. Make sure to call ``super(self).loadPlugins()`` as well if have subclassed a manager other than ``PluginManager``. N)chain)warn)Failure)IPluginInterface) sort_list)StringIODefaultPluginManager PluginManagerEntryPointPluginManagerBuiltinPluginManagerRestrictedPluginManagerc@sVeZdZdZeZddZddZddZdd Z d d Z d d Z ddZ dddZ dS) PluginProxya#Proxy for plugin calls. Essentially a closure bound to the given call and plugin list. The plugin proxy also must be bound to a particular plugin interface specification, so that it knows what calls are available and any special handling that is required for each call. cCshzt|j||_Wn(tk r:td||jjfYnX|||_g|_|D]}|||qRdS)Nz%s is not a valid %s method) getattr interfacemethodAttributeError__name__makeCallcallplugins addPlugin)selfrrprB/opt/hc_python/lib/python3.8/site-packages/nose/plugins/manager.py__init__Ws  zPluginProxy.__init__cOs |j||SN)r)rargkwrrr__call__bszPluginProxy.__call__csVt||d}|dk rR|dkrBtt|ddkrB|fdd}|j||fdS)z`Add plugin to my list of plugins to call, if it has the attribute I'm bound to. NZloadTestsFromModulercs|Srr)modulepathkwargsZ orig_methrrnz'PluginProxy.addPlugin..)rleninspect getargspecrappend)rpluginrmethrr$rres  zPluginProxy.addPlugincsH|dkrjSj}t|ddr,fddSt|ddr>jSjSdS)NZloadTestsFromNames generativeFcstj||Sr)listgenerate)rrrrrr%{r&z&PluginProxy.makeCall..Z chainable)_loadTestsFromNamesrrrsimple)rrr,rr0rrqs   zPluginProxy.makeCallcOsVd}ddtt|jdg|D}|jD](\}}|||}|dd}||q(|S)zCall plugins in a chain, where the result of each plugin call is sent to the next plugin as input. The final output result is returned. NcSsg|]\}}|r|qSrr).0staticarrr sz%PluginProxy.chain..Z static_args)ziprrrr*)rrrresultr4rr,rrrrs   zPluginProxy.chainc osz|jD]n\}}d}z&|||}|dk r6|D] }|Vq*Wqttfk rRYqt}t|VYqYqXqdS)zFCall all plugins, yielding each item in each non-None result. N)rKeyboardInterrupt SystemExitsysexc_infor)rrrrr,r8rexcrrrr/s   zPluginProxy.generatecOs.|jD]"\}}|||}|dk r|SqdS)z?Call all plugins, returning the first non-None result. N)r)rrrrr,r8rrrr2s zPluginProxy.simpleNcCsFg}|jD]2\}}|||d}|dk r |\}}|r ||q ||fS)a Chainable but not quite normal. Plugins return a tuple of (tests, names) after processing the names. The tests are added to a suite that is accumulated throughout the full call, while names are input for the next plugin in the chain. )r!N)rextend)rnamesr!Zsuiterr,r8Z suite_partrrrr1s  zPluginProxy._loadTestsFromNames)N)r __module__ __qualname____doc__rrrrrrrr/r2r1rrrrr Ns  r c@sdeZdZdZeZddZddZddZdd Z d d Z d d Z ddZ ddZ ddZddZdS) NoPluginsz(Null Plugin manager that has no plugins.cCsd|_|_dSNr)_pluginsrr0rrrrszNoPlugins.__init__cCsdSrErr0rrr__iter__szNoPlugins.__iter__cOsdSrrrargskwdsrrr _doNothingszNoPlugins._doNothingcOsdSrErrHrrr_emptyIteratorszNoPlugins._emptyIteratorcCs(t|j|}t|ddr|jS|jSdS)Nr-F)rrrLrK)rrrrrr __getattr__s  zNoPlugins.__getattr__cCs tdSrNotImplementedErrorrplugrrrrszNoPlugins.addPlugincCs tdSrrNrrrrr addPluginsszNoPlugins.addPluginscCsdSrr)roptionsconfigrrr configureszNoPlugins.configurecCsdSrrr0rrr loadPluginsszNoPlugins.loadPluginscCsdSrrr0rrrsortszNoPlugins.sortN)rrArBrCrrrrGrKrLrMrrSrVrWrXrrrrrDsrDc@sveZdZdZeZdddZddZdd Zd d Z dd d Z ddZ ddZ ddZ ddZddZeeeddZdS)r aBase class for plugin managers. PluginManager is intended to be used only with a static list of plugins. The loadPlugins() implementation only reloads plugins from _extraplugins to prevent those from being overridden by a subclass. The basic functionality of a plugin manager is to proxy all unknown attributes through a ``PluginProxy`` to a list of plugins. Note that the list of plugins *may not* be changed after the first plugin call. rNcCs2g|_d|_i|_|r |||dk r.||_dSrE)rF _extraplugins_proxiesrS proxyClass)rrr[rrrrs zPluginManager.__init__cCs>z |j|WStk r8|||j}||j|<YnX|Sr)rZKeyErrorr[rF)rrproxyrrrrMs  zPluginManager.__getattr__cCs t|jSr)iterrr0rrrrGszPluginManager.__iter__cs<t|dtfdd|jD|jdd<|j|dS)Nnamecs g|]}t|ddkr|qS)r_Nr)r3rnew_namerrr6sz+PluginManager.addPlugin..)robjectrFr*rPrrarrszPluginManager.addPlugincCs$||_t||D]}||qdS)zextraplugins are maintained in a separate list and re-added by loadPlugins() to prevent their being overwritten by plugins added by a subclass of PluginManager N)rY iterchainr)rrZ extrapluginsrQrrrrS szPluginManager.addPluginscCsTtd||_td|j}|||dd|jD}||_|td|dS)zConfigure the set of plugins with the given options and config instance. After configuration, disabled plugins are removed from the plugins list. zConfiguring pluginsrVcSsg|]}|jr|qSr)enabled)r3rQrrrr6sz+PluginManager.configure..zPlugins enabled: %sN)logdebugrUr rFrrX)rrTrUcfgrerrrrVs   zPluginManager.configurecCs|jD]}||qdSr)rYrrPrrrrW"s zPluginManager.loadPluginscCst|jddddS)NcSs t|ddS)NZscorer`)xrrrr%'r&z$PluginManager.sort..T)reverse)rrFr0rrrrX&szPluginManager.sortcCs|jSr)rFr0rrr _get_plugins)szPluginManager._get_pluginscCsg|_||dSr)rFrSrRrrr _set_plugins,szPluginManager._set_pluginszPAccess the list of plugins managed by this plugin manager)rN)rr)rrArBrCr r[rrMrGrrSrVrWrXrlrmpropertyrrrrrr s   c@s^eZdZdZddZejfddZddZdd Z d d Z d d Z ddZ ddZ ddZdS)ZeroNinePluginz>Proxy for 0.9 plugins, adapts 0.10 calls to 0.9 standard. cCs ||_dSr)r+)rr+rrrr8szZeroNinePlugin.__init__cCs|j||dSr)r+ add_options)rparserenvrrrrT;szZeroNinePlugin.optionsc Cst|jdsdSddlm}m}|\}}}t||rRt|jdsDdS|j|jSt||rzt|jdsldS|j|jS|j }|j |j||S)NaddErrorr)SkipTestDeprecatedTestaddSkip addDeprecated) hasattrr+Znose.excrtru issubclassrvtestrwcapturedOutputrs) rrzerrrtruecZevtbcaptrrrrs>s      zZeroNinePlugin.addErrorcCst|jdr|j|SdS)NloadTestsFromPath)rxr+r)rfilenamerrrloadTestsFromFilePs z ZeroNinePlugin.loadTestsFromFilecCs0t|jdsdS|j}|j}|j|j|||S)N addFailure)rxr+r{tbinforrz)rrzr|rrrrrrTs  zZeroNinePlugin.addFailurecCs*t|jdsdS|j}|j|j|dS)N addSuccess)rxr+r{rrz)rrzrrrrr\s zZeroNinePlugin.addSuccesscCst|jdsdS|j|jS)N startTest)rxr+rrzrrzrrrrbs zZeroNinePlugin.startTestcCst|jdsdS|j|jS)NstopTest)rxr+rrzrrrrrgs zZeroNinePlugin.stopTestcCs t|j|Sr)rr+)rvalrrrrMlszZeroNinePlugin.__getattr__N)rrArBrCrosenvironrTrsrrrrrrMrrrrro5srocs,eZdZdZddeffZfddZZS)r zhPlugin manager that loads plugins from the `nose.plugins` and `nose.plugins.0.10` entry points. )znose.plugins.0.10Nz nose.pluginsc sddlm}i}|jD]\}}||D]}|j|kr6q&d||j<td|jj|z |}WnPt k rtYn<t k r}zt d||ft WYq&W5d}~XYnX|r||}n|}| |q&qtt|dS)zBLoad plugins by iterating the `nose.plugins` entry point. r)iter_entry_pointsTz%s load plugin %szUnable to load plugin %s: %sN) pkg_resourcesr entry_pointsr_rfrg __class__rloadr9 ExceptionrRuntimeWarningrsuperr rW) rrZloaded entry_pointZadaptepZplugclserQrrrrWws,       z#EntryPointPluginManager.loadPlugins)rrArBrCrorrW __classcell__rrrrr ps cs eZdZdZfddZZS)r zSPlugin manager that loads plugins from the list in `nose.plugins.builtin`. cs6ddlm}|jD]}||qtt|dS)z-Load plugins in nose.plugins.builtin r)builtinN)Z nose.pluginsrrrrr rW)rrrQrrrrWs  z BuiltinPluginManager.loadPlugins)rrArBrCrWrrrrrr sc@s eZdZdSrNrrArBrrrrrsc@s eZdZdSrrrrrrrsc@s*eZdZdZd ddZddZdd Zd S) r zPlugin manager that restricts the plugin list to those not excluded by a list of exclude methods. Any plugin that implements an excluded method will be removed from the manager's plugin list after plugins are loaded. rTcCs(t||||_||_g|_d|_dSr)rrrexcludeexcluded _excludedOpts)rrrrrrrrs  z RestrictedPluginManager.__init__cCsN|jdkr>ddlm}|dd|_|jD]}|j|jidq(|jd|S)Nr) OptionParserF)add_help_option)rrz--)roptparserrrT get_option)rr_rr+rrrexcludedOptions     z&RestrictedPluginManager.excludedOptioncCsf|jrt|g}|jD]@}d}|jD]"}t||r(d}|j|qLq(|r||q||_dS)NTF)rrrWrrrxrr*)rZallowr+okrrrrrWs      z#RestrictedPluginManager.loadPluginsN)rrT)rrArBrCrrrWrrrrr s )$rCr(loggingrr; itertoolsrrdwarningsrZ nose.confignoseZ nose.failurerZnose.plugins.baserZnose.pyversionrpickleior__all__ getLoggerrrfrcr rDr ror r rr ImportErrorr rrrrsF2       m&T;%