66import platform
77import threading
88import collections
9- import queue as Queue
109from multiprocessing import Manager , Process
1110
11+ __version__ = '0.0.1'
12+
13+ try :
14+ # py3
15+ import queue as Queue
16+ except Exception :
17+ # py2
18+ import Queue as Queue
19+
1220
1321def parse_config (config , name ):
1422 return getattr (config .option , name , config .getini (name ))
@@ -24,8 +32,10 @@ def force(fn):
2432
2533
2634def pytest_addoption (parser ):
27- workers_help = 'Set the max num of workers (aka processes) to start (int or "auto" - one per core)'
28- tests_per_worker_help = 'Set the max num of concurrent tests for each worker (int or "auto" - split evenly)'
35+ workers_help = ('Set the max num of workers (aka processes) to start '
36+ '(int or "auto" - one per core)' )
37+ tests_per_worker_help = ('Set the max num of concurrent tests for each '
38+ 'worker (int or "auto" - split evenly)' )
2939
3040 group = parser .getgroup ('pytest-parallel' )
3141 group .addoption (
@@ -63,7 +73,7 @@ def __init__(self, queue, session):
6373 threading .Thread .__init__ (self )
6474 self .queue = queue
6575 self .session = session
66-
76+
6777 def run (self ):
6878 while True :
6979 try :
@@ -139,7 +149,9 @@ class ParallelRunner(object):
139149 def __init__ (self , config ):
140150 self ._manager = Manager ()
141151 reporter = config .pluginmanager .getplugin ('terminalreporter' )
142- reporter .showfspath = False # prevent mangling the output
152+
153+ # prevent mangling the output
154+ reporter .showfspath = False
143155
144156 # get the number of workers
145157 workers = parse_config (config , 'workers' )
@@ -155,62 +167,74 @@ def __init__(self, config):
155167 print ('INFO: pytest-parallel forces 1 worker on Windows' )
156168 except ValueError :
157169 raise ValueError ('workers can only be an integer or "auto"' )
158-
170+
159171 self .workers = workers
160172
161173 if self .workers > 1 :
162174 # ensure stats are process-safe
163175 reporter .stats = self ._manager .dict ()
164176 setdefault = reporter .stats .setdefault
177+
165178 def setdefault_proxy (key , default = None ):
166179 if isinstance (default , list ) and len (default ) == 0 :
167180 default = force (lambda : self ._manager .list ())
168181 return force (lambda : setdefault (key , default ))
169182 reporter .stats .setdefault = setdefault_proxy
170183
171-
172184 @pytest .mark .tryfirst
173185 def pytest_sessionstart (self , session ):
174186 # make the session threadsafe
175187 _pytest .runner .SetupState = ThreadLocalSetupState
176-
188+
177189 # ensure that the fixtures (specifically finalizers) are threadsafe
178190 _pytest .fixtures .FixtureDef = ThreadLocalFixtureDef
179191
180192 # make the environment threadsafe
181193 os .environ = ThreadLocalEnviron (os .environ )
182194
183-
184195 def pytest_runtestloop (self , session ):
185196 # get the number of tests per worker
186197 tests_per_worker = parse_config (session .config , 'tests_per_worker' )
187198 try :
188199 if tests_per_worker == 'auto' :
189200 tests_per_worker = 50
190201 if tests_per_worker :
191- tests_per_worker = min (int (tests_per_worker ), math .ceil (len (session .items )/ self .workers ))
202+ tests_per_worker = int (tests_per_worker )
203+ evenly_divided = math .ceil (len (session .items )/ self .workers )
204+ tests_per_worker = min (tests_per_worker , evenly_divided )
192205 else :
193206 tests_per_worker = 1
194207 except ValueError :
195- raise ValueError ('tests_per_worker can only be an integer or "auto"' )
208+ raise ValueError (('tests_per_worker can only be '
209+ 'an integer or "auto"' ))
196210
197- worker_noun = 'workers' if self .workers > 1 else 'worker'
198- test_noun = 'tests' if tests_per_worker > 1 else 'test'
199- print ('pytest-parallel: {} {} (processes), {} {} per worker (threads)'
200- .format (self .workers , worker_noun , tests_per_worker , test_noun ))
211+ if self .workers > 1 :
212+ worker_noun , process_noun = ('workers' , 'processes' )
213+ else :
214+ worker_noun , process_noun = ('worker' , 'process' )
215+
216+ if tests_per_worker > 1 :
217+ test_noun , thread_noun = ('tests' , 'threads' )
218+ else :
219+ test_noun , thread_noun = ('test' , 'thread' )
220+
221+ print ('pytest-parallel: {} {} ({}), {} {} per worker ({})'
222+ .format (self .workers , worker_noun , process_noun ,
223+ tests_per_worker , test_noun , thread_noun ))
201224
202225 queue = Queue .Queue () if self .workers == 1 else self ._manager .Queue ()
203226
204227 for i in range (len (session .items )):
205228 queue .put (i )
206-
229+
207230 if self .workers == 1 :
208231 process_with_threads (queue , session , tests_per_worker )
209232 return True
210233
211234 processes = []
212235 for _ in range (self .workers ):
213- process = Process (target = process_with_threads , args = (queue , session , tests_per_worker ))
236+ process = Process (target = process_with_threads ,
237+ args = (queue , session , tests_per_worker ))
214238 process .start ()
215239 processes .append (process )
216240 [p .join () for p in processes ]
0 commit comments