Skip to content

Commit

Permalink
Added exclude_frames filter to snapshot
Browse files Browse the repository at this point in the history
  • Loading branch information
david-yz-liu committed Dec 8, 2024
1 parent 3351a83 commit 459c0dd
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 8 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ and adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
### ✨ Enhancements

- Added `include_frames` filter to `snapshot`
- Added `exclude_frames` filter to `snapshot`
- Added `exclude_vars` filter to `snapshot`
- Added new `python_ta.debug` module with an `SnapshotTracer` context manager for generating memory models
- Added `z3` option to `inconsistent-or-missing-returns`, `redundant-assignment`, and `possibly-undefined` checkers to only check for feasible code blocks based on edge z3 constraints
Expand All @@ -19,6 +20,7 @@ and adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
- Added integration with MemoryViz Webstepper
- Added `z3` option to `one-iteration-checker` to only check for feasible code blocks based on edge z3 constraints
- Added reporting for errors raised by custom transforms (`Z3Visitor`, `CFGVisitor`)
- Ensured `SnapshotTracer` does not include the `_trace_func` stack frame

### 💫 New checkers

Expand Down
31 changes: 23 additions & 8 deletions python_ta/debug/snapshot.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ def snapshot(
memory_viz_args: Optional[list[str]] = None,
memory_viz_version: str = "latest",
include_frames: Optional[Iterable[str | re.Pattern]] = None,
exclude_frames: Optional[Iterable[str | re.Pattern]] = None,
exclude_vars: Optional[Iterable[str | re.Pattern]] = None,
):
"""Capture a snapshot of local variables from the current and outer stack frames
Expand All @@ -72,23 +73,37 @@ def snapshot(
include_frames can be used to specify a collection of function names, either as strings or regular expressions,
whose variables will be captured. By default, all variables in all functions will be captured if no `include_frames`
argument is provided.
exclude_frames can be used to specify a collection of function names, either as strings or regular expressions,
whose variables should be excluded.
exclude_vars can be used to specify a collection of variable names, either as strings or regular expressions,
that will be excluded from the snapshot. By default, all variables will be captured if no `exclude_vars` is provided.
"""
variables = []
frame = inspect.currentframe().f_back

while frame:
if include_frames is None or any(
re.search(regex, frame.f_code.co_name) for regex in include_frames
frame_name = frame.f_code.co_name

# Check whether frame_name is included
if include_frames is not None and all(
not re.search(regex, frame_name) for regex in include_frames
):
frame = frame.f_back
continue

# Check whether frame_name is excluded
if exclude_frames is not None and any(
re.search(regex, frame_name) for regex in exclude_frames
):
if frame.f_code.co_name != "<module>":
local_vars = get_filtered_local_variables(frame, exclude_vars)
variables.append({frame.f_code.co_name: local_vars})
else:
global_vars = get_filtered_global_variables(frame)
variables.append(global_vars)
frame = frame.f_back
continue

if frame_name != "<module>":
local_vars = get_filtered_local_variables(frame, exclude_vars)
variables.append({frame_name: local_vars})
else:
global_vars = get_filtered_global_variables(frame)
variables.append(global_vars)
frame = frame.f_back

if save:
Expand Down
2 changes: 2 additions & 0 deletions python_ta/debug/snapshot_tracer.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ def __init__(
self._snapshots = []
self._snapshot_args = kwargs
self._snapshot_args["memory_viz_args"] = copy.deepcopy(kwargs.get("memory_viz_args", []))
self._snapshot_args["exclude_frames"] = copy.deepcopy(kwargs.get("exclude_frames", []))
self._snapshot_args["exclude_frames"].append("_trace_func")
self.output_directory = os.path.abspath(output_directory if output_directory else ".")
self.webstepper = webstepper
self._first_line = float("inf")
Expand Down

0 comments on commit 459c0dd

Please sign in to comment.