From cef176cff70fa631af7ac4b638181fa1a6017d6d Mon Sep 17 00:00:00 2001 From: Yilei Date: Fri, 10 Jun 2022 12:26:51 -0700 Subject: [PATCH] When stashing the singleton to sys.modules, use an actual module object. At least this won't trip anyone iterating through sys.modules and expects the values are actual modules. --- coverage/debug.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/coverage/debug.py b/coverage/debug.py index 7ec3ae42b..4286bc501 100644 --- a/coverage/debug.py +++ b/coverage/debug.py @@ -12,6 +12,7 @@ import pprint import reprlib import sys +import types import _thread from coverage.misc import isolate_module @@ -282,6 +283,7 @@ def __init__(self, outfile, show_process, filters): self.write(f"New process: pid: {os.getpid()!r}, parent pid: {os.getppid()!r}\n") SYS_MOD_NAME = '$coverage.debug.DebugOutputFile.the_one' + SINGLETON_ATTR = 'the_one_and_is_interim' @classmethod def get_one(cls, fileobj=None, show_process=True, filters=(), interim=False): @@ -310,7 +312,8 @@ def get_one(cls, fileobj=None, show_process=True, filters=(), interim=False): # this class can be defined more than once. But we really want # a process-wide singleton. So stash it in sys.modules instead of # on a class attribute. Yes, this is aggressively gross. - the_one, is_interim = sys.modules.get(cls.SYS_MOD_NAME, (None, True)) + singleton_module = sys.modules.get(cls.SYS_MOD_NAME) + the_one, is_interim = getattr(singleton_module, cls.SINGLETON_ATTR, (None, True)) if the_one is None or is_interim: if fileobj is None: debug_file_name = os.environ.get("COVERAGE_DEBUG_FILE", FORCED_DEBUG_FILE) @@ -321,7 +324,9 @@ def get_one(cls, fileobj=None, show_process=True, filters=(), interim=False): else: fileobj = sys.stderr the_one = cls(fileobj, show_process, filters) - sys.modules[cls.SYS_MOD_NAME] = (the_one, interim) + singleton_module = types.ModuleType(cls.SYS_MOD_NAME) + setattr(singleton_module, cls.SINGLETON_ATTR, (the_one, interim)) + sys.modules[cls.SYS_MOD_NAME] = singleton_module return the_one def write(self, text):