8 import os |
8 import os |
9 import os.path |
9 import os.path |
10 import sys |
10 import sys |
11 import traceback |
11 import traceback |
12 |
12 |
13 from coverage import env |
|
14 from coverage.misc import contract |
13 from coverage.misc import contract |
15 |
14 |
16 # An attribute that will be set on the module to indicate that it has been |
15 # An attribute that will be set on the module to indicate that it has been |
17 # monkey-patched. |
16 # monkey-patched. |
18 PATCHED_MARKER = "_coverage$patched" |
17 PATCHED_MARKER = "_coverage$patched" |
19 |
18 |
20 |
19 |
21 if env.PYVERSION >= (3, 4): |
20 OriginalProcess = multiprocessing.process.BaseProcess |
22 OriginalProcess = multiprocessing.process.BaseProcess |
|
23 else: |
|
24 OriginalProcess = multiprocessing.Process |
|
25 |
|
26 original_bootstrap = OriginalProcess._bootstrap |
21 original_bootstrap = OriginalProcess._bootstrap |
27 |
22 |
28 class ProcessWithCoverage(OriginalProcess): # pylint: disable=abstract-method |
23 class ProcessWithCoverage(OriginalProcess): # pylint: disable=abstract-method |
29 """A replacement for multiprocess.Process that starts coverage.""" |
24 """A replacement for multiprocess.Process that starts coverage.""" |
30 |
25 |
51 cov.stop() |
46 cov.stop() |
52 cov.save() |
47 cov.save() |
53 if debug.should("multiproc"): |
48 if debug.should("multiproc"): |
54 debug.write("Saved multiprocessing data") |
49 debug.write("Saved multiprocessing data") |
55 |
50 |
56 class Stowaway(object): |
51 class Stowaway: |
57 """An object to pickle, so when it is unpickled, it can apply the monkey-patch.""" |
52 """An object to pickle, so when it is unpickled, it can apply the monkey-patch.""" |
58 def __init__(self, rcfile): |
53 def __init__(self, rcfile): |
59 self.rcfile = rcfile |
54 self.rcfile = rcfile |
60 |
55 |
61 def __getstate__(self): |
56 def __getstate__(self): |
77 """ |
72 """ |
78 |
73 |
79 if hasattr(multiprocessing, PATCHED_MARKER): |
74 if hasattr(multiprocessing, PATCHED_MARKER): |
80 return |
75 return |
81 |
76 |
82 if env.PYVERSION >= (3, 4): |
77 OriginalProcess._bootstrap = ProcessWithCoverage._bootstrap |
83 OriginalProcess._bootstrap = ProcessWithCoverage._bootstrap |
|
84 else: |
|
85 multiprocessing.Process = ProcessWithCoverage |
|
86 |
78 |
87 # Set the value in ProcessWithCoverage that will be pickled into the child |
79 # Set the value in ProcessWithCoverage that will be pickled into the child |
88 # process. |
80 # process. |
89 os.environ["COVERAGE_RCFILE"] = os.path.abspath(rcfile) |
81 os.environ["COVERAGE_RCFILE"] = os.path.abspath(rcfile) |
90 |
82 |