diff --git a/pudb/debugger.py b/pudb/debugger.py index 8a9c07ad..a39e5bf9 100644 --- a/pudb/debugger.py +++ b/pudb/debugger.py @@ -183,15 +183,24 @@ # {{{ debugger interface -class Debugger(bdb.Bdb): +class Singleton(type): + _instance = None + + def __call__(cls, *args, **kwargs): + if not cls._instance: + cls._instance = super(Singleton, cls).__call__(*args, **kwargs) + else: + cls._pytest_postmortem = True + return cls._instance + + +class Debugger(bdb.Bdb, metaclass=Singleton): _current_debugger = [] + _pytest_postmortem = False def __init__(self, stdin=None, stdout=None, term_size=None, steal_output=False, _continue_at_start=False, tty_file=None, **kwargs): - if Debugger._current_debugger: - raise ValueError("a Debugger instance already exists") - # Pass remaining kwargs to python debugger framework bdb.Bdb.__init__(self, **kwargs) self.ui = DebuggerUI(self, stdin=stdin, stdout=stdout, term_size=term_size) @@ -214,6 +223,32 @@ def __init__(self, stdin=None, stdout=None, term_size=None, steal_output=False, # Okay, now we have a debugger self._current_debugger.append(self) + def reset(self): + """Set values of attributes as ready to start debugging. + + Override from Bdb.reset() + + When pytest starts a postmortem analysis, but the debugger is already active, + calling .reset() in src/_pytest/debugging.py::post_mortem + causes the self.stopframe to be set to None. + This pauses the debugger somewhere in the source code of the debugger. See #67 + + We detect using _pytest_postmortem that this is the case and do not set the + stopframe to None then. + + Related #607, #52 + """ + import linecache + linecache.checkcache() + self.botframe = None + if not self._pytest_postmortem: + self.stopframe = None + else: + self._pytest_postmortem = False + self.returnframe = None + self.quitting = False + self.stoplineno = 0 + def __del__(self): # according to https://stackoverflow.com/a/1481512/1054322, the garbage # collector cannot be relied on to call this, so we call it explicitly