diff --git a/coverage/control.py b/coverage/control.py index 086490730..e93845587 100644 --- a/coverage/control.py +++ b/coverage/control.py @@ -434,7 +434,10 @@ def _init_for_start(self): raise CoverageException( # pragma: only jython "multiprocessing is not supported on this Python" ) - patch_multiprocessing(rcfile=self.config.config_file) + patch_multiprocessing( + rcfile=self.config.config_file, + static_context=self.config.context or "" + ) dycon = self.config.dynamic_context if not dycon or dycon == "none": diff --git a/coverage/multiproc.py b/coverage/multiproc.py index 0afcb0c9b..d7248391b 100644 --- a/coverage/multiproc.py +++ b/coverage/multiproc.py @@ -32,7 +32,10 @@ def _bootstrap(self, *args, **kwargs): # pylint: disable=signature-diff """Wrapper around _bootstrap to start coverage.""" try: from coverage import Coverage # avoid circular import - cov = Coverage(data_suffix=True) + cov = Coverage( + data_suffix=True, + context=os.environ.get("COVERAGE_STATIC_CONTEXT") or None + ) cov._warn_preimported_source = False cov.start() debug = cov._debug @@ -55,18 +58,19 @@ def _bootstrap(self, *args, **kwargs): # pylint: disable=signature-diff class Stowaway(object): """An object to pickle, so when it is unpickled, it can apply the monkey-patch.""" - def __init__(self, rcfile): + def __init__(self, rcfile, static_context): self.rcfile = rcfile + self.static_context = static_context def __getstate__(self): - return {'rcfile': self.rcfile} + return {'rcfile': self.rcfile, "static_context": self.static_context} def __setstate__(self, state): - patch_multiprocessing(state['rcfile']) + patch_multiprocessing(state['rcfile'], state["static_context"]) -@contract(rcfile=str) -def patch_multiprocessing(rcfile): +@contract(rcfile=str, static_context=str) +def patch_multiprocessing(rcfile, static_context): """Monkey-patch the multiprocessing module. This enables coverage measurement of processes started by multiprocessing. @@ -87,6 +91,7 @@ def patch_multiprocessing(rcfile): # Set the value in ProcessWithCoverage that will be pickled into the child # process. os.environ["COVERAGE_RCFILE"] = os.path.abspath(rcfile) + os.environ["COVERAGE_STATIC_CONTEXT"] = static_context # When spawning processes rather than forking them, we have no state in the # new process. We sneak in there with a Stowaway: we stuff one of our own @@ -103,7 +108,7 @@ def patch_multiprocessing(rcfile): def get_preparation_data_with_stowaway(name): """Get the original preparation data, and also insert our stowaway.""" d = original_get_preparation_data(name) - d['stowaway'] = Stowaway(rcfile) + d['stowaway'] = Stowaway(rcfile, static_context) return d spawn.get_preparation_data = get_preparation_data_with_stowaway