g<dZddlZddlZddlZddlZddlmZddlm Z ddl Z ddl m Z ddlmZddlmZ ddlZ ddlmZgd Zej,eZGd d eZGd d eZGddeZGddZGddeZGddeZ ddl Z GddeeZ!Gdde!Z#y#ddlZYxYw#ddlmZYxYw#e"$rGddeZ!Y6wxYw)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)StringIO)DefaultPluginManager PluginManagerEntryPointPluginManagerBuiltinPluginManagerRestrictedPluginManagercFeZdZdZeZdZdZdZdZ dZ dZ dZ d d Z y ) 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. c  t|j||_|j ||_g|_|D]}|j||y#t$r&t|d|jjdwxYw)Nz is not a valid z method) getattr interfacemethodAttributeError__name__makeCallcallplugins addPlugin)selfrrps C/opt/hc_python/lib/python3.12/site-packages/nose/plugins/manager.py__init__zPluginProxy.__init__Ws D!$..$7DKMM$'  A NN1d #  D $($..*A*A"CD D Ds A/Bc&|j|i|SN)r)rargkws r__call__zPluginProxy.__call__bstyy#$$$ct||d}|N|dk(r+ttj|ddk(r|fd}|jj ||fyy)z`Add plugin to my list of plugins to call, if it has the attribute I'm bound to. NloadTestsFromModulerc|Sr)modulepathkwargs orig_meths rz'PluginProxy.addPlugin..ns i6Gr#)rleninspect getargspecrappend)rpluginrmethr,s @rrzPluginProxy.addPluginesdvtT*  ,,**40349 G LL   / r#c|dk(r jSj}t|ddrfdSt|ddr jSjS)NloadTestsFromNames generativeFc:tj|i|Sr)listgenerate)r r!rs rr-z&PluginProxy.makeCall..{sd=4==#+D+D&Er# chainable)_loadTestsFromNamesrrrsimple)rrr3s` rrzPluginProxy.makeCallqsW ' '++ +{{ 4u -E E T; .:: ;; r#cd}tt|jdg|Dcgc] \}}|r| c}}}|jD]#\}}||i|}|dd}|j |%|Scc}}w)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. N static_args)ziprrrr1)rr r!resultstaticarr3s rrzPluginProxy.chainsmR@#FF$F||GAt3%"%F)C JJv $ sA-c/K|jD]\}}d} ||i|}| |D]}|y#ttf$rtj}t |YRxYww)zFCall all plugins, yielding each item in each non-None result. N)rKeyboardInterrupt SystemExitsysexc_infor)rr r!rr3r@rexcs rr9zPluginProxy.generatesy||GAtF s)b)%#$ $&z2  llnsm#sA$0A$/A!A$cH|jD]\}}||i|}||cSy)z?Call all plugins, returning the first non-None result. N)r)rr r!rr3r@s rr<zPluginProxy.simples0||GAt3%"%F! $r#Ncg}|jD]+\}}|||}||\}}|s|j|-||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))rextend)rnamesr)suiterr3r@ suite_parts rr;zPluginProxy._loadTestsFromNamessR ||GAt%/F!$*! ELL, $ e|r#r)r __module__ __qualname____doc__rrrr"rrrr9r<r;r(r#rrrNs6!I $% 0" " r#rcPeZdZdZeZdZdZdZdZ dZ dZ dZ d Z d Zd Zy ) NoPluginsz(Null Plugin manager that has no plugins.c dx|_|_yNr()_pluginsrrs rrzNoPlugins.__init__s'))  r#cyrVr(rXs r__iter__zNoPlugins.__iter__r#cyrr(rargskwdss r _doNothingzNoPlugins._doNothing r#cyrVr(r]s r_emptyIteratorzNoPlugins._emptyIteratorr[r#cxt|j|}t|ddr |jS|jS)Nr6F)rrrcr`)rrrs r __getattr__zNoPlugins.__getattr__s4. 6< /&& &?? "r#ctrNotImplementedErrorrplugs rrzNoPlugins.addPlugin !##r#ctrrgrrs r addPluginszNoPlugins.addPluginsrkr#cyrr()roptionsconfigs r configurezNoPlugins.configurerar#cyrr(rXs r loadPluginszNoPlugins.loadPluginsrar#cyrr(rXs rsortzNoPlugins.sortrar#N)rrPrQrRrrrrZr`rcrerrnrrrtrvr(r#rrTrTs<2 I* #$$   r#rTcjeZdZdZeZddZdZdZdZ ddZ dZ d Z d Z d Zd Zeeedd Zy)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. Nchg|_d|_i|_|r|j||||_yyrV)rW _extraplugins_proxiesrn proxyClass)rrr{s rrzPluginManager.__init__s9   OOG $  !(DO "r#c |j|S#t$r/|j||j}||j|<Y|SwxYwr)rzKeyErrorr{rW)rrproxys rrezPluginManager.__getattr__sL (==& & (OOD$--8E"'DMM$   (s4A A c,t|jSr)iterrrXs rrZzPluginManager.__iter__sDLL!!r#ct|dt}|jDcgc]}t|dd|k7r|c}|jdd|jj|ycc}w)Nname)robjectrWr1)rrjnew_namers rrzPluginManager.addPluginsg42'+}}E}!&q&$78C}E a T"EsA)cV||_t||D]}|j|y)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)rr extrapluginsrjs rrnzPluginManager.addPlugins s) *g|4D NN4 5r#c*tjd||_td|j}||||jDcgc]}|j s|}}||_|jtjd|ycc}w)zConfigure the set of plugins with the given options and config instance. After configuration, disabled plugins are removed from the plugins list. zConfiguring pluginsrrzPlugins enabled: %sN)logdebugrqrrWenabledrrv)rrprqcfgrjrs rrrzPluginManager.configuresu '( +t}}5 GV$(MMBMDT\\4MB   '1Cs BBcH|jD]}|j|yr)ryrris rrtzPluginManager.loadPlugins"s&&D NN4 'r#c4t|jddS)Nct|ddS)Nscore)r)xs rr-z$PluginManager.sort..'s '!Wa2Hr#T)reverse)rrWrXs rrvzPluginManager.sort&s(HRVWWr#c|jSr)rWrXs r _get_pluginszPluginManager._get_plugins)s }}r#c4g|_|j|yr)rWrnrms r _set_pluginszPluginManager._set_plugins,s   r#zPAccess the list of plugins managed by this plugin manager)r(N)r(r()rrPrQrRrr{rrerZrrnrrrtrvrrpropertyrr(r#rr r sX J)"#! 2!X!|\4./Gr#r c^eZdZdZdZej fdZdZdZ dZ dZ dZ d Z d Zy ) ZeroNinePluginz>Proxy for 0.9 plugins, adapts 0.10 calls to 0.9 standard. c||_yr)r2)rr2s rrzZeroNinePlugin.__init__8s  r#c<|jj||yr)r2 add_options)rparserenvs rrpzZeroNinePlugin.options;s ,r#ct|jdsyddlm}m}|\}}}t ||rst{{J/ 5 B b( #4;; 2;;&&tyy1 1 N +4;;8;;,,TYY7 7""{{##DIIsD99r#cft|jdr|jj|Sy)NloadTestsFromPath)rr2r)rfilenames rloadTestsFromFilez ZeroNinePlugin.loadTestsFromFilePs+ 4;; 3 4;;00: : 5r#ct|jdsy|j}|j}|jj |j |||S)N addFailure)rr2rtbinforr)rrrrrs rrzZeroNinePlugin.addFailureTsFt{{L1 ""{{%%diidFCCr#ct|jdsy|j}|jj|j|y)N addSuccess)rr2rrr)rrrs rrzZeroNinePlugin.addSuccess\s6t{{L1 "" tyy$/r#czt|jdsy|jj|jS)N startTest)rr2rrrrs rrzZeroNinePlugin.startTestbs,t{{K0 {{$$TYY//r#czt|jdsy|jj|jS)NstopTest)rr2rrrs rrzZeroNinePlugin.stopTestgs,t{{J/ {{##DII..r#c.t|j|Sr)rr2)rvals rrezZeroNinePlugin.__getattr__lst{{C((r#N)rrPrQrRrosenvironrprrrrrrrer(r#rrr5s>#%**-:$;D0 0 / )r#rc.eZdZdZddeffZfdZxZS)r zhPlugin manager that loads plugins from the `nose.plugins` and `nose.plugins.0.10` entry points. )znose.plugins.0.10Nz nose.pluginsc ddlm}i}|jD]\}}||D]}|j|vrd||j<tj d|j j| |j}|r||}n|}|j|tt|Cy#t$rt$r }td|d|tYd}~d}~wwxYw)zBLoad plugins by iterating the `nose.plugins` entry point. r)iter_entry_pointsTz%s load plugin %szUnable to load plugin z: N) pkg_resourcesr entry_pointsrrr __class__rloadrD ExceptionrRuntimeWarningrsuperr rt) rrloaded entry_pointadaptepplugclserjrs rrtz#EntryPointPluginManager.loadPluginsws 4"&"3"3 K' 477f$"&rww -t~~/F/FK  ggiG +D"9Dt$)5#4, %t8:) 2qA') s1CC2C--C2)rrPrQrRrrrt __classcell__rs@rr r ps&0#^46L;;r#r c"eZdZdZfdZxZS)r zSPlugin manager that loads plugins from the list in `nose.plugins.builtin`. cddlm}|jD]}|j|tt |y)z-Load plugins in nose.plugins.builtin r)builtinN) nose.pluginsrrrrr rt)rrrjrs rrtz BuiltinPluginManager.loadPluginss2 )OOD NN46 "$ "D57r#)rrPrQrRrtrrs@rr r s88r#r c eZdZyr NrrPrQr(r#rr r  r#r c eZdZyrrr(r#rr r rr#c$eZdZdZddZdZdZy)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. chtj||||_||_g|_d|_yr)r rrexcludeexcluded _excludedOpts)rrrrs rrz RestrictedPluginManager.__init__s/%%dG4   !r#c|jBddlm}|d|_|jD]}|j |ji!|jj d|zS)Nr) OptionParserF)add_help_option)rz--)roptparserrrp get_option)rrrr2s rexcludedOptionz&RestrictedPluginManager.excludedOptions]    % -!-e!DD --t11r:(!!,,TD[99r#c|jrtj|g}|jD]T}d}|jD]-}t ||sd}|j j|n|sD|j|V||_y)NTF)rr rtrrrrr1)rallowr2okrs rrtz#RestrictedPluginManager.loadPluginss{ 99 , ,T 2llFB,,66*BMM((0 '  V$# r#N)r(r(T)rrPrQrRrrrtr(r#rr r s ": r#r )$rRr/loggingrrF itertoolsrrwarningsr nose.confignose nose.failurernose.plugins.basernose.pyversionrpickleior__all__ getLoggerrrrrrTr rr r rr ImportErrorr r(r#rrs1d ( .$  >g!j&jZ# # LQ/FQ/h8)8)v";m";J 8= 8  68L "2"U B   3  s(B5CC 5B=C  C C