From 4630f070dd9ed86ec60894b5e2cd0910f10bdec0 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sat, 30 Apr 2022 17:21:07 +0200 Subject: [PATCH 1/6] [pre-commit.ci] pre-commit autoupdate (#1608) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/pre-commit/mirrors-eslint: v8.13.0 → v8.14.0](https://github.com/pre-commit/mirrors-eslint/compare/v8.13.0...v8.14.0) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 0ac25c776..172c4ddeb 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -43,7 +43,7 @@ repos: - id: prettier types_or: [javascript, css] - repo: https://github.com/pre-commit/mirrors-eslint - rev: v8.13.0 + rev: v8.14.0 hooks: - id: eslint files: \.js?$ From c39b84bde3c0f502b67d92528e61febbd6deb58a Mon Sep 17 00:00:00 2001 From: Tim Schilling Date: Mon, 2 May 2022 11:33:05 -0500 Subject: [PATCH 2/6] The path may not always be a true path for stacktraces. (#1613) Occassionally we will get a stacktrace that's an importlib instance string representation. While we may be able to put the python path or something else it's likely easier (and more logical) to simply pass that onto the user. I was unable to reproduce the issue in our tests, so I've mocked the case in test_importlib_path_issue_1612. Fixes #1612 --- debug_toolbar/utils.py | 11 +++++++++-- tests/test_utils.py | 28 +++++++++++++++++++++++++++- 2 files changed, 36 insertions(+), 3 deletions(-) diff --git a/debug_toolbar/utils.py b/debug_toolbar/utils.py index ae4d49168..6b80c5af0 100644 --- a/debug_toolbar/utils.py +++ b/debug_toolbar/utils.py @@ -72,10 +72,17 @@ def render_stacktrace(trace): show_locals = dt_settings.get_config()["ENABLE_STACKTRACES_LOCALS"] html = "" for abspath, lineno, func, code, locals_ in trace: - directory, filename = abspath.rsplit(os.path.sep, 1) + if os.path.sep in abspath: + directory, filename = abspath.rsplit(os.path.sep, 1) + # We want the separator to appear in the UI so add it back. + directory += os.path.sep + else: + # abspath could be something like "" + directory = "" + filename = abspath html += format_html( ( - '{}/' + '{}' + '{} in' + ' {}' + '({})\n' diff --git a/tests/test_utils.py b/tests/test_utils.py index fa1312482..9cfc33bc7 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -1,6 +1,6 @@ import unittest -from debug_toolbar.utils import get_name_from_obj +from debug_toolbar.utils import get_name_from_obj, render_stacktrace class GetNameFromObjTestCase(unittest.TestCase): @@ -21,3 +21,29 @@ class A: res = get_name_from_obj(A) self.assertEqual(res, "tests.test_utils.A") + + +class RenderStacktraceTestCase(unittest.TestCase): + def test_importlib_path_issue_1612(self): + trace = [ + ("/server/app.py", 1, "foo", ["code line 1", "code line 2"], {"foo": "bar"}) + ] + result = render_stacktrace(trace) + self.assertIn('/server/', result) + self.assertIn('app.py in', result) + + trace = [ + ( + "", + 1, + "foo", + ["code line 1", "code line 2"], + {"foo": "bar"}, + ) + ] + result = render_stacktrace(trace) + self.assertIn('', result) + self.assertIn( + '<frozen importlib._bootstrap> in', + result, + ) From 1923f7efb69c372bbbd11c4db34ba1367fb4f551 Mon Sep 17 00:00:00 2001 From: Tim Schilling Date: Tue, 3 May 2022 07:36:41 -0500 Subject: [PATCH 3/6] Add changelog for unpacking error when rendering stacktrace. (#1614) --- docs/changes.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/changes.rst b/docs/changes.rst index 0f1b37ae6..e9131d483 100644 --- a/docs/changes.rst +++ b/docs/changes.rst @@ -4,6 +4,10 @@ Change log Next version ------------ +* Fixed issue of stacktrace having frames that have no path to the file, + but are instead a stringified version of the code such as + ``''``. + 3.3.0 (2022-04-28) ------------------ From a0080f342b24c73cc6556ddbc03d1353094fd53f Mon Sep 17 00:00:00 2001 From: Tim Schilling Date: Tue, 3 May 2022 07:20:14 -0500 Subject: [PATCH 4/6] Rename SQLPanel context var to control SQL access. The current build started failing for py3.8+ because the inner exception SQLQueryTriggered was raised in the test test_cursor_wrapper_asyncio_ctx. This was identified as being caused by sql.tracking.recording being set to false. The name recording made it seem as if this context var was controlling whether recording was occurring or not. However, it's true functionality was preventing SQL queries from being sent during the template panel's processing. Renaming that context var to allow_sql is more indicative of its purpose and makes the fixed test change clearer. --- debug_toolbar/panels/sql/tracking.py | 9 ++++++--- debug_toolbar/panels/templates/panel.py | 6 +++--- tests/panels/test_sql.py | 15 ++++++++------- 3 files changed, 17 insertions(+), 13 deletions(-) diff --git a/debug_toolbar/panels/sql/tracking.py b/debug_toolbar/panels/sql/tracking.py index e3b225e9a..93304b21f 100644 --- a/debug_toolbar/panels/sql/tracking.py +++ b/debug_toolbar/panels/sql/tracking.py @@ -13,7 +13,10 @@ except ImportError: PostgresJson = None -recording = contextvars.ContextVar("debug-toolbar-recording", default=True) +# Prevents SQL queries from being sent to the DB. It's used +# by the TemplatePanel to prevent the toolbar from issuing +# additional queries. +allow_sql = contextvars.ContextVar("debug-toolbar-allow-sql", default=True) class SQLQueryTriggered(Exception): @@ -32,7 +35,7 @@ def cursor(*args, **kwargs): # See: # https://github.com/jazzband/django-debug-toolbar/pull/615 # https://github.com/jazzband/django-debug-toolbar/pull/896 - if recording.get(): + if allow_sql.get(): wrapper = NormalCursorWrapper else: wrapper = ExceptionCursorWrapper @@ -43,7 +46,7 @@ def chunked_cursor(*args, **kwargs): # solves https://github.com/jazzband/django-debug-toolbar/issues/1239 cursor = connection._djdt_chunked_cursor(*args, **kwargs) if not isinstance(cursor, BaseCursorWrapper): - if recording.get(): + if allow_sql.get(): wrapper = NormalCursorWrapper else: wrapper = ExceptionCursorWrapper diff --git a/debug_toolbar/panels/templates/panel.py b/debug_toolbar/panels/templates/panel.py index 0615a7601..1c2c96e09 100644 --- a/debug_toolbar/panels/templates/panel.py +++ b/debug_toolbar/panels/templates/panel.py @@ -13,7 +13,7 @@ from django.utils.translation import gettext_lazy as _ from debug_toolbar.panels import Panel -from debug_toolbar.panels.sql.tracking import SQLQueryTriggered, recording +from debug_toolbar.panels.sql.tracking import SQLQueryTriggered, allow_sql from debug_toolbar.panels.templates import views # Monkey-patch to enable the template_rendered signal. The receiver returns @@ -118,7 +118,7 @@ def _store_template_info(self, sender, **kwargs): value.model._meta.label, ) else: - token = recording.set(False) + token = allow_sql.set(False) try: saferepr(value) # this MAY trigger a db query except SQLQueryTriggered: @@ -130,7 +130,7 @@ def _store_template_info(self, sender, **kwargs): else: temp_layer[key] = value finally: - recording.reset(token) + allow_sql.reset(token) pformatted = pformat(temp_layer) self.pformat_layers.append((context_layer, pformatted)) context_list.append(pformatted) diff --git a/tests/panels/test_sql.py b/tests/panels/test_sql.py index 2445827c7..9824a1bec 100644 --- a/tests/panels/test_sql.py +++ b/tests/panels/test_sql.py @@ -18,7 +18,6 @@ from ..base import BaseTestCase from ..models import PostgresJSON -from ..sync import database_sync_to_async def sql_call(use_iterator=False): @@ -98,19 +97,21 @@ async def test_cursor_wrapper_async(self, mock_wrapper): wraps=sql_tracking.NormalCursorWrapper, ) async def test_cursor_wrapper_asyncio_ctx(self, mock_wrapper): - self.assertTrue(sql_tracking.recording.get()) + self.assertTrue(sql_tracking.allow_sql.get()) await sync_to_async(sql_call)() async def task(): - sql_tracking.recording.set(False) - # Calling this in another context requires the db connections - # to be closed properly. - await database_sync_to_async(sql_call)() + sql_tracking.allow_sql.set(False) + # By disabling sql_tracking.allow_sql, we are indicating that any + # future SQL queries should be stopped. If SQL query occurs, + # it raises an exception. + with self.assertRaises(sql_tracking.SQLQueryTriggered): + await sync_to_async(sql_call)() # Ensure this is called in another context await asyncio.create_task(task()) # Because it was called in another context, it should not have affected ours - self.assertTrue(sql_tracking.recording.get()) + self.assertTrue(sql_tracking.allow_sql.get()) self.assertEqual(mock_wrapper.call_count, 1) def test_generate_server_timing(self): From e262e6a5fee406152220ee594a9fcd0ca7d1690b Mon Sep 17 00:00:00 2001 From: Tim Schilling Date: Tue, 3 May 2022 07:51:07 -0500 Subject: [PATCH 5/6] Fix mispelling in changelog and add missing change. --- docs/changes.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/changes.rst b/docs/changes.rst index e9131d483..5918855e7 100644 --- a/docs/changes.rst +++ b/docs/changes.rst @@ -5,8 +5,10 @@ Next version ------------ * Fixed issue of stacktrace having frames that have no path to the file, - but are instead a stringified version of the code such as + but are instead a string of the code such as ``''``. +* Renamed internal SQL tracking context var from ``recording`` to + ``allow_sql``. 3.3.0 (2022-04-28) ------------------ From 1d6c953b5554058ac563a56dfded6a9124063606 Mon Sep 17 00:00:00 2001 From: Tim Schilling Date: Tue, 3 May 2022 07:51:22 -0500 Subject: [PATCH 6/6] Version 3.4 --- README.rst | 2 +- debug_toolbar/__init__.py | 2 +- docs/changes.rst | 4 ++-- docs/conf.py | 2 +- setup.cfg | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/README.rst b/README.rst index 66cca214b..d146726d5 100644 --- a/README.rst +++ b/README.rst @@ -44,7 +44,7 @@ Here's a screenshot of the toolbar in action: In addition to the built-in panels, a number of third-party panels are contributed by the community. -The current stable version of the Debug Toolbar is 3.3.0. It works on +The current stable version of the Debug Toolbar is 3.4.0. It works on Django ≥ 3.2. Documentation, including installation and configuration instructions, is diff --git a/debug_toolbar/__init__.py b/debug_toolbar/__init__.py index 0e749bdc0..e085bea73 100644 --- a/debug_toolbar/__init__.py +++ b/debug_toolbar/__init__.py @@ -4,7 +4,7 @@ # Do not use pkg_resources to find the version but set it here directly! # see issue #1446 -VERSION = "3.3.0" +VERSION = "3.4.0" # Code that discovers files or modules in INSTALLED_APPS imports this module. urls = "debug_toolbar.urls", APP_NAME diff --git a/docs/changes.rst b/docs/changes.rst index 5918855e7..bad3bc033 100644 --- a/docs/changes.rst +++ b/docs/changes.rst @@ -1,8 +1,8 @@ Change log ========== -Next version ------------- +3.4.0 (2022-05-03) +------------------ * Fixed issue of stacktrace having frames that have no path to the file, but are instead a string of the code such as diff --git a/docs/conf.py b/docs/conf.py index 7a49fd3fb..6bf4770dc 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -25,7 +25,7 @@ copyright = copyright.format(datetime.date.today().year) # The full version, including alpha/beta/rc tags -release = "3.3.0" +release = "3.4.0" # -- General configuration --------------------------------------------------- diff --git a/setup.cfg b/setup.cfg index 66f2bc47f..b984e23cc 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,6 +1,6 @@ [metadata] name = django-debug-toolbar -version = 3.3.0 +version = 3.4.0 description = A configurable set of panels that display various debug information about the current request/response. long_description = file: README.rst long_description_content_type = text/x-rst