Plan 9 from Bell Labs’s /usr/web/sources/contrib/jas/root/sys/lib/python2.7/site-packages/nose/plugins/multiprocess.pyc

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


�9�c@s@dZddlZddlZddlZddlZddlZddlZddlZddlZddl	Z
ddlmZddl
m
Z
ddl
mZddlmZddlmZddlmZdd	lmZdd
lmZyddlmZWn!ek
r)ddlmZnXddlmZdd
lmZyddl m!Z!Wnek
r}ddl!Z!nXe"Z#ej$e%�Z&e"a'aa(a)a*a+de,fd��YZ-d�Z.dfd��YZ/defd��YZ0d�Z1defd��YZ2d�Z3d�Z4defd��YZ5dS(s�
Overview
========

The multiprocess plugin enables you to distribute your test run among a set of
worker processes that run tests in parallel. This can speed up CPU-bound test
runs (as long as the number of work processeses is around the number of
processors or cores available), but is mainly useful for IO-bound tests that
spend most of their time waiting for data to arrive from someplace else.

.. note ::

   See :doc:`../doc_tests/test_multiprocess/multiprocess` for
   additional documentation and examples. Use of this plugin on python
   2.5 or earlier requires the multiprocessing_ module, also available
   from PyPI.

.. _multiprocessing : http://code.google.com/p/python-multiprocessing/

How tests are distributed
=========================

The ideal case would be to dispatch each test to a worker process
separately. This ideal is not attainable in all cases, however, because many
test suites depend on context (class, module or package) fixtures.

The plugin can't know (unless you tell it -- see below!) if a context fixture
can be called many times concurrently (is re-entrant), or if it can be shared
among tests running in different processes. Therefore, if a context has
fixtures, the default behavior is to dispatch the entire suite to a worker as
a unit.

Controlling distribution
^^^^^^^^^^^^^^^^^^^^^^^^

There are two context-level variables that you can use to control this default
behavior.

If a context's fixtures are re-entrant, set ``_multiprocess_can_split_ = True``
in the context, and the plugin will dispatch tests in suites bound to that
context as if the context had no fixtures. This means that the fixtures will
execute concurrently and multiple times, typically once per test.

If a context's fixtures can be shared by tests running in different processes
-- such as a package-level fixture that starts an external http server or
initializes a shared database -- then set ``_multiprocess_shared_ = True`` in
the context. These fixtures will then execute in the primary nose process, and
tests in those contexts will be individually dispatched to run in parallel.

How results are collected and reported
======================================

As each test or suite executes in a worker process, results (failures, errors,
and specially handled exceptions like SkipTest) are collected in that
process. When the worker process finishes, it returns results to the main
nose process. There, any progress output is printed (dots!), and the
results from the test run are combined into a consolidated result
set. When results have been received for all dispatched tests, or all
workers have died, the result summary is output as normal.

Beware!
=======

Not all test suites will benefit from, or even operate correctly using, this
plugin. For example, CPU-bound tests will run more slowly if you don't have
multiple processors. There are also some differences in plugin
interactions and behaviors due to the way in which tests are dispatched and
loaded. In general, test loading under this plugin operates as if it were
always in directed mode instead of discovered mode. For instance, doctests
in test modules will always be found when using this plugin with the doctest
plugin.

But the biggest issue you will face is probably concurrency. Unless you
have kept your tests as religiously pure unit tests, with no side-effects, no
ordering issues, and no external dependencies, chances are you will experience
odd, intermittent and unexplainable failures and errors when using this
plugin. This doesn't necessarily mean the plugin is broken; it may mean that
your test suite is not safe for concurrency.

New Features in 1.1.0
=====================

* functions generated by test generators are now added to the worker queue
  making them multi-threaded.
* fixed timeout functionality, now functions will be terminated with a
  TimedOutException exception when they exceed their execution time. The
  worker processes are not terminated.
* added ``--process-restartworker`` option to restart workers once they are
  done, this helps control memory usage. Sometimes memory leaks can accumulate
  making long runs very difficult.
