From bcc3c46d26df451ff281d6b9c84a34c5f662ce67 Mon Sep 17 00:00:00 2001 From: Daniel Harding Date: Thu, 21 Apr 2022 14:45:23 +0300 Subject: [PATCH 1/3] Remove debug_toolbar.utils.django_path variable Not used since commit 03fd1cc81c02a5462aeb4dbce0bfe8a2afdef43d. --- debug_toolbar/utils.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/debug_toolbar/utils.py b/debug_toolbar/utils.py index 6ae036456..7c8381aa9 100644 --- a/debug_toolbar/utils.py +++ b/debug_toolbar/utils.py @@ -6,7 +6,6 @@ from importlib import import_module from pprint import pformat -import django from asgiref.local import Local from django.core.exceptions import ImproperlyConfigured from django.template import Node @@ -24,10 +23,6 @@ _local_data = Local() -# Figure out some paths -django_path = os.path.realpath(os.path.dirname(django.__file__)) - - def get_module_path(module_name): try: module = import_module(module_name) From cd4c7480c52cc90d9fda4d7a66e89a6e75266d33 Mon Sep 17 00:00:00 2001 From: Daniel Harding Date: Tue, 31 May 2022 00:03:50 +0300 Subject: [PATCH 2/3] Replace path-based stack frame exclusion Prior to this commit, the HIDE_IN_STACKTRACES setting was implemented by importing the modules listed in the setting and recording their file system paths. Then tidy_stacktrace() and _StackRecorder.get_stack_trace() would look up the file system path for each frame's code object and compare that path against the paths for the excluded modules to see if it matched. If so, the frame would be excluded. This was inefficient since it used a file system access, os.path.realpath(), for each frame (although the _StackRecorder implementation included some caching to reduce the cost). It also would not work correctly for namespace packages since they can have multiple file system hierarchies. Replace with a new implementation that instead retrieves the __name__ variable from the frame's f_globals attribute and matches that module name against the list of excluded modules directly. --- debug_toolbar/utils.py | 62 ++++++++++++++---------------------------- 1 file changed, 20 insertions(+), 42 deletions(-) diff --git a/debug_toolbar/utils.py b/debug_toolbar/utils.py index 7c8381aa9..5dc9a28bb 100644 --- a/debug_toolbar/utils.py +++ b/debug_toolbar/utils.py @@ -3,11 +3,9 @@ import os.path import sys import warnings -from importlib import import_module from pprint import pformat from asgiref.local import Local -from django.core.exceptions import ImproperlyConfigured from django.template import Node from django.utils.html import format_html from django.utils.safestring import mark_safe @@ -23,26 +21,17 @@ _local_data = Local() -def get_module_path(module_name): - try: - module = import_module(module_name) - except ImportError as e: - raise ImproperlyConfigured(f"Error importing HIDE_IN_STACKTRACES: {e}") - else: - source_path = inspect.getsourcefile(module) - if source_path.endswith("__init__.py"): - source_path = os.path.dirname(source_path) - return os.path.realpath(source_path) - - -hidden_paths = [ - get_module_path(module_name) - for module_name in dt_settings.get_config()["HIDE_IN_STACKTRACES"] -] - - -def omit_path(path): - return any(path.startswith(hidden_path) for hidden_path in hidden_paths) +def _is_excluded_frame(frame, excluded_modules): + if not excluded_modules: + return False + frame_module = frame.f_globals.get("__name__") + if not isinstance(frame_module, str): + return False + return any( + frame_module == excluded_module + or frame_module.startswith(excluded_module + ".") + for excluded_module in excluded_modules + ) def _stack_trace_deprecation_warning(): @@ -65,8 +54,9 @@ def tidy_stacktrace(stack): _stack_trace_deprecation_warning() trace = [] + excluded_modules = dt_settings.get_config()["HIDE_IN_STACKTRACES"] for frame, path, line_no, func_name, text in (f[:5] for f in stack): - if omit_path(os.path.realpath(path)): + if _is_excluded_frame(frame, excluded_modules): continue text = "".join(text).strip() if text else "" frame_locals = ( @@ -267,10 +257,8 @@ def _stack_frames(depth=1): class _StackTraceRecorder: - def __init__(self, excluded_paths): - self.excluded_paths = excluded_paths + def __init__(self): self.filename_cache = {} - self.is_excluded_cache = {} def get_source_file(self, frame): frame_filename = frame.f_code.co_filename @@ -291,25 +279,14 @@ def get_source_file(self, frame): return value - def is_excluded_path(self, path): - excluded = self.is_excluded_cache.get(path) - if excluded is None: - resolved_path = os.path.realpath(path) - excluded = any( - resolved_path.startswith(excluded_path) - for excluded_path in self.excluded_paths - ) - self.is_excluded_cache[path] = excluded - return excluded - - def get_stack_trace(self, include_locals=False, depth=1): + def get_stack_trace(self, excluded_modules=None, include_locals=False, depth=1): trace = [] for frame in _stack_frames(depth=depth + 1): - filename, is_source = self.get_source_file(frame) - - if self.is_excluded_path(filename): + if _is_excluded_frame(frame, excluded_modules): continue + filename, is_source = self.get_source_file(frame) + line_no = frame.f_lineno func_name = frame.f_code.co_name @@ -334,9 +311,10 @@ def get_stack_trace(depth=1): if config["ENABLE_STACKTRACES"]: stack_trace_recorder = getattr(_local_data, "stack_trace_recorder", None) if stack_trace_recorder is None: - stack_trace_recorder = _StackTraceRecorder(hidden_paths) + stack_trace_recorder = _StackTraceRecorder() _local_data.stack_trace_recorder = stack_trace_recorder return stack_trace_recorder.get_stack_trace( + excluded_modules=config["HIDE_IN_STACKTRACES"], include_locals=config["ENABLE_STACKTRACES_LOCALS"], depth=depth, ) From 56f397caecad25e57f613ae0677edad088a87663 Mon Sep 17 00:00:00 2001 From: Daniel Harding Date: Tue, 31 May 2022 17:40:17 +0300 Subject: [PATCH 3/3] Make get_stack_trace() kwarg-only --- debug_toolbar/utils.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/debug_toolbar/utils.py b/debug_toolbar/utils.py index 5dc9a28bb..32aa27420 100644 --- a/debug_toolbar/utils.py +++ b/debug_toolbar/utils.py @@ -279,7 +279,7 @@ def get_source_file(self, frame): return value - def get_stack_trace(self, excluded_modules=None, include_locals=False, depth=1): + def get_stack_trace(self, *, excluded_modules=None, include_locals=False, depth=1): trace = [] for frame in _stack_frames(depth=depth + 1): if _is_excluded_frame(frame, excluded_modules): @@ -306,7 +306,7 @@ def get_stack_trace(self, excluded_modules=None, include_locals=False, depth=1): return trace -def get_stack_trace(depth=1): +def get_stack_trace(*, depth=1): config = dt_settings.get_config() if config["ENABLE_STACKTRACES"]: stack_trace_recorder = getattr(_local_data, "stack_trace_recorder", None)