280 self.write("New process: cmd: {!r}\n".format(getattr(sys, 'argv', None))) |
281 self.write("New process: cmd: {!r}\n".format(getattr(sys, 'argv', None))) |
281 if hasattr(os, 'getppid'): |
282 if hasattr(os, 'getppid'): |
282 self.write(f"New process: pid: {os.getpid()!r}, parent pid: {os.getppid()!r}\n") |
283 self.write(f"New process: pid: {os.getpid()!r}, parent pid: {os.getppid()!r}\n") |
283 |
284 |
284 SYS_MOD_NAME = '$coverage.debug.DebugOutputFile.the_one' |
285 SYS_MOD_NAME = '$coverage.debug.DebugOutputFile.the_one' |
|
286 SINGLETON_ATTR = 'the_one_and_is_interim' |
285 |
287 |
286 @classmethod |
288 @classmethod |
287 def get_one(cls, fileobj=None, show_process=True, filters=(), interim=False): |
289 def get_one(cls, fileobj=None, show_process=True, filters=(), interim=False): |
288 """Get a DebugOutputFile. |
290 """Get a DebugOutputFile. |
289 |
291 |
308 |
310 |
309 # Because of the way igor.py deletes and re-imports modules, |
311 # Because of the way igor.py deletes and re-imports modules, |
310 # this class can be defined more than once. But we really want |
312 # this class can be defined more than once. But we really want |
311 # a process-wide singleton. So stash it in sys.modules instead of |
313 # a process-wide singleton. So stash it in sys.modules instead of |
312 # on a class attribute. Yes, this is aggressively gross. |
314 # on a class attribute. Yes, this is aggressively gross. |
313 the_one, is_interim = sys.modules.get(cls.SYS_MOD_NAME, (None, True)) |
315 singleton_module = sys.modules.get(cls.SYS_MOD_NAME) |
|
316 the_one, is_interim = getattr(singleton_module, cls.SINGLETON_ATTR, (None, True)) |
314 if the_one is None or is_interim: |
317 if the_one is None or is_interim: |
315 if fileobj is None: |
318 if fileobj is None: |
316 debug_file_name = os.environ.get("COVERAGE_DEBUG_FILE", FORCED_DEBUG_FILE) |
319 debug_file_name = os.environ.get("COVERAGE_DEBUG_FILE", FORCED_DEBUG_FILE) |
317 if debug_file_name in ("stdout", "stderr"): |
320 if debug_file_name in ("stdout", "stderr"): |
318 fileobj = getattr(sys, debug_file_name) |
321 fileobj = getattr(sys, debug_file_name) |
319 elif debug_file_name: |
322 elif debug_file_name: |
320 fileobj = open(debug_file_name, "a") |
323 fileobj = open(debug_file_name, "a") |
321 else: |
324 else: |
322 fileobj = sys.stderr |
325 fileobj = sys.stderr |
323 the_one = cls(fileobj, show_process, filters) |
326 the_one = cls(fileobj, show_process, filters) |
324 sys.modules[cls.SYS_MOD_NAME] = (the_one, interim) |
327 singleton_module = types.ModuleType(cls.SYS_MOD_NAME) |
|
328 setattr(singleton_module, cls.SINGLETON_ATTR, (the_one, interim)) |
|
329 sys.modules[cls.SYS_MOD_NAME] = singleton_module |
325 return the_one |
330 return the_one |
326 |
331 |
327 def write(self, text): |
332 def write(self, text): |
328 """Just like file.write, but filter through all our filters.""" |
333 """Just like file.write, but filter through all our filters.""" |
329 self.outfile.write(filter_text(text, self.filters)) |
334 self.outfile.write(filter_text(text, self.filters)) |