mirror of
https://github.com/pallets-eco/flask-debugtoolbar.git
synced 2025-12-31 02:29:33 -06:00
Compare commits
45 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2f8ec9027b | ||
|
|
ab9a41df6a | ||
|
|
2b1e7d9907 | ||
|
|
d0360218fd | ||
|
|
e9fd3072a9 | ||
|
|
1aedfb0e2e | ||
|
|
e6ae9d0288 | ||
|
|
62ce443f8b | ||
|
|
2b8bf9cc44 | ||
|
|
42d859534a | ||
|
|
f959951185 | ||
|
|
e1c8704444 | ||
|
|
8a4cfa5e3c | ||
|
|
51d105afad | ||
|
|
15192f19e0 | ||
|
|
5712e57869 | ||
|
|
9571d06df5 | ||
|
|
3b25e114e9 | ||
|
|
f7ae3fd591 | ||
|
|
ce02d2da3c | ||
|
|
bd346a0fc1 | ||
|
|
ed8243e17e | ||
|
|
02c99a7b64 | ||
|
|
96514793e4 | ||
|
|
ec8cc3a0ba | ||
|
|
e3c8ab0ca2 | ||
|
|
fefb32b04d | ||
|
|
b5a7c032ab | ||
|
|
6af24f5f44 | ||
|
|
b4a197f87f | ||
|
|
15b6fee933 | ||
|
|
9e03576c94 | ||
|
|
bfa48c5a2c | ||
|
|
890fd9c7fb | ||
|
|
42a9651950 | ||
|
|
ff01910f6a | ||
|
|
9cdb04edcb | ||
|
|
f546d4633b | ||
|
|
db07028aa0 | ||
|
|
d44ab40729 | ||
|
|
0d409f54f5 | ||
|
|
708df1c07a | ||
|
|
10186a4202 | ||
|
|
3cd2dceace | ||
|
|
376c3deab3 |
41
.github/workflows/tests.yml
vendored
Normal file
41
.github/workflows/tests.yml
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
name: Tests
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
paths-ignore:
|
||||
- 'docs/**'
|
||||
- '*.rst'
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- 'docs/**'
|
||||
- '*.rst'
|
||||
jobs:
|
||||
tests:
|
||||
name: ${{ matrix.name }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- {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: '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
|
||||
- uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: ${{ matrix.python }}
|
||||
- name: update pip
|
||||
run: |
|
||||
pip install -U setuptools wheel
|
||||
python -m pip install -U pip
|
||||
- run: pip install tox
|
||||
- run: tox -e ${{ matrix.tox }}
|
||||
162
.gitignore
vendored
162
.gitignore
vendored
@@ -1,6 +1,160 @@
|
||||
*.egg-info
|
||||
*.pyc
|
||||
# Byte-compiled / optimized / DLL files
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
|
||||
# C extensions
|
||||
*.so
|
||||
|
||||
# Distribution / packaging
|
||||
.Python
|
||||
build/
|
||||
develop-eggs/
|
||||
dist/
|
||||
docs/_build
|
||||
.tox
|
||||
downloads/
|
||||
eggs/
|
||||
.eggs/
|
||||
lib/
|
||||
lib64/
|
||||
parts/
|
||||
sdist/
|
||||
var/
|
||||
wheels/
|
||||
share/python-wheels/
|
||||
*.egg-info/
|
||||
.installed.cfg
|
||||
*.egg
|
||||
MANIFEST
|
||||
|
||||
# PyInstaller
|
||||
# Usually these files are written by a python script from a template
|
||||
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||
*.manifest
|
||||
*.spec
|
||||
|
||||
# Installer logs
|
||||
pip-log.txt
|
||||
pip-delete-this-directory.txt
|
||||
|
||||
# Unit test / coverage reports
|
||||
htmlcov/
|
||||
.tox/
|
||||
.nox/
|
||||
.coverage
|
||||
.coverage.*
|
||||
.cache
|
||||
nosetests.xml
|
||||
coverage.xml
|
||||
*.cover
|
||||
*.py,cover
|
||||
.hypothesis/
|
||||
.pytest_cache/
|
||||
cover/
|
||||
|
||||
# Translations
|
||||
*.mo
|
||||
*.pot
|
||||
|
||||
# Django stuff:
|
||||
*.log
|
||||
local_settings.py
|
||||
db.sqlite3
|
||||
db.sqlite3-journal
|
||||
|
||||
# Flask stuff:
|
||||
instance/
|
||||
.webassets-cache
|
||||
|
||||
# Scrapy stuff:
|
||||
.scrapy
|
||||
|
||||
# Sphinx documentation
|
||||
docs/_build/
|
||||
|
||||
# PyBuilder
|
||||
.pybuilder/
|
||||
target/
|
||||
|
||||
# Jupyter Notebook
|
||||
.ipynb_checkpoints
|
||||
|
||||
# IPython
|
||||
profile_default/
|
||||
ipython_config.py
|
||||
|
||||
# pyenv
|
||||
# For a library or package, you might want to ignore these files since the code is
|
||||
# intended to run in multiple environments; otherwise, check them in:
|
||||
# .python-version
|
||||
|
||||
# pipenv
|
||||
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
||||
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
||||
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
||||
# install all needed dependencies.
|
||||
#Pipfile.lock
|
||||
|
||||
# poetry
|
||||
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
||||
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
||||
# commonly ignored for libraries.
|
||||
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
||||
#poetry.lock
|
||||
|
||||
# pdm
|
||||
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
||||
#pdm.lock
|
||||
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
|
||||
# in version control.
|
||||
# https://pdm.fming.dev/#use-with-ide
|
||||
.pdm.toml
|
||||
|
||||
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
||||
__pypackages__/
|
||||
|
||||
# Celery stuff
|
||||
celerybeat-schedule
|
||||
celerybeat.pid
|
||||
|
||||
# SageMath parsed files
|
||||
*.sage.py
|
||||
|
||||
# Environments
|
||||
.env
|
||||
.venv
|
||||
env/
|
||||
venv/
|
||||
ENV/
|
||||
env.bak/
|
||||
venv.bak/
|
||||
|
||||
# Spyder project settings
|
||||
.spyderproject
|
||||
.spyproject
|
||||
|
||||
# Rope project settings
|
||||
.ropeproject
|
||||
|
||||
# mkdocs documentation
|
||||
/site
|
||||
|
||||
# mypy
|
||||
.mypy_cache/
|
||||
.dmypy.json
|
||||
dmypy.json
|
||||
|
||||
# Pyre type checker
|
||||
.pyre/
|
||||
|
||||
# pytype static type analyzer
|
||||
.pytype/
|
||||
|
||||
# Cython debug symbols
|
||||
cython_debug/
|
||||
|
||||
# PyCharm
|
||||
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
||||
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
||||
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
||||
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
||||
#.idea/
|
||||
|
||||
2
.gitmodules
vendored
2
.gitmodules
vendored
@@ -1,3 +1,3 @@
|
||||
[submodule "docs/_themes"]
|
||||
path = docs/_themes
|
||||
url = git://github.com/mitsuhiko/flask-sphinx-themes.git
|
||||
url = https://github.com/mitsuhiko/flask-sphinx-themes.git
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
sudo: false
|
||||
language: python
|
||||
python: "3.8"
|
||||
env:
|
||||
- TOXENV=py27
|
||||
- TOXENV=py38
|
||||
install:
|
||||
- pip install tox
|
||||
script: tox
|
||||
224
CHANGES.rst
224
CHANGES.rst
@@ -1,224 +0,0 @@
|
||||
Changes
|
||||
=======
|
||||
|
||||
0.14.0 (Unreleased)
|
||||
-------------------
|
||||
|
||||
Enhancements:
|
||||
|
||||
- ??
|
||||
|
||||
Fixes:
|
||||
|
||||
- ??
|
||||
|
||||
0.13.1 (2022-03-29)
|
||||
-------------------
|
||||
|
||||
Fixes:
|
||||
|
||||
- Use a consistent version naming convention, 0.13 should have been 0.13.0 but it was yanked and you can't re-push yanked packages with the same version
|
||||
|
||||
0.13 (2022-03-29)
|
||||
-------------------
|
||||
|
||||
Fixes:
|
||||
|
||||
- Correct `setup.cfg` to include package files by @nickjj in https://github.com/flask-debugtoolbar/flask-debugtoolbar/pull/172
|
||||
|
||||
0.12.1 (2022-03-28)
|
||||
-------------------
|
||||
|
||||
Fixes:
|
||||
|
||||
- Correct changelog and docs URLs on PyPI
|
||||
|
||||
|
||||
0.12.0 (2022-03-28)
|
||||
-------------------
|
||||
|
||||
Enhancements:
|
||||
|
||||
- Add flask.g section to show g object content. by @Yaser-Amiri in https://github.com/flask-debugtoolbar/flask-debugtoolbar/pull/118
|
||||
- Support gzip response by @zaw007 in https://github.com/flask-debugtoolbar/flask-debugtoolbar/pull/154
|
||||
- Update PyPI metadata files: add `setup.cfg` etc by @jeffwidman in https://github.com/flask-debugtoolbar/flask-debugtoolbar/pull/164
|
||||
|
||||
Fixes:
|
||||
|
||||
- Remove deprecated Jinja with_ extension for Jinja 3.0 (related to Flask 2.0) by @nickjj in https://github.com/flask-debugtoolbar/flask-debugtoolbar/pull/157
|
||||
- Fix SQLAlchemy SELECT/EXPLAIN to use url_for to respect app prefixes.… by @mattaw in https://github.com/flask-debugtoolbar/flask-debugtoolbar/pull/143
|
||||
- Setup DB properly by @jeffwidman in https://github.com/flask-debugtoolbar/flask-debugtoolbar/pull/148
|
||||
- prefixed css classes, fixes #152 by @jnnkB in https://github.com/flask-debugtoolbar/flask-debugtoolbar/pull/153
|
||||
|
||||
|
||||
0.11.0 (2020-02-18)
|
||||
-------------------
|
||||
|
||||
Enhancements:
|
||||
|
||||
- Switch to Flask's native CLI, dropping flask_script in the process (b92391d, thanks @jeffwidman)
|
||||
- Do not show DebugToolbar routes in the route map (#86, thanks @floqqi)
|
||||
- Document Pygments for SQL highlighting (#127, thanks @pgiraud)
|
||||
|
||||
Fixes:
|
||||
|
||||
- Remove deprecated flask.json_available (#119, thanks @davidism)
|
||||
- Remove deprecated request.is_xhr (7ce099c, thanks @jeffwidman)
|
||||
- Explicitly disable `SQLALCHEMY_TRACK_MODIFICATIONS` (9c7db48, thanks @jeffwidman)
|
||||
- Fix typo (#142, thanks @timgates42)
|
||||
|
||||
|
||||
0.10.1 (2017-02-12)
|
||||
-------------------
|
||||
|
||||
Enhancements:
|
||||
- Add support for Python wheels
|
||||
|
||||
Fixes:
|
||||
|
||||
- Switch imports from deprecated flask.ext.* to flask_* syntax (#94, thanks
|
||||
Michael Lenzen & #97 thanks Iuri de Silvio)
|
||||
|
||||
0.10.0 (2015-04-17)
|
||||
-------------------
|
||||
|
||||
Enhancements:
|
||||
|
||||
- Added new "Routes" panel displaying URL routing rules (#69, thanks Justin McKay)
|
||||
- "Versions" panel displays versions of all installed packages (#49, thanks Lucas Taylor)
|
||||
- SQLAlchemy displays necessary setup steps to set up query recording
|
||||
- Support reformatting SQL queries if ``sqlparse`` library is available (#48, thanks Hyunjun Kim)
|
||||
- Enable sorting SQLAlchemy queries (#81, thanks Eric Workman)
|
||||
- Support inserting toolbar on HTML5 pages without ``</body>`` tag
|
||||
- Log a warning if unable to insert the toolbar (#20, thanks Rune Halvorsen)
|
||||
|
||||
Fixes:
|
||||
|
||||
- Ensure numeric sorting of profiler "Calls" column
|
||||
|
||||
0.9.2 (2014-12-05)
|
||||
------------------
|
||||
|
||||
Fixes:
|
||||
|
||||
- HTML escape SQL queries when syntax highlighting is not available
|
||||
- Use case-insensitive comparison to normalize filenames on Windows
|
||||
- Fix exception when SQL query contained non-ASCII characters
|
||||
|
||||
0.9.1 (2014-11-24)
|
||||
------------------
|
||||
|
||||
Fixes:
|
||||
|
||||
- Fix SQL queries with byte strings on Python 3
|
||||
- Fix displaying values whose `repr()` contains unprintable characters
|
||||
|
||||
|
||||
0.9.0 (2014-01-03)
|
||||
------------------
|
||||
|
||||
Enhancements:
|
||||
|
||||
- Python 3 compatibility (#54, thanks justinmayer and jmagnusson)
|
||||
- Support .init_app() (#38)
|
||||
- New "Config" panel displaying Flask config values (#51, thanks Alexey Diyan)
|
||||
- Better PEP8-style formatting (#63, thanks Ivan Ivaschenko)
|
||||
|
||||
Fixes:
|
||||
|
||||
- Fix template editor with non-ASCII templates (#46)
|
||||
|
||||
|
||||
0.8 (2013-02-21)
|
||||
----------------
|
||||
|
||||
Enhancements:
|
||||
|
||||
- Use `itsdangerous <http://pythonhosted.org/itsdangerous/>`_ to sign SQL queries
|
||||
- Expose the jQuery object as ``fldt.$`` so extensions can use the toolbar's
|
||||
copy of jQuery (#42)
|
||||
|
||||
Fixes:
|
||||
|
||||
- Don't intercept redirects on XHR requests (#41)
|
||||
- Fix SQL query time display as milliseconds (#36)
|
||||
- Fix ``functools.partial`` error (#35)
|
||||
- Fix werkzeug request logging with logging panel (#33)
|
||||
- Fix SQL panel unicode encoding error (#31)
|
||||
|
||||
|
||||
0.7.1 (2012-05-18)
|
||||
------------------
|
||||
|
||||
Fixes:
|
||||
|
||||
- loading template editor in-place over current page
|
||||
|
||||
|
||||
0.7 (2012-05-18)
|
||||
----------------
|
||||
|
||||
Enhancements:
|
||||
|
||||
- Add an in-browser template editor to the template panel
|
||||
- ``DEBUG_TB_PROFILER_ENABLED`` config option to enable the profiler on all
|
||||
requests (normally it is user-enabled by clicking the checkmark)
|
||||
|
||||
|
||||
0.6.3.1 (2012-04-16)
|
||||
--------------------
|
||||
|
||||
New release to add missing changelog for 0.6.3
|
||||
|
||||
|
||||
0.6.3 (2012-04-16)
|
||||
------------------
|
||||
Fixes:
|
||||
|
||||
- Compatibility with Flask-SQLAlchemy 0.16 package name
|
||||
|
||||
|
||||
0.6.2 (2012-02-18)
|
||||
------------------
|
||||
|
||||
Fixes:
|
||||
|
||||
- Installation issue on Windows with trailing slashes in MANIFEST.in
|
||||
|
||||
- JavaScript error when using conditional comments for ``<html>`` tag
|
||||
(like in HTML5 Boilerplate)
|
||||
|
||||
|
||||
0.6.1 (2012-02-15)
|
||||
------------------
|
||||
|
||||
Fixes:
|
||||
|
||||
- Memory leak when toolbar was enabled
|
||||
|
||||
- UnicodeDecodeError when request data contained binary data (e.g. session values)
|
||||
|
||||
|
||||
Enhancements:
|
||||
|
||||
- ``DEBUG_TB_ENABLED`` config setting to explicitly enable or disable the toolbar
|
||||
|
||||
- ``DEBUG_TB_HOSTS`` config setting to enable toolbar only for specific remote hosts
|
||||
|
||||
- New logo for Flask instead of Django
|
||||
|
||||
- Monospaced font on table data
|
||||
|
||||
Thanks to kennethreitz and joeshaw for their contributions.
|
||||
|
||||
|
||||
0.6 (2012-01-04)
|
||||
----------------
|
||||
|
||||
Flask 0.8 or higher is required
|
||||
|
||||
Enhancements:
|
||||
|
||||
- Flask 0.8 compatibility
|
||||
|
||||
Thanks to mvantellingen
|
||||
@@ -1,11 +1,11 @@
|
||||
Flask Debug-toolbar
|
||||
===================
|
||||
|
||||
This is a port of the excellent `django-debug-toolbar <https://github.com/django-debug-toolbar/django-debug-toolbar>`_
|
||||
This is a port of the excellent `django-debug-toolbar <https://github.com/jazzband/django-debug-toolbar>`_
|
||||
for Flask applications.
|
||||
|
||||
.. image:: https://travis-ci.org/flask-debugtoolbar/flask-debugtoolbar.png?branch=master
|
||||
:target: https://travis-ci.org/flask-debugtoolbar/flask-debugtoolbar
|
||||
.. image:: https://github.com/pallets-eco/flask-debugtoolbar/actions/workflows/tests.yml/badge.svg
|
||||
:target: https://github.com/pallets-eco/flask-debugtoolbar/actions
|
||||
|
||||
|
||||
Installation
|
||||
|
||||
@@ -99,7 +99,7 @@ pygments_style = 'sphinx'
|
||||
#modindex_common_prefix = []
|
||||
|
||||
intersphinx_mapping = {
|
||||
'flasksqlalchemy': ('http://flask-sqlalchemy.pocoo.org/latest/', None)
|
||||
'flasksqlalchemy': ('https://flask-sqlalchemy.palletsprojects.com/', None)
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -76,16 +76,16 @@ Panels
|
||||
Contributing
|
||||
------------
|
||||
|
||||
Fork us `on GitHub <https://github.com/mgood/flask-debugtoolbar>`_
|
||||
Fork us `on GitHub <https://github.com/pallets-eco/flask-debugtoolbar>`_
|
||||
|
||||
Thanks
|
||||
------
|
||||
|
||||
This was based on the original `django-debug-toolbar`_. Thanks to `Michael van Tellingen`_ for the original development of this Flask extension, and to all the `individual contributors`_.
|
||||
|
||||
.. _django-debug-toolbar: https://github.com/django-debug-toolbar/django-debug-toolbar
|
||||
.. _django-debug-toolbar: https://github.com/jazzband/django-debug-toolbar
|
||||
.. _Michael van Tellingen: https://github.com/mvantellingen
|
||||
.. _individual contributors: https://github.com/mgood/flask-debugtoolbar/graphs/contributors
|
||||
.. _individual contributors: https://github.com/pallets-eco/flask-debugtoolbar/graphs/contributors
|
||||
|
||||
Indices and tables
|
||||
==================
|
||||
|
||||
@@ -76,9 +76,9 @@ Shows SQL queries run during the current request.
|
||||
|
||||
.. image:: _static/screenshot-sqlalchemy-panel.png
|
||||
|
||||
.. _Flask-SQLAlchemy: http://flask-sqlalchemy.pocoo.org/
|
||||
.. _Flask-SQLAlchemy: https://flask-sqlalchemy.palletsprojects.com/
|
||||
|
||||
.. _Pygments: http://pygments.org/
|
||||
.. _Pygments: https://pygments.org/
|
||||
|
||||
|
||||
Logging
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Run using: `FLASK_ENV=development flask run`
|
||||
# Run using: `FLASK_DEBUG=True flask run`
|
||||
|
||||
from flask import Flask, render_template, redirect, url_for
|
||||
from flask_sqlalchemy import SQLAlchemy
|
||||
@@ -14,13 +14,12 @@ app.config['DEBUG_TB_INTERCEPT_REDIRECTS'] = True
|
||||
#)
|
||||
#app.config['DEBUG_TB_HOSTS'] = ('127.0.0.1', '::1' )
|
||||
app.config['SECRET_KEY'] = 'asd'
|
||||
|
||||
# TODO: This can be removed once flask_sqlalchemy 3.0 ships
|
||||
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
|
||||
|
||||
app.config['SQLALCHEMY_RECORD_QUERIES'] = True
|
||||
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:////tmp/test.db'
|
||||
db = SQLAlchemy(app)
|
||||
# This is no longer needed for Flask-SQLAlchemy 3.0+, if you're using 2.X you'll want to define this:
|
||||
# app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
|
||||
|
||||
db = SQLAlchemy(app)
|
||||
toolbar = DebugToolbarExtension(app)
|
||||
|
||||
|
||||
@@ -29,11 +28,6 @@ class ExampleModel(db.Model):
|
||||
value = db.Column(db.String(100), primary_key=True)
|
||||
|
||||
|
||||
@app.before_first_request
|
||||
def setup():
|
||||
db.create_all()
|
||||
|
||||
|
||||
@app.route('/')
|
||||
def index():
|
||||
app.logger.info("Hello there")
|
||||
@@ -46,3 +40,7 @@ def redirect_example():
|
||||
response = redirect(url_for('index'))
|
||||
response.set_cookie('test_cookie', '1')
|
||||
return response
|
||||
|
||||
|
||||
with app.app_context():
|
||||
db.create_all()
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[metadata]
|
||||
name = Flask-DebugToolbar
|
||||
version = 0.13.1
|
||||
version = 0.14.1
|
||||
author = Michael van Tellingen
|
||||
author_email = michaelvantellingen@gmail.com
|
||||
maintainer = Matt Good
|
||||
@@ -9,9 +9,9 @@ description = A toolbar overlay for debugging Flask applications.
|
||||
long_description = file: README.rst
|
||||
long_description_content_type = text/x-rst
|
||||
keywords = flask, debug, toolbar
|
||||
url = https://github.com/flask-debugtoolbar/flask-debugtoolbar
|
||||
url = https://github.com/pallets-eco/flask-debugtoolbar
|
||||
project_urls =
|
||||
Changelog = https://github.com/flask-debugtoolbar/flask-debugtoolbar/blob/master/CHANGES.rst
|
||||
Changelog = https://github.com/pallets-eco/flask-debugtoolbar/releases
|
||||
Documentation = https://flask-debugtoolbar.readthedocs.io/
|
||||
classifiers =
|
||||
Development Status :: 4 - Beta
|
||||
|
||||
2
setup.py
2
setup.py
@@ -8,5 +8,7 @@ setup(
|
||||
'Blinker',
|
||||
'itsdangerous',
|
||||
'werkzeug',
|
||||
'MarkupSafe',
|
||||
'packaging',
|
||||
],
|
||||
)
|
||||
|
||||
@@ -1,11 +1,20 @@
|
||||
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
|
||||
from flask.globals import _request_ctx_stack
|
||||
|
||||
|
||||
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 jinja2 import __version__ as __jinja_version__
|
||||
from jinja2 import Environment, PackageLoader
|
||||
from werkzeug.urls import url_quote_plus
|
||||
|
||||
from flask_debugtoolbar.compat import iteritems
|
||||
from flask_debugtoolbar.toolbar import DebugToolbar
|
||||
@@ -50,6 +59,7 @@ class DebugToolbarExtension(object):
|
||||
_static_dir = os.path.realpath(
|
||||
os.path.join(os.path.dirname(__file__), 'static'))
|
||||
|
||||
_toolbar_codes = [200, 201, 400, 401, 403, 404, 405, 500, 501, 502, 503, 504]
|
||||
_redirect_codes = [301, 302, 303, 304]
|
||||
|
||||
def __init__(self, app=None):
|
||||
@@ -66,7 +76,7 @@ class DebugToolbarExtension(object):
|
||||
autoescape=True,
|
||||
extensions=jinja_extensions,
|
||||
loader=PackageLoader(__name__, 'templates'))
|
||||
self.jinja_env.filters['urlencode'] = url_quote_plus
|
||||
self.jinja_env.filters['urlencode'] = urllib.parse.quote_plus
|
||||
self.jinja_env.filters['printable'] = _printable
|
||||
self.jinja_env.globals['url_for'] = url_for
|
||||
|
||||
@@ -117,11 +127,16 @@ class DebugToolbarExtension(object):
|
||||
'flask_debugtoolbar.panels.profiler.ProfilerDebugPanel',
|
||||
'flask_debugtoolbar.panels.g.GDebugPanel',
|
||||
),
|
||||
'SQLALCHEMY_RECORD_QUERIES': app.debug,
|
||||
}
|
||||
|
||||
def dispatch_request(self):
|
||||
"""Modified version of Flask.dispatch_request to call process_view."""
|
||||
req = _request_ctx_stack.top.request
|
||||
if version_builder.parse(flask.__version__) >= version_builder.parse("2.2.0"):
|
||||
req = request_ctx.request
|
||||
else:
|
||||
req = _request_ctx_stack.top.request
|
||||
|
||||
app = current_app
|
||||
|
||||
if req.routing_exception is not None:
|
||||
@@ -208,17 +223,18 @@ class DebugToolbarExtension(object):
|
||||
response.response = [content]
|
||||
response.status_code = 200
|
||||
|
||||
# If the http response code is 200 then we process to add the
|
||||
# If the http response code is an allowed code then we process to add the
|
||||
# toolbar to the returned html response.
|
||||
if not (response.status_code == 200 and
|
||||
if not (response.status_code in self._toolbar_codes and
|
||||
response.is_sequence and
|
||||
response.headers['content-type'].startswith('text/html')):
|
||||
return response
|
||||
|
||||
if 'gzip' in response.headers.get('Content-Encoding', ''):
|
||||
response_html = gzip_decompress(response.data).decode(response.charset)
|
||||
content_encoding = response.headers.get('Content-Encoding')
|
||||
if content_encoding and 'gzip' in content_encoding:
|
||||
response_html = gzip_decompress(response.data).decode()
|
||||
else:
|
||||
response_html = response.data.decode(response.charset)
|
||||
response_html = response.get_data(as_text=True)
|
||||
|
||||
no_case = response_html.lower()
|
||||
body_end = no_case.rfind('</body>')
|
||||
@@ -242,8 +258,8 @@ class DebugToolbarExtension(object):
|
||||
toolbar_html = toolbar.render_toolbar()
|
||||
|
||||
content = ''.join((before, toolbar_html, after))
|
||||
content = content.encode(response.charset)
|
||||
if 'gzip' in response.headers.get('Content-Encoding', ''):
|
||||
content = content.encode('utf-8')
|
||||
if content_encoding and 'gzip' in content_encoding:
|
||||
content = gzip_compress(content)
|
||||
response.response = [content]
|
||||
response.content_length = len(content)
|
||||
|
||||
@@ -19,11 +19,10 @@ class GDebugPanel(DebugPanel):
|
||||
|
||||
def url(self):
|
||||
return ''
|
||||
|
||||
|
||||
def content(self):
|
||||
context = self.context.copy()
|
||||
context.update({
|
||||
'g_content': g.__dict__
|
||||
})
|
||||
return self.render('panels/g.html', context)
|
||||
|
||||
|
||||
@@ -30,14 +30,14 @@ class ThreadTrackingHandler(logging.Handler):
|
||||
provided, returns a list for the current thread.
|
||||
"""
|
||||
if thread is None:
|
||||
thread = threading.currentThread()
|
||||
thread = threading.current_thread()
|
||||
if thread not in self.records:
|
||||
self.records[thread] = []
|
||||
return self.records[thread]
|
||||
|
||||
def clear_records(self, thread=None):
|
||||
if thread is None:
|
||||
thread = threading.currentThread()
|
||||
thread = threading.current_thread()
|
||||
if thread in self.records:
|
||||
del self.records[thread]
|
||||
|
||||
|
||||
@@ -73,7 +73,7 @@ class ProfilerDebugPanel(DebugPanel):
|
||||
# Cumulative time
|
||||
current['cumtime'] = info[3] * 1000
|
||||
|
||||
# Quotient of the cumulative time divded by the number of
|
||||
# Quotient of the cumulative time divided by the number of
|
||||
# primitive calls.
|
||||
if info[0]:
|
||||
current['percall_cum'] = info[3] * 1000 / info[0]
|
||||
@@ -94,7 +94,7 @@ class ProfilerDebugPanel(DebugPanel):
|
||||
def title(self):
|
||||
if not self.is_active:
|
||||
return "Profiler not active"
|
||||
return 'View: %.2fms' % (float(self.stats.total_tt)*1000,)
|
||||
return 'View: %.2fms' % (float(self.stats.total_tt) * 1000,)
|
||||
|
||||
def nav_title(self):
|
||||
return 'Profiler'
|
||||
@@ -102,7 +102,7 @@ class ProfilerDebugPanel(DebugPanel):
|
||||
def nav_subtitle(self):
|
||||
if not self.is_active:
|
||||
return "in-active"
|
||||
return 'View: %.2fms' % (float(self.stats.total_tt)*1000,)
|
||||
return 'View: %.2fms' % (float(self.stats.total_tt) * 1000,)
|
||||
|
||||
def url(self):
|
||||
return ''
|
||||
|
||||
@@ -1,9 +1,18 @@
|
||||
try:
|
||||
from flask_sqlalchemy import get_debug_queries, SQLAlchemy
|
||||
from flask_sqlalchemy import SQLAlchemy
|
||||
except ImportError:
|
||||
sqlalchemy_available = False
|
||||
get_debug_queries = SQLAlchemy = None
|
||||
get_recorded_queries = SQLAlchemy = None
|
||||
else:
|
||||
try:
|
||||
from flask_sqlalchemy.record_queries import get_recorded_queries
|
||||
except ImportError:
|
||||
# For flask_sqlalchemy < 3.0.0
|
||||
from flask_sqlalchemy import get_debug_queries as get_recorded_queries
|
||||
|
||||
location_property = 'context'
|
||||
else:
|
||||
location_property = 'location'
|
||||
sqlalchemy_available = True
|
||||
|
||||
from flask import request, current_app, abort, g
|
||||
@@ -12,7 +21,6 @@ from flask_debugtoolbar.panels import DebugPanel
|
||||
from flask_debugtoolbar.utils import format_fname, format_sql
|
||||
import itsdangerous
|
||||
|
||||
|
||||
_ = lambda x: x
|
||||
|
||||
|
||||
@@ -54,8 +62,7 @@ def extension_used():
|
||||
|
||||
|
||||
def recording_enabled():
|
||||
return (current_app.debug
|
||||
or current_app.config.get('SQLALCHEMY_RECORD_QUERIES'))
|
||||
return (current_app.debug or current_app.config.get('SQLALCHEMY_RECORD_QUERIES'))
|
||||
|
||||
|
||||
def is_available():
|
||||
@@ -63,8 +70,8 @@ def is_available():
|
||||
|
||||
|
||||
def get_queries():
|
||||
if get_debug_queries:
|
||||
return get_debug_queries()
|
||||
if get_recorded_queries:
|
||||
return get_recorded_queries()
|
||||
else:
|
||||
return []
|
||||
|
||||
@@ -118,11 +125,12 @@ class SQLAlchemyDebugPanel(DebugPanel):
|
||||
'duration': query.duration,
|
||||
'sql': format_sql(query.statement, query.parameters),
|
||||
'signed_query': dump_query(query.statement, query.parameters),
|
||||
'context_long': query.context,
|
||||
'context': format_fname(query.context)
|
||||
'location_long': getattr(query, location_property),
|
||||
'location': format_fname(getattr(query, location_property))
|
||||
})
|
||||
return self.render('panels/sqlalchemy.html', {'queries': data})
|
||||
|
||||
|
||||
# Panel views
|
||||
|
||||
|
||||
|
||||
@@ -52,8 +52,7 @@ class TimerDebugPanel(DebugPanel):
|
||||
return ''
|
||||
|
||||
def _elapsed_ru(self, name):
|
||||
return (getattr(self._end_rusage, name)
|
||||
- getattr(self._start_rusage, name))
|
||||
return (getattr(self._end_rusage, name) - getattr(self._start_rusage, name))
|
||||
|
||||
def content(self):
|
||||
|
||||
|
||||
@@ -183,7 +183,7 @@ CodeMirror.defineMode('rst', function(config, options) {
|
||||
setState(state, inline, {
|
||||
ch: orig, // inline() has to know what to search for
|
||||
wide: wide, // are we looking for `ch` or `chch`
|
||||
prev: null, // terminator must not be preceeded with whitespace
|
||||
prev: null, // terminator must not be preceded with whitespace
|
||||
token: token // I don't want to recompute this all the time
|
||||
});
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ CodeMirror.defineMode("xquery", function(config, parserConfig) {
|
||||
// function. Each keyword is a property of the keywords object whose
|
||||
// value is {type: atype, style: astyle}
|
||||
var keywords = function(){
|
||||
// conveinence functions used to build keywords object
|
||||
// convenience functions used to build keywords object
|
||||
function kw(type) {return {type: type, style: "keyword"};}
|
||||
var A = kw("keyword a")
|
||||
, B = kw("keyword b")
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
bottom:0;
|
||||
right:0;
|
||||
opacity:0.9;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
#flDebug #flDebugToolbar small {
|
||||
@@ -167,6 +168,7 @@
|
||||
left:0px;
|
||||
background-color:#eee;
|
||||
color:#666;
|
||||
overflow: auto;
|
||||
z-index:100000000;
|
||||
}
|
||||
|
||||
@@ -200,11 +202,11 @@
|
||||
padding:0 0 0 20px;
|
||||
}
|
||||
|
||||
#flDebug .flDebugPanelContent .scroll {
|
||||
#flDebug .flDebugPanelContent .flDebugScroll {
|
||||
height:100%;
|
||||
overflow:auto;
|
||||
display:block;
|
||||
padding:0 10px 0 0;
|
||||
padding:0 10px 10px 0;
|
||||
}
|
||||
|
||||
#flDebug h3 {
|
||||
|
||||
@@ -13,13 +13,13 @@
|
||||
*/
|
||||
/**
|
||||
*
|
||||
* @description Create a sortable table with multi-column sorting capabilitys
|
||||
* @description Create a sortable table with multi-column sorting capabilities
|
||||
*
|
||||
* @example $('table').tablesorter();
|
||||
* @desc Create a simple tablesorter interface.
|
||||
*
|
||||
* @example $('table').tablesorter({ sortList:[[0,0],[1,0]] });
|
||||
* @desc Create a tablesorter interface and sort on the first and secound column column headers.
|
||||
* @desc Create a tablesorter interface and sort on the first and second column column headers.
|
||||
*
|
||||
* @example $('table').tablesorter({ headers: { 0: { sorter: false}, 1: {sorter: false} } });
|
||||
*
|
||||
@@ -49,7 +49,7 @@
|
||||
* to sortable tr elements in the thead on a descending sort. Default
|
||||
* value: "headerSortDown"
|
||||
*
|
||||
* @option String sortInitialOrder (optional) A string of the inital sorting
|
||||
* @option String sortInitialOrder (optional) A string of the initial sorting
|
||||
* order can be asc or desc. Default value: "asc"
|
||||
*
|
||||
* @option String sortMultisortKey (optional) A string of the multi-column sort
|
||||
@@ -90,7 +90,7 @@
|
||||
* Default value: true
|
||||
*
|
||||
* @option Boolean debug (optional) Boolean flag indicating if tablesorter
|
||||
* should display debuging information usefull for development.
|
||||
* should display debugging information usefull for development.
|
||||
*
|
||||
* @type jQuery
|
||||
*
|
||||
@@ -134,7 +134,7 @@
|
||||
debug: false
|
||||
};
|
||||
|
||||
/* debuging utils */
|
||||
/* debugging utils */
|
||||
|
||||
function benchmark(s, d) {
|
||||
log(s + "," + (new Date().getTime() - d.getTime()) + "ms");
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<div id="flDebug" style="display:none;">
|
||||
<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>
|
||||
<script type="text/javascript" src="{{ static_path }}js/jquery.tablesorter.js"></script>
|
||||
|
||||
@@ -17,8 +17,8 @@
|
||||
<a class="flDebugRemoteCall" href="{{ url_for('debugtoolbar.sql_select', explain=True, query=query.signed_query, duration=query.duration )}}">EXPLAIN</a><br />
|
||||
{% endif %}
|
||||
</td>
|
||||
<td title="{{ query.context_long }}">
|
||||
{{ query.context }}
|
||||
<td title="{{ query.location_long }}">
|
||||
{{ query.location }}
|
||||
</td>
|
||||
<td class="flDebugSyntax">
|
||||
<div class="flDebugSqlWrap">
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
<h5>Configure Flask-SQLAlchemy:</h5>
|
||||
<p>
|
||||
The Flask-SQLAlchemy extension needs to be configured for this application.
|
||||
Please see the <a href="https://flask-sqlalchemy.palletsprojects.com/en/master/quickstart/">
|
||||
Please see the <a href="https://flask-sqlalchemy.palletsprojects.com/quickstart/">
|
||||
Flask-SQLAlchemy documentation</a> for details.
|
||||
</p>
|
||||
</li>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<h3>SQL Details</h3>
|
||||
</div>
|
||||
<div class="flDebugPanelContent">
|
||||
<div class="scroll">
|
||||
<div class="flDebugScroll">
|
||||
<dl>
|
||||
<dt>Executed SQL</dt>
|
||||
<dd>{{ sql }}</dd>
|
||||
|
||||
@@ -20,7 +20,9 @@ try:
|
||||
except ImportError:
|
||||
HAVE_SQLPARSE = False
|
||||
|
||||
from flask import current_app, Markup
|
||||
from flask import current_app
|
||||
|
||||
from markupsafe import Markup
|
||||
|
||||
|
||||
def format_fname(value):
|
||||
@@ -86,6 +88,7 @@ def format_sql(query, args):
|
||||
SqlLexer(),
|
||||
HtmlFormatter(noclasses=True, style=PYGMENT_STYLE)))
|
||||
|
||||
|
||||
def gzip_compress(data, compresslevel=6):
|
||||
buff = io.BytesIO()
|
||||
with gzip.GzipFile(fileobj=buff, mode='wb', compresslevel=compresslevel) as f:
|
||||
|
||||
@@ -3,12 +3,14 @@ from flask_sqlalchemy import SQLAlchemy
|
||||
|
||||
from flask_debugtoolbar import DebugToolbarExtension
|
||||
|
||||
|
||||
app = Flask('basic_app')
|
||||
app.config['DEBUG'] = True
|
||||
app.config['SECRET_KEY'] = 'abc123'
|
||||
|
||||
# TODO: This can be removed once flask_sqlalchemy 3.0 ships
|
||||
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
|
||||
app.config['SQLALCHEMY_RECORD_QUERIES'] = True
|
||||
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///:memory:'
|
||||
# This is no longer needed for Flask-SQLAlchemy 3.0+,
|
||||
# if you're using 2.X you'll want to define this:
|
||||
# app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
|
||||
|
||||
# make sure these are printable in the config panel
|
||||
app.config['BYTES_VALUE'] = b'\x00'
|
||||
@@ -23,12 +25,11 @@ class Foo(db.Model):
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
|
||||
|
||||
@app.before_first_request
|
||||
def setup():
|
||||
db.create_all()
|
||||
|
||||
|
||||
@app.route('/')
|
||||
def index():
|
||||
Foo.query.filter_by(id=1).all()
|
||||
return render_template('basic_app.html')
|
||||
|
||||
|
||||
with app.app_context():
|
||||
db.create_all()
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import ntpath
|
||||
import posixpath
|
||||
|
||||
from flask import Markup
|
||||
from markupsafe import Markup
|
||||
|
||||
import pytest
|
||||
|
||||
from flask_debugtoolbar.utils import (_relative_paths, _shortest_relative_path,
|
||||
|
||||
10
tox.ini
10
tox.ini
@@ -1,5 +1,9 @@
|
||||
[tox]
|
||||
envlist = py27,py36,py37,py38,stylecheck
|
||||
envlist =
|
||||
py27
|
||||
py3{12,11,10,9,8,7,6}
|
||||
stylecheck
|
||||
skip_missing_interpreters = True
|
||||
|
||||
[testenv]
|
||||
deps =
|
||||
@@ -13,7 +17,9 @@ commands =
|
||||
deps =
|
||||
pycodestyle
|
||||
commands =
|
||||
pycodestyle flask_debugtoolbar test
|
||||
# E731: do not assign a lambda expression, use a def
|
||||
# W504: line break after binary operator
|
||||
pycodestyle src/flask_debugtoolbar test --ignore=E731,W504
|
||||
|
||||
[pycodestyle]
|
||||
max-line-length = 100
|
||||
|
||||
Reference in New Issue
Block a user