* added global _instantiate_plugins to configure which plugins are started
  on the worker processes.

i�N(tTextTestRunner(tfailure(tloader(tPlugin(tbytes_(tTextTestResult(tContextSuite(ttest_address(t_WritelnDecorator(tEmpty(twarn(tStringIOtTimedOutExceptioncBseZdd�Zd�ZRS(s	Timed OutcCs
||_dS(N(tvalue(tselfR
((s=/sys/lib/python2.7/site-packages/nose/plugins/multiprocess.pyt__init__�scCs
t|j�S(N(treprR
(R((s=/sys/lib/python2.7/site-packages/nose/plugins/multiprocess.pyt__str__�s(t__name__t
__module__RR(((s=/sys/lib/python2.7/site-packages/nose/plugins/multiprocess.pyR�scCs�y�ddlm}matjtjtj�}|�}tjtj|�|j|j|j|j	|j
f\aaaa	a
Wntk
r�tdt
�nXdS(Ni�(tManagertProcesssKmultiprocessing module is not available, multiprocess plugin cannot be used(tmultiprocessingRRtsignaltSIGINTtSIG_IGNtQueuetPooltEventtValuetArraytImportErrorR
tRuntimeWarning(Rtoldtm((s=/sys/lib/python2.7/site-packages/nose/plugins/multiprocess.pyt
_import_mp�s	7
tTestLetcBs,eZd�Zd�Zd�Zd�ZRS(cCsIy|j�|_Wntk
r&nX|j�|_t|�|_dS(N(tidt_idtAttributeErrortshortDescriptiont_short_descriptiontstrt_str(Rtcase((s=/sys/lib/python2.7/site-packages/nose/plugins/multiprocess.pyR�s
cCs|jS(N(R&(R((s=/sys/lib/python2.7/site-packages/nose/plugins/multiprocess.pyR%�scCs|jS(N(R)(R((s=/sys/lib/python2.7/site-packages/nose/plugins/multiprocess.pyR(�scCs|jS(N(R+(R((s=/sys/lib/python2.7/site-packages/nose/plugins/multiprocess.pyR�s(RRRR%R(R(((s=/sys/lib/python2.7/site-packages/nose/plugins/multiprocess.pyR$�s			tMultiProcesscBs>eZdZdZiZd�Zd�Zd�Zd�ZRS(sF
    Run tests in multiple processes. Requires processing module.
    i�cCs�|jdddd|jdd�ddd	d
dd�|jd
ddd|jdd�ddd	ddd�|jdddd|jdt�dddd�dS(s0
        Register command-line options.
        s--processestactiontstoretdefaulttNOSE_PROCESSESitdesttmultiprocess_workerstmetavartNUMthelpsNSpread test run among this many processes. Set a number equal to the number of processors or cores in your machine for best results. Pass a negative number to have the number of processes automatically set to the number of cores. Passing 0 means to disable parallel testing. Default is 0 unless NOSE_PROCESSES is set. [NOSE_PROCESSES]s--process-timeouttNOSE_PROCESS_TIMEOUTi
tmultiprocess_timeouttSECONDSsfSet timeout for return of results from each test runner process. Default is 10. [NOSE_PROCESS_TIMEOUT]s--process-restartworkert
store_truetNOSE_PROCESS_RESTARTWORKERtmultiprocess_restartworkers�If set, will restart each worker process once their tests are done, this helps control memory leaks from killing the system. [NOSE_PROCESS_RESTARTWORKER]N(t
add_optiontgettFalse(Rtparsertenv((s=/sys/lib/python2.7/site-packages/nose/plugins/multiprocess.pytoptions�s	cCs[y|jjd�Wntk
r'nXt|d�sDt|_dS|jrQdS||_yt|j	�}Wnt
tfk
r�d}nX|rWt�t
dkr�t|_dS|dkr�ddl}|j�}Wq�k
r�t|_dSXnt|_||j_	t|j�}||j_t|j�}||j_t|jd<ndS(s#
        Configure plugin.
        tactiveR3Nii�(tstatustpoptKeyErrorthasattrR?tenabledtworkertconfigtintR3t	TypeErrort
ValueErrorR#RtNoneRt	cpu_counttNotImplementedErrortTruetfloatR8R<(RRBRJtworkersRtttr((s=/sys/lib/python2.7/site-packages/nose/plugins/multiprocess.pyt	configure�sB
			
	
		cCs|j|_dS(sbRemember loader class so MultiProcessTestRunner can instantiate
        the right loader.
        N(t	__class__tloaderClass(RR((s=/sys/lib/python2.7/site-packages/nose/plugins/multiprocess.pytprepareTestLoadersc	Cs.td|jd|jjd|jd|j�S(s9Replace test runner with MultiProcessTestRunner.
        tstreamt	verbosityRJRX(tMultiProcessTestRunnerRZRJR[RX(Rtrunner((s=/sys/lib/python2.7/site-packages/nose/plugins/multiprocess.pytprepareTestRunner
s	(	RRt__doc__tscoreRDRBRVRYR^(((s=/sys/lib/python2.7/site-packages/nose/plugins/multiprocess.pyR-�s	 	)	cCs
t��dS(N(R(tsigtframe((s=/sys/lib/python2.7/site-packages/nose/plugins/multiprocess.pyt
signalhandlersR\cBs�eZdZd�Zd�Zd�Zd�Zd�Zee�Zd�Z	ee	�Z	d�Z
d�Zee�Zd	�Zd
�Z
RS(g@cKs2|jdtj�|_tt|�j|�dS(NRX(RERtdefaultTestLoaderRXtsuperR\R(Rtkw((s=/sys/lib/python2.7/site-packages/nose/plugins/multiprocess.pyRsc

Cs�x�j|�D]�tjd|t|��t|tjj�rvt|jt	j
�rvtjd�||�qnt|t�r�|jt	j
kr�tjd�||�qqt|t�r�|j
|�r�tjd|�y|j�WnLttfk
r�q�tjdtj��|j|tj��q�j|�|jr�|jjj|g�}x3|d D]$}t|dt�rxt|_qxqxWn|j|||||�q|j|||�}	tjdt|�|	|�qWdS(NsNext batch %s (%s)sCase is a Failures%s has shared fixturess%s setup failedit_multiprocess_shared_sQueued test %s (%s) to %s(t	nextBatchtlogtdebugttypet
isinstancetnoseR,tTestttestRtFailureRtcontexttsharedFixturestsetUptKeyboardInterruptt
SystemExittsystexc_infotaddErrortappendtfactoryR>tgetattrR?RQt_multiprocess_can_split_tcollecttaddtasktlen(
RRot	testQueuettaskstto_teardowntresultR,t	ancestorstant	test_addr((s=/sys/lib/python2.7/site-packages/nose/plugins/multiprocess.pyR}s<

!


		cCs�tdtd��}tdtj��}t�}tdtd||||||||j|jtj	|j
�f
�}	||	_||	_||	_
tjtjt�}
|	j�tjtj|
�|	S(Ntcttdttargettargs(RRttimeRRR]RXRWtpickletdumpsRJtcurrentaddrtcurrentstarttkeyboardCaughtRtSIGILLRctstart(RtiworkerR�tresultQueuet
shouldStopR�R�R�R�tpR!((s=/sys/lib/python2.7/site-packages/nose/plugins/multiprocess.pytstartProcessEs(				
c
Cs�tjd||tj��|jjj|�}|dk	rF|}n|jjj|j	�}|dk	rv||_	nt
�}t
�}g}g}g}g}	t�}
|j�}t
j
�}|j||||	|�tjd|jj�xVt|jj�D]B}
|j|
|||
|�}|j|�tjd|
d�qWt|�}|jj}d}yxY|r�tjdt|�||�y�|jd|�\}}}}tjd||t|��yYy|j|�Wn$tk
rtjd||�nX|t|�7}|j|�WnAtk
rhtjd	|�tjd
tt|�d��nX|j||g�|j||�|jjr�|j�r�|
j �Pn|jj!r2tjd|�||j"dd�|
j#�r2|j$�r2tjd
|�|j||||
|�||<q2nWnt%k
r9tjdt|�|j$�t|��t&}x�t'|�D]�\}}|j(�r~t)|j*j+d�}t
j
�|j,j+}t|�dkr�|jjdkr�jd|�nt-}t|�dkr||jjdkrtjd||�t)d�|j*_+|j.j/�t
j
�}x�|j.j#�r|j(�rt
j
�||j0kr�j1d|�|j2�|j||||
|�||<}Pntj3|j4t5j6�t
j7d�qkWqq~q~W|r:|j$�r:tjd�Pq:nX|jj}xy|D]q}|j(�rMt|j*j+�dkrMt
j
�|j,j+}||jjkr�t8||jj|�}q�qMqMWqmWtjdt|�t|��WnBt9t:fk
r*}tj;d�|}|j<|t=j>��nXyYxe|	D]]}tjd|�y|j?�Wq5t9t:fk
ru�q5|j<|t=j>��q5Xq5Wt
j
�}|j@�|jA||�|jjjB|�|dkrtjd�x3|D](}|j(�r�jCddt&�q��nxbt'|�D]T\}}|j(�r+tjd|�|j"�|j(�rtjd|�qq+q+WWn`t9t:fk
r�tj;d�x'|D]}|j(�r�|j2�q�q�W|r��q�nX|S(s
        Execute the test (which may be a test suite). If the test is a suite,
        distribute it out among as many processes as have been configured, at
        as fine a level as is possible given the context fixtures defined in
        the suite or any sub-suites.

        s%s.run(%s) (%s)sStarting %s workerssStarted worker process %sis5Waiting for results (%s/%s tasks), next timeout=%.3fsttimeouts1Results received for worker %d, %s, new tasks: %ds)worker %s failed to remove from tasks: %ssGot result for unknown task? %sscurrent: %sisjoining worker %ss!starting new process on worker %ss8Timed out with %s tasks pending (empty testQueue=%r): %stasciig����sLworker %d has finished its work item, but is not exiting? do we wait for it?stimed out worker %s: %sR�sterminating worker %ssAll workers deadsCompleted %s tasks (%s remain)s4parent received ctrl-c when waiting for test resultss#Tearing down shared fixtures for %ssTell all workers to stoptSTOPtblocksfailed to join worker %ss=parent received ctrl-c when shutting down: stop all processesN(DRiRjtostgetpidRJtpluginstprepareTestRNtsetOutputStreamRZRRt_makeResultR�R}R3trangeR�RyRR8R>tremoveRMR
textendRFR*tlisttconsolidatetstopOnErrort
wasSuccessfultsetR<tjointis_settemptyR	R?t	enumeratetis_aliveRR�R
R�RQR�tcleartwaitkilltimeterrort	terminatetkilltpidRR�tsleeptminRtRutinfoRxRvRwttearDowntprintErrorstprintSummarytfinalizetput(RRotwrappertwrappedR�R�R�t	completedRSR�R�R�R�tiR�ttotal_taskstnexttimeouttthrownErrorR�taddrt
newtask_addrstbatch_resultt	any_alivetwtworker_addrttimeprocessingt
startkilltimeteR,tstopRI((s=/sys/lib/python2.7/site-packages/nose/plugins/multiprocess.pytrun[s
				
				
	
$

)
		
	


#

$!#







	cCs�d}t|tjj�rHt|jd�rHd|j_|jj}nt	j
|�}|j||fdt�|dk	r�|t
|�7}n|dk	r�|j|�n|S(NtargR�(RNRlRmR,RnRGRot
descriptorR�R\taddressR�R?R*Ry(R�R�R,R�R�((s=/sys/lib/python2.7/site-packages/nose/plugins/multiprocess.pyR~s'cCst|d�r'|j�\}}}n:t|d�rQt|j�\}}}ntd|��g}|dkr�|dkr�td|��q�|j|�n=tjj	|�\}}|j
d�r�|}n|j|�|dk	r�j|�ndjtt
|��S(NR�RqsUnable to convert %s to addresssUnaddressable case %sRt:(RGR�RRqt	ExceptionRNRyR�tpathtsplitt
startswithR�tmapR*(R,tfiletmodtcalltpartstdirnametbasename((s=/sys/lib/python2.7/site-packages/nose/plugins/multiprocess.pyR�!s"	
ccs
t|d�r+t|jdt�s+dSnt|t�rL|j|j�srt|dt�srt|tj	�r�t|t�r�t
|�}t|�dkr�t|ddd�|jkr�|d}q�n|Vn0x-|D]%}x|j
|�D]}|Vq��WdS(NRqt_multiprocess_t	can_splitii(RGR{RqRQRlRthasFixturest
checkCanSplittunittestt	TestSuiteR�RRNRh(RRot	containedR,tbatch((s=/sys/lib/python2.7/site-packages/nose/plugins/multiprocess.pyRh:s"

cCs$|s
tSt|dt�r tStS(s8
        Callback that we use to check whether the fixtures found in a
        context or ancestor are ones we care about.

        Contexts can tell us that their fixtures are reentrant by setting
        _multiprocess_can_split_. So if we see that, we return False to
        disregard those fixtures.
        R|(R?R{RQ(Rqtfixt((s=/sys/lib/python2.7/site-packages/nose/plugins/multiprocess.pyR�Zs
	cCs,t|dd�}|stSt|dt�S(NRqRg(R{RNR?(RR,Rq((s=/sys/lib/python2.7/site-packages/nose/plugins/multiprocess.pyRrjscCs1tjd|�y|\}}}}}Wn;tk
rftjd|�tjtj��|�dSX|jj|�|j	|7_	|j
j|�|jj|�xn|j
�D]`\}\}	}
}||jkr�|
|f|j|<n|j|\}}
}
|j|	�q�Wtjd||j	�dS(Nsbatch result is %ssresult in unexpected format %ssRan %s tests (total: %s)(RiRjRMRRpRvRwRZtwritettestsRuntfailuresR�terrorstitemsterrorClasses(RR�R�toutputR�R�R�R�tkeytstoragetlabeltisfailt	mystoraget_junk((s=/sys/lib/python2.7/site-packages/nose/plugins/multiprocess.pyR�ps"
"(RRR�RR}R�R�R~tstaticmethodR�RhR�RrR�(((s=/sys/lib/python2.7/site-packages/nose/plugins/multiprocess.pyR\s		(		�		 		c

CsyyQy)t||||||||||	�SWn!tk
rOtjd|�nXWn!tk
rttjd|�nXdS(Ns&Worker %s keyboard interrupt, stoppings%Worker %s timed out waiting for tasks(t__runnerRtRiRjR	(
tixR�R�R�R�R�R�RXtresultClassRJ((s=/sys/lib/python2.7/site-packages/nose/plugins/multiprocess.pyR]�s

c
s�tj����j�}
tdk	rdx:tD]/}|�}|j|
i��jj|�q.Wn�jj�j	���jj
�tjd|t
j��|d��}
t|
j_��fd�}��fd�}d�}x�t|d�D]�\}}|j�r$tjd|�Pn|�}|
j|g�}�|_g|_||_tjd|||�y||dk	r�|t|�}nt|�|_tj�|_||�td	�|_|j|||j||�f�Wn�tk
r�t|t�}|r |j �nt!|j�r�|r>d
}nd}tj|||�td	�|_t"j#t$j%��|�|j|||j||�f�nJ|r�d}nd
}tj|||�|j|||j||�f�|s��q�n�t&k
r/td	�|_tjd|��natd	�|_tjd|�t"j#t$j%��|�|j|||j||�f�nX�j'r��Wtjd|�dS(NsWorker %s executing, pid=%dRJcs�jd�j�S(NR�(R>R8((RJR�(s=/sys/lib/python2.7/site-packages/nose/plugins/multiprocess.pyR>�scsPtt��}�|ddd�jd��}�jj|�}|rL|S|S(NtdescriptionsiR[RJ(RRR[R�tprepareTestResult(RZR�tplug_result(RJR�(s=/sys/lib/python2.7/site-packages/nose/plugins/multiprocess.pyt
makeResult�s		c
Ss�g|jD]\}}t|�|f^q
}g|jD]\}}t|�|f^q8}i}x^|jj�D]M\}\}}}	g|D]\}}t|�|f^q�||	f||<qrW|jj�|j|||fS(N(R�R$R�R�R�RZtgetvalueR�(
R�R�terrR�R�R�R�R�R�R�((s=/sys/lib/python2.7/site-packages/nose/plugins/multiprocess.pyR��s..%(R�sWorker %d STOPPEDsWorker %s Test is %s (%s)R�s,Worker %s timed out, failing current test %ss5Worker %s keyboard interrupt, failing current test %ssWorker %s test %s timed outs$Worker %s test %s keyboard interruptsWorker %s system exits1Worker %s error running test or returning resultssWorker %s ending((R�tloadstparserClasst_instantiate_pluginsRNt
addOptionsR�t	addPluginRVRBtbeginRiRjR�R�tNoSharedFixtureContextSuitet
suiteClasstiterR�t	exceptiontloadTestsFromNamesR�R�R�R*RR
R�R�RtRlRR�RRRpRvRwRuR<(R�R�R�R�R�R�R�RXR�RJtdummy_parsertpluginclasstpluginRR>R�R�R�R�R�RoR�R�tmsg((RJR�R�s=/sys/lib/python2.7/site-packages/nose/plugins/multiprocess.pyR��s�
	

	
				
&
	%	"	
	&	RcBs;eZdZdZdZdZd�Zd�Zd�Z	RS(s
    Context suite that never fires shared fixtures.

    When a context sets _multiprocess_shared_, fixtures in that context
    are executed by the main process. Using this suite class prevents them
    from executing in the runner process as well.

    cCs0t|dt�rdStt|�j|�dS(NRg(R{R?ReRtsetupContext(RRq((s=/sys/lib/python2.7/site-packages/nose/plugins/multiprocess.pyR�scCs0t|dt�rdStt|�j|�dS(NRg(R{R?ReRtteardownContext(RRq((s=/sys/lib/python2.7/site-packages/nose/plugins/multiprocess.pyRscCs5tjdt|�||j�|jrD|j||�|}}n
||}}y|j�Wn:tk
ru�n'd|_|j||j	��dSXz>x7|jD],}t
|tjj
�r�jdk	r�j|j_n|j|_|j|_|j|_|jr#tjd�Pny||�Wq�tk
r�}t
|t�}|rad}nd}tj|||�ttt|��tj�df}|jjj||�|j||�|s��q�q�Xq�WWdt|_y|j�Wn9tk
r
�n&d|_|j||j	��nXXdS(	s5Run tests in suite inside of suite fixtures.
        s#suite %s (%s) run called, tests: %stsetupNtstoppings(Timeout when running test %s in suite %ss2KeyboardInterrupt when running test %s in suite %sitteardown(RiRjR%t_teststresultProxyRsRtt
error_contextRxt	_exc_infoRlRmR,RnR�RNRoR�R�R�RR*RvRwRJR�RQthas_runR�(RR�torigRoR�R�R
R�((s=/sys/lib/python2.7/site-packages/nose/plugins/multiprocess.pyR�s\		

		
		
	N(
RRR_RNR�R�R�RRR�(((s=/sys/lib/python2.7/site-packages/nose/plugins/multiprocess.pyR�s		(6R_tloggingR�RvR�t	tracebackR�R�Rt	nose.caseRmt	nose.coreRRRtnose.plugins.baseRtnose.pyversionRtnose.resultRt
nose.suiteRt	nose.utilRtunittest.runnerRRRR	twarningsR
t	cStringIORRNRt	getLoggerRRiRRRRRRtRR#R$R-RcR\R]R�R(((s=/sys/lib/python2.7/site-packages/nose/plugins/multiprocess.pyt<module>^sP

	_	�	a

Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to [email protected].