Skip to content

Commit

Permalink
Remove comment that is no longer applicable.
Browse files Browse the repository at this point in the history
Use consistent naming.
  • Loading branch information
Pavel Minaev authored and int19h committed Mar 26, 2024
1 parent 1d4e23b commit 117704d
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 40 deletions.
2 changes: 1 addition & 1 deletion src/debugpy/server/eval.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ def __setattr__(self, name, value):
pass
else:
PyFrame_LocalsToFast(
ctypes.py_object(frame.frame_object), ctypes.c_int(0)
ctypes.py_object(frame.python_frame), ctypes.c_int(0)
)

super().__init__(frame, name, ScopeObject())
50 changes: 26 additions & 24 deletions src/debugpy/server/tracing/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,7 @@ def stack_trace(self) -> Iterable["StackFrame"]:
except ValueError:
raise ValueError(f"Can't get frames for inactive Thread({self.id})")
for python_frame, _ in traceback.walk_stack(python_frame):
frame = StackFrame.from_frame_object(self, python_frame)
frame = StackFrame.from_python_frame(self, python_frame)
log.info("{0}", f"{self}: {frame}")
if not is_internal_python_frame(python_frame):
yield frame
Expand All @@ -271,66 +271,67 @@ def stack_trace(self) -> Iterable["StackFrame"]:
class StackFrame:
"""
Represents a DAP StackFrame object. Instances must never be created directly;
use StackFrame.from_frame_object() instead.
use StackFrame.from_python_frame() instead.
"""

id: int

thread: Thread
frame_object: FrameType
python_frame: FrameType

id: int
_source: Source | None
_scopes: List[Scope]

_all: ClassVar[Dict[int, "StackFrame"]] = {}

def __init__(self, thread: Thread, frame_object: FrameType):
def __init__(self, thread: Thread, python_frame: FrameType):
"""
Create a new StackFrame object for the given thread and frame object. Do not
invoke directly; use StackFrame.from_frame_object() instead.
invoke directly; use StackFrame.from_python_frame() instead.
"""
self.id = new_dap_id()
self.thread = thread
self.frame_object = frame_object
self.python_frame = python_frame
self._source = None
self._scopes = None
self._all[self.id] = self

def __getstate__(self) -> dict:
return {
"id": self.id,
"name": self.frame_object.f_code.co_name,
"name": self.python_frame.f_code.co_name,
"source": self.source(),
"line": self.frame_object.f_lineno,
"line": self.python_frame.f_lineno,
"column": 1, # TODO
# TODO: "endLine", "endColumn", "moduleId", "instructionPointerReference"
}

def __repr__(self) -> str:
result = f"StackFrame({self.id}, {self.frame_object}"
if is_internal_python_frame(self.frame_object):
result = f"StackFrame({self.id}, {self.python_frame}"
if is_internal_python_frame(self.python_frame):
result += ", internal=True"
result += ")"
return result

@property
def line(self) -> int:
return self.frame_object.f_lineno
return self.python_frame.f_lineno

def source(self) -> Source:
if self._source is None:
# No need to sync this since all instances created from the same path
# are equivalent for all purposes.
self._source = Source(self.frame_object.f_code.co_filename)
self._source = Source(self.python_frame.f_code.co_filename)
return self._source

