MCPcopy Create free account
hub / github.com/fabioz/PyDev.Debugger / trace_dispatch

Method trace_dispatch

_pydevd_bundle/pydevd_frame.py:346–1055  ·  view source on GitHub ↗
(self, frame, event, arg)

Source from the content-addressed store, hash-verified

344 # cdef tuple pydev_smart_step_into_variants
345 # ELSE
346 def trace_dispatch(self, frame, event, arg):
347 # ENDIF
348 # Note: this is a big function because most of the logic related to hitting a breakpoint and
349 # stepping is contained in it. Ideally this could be split among multiple functions, but the
350 # problem in this case is that in pure-python function calls are expensive and even more so
351 # when tracing is on (because each function call will get an additional tracing call). We
352 # try to address this by using the info.is_tracing for the fastest possible return, but the
353 # cost is still high (maybe we could use code-generation in the future and make the code
354 # generation be better split among what each part does).
355
356 try:
357 # DEBUG = '_debugger_case_yield_from.py' in frame.f_code.co_filename
358 py_db, abs_path_canonical_path_and_base, info, thread, frame_skips_cache, frame_cache_key = self._args
359 # if DEBUG: print('frame trace_dispatch %s %s %s %s %s %s, stop: %s' % (frame.f_lineno, frame.f_code.co_name, frame.f_code.co_filename, event, constant_to_str(info.pydev_step_cmd), arg, info.pydev_step_stop))
360 info.is_tracing += 1
361
362 # TODO: This shouldn't be needed. The fact that frame.f_lineno
363 # is None seems like a bug in Python 3.11.
364 # Reported in: https://github.com/python/cpython/issues/94485
365 line = frame.f_lineno or 0 # Workaround or case where frame.f_lineno is None
366 line_cache_key = (frame_cache_key, line)
367
368 if py_db.pydb_disposed:
369 return None if event == "call" else NO_FTRACE
370
371 plugin_manager = py_db.plugin
372 has_exception_breakpoints = (
373 py_db.break_on_caught_exceptions or py_db.break_on_user_uncaught_exceptions or py_db.has_plugin_exception_breaks
374 )
375
376 stop_frame = info.pydev_step_stop
377 step_cmd = info.pydev_step_cmd
378 function_breakpoint_on_call_event = None
379
380 if frame.f_code.co_flags & 0xA0: # 0xa0 == CO_GENERATOR = 0x20 | CO_COROUTINE = 0x80
381 # Dealing with coroutines and generators:
382 # When in a coroutine we change the perceived event to the debugger because
383 # a call, StopIteration exception and return are usually just pausing/unpausing it.
384 if event == "line":
385 is_line = True
386 is_call = False
387 is_return = False
388 is_exception_event = False
389
390 elif event == "return":
391 is_line = False
392 is_call = False
393 is_return = True
394 is_exception_event = False
395
396 returns_cache_key = (frame_cache_key, "returns")
397 return_lines = frame_skips_cache.get(returns_cache_key)
398 if return_lines is None:
399 # Note: we're collecting the return lines by inspecting the bytecode as
400 # there are multiple returns and multiple stop iterations when awaiting and
401 # it doesn't give any clear indication when a coroutine or generator is
402 # finishing or just pausing.
403 return_lines = set()

Callers 1

__call__Method · 0.45

Calls 15

handle_user_exceptionMethod · 0.95
_is_same_frameMethod · 0.95
_show_return_valuesMethod · 0.95
_remove_return_valuesMethod · 0.95
set_suspendMethod · 0.95
do_wait_suspendMethod · 0.95
should_stop_on_exceptionFunction · 0.85
handle_exceptionFunction · 0.85
apply_files_filterMethod · 0.80

Tested by

no test coverage detected