31 Commits

Author SHA1 Message Date
Jeff Widman
4225f7f4ad Bump to 0.15.1 (#254)
Bump to `0.15.1` release so that we can get this minor bugfix live:
* #253
2024-04-27 11:03:27 -07:00
Joel Burton
a63f64051b Fix prob w/using w/o SQLAlchemy (#253) 2024-04-25 14:47:07 -07:00
Mac Newbold
bf21647c4b Bump to 0.15.0 (#251) 2024-04-24 14:38:33 -06:00
Jeff Widman
818e5f2d62 Bump to 0.15.0
We've merged a number of deprecation fixes, let's get them live to our users via a new release.
2024-04-24 07:59:07 -07:00
Jeff Widman
c65c6b94e5 Add .readthedocs.yaml file (#246)
Add `.readthedocs.yaml` file.

This config file is now required by RTD in order to build the docs.
2024-04-24 14:46:37 +00:00
Jeff Widman
0ca1f6b241 Install custom Sphinx theme via extras_require (#250)
Previously the custom theme was vendored in via a `git` submodule...

Now this theme is available via a python package, so install it using `extras_require` instead.

This also unlocks letting other tooling such as ReadTheDocs install the custom theme without having to do custom git incantations.

I also removed the `index_logo` config as Sphinx warns that it's not a supported option by the theme. I grep'd the theme package, and it makes no mention of this option, besides we were leaving it blank already, so there's no point in having it.
2024-04-24 07:40:27 -07:00
Mac Newbold
48de4e4a3c Prevent LookupError when accessing debug_toolbars_var (#245) 2024-04-18 10:59:27 -06:00
Mac Newbold
b139c60a60 Merge branch 'master' into master 2024-04-18 10:58:04 -06:00
Marc Aymerich Gunern
05f23436ac Prevent LookupError when accessing debug_toolbars_var when toolbar is being disabled in the middle of a request 2024-04-18 12:16:43 +01:00
Jeff Widman
7012193220 Replace deprecated pkg_resources with stdlib (#239)
`pkg_resources` has been deprecated by `setuptools` for quite a while: https://setuptools.pypa.io/en/latest/pkg_resources.html

It's got some bugs/warts:

* https://github.com/pypa/setuptools/issues/2531
* https://discuss.python.org/t/will-setuptools-remove-pkg-resource-module-in-the-future/27182

So switch to using `importlib` functions which are part of the Python standard library as of `3.8`.

This is less error-prone, and also removes the need for `setuptools` to be installed in order for this panel to work.

I realize we technically still support `3.7`, but I thought it was fine to change this particular panel to require `3.8`, as `3.7` support is best effort given that it's now EOL'd by the core Python team.

I also removed the relative path location for specific libraries as it was simply blank for me on Python 3.12... I think showing the location of the site packages directory should suffice. If someone later wants to build this out further, they're more than welcome to.

Note that `importlib.metadata.distributions()` does have an outstanding issue that it reports a local editable install twice, but they plan to eventually fix that:
* https://github.com/pypa/setuptools/issues/4170
2024-04-13 13:54:46 +00:00
Jeff Widman
7f3defff7c Fix some jquery deprecation warnings (#242)
Ths is a follow-on PR to
https://github.com/pallets-eco/flask-debugtoolbar/pull/241 in order to fix the deprecation warnings:
* `bind()` replaced by `on()`
* `click(handler)` replaced by `on('click', handler)`

Three deprecation warnings remain, but they are caused by the `jquery.tablesorter.js` plugin, so need to be handled upstream:
* https://github.com/Mottie/tablesorter/issues/1787
* https://github.com/Mottie/tablesorter/pull/1786

Related:
* https://github.com/pallets-eco/flask-debugtoolbar/issues/166
2024-04-13 13:48:56 +00:00
Jeff Widman
969cce532d Bump jquery to 3.7.1 and jquery-migrate to 3.4.1 (#241)
Bump to the latest versions of `jquery` and `jquery-migrate`.

I popped open the browser console and I see five deprecation warnings, but 3 out of the 5 are triggered by `jquery.tablesorter.js` which we vendor, so nothing we can do there.

The other two we should address, but we can do so in a follow-on PR as they are merely deprecations at this point, not fatal errors.

So getting onto the `3.x` series, even with deprecation warnings, is a nice step forward.

Previously we shipped the minified version of `jquery`, and we could
continue to do so, but given this is a dev tool and we still have
warnings we need to fix, I opted for the non-minified version for now.

Additionally, they offer a `slim` varient that is stripped down... we
could probably use that too, but I didn't take the time to investigate.

Fix: https://github.com/pallets-eco/flask-debugtoolbar/issues/166
2024-04-13 13:42:23 +00:00
Jeff Widman
c2804c4917 Bump jquery to 1.12.4 (#236)
This will allow us to migrate to the latest version of jquery 1.x series.

After we're on 1.9.x we can upgrade to the 3.x series.

I bumped this, and then checked the developer console while clicking
through the various panels offered in FDBT... Everything worked as
expected and I got zero warnings from `jquery-migrate`. So I think it's
safe to pull this in.

This is a pre-requesite to upgrading to the latest version of `jquery`,
as per their docs we have to first bump to `1.9+`, then bump the version
of `jquery-migrate`, then can bump to latest `jquery` version.

While I could do this in a single PR, I thought simpler to do it as a
series of PRs for easier reversion if we later run into problems.

Related:
* https://github.com/pallets-eco/flask-debugtoolbar/issues/166
2024-04-13 13:39:41 +00:00
Jeff Widman
56beb35c36 Update jquery.tablesorter.js plugin (#235)
Update to the latest `v2.31.3` version of this `jquery` plugin, which
unblocks upgrading to `jquery` >= `1.9.x`.

Using a fork because:

1. The original repo hasn't been updated in seven years: https://github.com/christianbach/tablesorter
2. The most recent committer to the original repo ☝️  now maintains the fork.
3. The fork was updated just a few months ago.
4. The fork supports the latest versions of `jquery`:
     > Works with jQuery 1.9+ (`$.browser.msie` was removed; needed in the original version)

As far as I can tell, no other changes are needed.

This is a straight copy/paste of the non-minized code from: https://github.com/Mottie/tablesorter

I used non-minimized for simplicity, since this is a dev-only tool, the
perf impacts of minimization don't really matter.

I tested this manually by:

```shell
$ cd flask-debugtoolbar/test
$ flask --app basic_app run --debug
```

Then loading `http://127.0.0.1:5000/` in a recent version of Chrome and
finding a FDBT panel that uses the sorter. In this case, the SQLAlchemy
panel. I visually compared behavior pre/past upgrade and it appeared
identical.

Related:
* https://github.com/pallets-eco/flask-debugtoolbar/issues/166
2024-04-13 06:37:37 -07:00
Jeff Widman
98bf17aa58 Fix trailing whitespace (#237)
I noticed some trailing whitespace has crept into these files. It wasn't caught by `pycodestyle` because that only checks Python files.

Ideally we'd add a linter that catches these, but I didn't want to take the time to configure one right now, I just want my editor to stop flagging these while I'm working on trying to upgrade `jquery` versions.

Long term, we'll probably want a meta-linter like `prettier` or whatever the newest kid on the block is.
2024-04-12 16:27:04 +00:00
Grey Li
716f05d953 Remove deprecated Flask version attribute (#243)
The `flask.__version__` attr is deprecated and will be removed in the Flask 3.1 version. This PR replaced this attr to `importlib.metadata.version`.

We could remove the use of `pkg_resources` when we drop the Python 3.7 support.
2024-04-12 09:20:53 -07:00
Jeff Widman
fb28aa9d61 Fix missing distutils error on Python 3.12 (#238)
Running on Python 3.12 I see:

```shell
[2024-04-11 11:01:12,915] WARNING in toolbar: Disabled flask_debugtoolbar.panels.versions.VersionDebugPanel due to ImportError: import_string() failed for 'flask_debugtoolbar.panels.versions.VersionDebugPanel'. Possible reasons are:

- missing __init__.py in a package;
- package or module path not included in sys.path;
- duplicated package or module name taking precedence in sys.path;
- missing module, class, function or variable;

Debugged import:

- 'flask_debugtoolbar' found in '/Users/jeffwidman/Code/open-source/flask-debugtoolbar/src/flask_debugtoolbar/__init__.py'.
- 'flask_debugtoolbar.panels' found in '/Users/jeffwidman/Code/open-source/flask-debugtoolbar/src/flask_debugtoolbar/panels/__init__.py'.
- 'flask_debugtoolbar.panels.versions' not found.

Original exception:

ModuleNotFoundError: No module named 'distutils'
```

This is because Python 3.12 removed `distutils`.

Fix pulled from https://bugs.python.org/issue41282#msg393018.

This will not work on Python `3.6`, but we've already dropped support for that.

After the fix, the error is gone and the Versions panel re-appears.
2024-04-11 18:18:04 -07:00
Mac Newbold
efe447fb5f Fix SQLAlchemy recording warning for versions >= 3 (#233) 2024-03-20 09:28:47 -06:00
Jonty Wareing
9656a2cf33 Fix SQLAlchemy recording warning for versions >= 3
Since SQLAlchemy 3.0 `SQLALCHEMY_RECORD_QUERIES` is no longer
automatically enabled when Flask is running in debug or testing mode so
the debug toolbar warning will never be shown.

https://flask-sqlalchemy.palletsprojects.com/en/3.0.x/config/#flask_sqlalchemy.config.SQLALCHEMY_RECORD_QUERIES
2024-03-20 14:25:36 +00:00
Mac Newbold
9b63ad1837 Support applications using flask.copy_current_request_context (#231) 2024-01-17 09:40:50 -07:00
Marc Aymerich Gunern
765f22126e Handle cases when debug toolbar has not been installed 2024-01-11 18:06:28 +00:00
Marc Aymerich Gunern
d4a8cc963e Support applications using flask.copy_current_request_context 2024-01-09 13:50:02 +00:00
Mac Newbold
b7f5a725cd Add init_app() method to DebugPanel base class (#95) 2023-12-20 09:35:17 -07:00
Malthe Jørgensen
5bf5e093bb [Add] init_app()-method to DebugPanel base class
Adds a method `DebugPanel.init_app()` that gets called from
`DebugToolbar.init_app()`.

This allows DebugPanels to register their own routes, and do setup work
that should go across requests (as opposed to per-request setup) and
needs access to the Flask `app`-object.
2023-12-15 10:14:33 +01:00
Mac Newbold
719fe02df5 Add option to dump profiler stats (#204) 2023-12-13 10:49:10 -07:00
Dosenpfand
f18bcc708a Remove trailing whitespaces 2023-12-13 10:47:24 -07:00
Dosenpfand
95c2b86bcd Add profile dump stats option 2023-12-13 10:47:24 -07:00
Mac Newbold
b03a2e6fb3 Require Flask >= 2.2.0 (#224) 2023-12-11 11:27:45 -07:00
Jeff Widman
1c39a9ce47 Require Flask >= 2.2.0, Python >= 3.7
Require Flask >= `2.2.0`.

I'm comfortable going up to requiring `3.x`, but when I grep'd for
places we use older Flask constructs, this was all I found.

So for now no need to jump further.

Flask `2.2.0` requires Python >= `3.7`, so also dropped older pythons.
2023-12-11 11:25:52 -07:00
Mac Newbold
8c8b2bb35c Add minimal test without extra deps (#230) 2023-12-10 20:18:10 -07:00
Grey Li
a2e773124f Add minimal test without extra deps
To prevent issues like https://github.com/pallets-eco/flask-debugtoolbar/pull/225,
This PR add a minimal test that no extra deps are involved, it only install
the package, then try to import the extension class.

fixes #226
2023-12-10 12:54:29 +08:00
28 changed files with 14811 additions and 1150 deletions

View File

@@ -21,12 +21,12 @@ jobs:
- {name: Linux, python: '3.12', os: ubuntu-latest, tox: py312}
- {name: Windows, python: '3.12', os: windows-latest, tox: py312}
- {name: Mac, python: '3.12', os: macos-latest, tox: py312}
- {name: Minimal, python: '3.12', os: ubuntu-latest, tox: minimal}
- {name: '3.11', python: '3.11', os: ubuntu-latest, tox: py311}
- {name: '3.10', python: '3.10', os: ubuntu-latest, tox: py310}
- {name: '3.9', python: '3.9', os: ubuntu-latest, tox: py39}
- {name: '3.8', python: '3.8', os: ubuntu-latest, tox: py38}
- {name: '3.7', python: '3.7', os: ubuntu-latest, tox: py37}
- {name: '3.6', python: '3.6', os: ubuntu-20.04, tox: py36} # ubuntu-latest doesn't support 3.6
- {name: Style, python: '3.10', os: ubuntu-latest, tox: stylecheck}
steps:
- uses: actions/checkout@v4

3
.gitmodules vendored
View File

@@ -1,3 +0,0 @@
[submodule "docs/_themes"]
path = docs/_themes
url = https://github.com/mitsuhiko/flask-sphinx-themes.git

37
.readthedocs.yaml Normal file
View File

@@ -0,0 +1,37 @@
# Read the Docs configuration file for Sphinx projects
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
# Required
version: 2
# Set the OS, Python version and other tools you might need
build:
os: ubuntu-lts-latest
tools:
python: "latest"
# You can also specify other tool versions:
# nodejs: "20"
# rust: "1.70"
# golang: "1.20"
# Build documentation in the "docs/" directory with Sphinx
sphinx:
configuration: docs/conf.py
# You can configure Sphinx to use a different builder, for instance use the dirhtml builder for simpler URLs
# builder: "dirhtml"
# Fail on all warnings to avoid broken references
fail_on_warning: true
# Optionally build your docs in additional formats such as PDF and ePub
# formats:
# - pdf
# - epub
# Optional but recommended, declare the Python requirements required
# to build your documentation
# See https://docs.readthedocs.io/en/stable/guides/reproducible-builds.html
python:
install:
- path: .
extra_requirements:
- docs

View File

@@ -4,10 +4,10 @@ All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.

View File

@@ -37,6 +37,7 @@ BUILD_DATE = datetime.datetime.utcfromtimestamp(int(os.environ.get('SOURCE_DATE_
extensions = [
'sphinx.ext.viewcode',
'sphinx.ext.intersphinx',
'pallets_sphinx_themes',
]
# Add any paths that contain templates here, relative to this directory.
@@ -112,9 +113,7 @@ html_theme = 'flask'
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
# documentation.
html_theme_options = {
'index_logo': None,
}
html_theme_options = {}
# Add any paths that contain custom themes here, relative to this directory.
sys.path.append(os.path.abspath('_themes'))

View File

@@ -59,6 +59,8 @@ Name Description De
``DEBUG_TB_PANELS`` List of module/class names of panels enable all built-in panels
``DEBUG_TB_PROFILER_ENABLED`` Enable the profiler on all requests ``False``, user-enabled
``DEBUG_TB_TEMPLATE_EDITOR_ENABLED`` Enable the template editor ``False``
``DEBUG_TB_PROFILER_DUMP_FILENAME`` Filename of the profiler stats dump, ``None``, no dump will be written
can be a ``str`` or a ``callable``
==================================== ===================================== ==========================
To change one of the config options, set it in the Flask app's config like::

View File

@@ -1,6 +1,6 @@
[metadata]
name = Flask-DebugToolbar
version = 0.14.1
version = 0.15.1
author = Michael van Tellingen
author_email = michaelvantellingen@gmail.com
maintainer = Matt Good
@@ -30,7 +30,7 @@ package_dir =
packages = find:
include_package_data = True
python_requires = >=2.7
python_requires = >=3.7
[options.packages.find]
where = src

View File

@@ -4,11 +4,17 @@ from setuptools import setup
setup(
name="Flask-DebugToolbar",
install_requires=[
'Flask>=0.8',
'Flask>=2.2.0',
'Blinker',
'itsdangerous',
'werkzeug',
'MarkupSafe',
'packaging',
],
extras_require={
"docs": [
'Sphinx>=1.2.2',
'Pallets-Sphinx-Themes',
],
}
)

View File

@@ -1,17 +1,11 @@
import contextvars
import os
import urllib.parse
import warnings
import flask
from packaging import version as version_builder
from flask import Blueprint, current_app, request, g, send_from_directory, url_for
if version_builder.parse(flask.__version__) >= version_builder.parse("2.2.0"):
from flask.globals import request_ctx
else:
from flask.globals import _request_ctx_stack
from flask.globals import request_ctx
from jinja2 import __version__ as __jinja_version__
from jinja2 import Environment, PackageLoader
@@ -64,7 +58,9 @@ class DebugToolbarExtension(object):
def __init__(self, app=None):
self.app = app
self.debug_toolbars = {}
# Support threads running `flask.copy_current_request_context` without
# poping toolbar during `teardown_request`
self.debug_toolbars_var = contextvars.ContextVar('debug_toolbars')
jinja_extensions = ['jinja2.ext.i18n']
if __jinja_version__[0] == '2':
@@ -132,11 +128,7 @@ class DebugToolbarExtension(object):
def dispatch_request(self):
"""Modified version of Flask.dispatch_request to call process_view."""
if version_builder.parse(flask.__version__) >= version_builder.parse("2.2.0"):
req = request_ctx.request
else:
req = _request_ctx_stack.top.request
req = request_ctx.request
app = current_app
if req.routing_exception is not None:
@@ -178,11 +170,11 @@ class DebugToolbarExtension(object):
return
real_request = request._get_current_object()
self.debug_toolbars[real_request] = (
self.debug_toolbars_var.set({})
self.debug_toolbars_var.get()[real_request] = (
DebugToolbar(real_request, self.jinja_env))
for panel in self.debug_toolbars[real_request].panels:
for panel in self.debug_toolbars_var.get()[real_request].panels:
panel.process_request(real_request)
def process_view(self, app, view_func, view_kwargs):
@@ -191,7 +183,7 @@ class DebugToolbarExtension(object):
"""
real_request = request._get_current_object()
try:
toolbar = self.debug_toolbars[real_request]
toolbar = self.debug_toolbars_var.get({})[real_request]
except KeyError:
return view_func
@@ -204,7 +196,7 @@ class DebugToolbarExtension(object):
def process_response(self, response):
real_request = request._get_current_object()
if real_request not in self.debug_toolbars:
if real_request not in self.debug_toolbars_var.get({}):
return response
# Intercept http redirect codes and display an html page with a
@@ -250,7 +242,7 @@ class DebugToolbarExtension(object):
' </body> tag not found in response.')
return response
toolbar = self.debug_toolbars[real_request]
toolbar = self.debug_toolbars_var.get()[real_request]
for panel in toolbar.panels:
panel.process_response(real_request, response)
@@ -267,7 +259,8 @@ class DebugToolbarExtension(object):
return response
def teardown_request(self, exc):
self.debug_toolbars.pop(request._get_current_object(), None)
# debug_toolbars_var won't be set under `flask.copy_current_request_context`
self.debug_toolbars_var.get({}).pop(request._get_current_object(), None)
def render(self, template_name, context):
template = self.jinja_env.get_template(template_name)

View File

@@ -25,6 +25,29 @@ class DebugPanel(object):
# If the client enabled the panel
self.is_active = False
@classmethod
def init_app(cls, app):
"""Method that can be overridden by child classes.
Can be used for setting up additional URL-rules/routes.
Example::
class UMLDiagramPanel(DebugPanel):
@classmethod
def init_app(cls, app):
app.add_url_rule(
'/_flask_debugtoolbar_umldiagram/<path:filename>',
'_flask_debugtoolbar_umldiagram.serve_generated_image',
cls.serve_generated_image
)
@classmethod
def serve_generated_image(cls, app):
return Response(...)
"""
pass
def render(self, template_name, context):
template = self.jinja_env.get_template(template_name)
return template.render(**context)

View File

@@ -14,6 +14,7 @@ class ProfilerDebugPanel(DebugPanel):
"""
Panel that displays the time a response took with cProfile output.
"""
name = 'Profiler'
user_activate = True
@@ -22,6 +23,9 @@ class ProfilerDebugPanel(DebugPanel):
DebugPanel.__init__(self, jinja_env, context=context)
if current_app.config.get('DEBUG_TB_PROFILER_ENABLED'):
self.is_active = True
self.dump_filename = current_app.config.get(
"DEBUG_TB_PROFILER_DUMP_FILENAME"
)
def has_content(self):
return bool(self.profiler)
@@ -88,7 +92,14 @@ class ProfilerDebugPanel(DebugPanel):
self.stats = stats
self.function_calls = function_calls
# destroy the profiler just in case
if self.dump_filename:
if callable(self.dump_filename):
filename = self.dump_filename()
else:
filename = self.dump_filename
self.profiler.dump_stats(filename)
return response
def title(self):

View File

@@ -3,13 +3,19 @@ try:
except ImportError:
sqlalchemy_available = False
get_recorded_queries = SQLAlchemy = None
debug_enables_record_queries = False
else:
try:
from flask_sqlalchemy.record_queries import get_recorded_queries
debug_enables_record_queries = False
except ImportError:
# For flask_sqlalchemy < 3.0.0
from flask_sqlalchemy import get_debug_queries as get_recorded_queries
# flask_sqlalchemy < 3.0.0 automatically enabled
# SQLALCHEMY_RECORD_QUERIES in debug or test mode
debug_enables_record_queries = True
location_property = 'context'
else:
location_property = 'location'
@@ -62,7 +68,10 @@ def extension_used():
def recording_enabled():
return (current_app.debug or current_app.config.get('SQLALCHEMY_RECORD_QUERIES'))
return (
(debug_enables_record_queries and current_app.debug) or
current_app.config.get('SQLALCHEMY_RECORD_QUERIES')
)
def is_available():

View File

@@ -1,22 +1,22 @@
import os
from distutils.sysconfig import get_python_lib
from sysconfig import get_path
from flask import __version__ as flask_version
from flask_debugtoolbar.panels import DebugPanel
try:
# Python 3.8+
from importlib.metadata import version
flask_version = version('flask')
except ImportError:
import pkg_resources
flask_version = pkg_resources.get_distribution('flask').version
_ = lambda x: x
def relpath(location, python_lib):
location = os.path.normpath(location)
relative = os.path.relpath(location, python_lib)
if relative == os.path.curdir:
return ''
elif relative.startswith(os.path.pardir):
return location
return relative
class VersionDebugPanel(DebugPanel):
"""
Panel that displays the Flask version.
@@ -38,15 +38,14 @@ class VersionDebugPanel(DebugPanel):
def content(self):
try:
import pkg_resources
import importlib.metadata
except ImportError:
packages = []
else:
packages = sorted(pkg_resources.working_set,
key=lambda p: p.project_name.lower())
packages_metadata = [p.metadata for p in importlib.metadata.distributions()]
packages = sorted(packages_metadata, key=lambda p: p['Name'].lower())
return self.render('panels/versions.html', {
'packages': packages,
'python_lib': os.path.normpath(get_python_lib()),
'relpath': relpath,
'python_lib_dir': os.path.normpath(get_path('platlib')),
})

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@@ -7,7 +7,7 @@
init: function() {
$('#flDebug').show();
var current = null;
$('#flDebugPanelList li a').click(function() {
$('#flDebugPanelList li a').on('click', function() {
if (!this.className) {
return false;
}
@@ -23,7 +23,7 @@
}
return false;
});
$('#flDebugPanelList li .flDebugSwitch').click(function() {
$('#flDebugPanelList li .flDebugSwitch').on('click', function() {
var $panel = $(this).parent();
var $this = $(this);
var dom_id = $panel.attr('id');
@@ -52,12 +52,12 @@
});
}
});
$('#flDebug a.flDebugClose').click(function() {
$('#flDebug a.flDebugClose').on('click', function() {
$(document).trigger('close.flDebug');
$('#flDebugToolbar li').removeClass('flDebugActive');
return false;
});
$('#flDebug a.flDebugRemoteCall').click(function() {
$('#flDebug a.flDebugRemoteCall').on('click', function() {
$('#flDebugWindow').load(this.href, {}, function() {
$('#flDebugWindow a.flDebugBack').click(function() {
$(this).parent().parent().hide();
@@ -67,24 +67,24 @@
$('#flDebugWindow').show();
return false;
});
$('#flDebugTemplatePanel a.flDebugTemplateShowContext').click(function() {
$('#flDebugTemplatePanel a.flDebugTemplateShowContext').on('click', function() {
fldt.toggle_arrow($(this).children('.flDebugToggleArrow'))
fldt.toggle_content($(this).parent().next());
return false;
});
$('#flDebugSQLPanel a.flDebugShowStacktrace').click(function() {
$('#flDebugSQLPanel a.flDebugShowStacktrace').on('click', function() {
fldt.toggle_content($('.flDebugHideStacktraceDiv', $(this).parents('tr')));
return false;
});
$('#flDebugHideToolBarButton').click(function() {
$('#flDebugHideToolBarButton').on('click', function() {
fldt.hide_toolbar(true);
return false;
});
$('#flDebugShowToolBarButton').click(function() {
$('#flDebugShowToolBarButton').on('click', function() {
fldt.show_toolbar();
return false;
});
$(document).bind('close.flDebug', function() {
$(document).on('close.flDebug', function() {
// If a sub-panel is open, close that
if ($('#flDebugWindow').is(':visible')) {
$('#flDebugWindow').hide();
@@ -153,7 +153,7 @@
},
show_toolbar: function(animate) {
// Set up keybindings
$(document).bind('keydown.flDebug', function(e) {
$(document).on('keydown.flDebug', function(e) {
if (e.keyCode == 27) {
fldt.close();
}

View File

@@ -1,6 +1,8 @@
<div id="flDebug" style="display:none;" role="navigation">
<script type="text/javascript">var DEBUG_TOOLBAR_STATIC_PATH = '{{ static_path }}'</script>
<script type="text/javascript" src="{{ static_path }}js/jquery.js"></script>
<!-- Temporarily adding jquery-migrate during the Jquery upgrade process, this can be removed post-upgrade -->
<script src="{{ static_path }}js/jquery-migrate.js"></script>
<script type="text/javascript" src="{{ static_path }}js/jquery.tablesorter.js"></script>
<script type="text/javascript" src="{{ static_path }}js/toolbar.js"></script>

View File

@@ -13,4 +13,4 @@
</tr>
{% endfor %}
</tbody>
</table>
</table>

View File

@@ -22,5 +22,3 @@
{% else %}
<p>No messages logged.</p>
{% endif %}

View File

@@ -21,4 +21,4 @@
</tr>
{% endfor %}
</tbody>
</table>
</table>

View File

@@ -10,6 +10,8 @@
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Editing {{ templates[0].name }}</title>
<script src="{{ static_path }}js/jquery.js"></script>
<!-- Temporarily adding jquery-migrate during the Jquery upgrade process, this can be removed post-upgrade -->
<script src="{{ static_path }}js/jquery-migrate.js"></script>
<link rel="stylesheet" href="{{ static_path }}codemirror/codemirror.css">
<link rel="stylesheet" href="{{ static_path }}codemirror/theme/rubyblue.css">
<link rel="stylesheet" href="{{ static_path }}codemirror/theme/lesser-dark.css">
@@ -116,7 +118,7 @@
delay = setTimeout(updatePreview, 300);
}
});
var previewFrame = document.getElementById('flDebugPreview');
var preview = previewFrame.contentDocument || previewFrame.contentWindow.document;
var errorLine = null;

View File

@@ -18,4 +18,3 @@
{% endfor %}
</tbody>
</table>

View File

@@ -1,10 +1,10 @@
<h4>Installed Packages</h4>
<p>
Installation paths relative to:
Current Site Packages Directory:
</p>
<pre>
{{ python_lib }}
{{ python_lib_dir }}
</pre>
<table>
@@ -12,21 +12,23 @@
<tr>
<th>Package</th>
<th>Version</th>
<th>Installed Path</th>
<th>Homepage</th>
<th>Summary</th>
</tr>
</thead>
<tbody>
{% for package in packages %}
<tr class="{{ loop.cycle('flDebugOdd', 'flDebugEven') }}">
<td>{{ package.project_name }}</td>
<td>{{ package.version }}</td>
<td>{{ relpath(package.location, python_lib) }}</td>
<td>{{ package.get('Name') }}</td>
<td>{{ package.get('Version') }}</td>
<td>{{ package.get('Home-page') }}</td>
<td>{{ package.get('Summary') }}</td>
</tr>
{% else %}
<tr>
<td>setuptools</td>
<td>Python 3.8</td>
<td>NOT INSTALLED</td>
<td>Install setuptools to display installed packages and version information</td>
<td>This panel requires Python >= 3.8 in order to display installed packages and version information.</td>
</tr>
{% endfor %}
</tbody>

View File

@@ -48,8 +48,8 @@ class DebugToolbar(object):
@classmethod
def load_panels(cls, app):
for panel_class in cls._iter_panels(app):
# just loop to make sure they've been loaded
pass
# Call `.init_app()` on panels
panel_class.init_app(app)
@classmethod
def _iter_panels(cls, app):

View File

@@ -1,4 +1,4 @@
<!doctype html>
<html>
<body>Hello world</body>
</html>
</html>

View File

@@ -1,7 +1,5 @@
import sys
import pytest
from flask_debugtoolbar import _printable
@@ -16,26 +14,3 @@ def test_basic_app():
index = app.get('/')
assert index.status_code == 200
assert b'<div id="flDebug"' in index.data
@pytest.mark.skipif(sys.version_info >= (3,),
reason='test only applies to Python 2')
def test_printable_unicode():
class UnicodeRepr(object):
def __repr__(self):
return u'\uffff'
printable = _printable(UnicodeRepr())
assert "raised UnicodeEncodeError: 'ascii' codec" in printable
@pytest.mark.skipif(sys.version_info >= (3,),
reason='test only applies to Python 2')
def test_printable_non_ascii():
class NonAsciiRepr(object):
def __repr__(self):
return 'a\xffb'
printable = u'%s' % _printable(NonAsciiRepr())
# should replace \xff with the unicode ? character
assert printable == u'a\ufffdb'

10
tox.ini
View File

@@ -1,8 +1,8 @@
[tox]
envlist =
py27
py3{12,11,10,9,8,7,6}
py3{12,11,10,9,8,7}
stylecheck
minimal
skip_missing_interpreters = True
[testenv]
@@ -13,6 +13,12 @@ deps =
commands =
pytest
[testenv:minimal]
deps =
.
commands =
python -c "from flask_debugtoolbar import DebugToolbarExtension"
[testenv:stylecheck]
deps =
pycodestyle