@classmethod
def from_frame_object(
self, thread: Thread, frame_object: FrameType
def from_python_frame(
self, thread: Thread, python_frame: FrameType
) -> "StackFrame":
for frame in self._all.values():
if frame.thread is thread and frame.frame_object is frame_object:
if frame.thread is thread and frame.python_frame is python_frame:
return frame
return StackFrame(thread, frame_object)
return StackFrame(thread, python_frame)

@classmethod
def get(self, id: int) -> "StackFrame":
Expand All @@ -339,21 +340,22 @@ def get(self, id: int) -> "StackFrame":
def scopes(self) -> List[Scope]:
if self._scopes is None:
self._scopes = [
Scope(self, "local", self.frame_object.f_locals),
Scope(self, "global", self.frame_object.f_globals),
Scope(self, "local", self.python_frame.f_locals),
Scope(self, "global", self.python_frame.f_globals),
]
return self._scopes

def evaluate(self, source: str, mode: Literal["eval", "exec", "single"] = "eval") -> object:
code = compile(source, "<string>", mode)
return eval(code, self.frame_object.f_globals, self.frame_object.f_locals)
return eval(code, self.python_frame.f_globals, self.python_frame.f_locals)

@classmethod
def invalidate(self, thread: Thread):
frames = [frame for frame in self._all.values() if frame.thread is thread]
VariableContainer.invalidate(*frames)
for frame in frames:
del self._all[frame.id]
frame.python_frame = None


@dataclass
Expand Down Expand Up @@ -418,8 +420,8 @@ def test(self, frame: StackFrame) -> bool:
try:
result = eval(
self._code,
frame.frame_object.f_globals,
frame.frame_object.f_locals,
frame.python_frame.f_globals,
frame.python_frame.f_locals,
)
return bool(result)
except BaseException as exc:
Expand Down Expand Up @@ -510,7 +512,7 @@ def format(self, frame: StackFrame) -> str:
"""
try:
return eval(
self._code, frame.frame_object.f_globals, frame.frame_object.f_locals
self._code, frame.python_frame.f_globals, frame.python_frame.f_locals
)
except BaseException as exc:
log.exception(
Expand Down
23 changes: 8 additions & 15 deletions src/debugpy/server/tracing/tracer.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,7 @@
# Licensed under the MIT License. See LICENSE in the project root
# for license information.

# Once callbacks are registered they are invoked even during finalization when the
# Python is shutting down. Thus, trace_* methods, and any other methods that they
# invoke, must not use any globals from this or other modules (including globals
# that represent imported modules or defined classes!) until it checks that they
# are present, or preload them into local variables or object attributes in advance.
# To facilitate this, Tracer is defined in a separate submodule which should not
# contain ANY top-level imports other than typing nor definitions other than the
# class itself. All other imports must be done in function or class scope.

import gc
import inspect
import sys
import threading
Expand Down Expand Up @@ -282,7 +274,7 @@ def _this_thread(self) -> Thread | None:
else Thread.from_python_thread(threading.current_thread())
)

def _suspend_this_thread(self, frame_obj: FrameType):
def _suspend_this_thread(self, python_frame: FrameType):
"""
Suspends execution of this thread until the current stop ends.
"""
Expand All @@ -293,19 +285,20 @@ def _suspend_this_thread(self, frame_obj: FrameType):
return

log.info(f"{thread} suspended.")
thread.current_frame = frame_obj
thread.current_frame = python_frame
while self._stopped_by is not None:
_cvar.wait()
thread.current_frame = None
StackFrame.invalidate(thread)
log.info(f"{thread} resumed.")
StackFrame.invalidate(thread)
gc.collect()

step = self._steps.get(thread, None)
if step is not None and step.origin is None:
# This step has just begun - update the Step object with information
# about current frame that will be used to track step completion.
step.origin = frame_obj
step.origin_line = frame_obj.f_lineno
step.origin = python_frame
step.origin_line = python_frame.f_lineno

def _trace_line(self, code: CodeType, line_number: int):
thread = self._this_thread()
Expand Down Expand Up @@ -380,7 +373,7 @@ def _trace_line(self, code: CodeType, line_number: int):
f"Stack frame {frame} stopping at breakpoints {[bp.__getstate__() for bp in stop_bps]}."
)
self._begin_stop(thread, "breakpoint", stop_bps)
self._suspend_this_thread(frame.frame_object)
self._suspend_this_thread(frame.python_frame)
finally:
del frame
del python_frame
Expand Down

0 comments on commit 117704d

Please sign in to comment.