From 6aa74e4efb30fd68e11e90086d4eb8a2aead9c0c Mon Sep 17 00:00:00 2001 From: Leandro de Souza Date: Mon, 14 Nov 2022 09:28:28 -0300 Subject: [PATCH 1/5] typing: Adds type hints to the `utils` module. A `stubs` file was added with type definitions --- debug_toolbar/stubs.py | 35 +++++++++++++++++++++++++++++++++++ debug_toolbar/utils.py | 35 ++++++++++++++++++++++------------- 2 files changed, 57 insertions(+), 13 deletions(-) create mode 100644 debug_toolbar/stubs.py diff --git a/debug_toolbar/stubs.py b/debug_toolbar/stubs.py new file mode 100644 index 000000000..75015a876 --- /dev/null +++ b/debug_toolbar/stubs.py @@ -0,0 +1,35 @@ +from typing import Any, List, NamedTuple, Optional, Tuple, TypedDict + +from django import template as dj_template + + +class InspectStack(NamedTuple): + frame: Any + filename: str + lineno: int + function: str + code_context: str + index: int + + +TidyStackTrace = List[Tuple[str, int, str, str, Optional[Any]]] + + +class DebugContext(TypedDict): + num: int + content: str + highlight: bool + + +class TemplateContext(TypedDict): + name: str + context: List[DebugContext] + + +class RenderContext(dj_template.context.RenderContext): + template: dj_template.Template + + +class RequestContext(dj_template.RequestContext): + template: dj_template.Template + render_context: RenderContext diff --git a/debug_toolbar/utils.py b/debug_toolbar/utils.py index bd74e6eed..692b3c5c6 100644 --- a/debug_toolbar/utils.py +++ b/debug_toolbar/utils.py @@ -4,13 +4,14 @@ import sys import warnings from pprint import pformat +from typing import Any, Dict, List, Optional, Sequence, Tuple from asgiref.local import Local from django.template import Node from django.utils.html import format_html -from django.utils.safestring import mark_safe +from django.utils.safestring import SafeString, mark_safe -from debug_toolbar import settings as dt_settings +from debug_toolbar import settings as dt_settings, stubs try: import threading @@ -21,7 +22,7 @@ _local_data = Local() -def _is_excluded_frame(frame, excluded_modules): +def _is_excluded_frame(frame: Any, excluded_modules: Optional[Sequence[str]]) -> bool: if not excluded_modules: return False frame_module = frame.f_globals.get("__name__") @@ -34,7 +35,7 @@ def _is_excluded_frame(frame, excluded_modules): ) -def _stack_trace_deprecation_warning(): +def _stack_trace_deprecation_warning() -> None: warnings.warn( "get_stack() and tidy_stacktrace() are deprecated in favor of" " get_stack_trace()", @@ -43,7 +44,7 @@ def _stack_trace_deprecation_warning(): ) -def tidy_stacktrace(stack): +def tidy_stacktrace(stack: List[stubs.InspectStack]) -> stubs.TidyStackTrace: """ Clean up stacktrace and remove all entries that are excluded by the HIDE_IN_STACKTRACES setting. @@ -68,7 +69,7 @@ def tidy_stacktrace(stack): return trace -def render_stacktrace(trace): +def render_stacktrace(trace: stubs.TidyStackTrace) -> SafeString: show_locals = dt_settings.get_config()["ENABLE_STACKTRACES_LOCALS"] html = "" for abspath, lineno, func, code, locals_ in trace: @@ -103,7 +104,7 @@ def render_stacktrace(trace): return mark_safe(html) -def get_template_info(): +def get_template_info() -> Optional[Dict[str, Any]]: template_info = None cur_frame = sys._getframe().f_back try: @@ -131,7 +132,7 @@ def get_template_info(): return template_info -def get_template_context(node, context, context_lines=3): +def get_template_context(node, context, context_lines=3) -> stubs.TemplateContext: line, source_lines, name = get_template_source_from_exception_info(node, context) debug_context = [] start = max(1, line - context_lines) @@ -146,7 +147,9 @@ def get_template_context(node, context, context_lines=3): return {"name": name, "context": debug_context} -def get_template_source_from_exception_info(node, context): +def get_template_source_from_exception_info( + node: Node, context: stubs.RequestContext +) -> Tuple[int, List[Tuple[int, str]], str]: if context.template.origin == node.origin: exception_info = context.template.get_exception_info( Exception("DDT"), node.token @@ -161,7 +164,7 @@ def get_template_source_from_exception_info(node, context): return line, source_lines, name -def get_name_from_obj(obj): +def get_name_from_obj(obj: Any) -> str: if hasattr(obj, "__name__"): name = obj.__name__ else: @@ -174,7 +177,7 @@ def get_name_from_obj(obj): return name -def getframeinfo(frame, context=1): +def getframeinfo(frame: Any, context=1) -> inspect.Traceback: """ Get information about a frame or traceback object. @@ -227,7 +230,7 @@ def get_sorted_request_variable(variable): return {"raw": variable} -def get_stack(context=1): +def get_stack(context=1) -> List[stubs.InspectStack]: """ Get a list of records for a frame and all higher (calling) frames. @@ -280,7 +283,13 @@ def get_source_file(self, frame): return value - def get_stack_trace(self, *, excluded_modules=None, include_locals=False, skip=0): + def get_stack_trace( + self, + *, + excluded_modules: Optional[Sequence[str]] = None, + include_locals: bool = False, + skip: int = 0, + ): trace = [] skip += 1 # Skip the frame for this method. for frame in _stack_frames(skip=skip): From 66112c6f836259cca1d38261b4c66537a25d02c2 Mon Sep 17 00:00:00 2001 From: Leandro de Souza Date: Mon, 14 Nov 2022 09:54:40 -0300 Subject: [PATCH 2/5] typing: Removes `typing.TypedDict` to keep the project python3.7 compatible --- debug_toolbar/stubs.py | 13 +------------ debug_toolbar/utils.py | 2 +- 2 files changed, 2 insertions(+), 13 deletions(-) diff --git a/debug_toolbar/stubs.py b/debug_toolbar/stubs.py index 75015a876..01d0b8637 100644 --- a/debug_toolbar/stubs.py +++ b/debug_toolbar/stubs.py @@ -1,4 +1,4 @@ -from typing import Any, List, NamedTuple, Optional, Tuple, TypedDict +from typing import Any, List, NamedTuple, Optional, Tuple from django import template as dj_template @@ -15,17 +15,6 @@ class InspectStack(NamedTuple): TidyStackTrace = List[Tuple[str, int, str, str, Optional[Any]]] -class DebugContext(TypedDict): - num: int - content: str - highlight: bool - - -class TemplateContext(TypedDict): - name: str - context: List[DebugContext] - - class RenderContext(dj_template.context.RenderContext): template: dj_template.Template diff --git a/debug_toolbar/utils.py b/debug_toolbar/utils.py index 692b3c5c6..4403ddb5b 100644 --- a/debug_toolbar/utils.py +++ b/debug_toolbar/utils.py @@ -132,7 +132,7 @@ def get_template_info() -> Optional[Dict[str, Any]]: return template_info -def get_template_context(node, context, context_lines=3) -> stubs.TemplateContext: +def get_template_context(node, context, context_lines=3) -> Dict[str, Any]: line, source_lines, name = get_template_source_from_exception_info(node, context) debug_context = [] start = max(1, line - context_lines) From 0c40ae3448debf504582779cf09bfb853047e0e5 Mon Sep 17 00:00:00 2001 From: Leandro de Souza Date: Mon, 14 Nov 2022 11:04:47 -0300 Subject: [PATCH 3/5] typing: Adds hints to the `get_sorted_request_variable` --- debug_toolbar/utils.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/debug_toolbar/utils.py b/debug_toolbar/utils.py index 4403ddb5b..af09dfd11 100644 --- a/debug_toolbar/utils.py +++ b/debug_toolbar/utils.py @@ -4,9 +4,10 @@ import sys import warnings from pprint import pformat -from typing import Any, Dict, List, Optional, Sequence, Tuple +from typing import Any, Dict, List, Optional, Sequence, Tuple, Union from asgiref.local import Local +from django.http import QueryDict from django.template import Node from django.utils.html import format_html from django.utils.safestring import SafeString, mark_safe @@ -216,7 +217,9 @@ def getframeinfo(frame: Any, context=1) -> inspect.Traceback: return inspect.Traceback(filename, lineno, frame.f_code.co_name, lines, index) -def get_sorted_request_variable(variable): +def get_sorted_request_variable( + variable: Union[Dict[str, Any], QueryDict] +) -> Dict[str, Union[List[Tuple[str, Any]], Any]]: """ Get a data structure for showing a sorted list of variables from the request data. From 376f792056afd9339adc62cbe9ee50993e8ba4bf Mon Sep 17 00:00:00 2001 From: Leandro de Souza Date: Mon, 14 Nov 2022 11:07:22 -0300 Subject: [PATCH 4/5] typing: Adds hints for `get_template_context` / `get_frame_info` on utils module --- debug_toolbar/utils.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/debug_toolbar/utils.py b/debug_toolbar/utils.py index af09dfd11..7186bf68d 100644 --- a/debug_toolbar/utils.py +++ b/debug_toolbar/utils.py @@ -133,7 +133,9 @@ def get_template_info() -> Optional[Dict[str, Any]]: return template_info -def get_template_context(node, context, context_lines=3) -> Dict[str, Any]: +def get_template_context( + node: Node, context: stubs.RequestContext, context_lines: int = 3 +) -> Dict[str, Any]: line, source_lines, name = get_template_source_from_exception_info(node, context) debug_context = [] start = max(1, line - context_lines) @@ -178,7 +180,7 @@ def get_name_from_obj(obj: Any) -> str: return name -def getframeinfo(frame: Any, context=1) -> inspect.Traceback: +def getframeinfo(frame: Any, context: int = 1) -> inspect.Traceback: """ Get information about a frame or traceback object. From ea924685db14a19e174c38de8555e737001c0a57 Mon Sep 17 00:00:00 2001 From: Leandro de Souza Date: Mon, 5 Dec 2022 09:10:54 -0300 Subject: [PATCH 5/5] Typing: renames stubs to _stubs making it clear that it's a private module --- debug_toolbar/{stubs.py => _stubs.py} | 0 debug_toolbar/utils.py | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename debug_toolbar/{stubs.py => _stubs.py} (100%) diff --git a/debug_toolbar/stubs.py b/debug_toolbar/_stubs.py similarity index 100% rename from debug_toolbar/stubs.py rename to debug_toolbar/_stubs.py diff --git a/debug_toolbar/utils.py b/debug_toolbar/utils.py index 7186bf68d..16727e7c8 100644 --- a/debug_toolbar/utils.py +++ b/debug_toolbar/utils.py @@ -12,7 +12,7 @@ from django.utils.html import format_html from django.utils.safestring import SafeString, mark_safe -from debug_toolbar import settings as dt_settings, stubs +from debug_toolbar import _stubs as stubs, settings as dt_settings try: import threading