def pytest_exception_interact(node, call, report): """ Drop into PyCharm debugger, if available, on uncaught exceptions. """ try: import pydevd from pydevd import pydevd_tracing except ImportError: pass else: exctype, value, traceback = call.excinfo._excinfo frames = [] while traceback: frames.append(traceback.tb_frame) traceback = traceback.tb_next thread = threading.current_thread() frames_by_id = dict([(id(frame), frame) for frame in frames]) frame = frames[-1] exception = (exctype, value, traceback) thread.additional_info.pydev_message = 'test fail' try: debugger = pydevd.debugger except AttributeError: debugger = pydevd.get_global_debugger() pydevd_tracing.SetTrace(None) # no tracing from here debugger.handle_post_mortem_stop(thread, frame, frames_by_id, exception) return report
def pytest_exception_interact(node, call, report): """ Drop into PyCharm debugger, if available, on uncaught exceptions. """ try: import pydevd from pydevd import pydevd_tracing except ImportError: pass else: exctype, value, traceback = call.excinfo._excinfo frames = [] while traceback: frames.append(traceback.tb_frame) traceback = traceback.tb_next thread = threading.current_thread() frames_by_id = dict([(id(frame), frame) for frame in frames]) frame = frames[-1] exception = (exctype, value, traceback) thread.additional_info.pydev_message = 'test fail' try: debugger = pydevd.debugger except AttributeError: debugger = pydevd.get_global_debugger() pydevd_tracing.SetTrace(None) # no tracing from here try: debugger.stop_on_unhandled_exception(thread, frame, frames_by_id, exception) except AttributeError: # fallback to pre PyCharm 2019.2 API debugger.handle_post_mortem_stop(thread, frame, frames_by_id, exception) return report
def check(): import pydevd py_db = pydevd.get_global_debugger() assert len(py_db.api_received_breakpoints) == 1 _a = 10 # break here # should remove the breakpoints when stopped on the previous line assert len(py_db.api_received_breakpoints) == 0
def attach(port, host, protocol=''): try: import sys fix_main_thread = 'threading' not in sys.modules if fix_main_thread: def on_warn(msg): from _pydev_bundle import pydev_log pydev_log.warn(msg) def on_exception(msg): from _pydev_bundle import pydev_log pydev_log.exception(msg) def on_critical(msg): from _pydev_bundle import pydev_log pydev_log.critical(msg) fix_main_thread_id(on_warn=on_warn, on_exception=on_exception, on_critical=on_critical) else: from _pydev_bundle import pydev_log # @Reimport pydev_log.debug( 'The threading module is already imported by user code.') if protocol: from _pydevd_bundle import pydevd_defaults pydevd_defaults.PydevdCustomization.DEFAULT_PROTOCOL = protocol import pydevd # I.e.: disconnect/reset if already connected. pydevd.SetupHolder.setup = None py_db = pydevd.get_global_debugger() if py_db is not None: py_db.dispose_and_kill_all_pydevd_threads(wait=False) # pydevd.DebugInfoHolder.DEBUG_RECORD_SOCKET_READS = True # pydevd.DebugInfoHolder.DEBUG_TRACE_BREAKPOINTS = 3 # pydevd.DebugInfoHolder.DEBUG_TRACE_LEVEL = 3 pydevd.settrace( port=port, host=host, stdoutToServer=True, stderrToServer=True, overwrite_prev_trace=True, suspend=False, trace_only_current_thread=False, patch_multiprocessing=False, ) except: import traceback traceback.print_exc()
def pydevd_breakpointhook(): hookname = os.getenv('PYTHONBREAKPOINT') if hookname is not None and len(hookname) > 0 and hasattr(sys, '__breakpointhook__'): sys.__breakpointhook__(*args, **kwargs) else: import pydevd py_db = pydevd.get_global_debugger() if (py_db is not None) and (py_db.frame_eval_func is not None): from _pydevd_frame_eval.pydevd_frame_tracing import suspend_at_builtin_breakpoint suspend_at_builtin_breakpoint() else: pydevd.settrace( suspend=True, trace_only_current_thread=True, patch_multiprocessing=False, stop_at_frame=sys._getframe().f_back, )
def pydevd_breakpointhook(): hookname = os.getenv('PYTHONBREAKPOINT') if hookname is not None and len(hookname) > 0 and hasattr( sys, '__breakpointhook__'): sys.__breakpointhook__(*args, **kwargs) else: import pydevd py_db = pydevd.get_global_debugger() if py_db is not None: from _pydevd_frame_eval.pydevd_frame_tracing import suspend_at_builtin_breakpoint suspend_at_builtin_breakpoint() else: pydevd.settrace( suspend=True, trace_only_current_thread=True, patch_multiprocessing=False, stop_at_frame=sys._getframe().f_back.f_back, )
def breakpoint_on_exception(): try: import pydevd from pydevd import pydevd_tracing except ImportError: pass else: exctype, value, traceback = sys.exc_info() frames = [] while traceback: frames.append(traceback.tb_frame) traceback = traceback.tb_next thread = threading.current_thread() frames_by_id = dict([(id(frame), frame) for frame in frames]) frame = frames[-1] if hasattr(thread, "additional_info"): thread.additional_info.pydev_message = "Uncaught exception" try: debugger = pydevd.debugger except AttributeError: debugger = pydevd.get_global_debugger() pydevd_tracing.SetTrace(None) # no tracing from here debugger.stop_on_unhandled_exception(thread, frame, frames_by_id, (exctype, value, traceback))
def check_step_in_then_step_return(): frame = sys._getframe() f_trace = frame.f_trace if f_trace.__class__.__name__ != 'SafeCallWrapper': raise AssertionError('Expected %s to be SafeCallWrapper' % (f_trace.__class__.__name__,)) check_with_no_trace() def check_revert_to_dummy(): check_with_no_trace() if __name__ == '__main__': # Check how frame eval works. if sys.version_info[0:2] < (3, 6): raise AssertionError('Only available for Python 3.6 onwards. Found: %s' % (sys.version_info[0:1],)) check_with_no_trace() # break on global (step over) check_step_in_then_step_return() import pydevd_tracing import pydevd # This is what a remote attach would do (should revert to the frame eval mode). pydevd_tracing.SetTrace(pydevd.get_global_debugger().trace_dispatch) check_revert_to_dummy() print('TEST SUCEEDED!')
assert sys.gettrace() is None print('enable attach to port: %s' % (port, )) pydevd._enable_attach(('127.0.0.1', port)) pydevd._enable_attach(('127.0.0.1', port)) # no-op in practice try: pydevd._enable_attach( ('127.0.0.1', port + 15)) # different port: raise error. except AssertionError: pass else: raise AssertionError( 'Expected _enable_attach to raise exception (because it is already hearing in another port).' ) assert pydevd.get_global_debugger() is not None assert sys.gettrace() is not None a = 10 # Break 1 print('wait for attach') pydevd._wait_for_attach() print('finished wait for attach') pydevd._wait_for_attach() # Should promptly return (already connected). a = 20 # Break 2 pydevd._wait_for_attach( ) # As we disconnected on the 2nd break, this one should wait until a new configurationDone. a = 20 # Break 3
def attach(setup): log = None try: import sys if "threading" not in sys.modules: try: def on_warn(msg): print(msg, file=sys.stderr) def on_exception(msg): print(msg, file=sys.stderr) def on_critical(msg): print(msg, file=sys.stderr) pydevd_attach_to_process_path = os.path.join( _debugpy_dir, "debugpy", "_vendored", "pydevd", "pydevd_attach_to_process", ) assert os.path.exists(pydevd_attach_to_process_path) sys.path.insert(0, pydevd_attach_to_process_path) # NOTE: that it's not a part of the pydevd PYTHONPATH import attach_script attach_script.fix_main_thread_id(on_warn=on_warn, on_exception=on_exception, on_critical=on_critical) # NOTE: At this point it should be safe to remove this. sys.path.remove(pydevd_attach_to_process_path) except: import traceback traceback.print_exc() raise sys.path.insert(0, _debugpy_dir) try: import debugpy import debugpy.server from debugpy.common import log import pydevd finally: assert sys.path[0] == _debugpy_dir del sys.path[0] py_db = pydevd.get_global_debugger() if py_db is not None: py_db.dispose_and_kill_all_pydevd_threads(wait=False) if setup["log_to"] is not None: debugpy.log_to(setup["log_to"]) log.info("Configuring injected debugpy: {0!j}", setup) if setup["mode"] == "listen": debugpy.listen(setup["address"]) elif setup["mode"] == "connect": debugpy.connect(setup["address"], access_token=setup["adapter_access_token"]) else: raise AssertionError(repr(setup)) except: import traceback traceback.print_exc() if log is None: raise else: log.reraise_exception() log.info("debugpy injected successfully")
def create_code(): cEll1_code = compile( ''' # line 1 import sys # line 2 frame = sys._getframe() # line 3 if py_db.in_project_scope(frame, '<cEll1>') != expect_in_project_scope: # line 4 raise AssertionError('Expected <cEll1> to be in project scope: %s' % (expect_in_project_scope,)) # line 5 a = 1 # line 6 b = 2 # line 7 ''', '<cEll1>', 'exec') return {'cEll1': cEll1_code} if __name__ == '__main__': code = create_code() import pydevd py_db = pydevd.get_global_debugger() expect_in_project_scope = True exec( code['cEll1'] ) # When executing, stop at breakpoint and then remove the source mapping. expect_in_project_scope = False exec(code['cEll1']) # Should no longer stop. print('TEST SUCEEDED')
if f_trace.__class__.__name__ != 'SafeCallWrapper': raise AssertionError('Expected %s to be SafeCallWrapper' % (f_trace.__class__.__name__, )) check_with_no_trace() def check_revert_to_dummy(): check_with_no_trace() if __name__ == '__main__': # Check how frame eval works. if sys.version_info[0:2] < (3, 6): raise AssertionError( 'Only available for Python 3.6 onwards. Found: %s' % (sys.version_info[0:1], )) check_with_no_trace() # break on global (step over) check_step_in_then_step_return() import pydevd_tracing import pydevd # This is what a remote attach would do (should revert to the frame eval mode). pydevd_tracing.SetTrace(pydevd.get_global_debugger().trace_dispatch) check_revert_to_dummy() print('TEST SUCEEDED!')
import pydevd # Some hackery to get the PyDevJsonCommandProcessor which is not exposed. try: json_command_processor = pydevd.get_global_debugger().reader.process_net_command_json.__self__ except: json_command_processor = pydevd.get_global_debugger().reader.process_net_command_json.im_self print(json_command_processor._options.to_json()) print('TEST SUCEEDED!')
else: raise AssertionError('Expected _wait_for_attach to raise exception.') assert sys.gettrace() is None print('enable attach to port: %s' % (port,)) pydevd._enable_attach(('127.0.0.1', port)) pydevd._enable_attach(('127.0.0.1', port)) # no-op in practice try: pydevd._enable_attach(('127.0.0.1', port + 15)) # different port: raise error. except AssertionError: pass else: raise AssertionError('Expected _enable_attach to raise exception (because it is already hearing in another port).') assert pydevd.get_global_debugger() is not None assert sys.gettrace() is not None a = 10 # Break 1 print('wait for attach') pydevd._wait_for_attach() print('finished wait for attach') pydevd._wait_for_attach() # Should promptly return (already connected). a = 20 # Break 2 pydevd._wait_for_attach() # As we disconnected on the 2nd break, this one should wait until a new configurationDone. a = 20 # Break 3 while a == 20: # Pause 1
def call(): import pydevd from _pydevd_bundle.pydevd_api import PyDevdAPI assert pydevd.get_global_debugger().get_arg_ppid() == PyDevdAPI().get_ppid( ) print("called") # break 1 here