mirror of
https://github.com/pallets-eco/flask-debugtoolbar.git
synced 2026-01-06 05:30:12 -06:00
Compare commits
96 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bf21647c4b | ||
|
|
818e5f2d62 | ||
|
|
c65c6b94e5 | ||
|
|
0ca1f6b241 | ||
|
|
48de4e4a3c | ||
|
|
b139c60a60 | ||
|
|
05f23436ac | ||
|
|
7012193220 | ||
|
|
7f3defff7c | ||
|
|
969cce532d | ||
|
|
c2804c4917 | ||
|
|
56beb35c36 | ||
|
|
98bf17aa58 | ||
|
|
716f05d953 | ||
|
|
fb28aa9d61 | ||
|
|
efe447fb5f | ||
|
|
9656a2cf33 | ||
|
|
9b63ad1837 | ||
|
|
765f22126e | ||
|
|
d4a8cc963e | ||
|
|
b7f5a725cd | ||
|
|
5bf5e093bb | ||
|
|
719fe02df5 | ||
|
|
f18bcc708a | ||
|
|
95c2b86bcd | ||
|
|
b03a2e6fb3 | ||
|
|
1c39a9ce47 | ||
|
|
8c8b2bb35c | ||
|
|
a2e773124f | ||
|
|
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 | ||
|
|
45d3588bb6 | ||
|
|
15e8d77a49 | ||
|
|
4d84f262ae | ||
|
|
db64ce632c | ||
|
|
956d7501ec | ||
|
|
a758a9df7a | ||
|
|
5eea25882c | ||
|
|
e954cd9fae | ||
|
|
03d79be02c | ||
|
|
7f17d2ce57 | ||
|
|
30fba11f36 | ||
|
|
d474a6a689 | ||
|
|
83d398d9d5 | ||
|
|
3929742d9c | ||
|
|
70abd78e55 | ||
|
|
dbea74b626 | ||
|
|
c6102aeb14 | ||
|
|
10c9c1ae5d | ||
|
|
9e600c6e13 | ||
|
|
9b8a8afa97 | ||
|
|
39ac97a7e0 | ||
|
|
a5cb5a709f |
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: 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: 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
|
# Byte-compiled / optimized / DLL files
|
||||||
*.pyc
|
__pycache__/
|
||||||
|
*.py[cod]
|
||||||
|
*$py.class
|
||||||
|
|
||||||
|
# C extensions
|
||||||
|
*.so
|
||||||
|
|
||||||
|
# Distribution / packaging
|
||||||
|
.Python
|
||||||
build/
|
build/
|
||||||
|
develop-eggs/
|
||||||
dist/
|
dist/
|
||||||
docs/_build
|
downloads/
|
||||||
.tox
|
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/
|
||||||
|
|||||||
3
.gitmodules
vendored
3
.gitmodules
vendored
@@ -1,3 +0,0 @@
|
|||||||
[submodule "docs/_themes"]
|
|
||||||
path = docs/_themes
|
|
||||||
url = git://github.com/mitsuhiko/flask-sphinx-themes.git
|
|
||||||
37
.readthedocs.yaml
Normal file
37
.readthedocs.yaml
Normal 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
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
sudo: false
|
|
||||||
language: python
|
|
||||||
python: "3.8"
|
|
||||||
env:
|
|
||||||
- TOXENV=py27
|
|
||||||
- TOXENV=py38
|
|
||||||
install:
|
|
||||||
- pip install tox
|
|
||||||
script: tox
|
|
||||||
174
CHANGES.rst
174
CHANGES.rst
@@ -1,174 +0,0 @@
|
|||||||
Changes
|
|
||||||
=======
|
|
||||||
|
|
||||||
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
|
|
||||||
6
LICENSE
6
LICENSE
@@ -4,10 +4,10 @@ All rights reserved.
|
|||||||
Redistribution and use in source and binary forms, with or without modification,
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
are permitted provided that the following conditions are met:
|
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.
|
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
|
notice, this list of conditions and the following disclaimer in the
|
||||||
documentation and/or other materials provided with the distribution.
|
documentation and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
include LICENSE
|
include LICENSE
|
||||||
recursive-include flask_debugtoolbar/templates *.html
|
recursive-include src/flask_debugtoolbar/templates *.html
|
||||||
recursive-include flask_debugtoolbar/static *
|
recursive-include src/flask_debugtoolbar/static *
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
Flask Debug-toolbar
|
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.
|
for Flask applications.
|
||||||
|
|
||||||
.. image:: https://travis-ci.org/mgood/flask-debugtoolbar.png?branch=master
|
.. image:: https://github.com/pallets-eco/flask-debugtoolbar/actions/workflows/tests.yml/badge.svg
|
||||||
:target: https://travis-ci.org/mgood/flask-debugtoolbar
|
:target: https://github.com/pallets-eco/flask-debugtoolbar/actions
|
||||||
|
|
||||||
|
|
||||||
Installation
|
Installation
|
||||||
|
|||||||
16
docs/conf.py
16
docs/conf.py
@@ -13,9 +13,12 @@
|
|||||||
|
|
||||||
import datetime
|
import datetime
|
||||||
import os
|
import os
|
||||||
|
import pkg_resources
|
||||||
import sys
|
import sys
|
||||||
import time
|
import time
|
||||||
|
|
||||||
|
import flask_debugtoolbar
|
||||||
|
|
||||||
|
|
||||||
BUILD_DATE = datetime.datetime.utcfromtimestamp(int(os.environ.get('SOURCE_DATE_EPOCH', time.time())))
|
BUILD_DATE = datetime.datetime.utcfromtimestamp(int(os.environ.get('SOURCE_DATE_EPOCH', time.time())))
|
||||||
|
|
||||||
@@ -34,6 +37,7 @@ BUILD_DATE = datetime.datetime.utcfromtimestamp(int(os.environ.get('SOURCE_DATE_
|
|||||||
extensions = [
|
extensions = [
|
||||||
'sphinx.ext.viewcode',
|
'sphinx.ext.viewcode',
|
||||||
'sphinx.ext.intersphinx',
|
'sphinx.ext.intersphinx',
|
||||||
|
'pallets_sphinx_themes',
|
||||||
]
|
]
|
||||||
|
|
||||||
# Add any paths that contain templates here, relative to this directory.
|
# Add any paths that contain templates here, relative to this directory.
|
||||||
@@ -56,10 +60,10 @@ copyright = u'2012-{0}'.format(BUILD_DATE.year)
|
|||||||
# |version| and |release|, also used in various other places throughout the
|
# |version| and |release|, also used in various other places throughout the
|
||||||
# built documents.
|
# built documents.
|
||||||
#
|
#
|
||||||
# The short X.Y version.
|
|
||||||
version = '0.11.0'
|
|
||||||
# The full version, including alpha/beta/rc tags.
|
# The full version, including alpha/beta/rc tags.
|
||||||
release = '0.11.0'
|
release = flask_debugtoolbar.__version__
|
||||||
|
# The short X.Y version.
|
||||||
|
version = '.'.join(release.split('.')[:2])
|
||||||
|
|
||||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||||
# for a list of supported languages.
|
# for a list of supported languages.
|
||||||
@@ -96,7 +100,7 @@ pygments_style = 'sphinx'
|
|||||||
#modindex_common_prefix = []
|
#modindex_common_prefix = []
|
||||||
|
|
||||||
intersphinx_mapping = {
|
intersphinx_mapping = {
|
||||||
'flasksqlalchemy': ('http://flask-sqlalchemy.pocoo.org/latest/', None)
|
'flasksqlalchemy': ('https://flask-sqlalchemy.palletsprojects.com/', None)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -109,9 +113,7 @@ html_theme = 'flask'
|
|||||||
# Theme options are theme-specific and customize the look and feel of a theme
|
# 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
|
# further. For a list of options available for each theme, see the
|
||||||
# documentation.
|
# documentation.
|
||||||
html_theme_options = {
|
html_theme_options = {}
|
||||||
'index_logo': None,
|
|
||||||
}
|
|
||||||
|
|
||||||
# Add any paths that contain custom themes here, relative to this directory.
|
# Add any paths that contain custom themes here, relative to this directory.
|
||||||
sys.path.append(os.path.abspath('_themes'))
|
sys.path.append(os.path.abspath('_themes'))
|
||||||
|
|||||||
@@ -59,6 +59,8 @@ Name Description De
|
|||||||
``DEBUG_TB_PANELS`` List of module/class names of panels enable all built-in panels
|
``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_PROFILER_ENABLED`` Enable the profiler on all requests ``False``, user-enabled
|
||||||
``DEBUG_TB_TEMPLATE_EDITOR_ENABLED`` Enable the template editor ``False``
|
``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::
|
To change one of the config options, set it in the Flask app's config like::
|
||||||
@@ -76,16 +78,16 @@ Panels
|
|||||||
Contributing
|
Contributing
|
||||||
------------
|
------------
|
||||||
|
|
||||||
Fork us `on GitHub <https://github.com/mgood/flask-debugtoolbar>`_
|
Fork us `on GitHub <https://github.com/pallets-eco/flask-debugtoolbar>`_
|
||||||
|
|
||||||
Thanks
|
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`_.
|
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
|
.. _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
|
Indices and tables
|
||||||
==================
|
==================
|
||||||
|
|||||||
@@ -76,9 +76,9 @@ Shows SQL queries run during the current request.
|
|||||||
|
|
||||||
.. image:: _static/screenshot-sqlalchemy-panel.png
|
.. 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
|
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 import Flask, render_template, redirect, url_for
|
||||||
from flask_sqlalchemy import SQLAlchemy
|
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['DEBUG_TB_HOSTS'] = ('127.0.0.1', '::1' )
|
||||||
app.config['SECRET_KEY'] = 'asd'
|
app.config['SECRET_KEY'] = 'asd'
|
||||||
|
app.config['SQLALCHEMY_RECORD_QUERIES'] = True
|
||||||
# TODO: This can be removed once flask_sqlalchemy 3.0 ships
|
|
||||||
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
|
|
||||||
|
|
||||||
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:////tmp/test.db'
|
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)
|
toolbar = DebugToolbarExtension(app)
|
||||||
|
|
||||||
|
|
||||||
@@ -38,11 +37,10 @@ def index():
|
|||||||
|
|
||||||
@app.route('/redirect')
|
@app.route('/redirect')
|
||||||
def redirect_example():
|
def redirect_example():
|
||||||
|
|
||||||
response = redirect(url_for('index'))
|
response = redirect(url_for('index'))
|
||||||
response.set_cookie('test_cookie', '1')
|
response.set_cookie('test_cookie', '1')
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
with app.app_context():
|
||||||
db.create_all()
|
db.create_all()
|
||||||
|
|||||||
16
flask_debugtoolbar/static/js/jquery.js
vendored
16
flask_debugtoolbar/static/js/jquery.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
@@ -1,33 +0,0 @@
|
|||||||
<h4>Installed Packages</h4>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Installation paths relative to:
|
|
||||||
</p>
|
|
||||||
<pre>
|
|
||||||
{{ python_lib }}
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
<table>
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Package</th>
|
|
||||||
<th>Version</th>
|
|
||||||
<th>Installed Path</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>
|
|
||||||
</tr>
|
|
||||||
{% else %}
|
|
||||||
<tr>
|
|
||||||
<td>setuptools</td>
|
|
||||||
<td>NOT INSTALLED</td>
|
|
||||||
<td>Install setuptools to display installed packages and version information</td>
|
|
||||||
</tr>
|
|
||||||
{% endfor %}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
6
pyproject.toml
Normal file
6
pyproject.toml
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
[build-system]
|
||||||
|
requires = [
|
||||||
|
"setuptools>=42",
|
||||||
|
"wheel"
|
||||||
|
]
|
||||||
|
build-backend = "setuptools.build_meta"
|
||||||
38
setup.cfg
38
setup.cfg
@@ -1,2 +1,36 @@
|
|||||||
[bdist_wheel]
|
[metadata]
|
||||||
universal=1
|
name = Flask-DebugToolbar
|
||||||
|
version = 0.15.0
|
||||||
|
author = Michael van Tellingen
|
||||||
|
author_email = michaelvantellingen@gmail.com
|
||||||
|
maintainer = Matt Good
|
||||||
|
maintainer_email = matt@matt-good.net
|
||||||
|
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/pallets-eco/flask-debugtoolbar
|
||||||
|
project_urls =
|
||||||
|
Changelog = https://github.com/pallets-eco/flask-debugtoolbar/releases
|
||||||
|
Documentation = https://flask-debugtoolbar.readthedocs.io/
|
||||||
|
classifiers =
|
||||||
|
Development Status :: 4 - Beta
|
||||||
|
Environment :: Web Environment
|
||||||
|
Framework :: Flask
|
||||||
|
Intended Audience :: Developers
|
||||||
|
License :: OSI Approved :: BSD License
|
||||||
|
Operating System :: OS Independent
|
||||||
|
Programming Language :: Python
|
||||||
|
Topic :: Internet :: WWW/HTTP :: Dynamic Content
|
||||||
|
Topic :: Software Development :: Libraries :: Python Modules
|
||||||
|
|
||||||
|
[options]
|
||||||
|
package_dir =
|
||||||
|
= src
|
||||||
|
|
||||||
|
packages = find:
|
||||||
|
include_package_data = True
|
||||||
|
python_requires = >=3.7
|
||||||
|
|
||||||
|
[options.packages.find]
|
||||||
|
where = src
|
||||||
|
|||||||
50
setup.py
50
setup.py
@@ -1,48 +1,20 @@
|
|||||||
import os
|
|
||||||
from setuptools import setup
|
from setuptools import setup
|
||||||
|
|
||||||
|
# Metadata goes in setup.cfg. These are here for GitHub's dependency graph.
|
||||||
here = os.path.abspath(os.path.dirname(__file__))
|
|
||||||
|
|
||||||
try:
|
|
||||||
README = open(os.path.join(here, 'README.rst')).read()
|
|
||||||
CHANGES = open(os.path.join(here, 'CHANGES.rst')).read()
|
|
||||||
except:
|
|
||||||
README = ''
|
|
||||||
CHANGES = ''
|
|
||||||
|
|
||||||
|
|
||||||
setup(
|
setup(
|
||||||
name='Flask-DebugToolbar',
|
name="Flask-DebugToolbar",
|
||||||
version='0.11.0',
|
|
||||||
url='https://flask-debugtoolbar.readthedocs.io/',
|
|
||||||
license='BSD',
|
|
||||||
author='Michael van Tellingen',
|
|
||||||
author_email='michaelvantellingen@gmail.com',
|
|
||||||
maintainer='Matt Good',
|
|
||||||
maintainer_email='matt@matt-good.net',
|
|
||||||
description='A toolbar overlay for debugging Flask applications.',
|
|
||||||
long_description=README + '\n\n' + CHANGES,
|
|
||||||
zip_safe=False,
|
|
||||||
platforms='any',
|
|
||||||
include_package_data=True,
|
|
||||||
packages=['flask_debugtoolbar',
|
|
||||||
'flask_debugtoolbar.panels'
|
|
||||||
],
|
|
||||||
install_requires=[
|
install_requires=[
|
||||||
'Flask>=0.8',
|
'Flask>=2.2.0',
|
||||||
'Blinker',
|
'Blinker',
|
||||||
'itsdangerous',
|
'itsdangerous',
|
||||||
'werkzeug',
|
'werkzeug',
|
||||||
|
'MarkupSafe',
|
||||||
|
'packaging',
|
||||||
],
|
],
|
||||||
classifiers=[
|
extras_require={
|
||||||
'Development Status :: 4 - Beta',
|
"docs": [
|
||||||
'Environment :: Web Environment',
|
'Sphinx>=1.2.2',
|
||||||
'Intended Audience :: Developers',
|
'Pallets-Sphinx-Themes',
|
||||||
'License :: OSI Approved :: BSD License',
|
],
|
||||||
'Operating System :: OS Independent',
|
}
|
||||||
'Programming Language :: Python',
|
|
||||||
'Topic :: Internet :: WWW/HTTP :: Dynamic Content',
|
|
||||||
'Topic :: Software Development :: Libraries :: Python Modules'
|
|
||||||
]
|
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,14 +1,28 @@
|
|||||||
|
import contextvars
|
||||||
import os
|
import os
|
||||||
|
import urllib.parse
|
||||||
import warnings
|
import warnings
|
||||||
|
|
||||||
from flask import Blueprint, current_app, request, g, send_from_directory
|
import flask
|
||||||
from flask.globals import _request_ctx_stack
|
from flask import Blueprint, current_app, request, g, send_from_directory, url_for
|
||||||
|
from flask.globals import request_ctx
|
||||||
|
|
||||||
|
from jinja2 import __version__ as __jinja_version__
|
||||||
from jinja2 import Environment, PackageLoader
|
from jinja2 import Environment, PackageLoader
|
||||||
from werkzeug.urls import url_quote_plus
|
|
||||||
|
|
||||||
from flask_debugtoolbar.compat import iteritems
|
from flask_debugtoolbar.compat import iteritems
|
||||||
from flask_debugtoolbar.toolbar import DebugToolbar
|
from flask_debugtoolbar.toolbar import DebugToolbar
|
||||||
from flask_debugtoolbar.utils import decode_text
|
from flask_debugtoolbar.utils import decode_text, gzip_compress, gzip_decompress
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Python 3.8+
|
||||||
|
from importlib.metadata import version
|
||||||
|
|
||||||
|
__version__ = version("Flask-DebugToolbar")
|
||||||
|
except ImportError:
|
||||||
|
import pkg_resources
|
||||||
|
|
||||||
|
__version__ = pkg_resources.get_distribution("Flask-DebugToolbar").version
|
||||||
|
|
||||||
|
|
||||||
module = Blueprint('debugtoolbar', __name__)
|
module = Blueprint('debugtoolbar', __name__)
|
||||||
@@ -39,20 +53,28 @@ class DebugToolbarExtension(object):
|
|||||||
_static_dir = os.path.realpath(
|
_static_dir = os.path.realpath(
|
||||||
os.path.join(os.path.dirname(__file__), 'static'))
|
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]
|
_redirect_codes = [301, 302, 303, 304]
|
||||||
|
|
||||||
def __init__(self, app=None):
|
def __init__(self, app=None):
|
||||||
self.app = app
|
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':
|
||||||
|
jinja_extensions.append('jinja2.ext.with_')
|
||||||
|
|
||||||
# Configure jinja for the internal templates and add url rules
|
# Configure jinja for the internal templates and add url rules
|
||||||
# for static data
|
# for static data
|
||||||
self.jinja_env = Environment(
|
self.jinja_env = Environment(
|
||||||
autoescape=True,
|
autoescape=True,
|
||||||
extensions=['jinja2.ext.i18n', 'jinja2.ext.with_'],
|
extensions=jinja_extensions,
|
||||||
loader=PackageLoader(__name__, 'templates'))
|
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.filters['printable'] = _printable
|
||||||
|
self.jinja_env.globals['url_for'] = url_for
|
||||||
|
|
||||||
if app is not None:
|
if app is not None:
|
||||||
self.init_app(app)
|
self.init_app(app)
|
||||||
@@ -99,12 +121,14 @@ class DebugToolbarExtension(object):
|
|||||||
'flask_debugtoolbar.panels.logger.LoggingPanel',
|
'flask_debugtoolbar.panels.logger.LoggingPanel',
|
||||||
'flask_debugtoolbar.panels.route_list.RouteListDebugPanel',
|
'flask_debugtoolbar.panels.route_list.RouteListDebugPanel',
|
||||||
'flask_debugtoolbar.panels.profiler.ProfilerDebugPanel',
|
'flask_debugtoolbar.panels.profiler.ProfilerDebugPanel',
|
||||||
|
'flask_debugtoolbar.panels.g.GDebugPanel',
|
||||||
),
|
),
|
||||||
|
'SQLALCHEMY_RECORD_QUERIES': app.debug,
|
||||||
}
|
}
|
||||||
|
|
||||||
def dispatch_request(self):
|
def dispatch_request(self):
|
||||||
"""Modified version of Flask.dispatch_request to call process_view."""
|
"""Modified version of Flask.dispatch_request to call process_view."""
|
||||||
req = _request_ctx_stack.top.request
|
req = request_ctx.request
|
||||||
app = current_app
|
app = current_app
|
||||||
|
|
||||||
if req.routing_exception is not None:
|
if req.routing_exception is not None:
|
||||||
@@ -146,11 +170,11 @@ class DebugToolbarExtension(object):
|
|||||||
return
|
return
|
||||||
|
|
||||||
real_request = request._get_current_object()
|
real_request = request._get_current_object()
|
||||||
|
self.debug_toolbars_var.set({})
|
||||||
self.debug_toolbars[real_request] = (
|
self.debug_toolbars_var.get()[real_request] = (
|
||||||
DebugToolbar(real_request, self.jinja_env))
|
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)
|
panel.process_request(real_request)
|
||||||
|
|
||||||
def process_view(self, app, view_func, view_kwargs):
|
def process_view(self, app, view_func, view_kwargs):
|
||||||
@@ -159,7 +183,7 @@ class DebugToolbarExtension(object):
|
|||||||
"""
|
"""
|
||||||
real_request = request._get_current_object()
|
real_request = request._get_current_object()
|
||||||
try:
|
try:
|
||||||
toolbar = self.debug_toolbars[real_request]
|
toolbar = self.debug_toolbars_var.get({})[real_request]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
return view_func
|
return view_func
|
||||||
|
|
||||||
@@ -172,7 +196,7 @@ class DebugToolbarExtension(object):
|
|||||||
|
|
||||||
def process_response(self, response):
|
def process_response(self, response):
|
||||||
real_request = request._get_current_object()
|
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
|
return response
|
||||||
|
|
||||||
# Intercept http redirect codes and display an html page with a
|
# Intercept http redirect codes and display an html page with a
|
||||||
@@ -191,14 +215,18 @@ class DebugToolbarExtension(object):
|
|||||||
response.response = [content]
|
response.response = [content]
|
||||||
response.status_code = 200
|
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.
|
# 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.is_sequence and
|
||||||
response.headers['content-type'].startswith('text/html')):
|
response.headers['content-type'].startswith('text/html')):
|
||||||
return response
|
return response
|
||||||
|
|
||||||
response_html = 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.get_data(as_text=True)
|
||||||
|
|
||||||
no_case = response_html.lower()
|
no_case = response_html.lower()
|
||||||
body_end = no_case.rfind('</body>')
|
body_end = no_case.rfind('</body>')
|
||||||
@@ -214,7 +242,7 @@ class DebugToolbarExtension(object):
|
|||||||
' </body> tag not found in response.')
|
' </body> tag not found in response.')
|
||||||
return response
|
return response
|
||||||
|
|
||||||
toolbar = self.debug_toolbars[real_request]
|
toolbar = self.debug_toolbars_var.get()[real_request]
|
||||||
|
|
||||||
for panel in toolbar.panels:
|
for panel in toolbar.panels:
|
||||||
panel.process_response(real_request, response)
|
panel.process_response(real_request, response)
|
||||||
@@ -222,14 +250,17 @@ class DebugToolbarExtension(object):
|
|||||||
toolbar_html = toolbar.render_toolbar()
|
toolbar_html = toolbar.render_toolbar()
|
||||||
|
|
||||||
content = ''.join((before, toolbar_html, after))
|
content = ''.join((before, toolbar_html, after))
|
||||||
content = content.encode(response.charset)
|
content = content.encode('utf-8')
|
||||||
|
if content_encoding and 'gzip' in content_encoding:
|
||||||
|
content = gzip_compress(content)
|
||||||
response.response = [content]
|
response.response = [content]
|
||||||
response.content_length = len(content)
|
response.content_length = len(content)
|
||||||
|
|
||||||
return response
|
return response
|
||||||
|
|
||||||
def teardown_request(self, exc):
|
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):
|
def render(self, template_name, context):
|
||||||
template = self.jinja_env.get_template(template_name)
|
template = self.jinja_env.get_template(template_name)
|
||||||
@@ -25,6 +25,29 @@ class DebugPanel(object):
|
|||||||
# If the client enabled the panel
|
# If the client enabled the panel
|
||||||
self.is_active = False
|
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):
|
def render(self, template_name, context):
|
||||||
template = self.jinja_env.get_template(template_name)
|
template = self.jinja_env.get_template(template_name)
|
||||||
return template.render(**context)
|
return template.render(**context)
|
||||||
28
src/flask_debugtoolbar/panels/g.py
Normal file
28
src/flask_debugtoolbar/panels/g.py
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
from flask import g
|
||||||
|
from flask_debugtoolbar.panels import DebugPanel
|
||||||
|
|
||||||
|
_ = lambda x: x
|
||||||
|
|
||||||
|
|
||||||
|
class GDebugPanel(DebugPanel):
|
||||||
|
"""
|
||||||
|
A panel to display flask.g content.
|
||||||
|
"""
|
||||||
|
name = 'g'
|
||||||
|
has_content = True
|
||||||
|
|
||||||
|
def nav_title(self):
|
||||||
|
return _('flask.g')
|
||||||
|
|
||||||
|
def title(self):
|
||||||
|
return _('flask.g content')
|
||||||
|
|
||||||
|
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.
|
provided, returns a list for the current thread.
|
||||||
"""
|
"""
|
||||||
if thread is None:
|
if thread is None:
|
||||||
thread = threading.currentThread()
|
thread = threading.current_thread()
|
||||||
if thread not in self.records:
|
if thread not in self.records:
|
||||||
self.records[thread] = []
|
self.records[thread] = []
|
||||||
return self.records[thread]
|
return self.records[thread]
|
||||||
|
|
||||||
def clear_records(self, thread=None):
|
def clear_records(self, thread=None):
|
||||||
if thread is None:
|
if thread is None:
|
||||||
thread = threading.currentThread()
|
thread = threading.current_thread()
|
||||||
if thread in self.records:
|
if thread in self.records:
|
||||||
del self.records[thread]
|
del self.records[thread]
|
||||||
|
|
||||||
@@ -14,6 +14,7 @@ class ProfilerDebugPanel(DebugPanel):
|
|||||||
"""
|
"""
|
||||||
Panel that displays the time a response took with cProfile output.
|
Panel that displays the time a response took with cProfile output.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
name = 'Profiler'
|
name = 'Profiler'
|
||||||
|
|
||||||
user_activate = True
|
user_activate = True
|
||||||
@@ -22,6 +23,9 @@ class ProfilerDebugPanel(DebugPanel):
|
|||||||
DebugPanel.__init__(self, jinja_env, context=context)
|
DebugPanel.__init__(self, jinja_env, context=context)
|
||||||
if current_app.config.get('DEBUG_TB_PROFILER_ENABLED'):
|
if current_app.config.get('DEBUG_TB_PROFILER_ENABLED'):
|
||||||
self.is_active = True
|
self.is_active = True
|
||||||
|
self.dump_filename = current_app.config.get(
|
||||||
|
"DEBUG_TB_PROFILER_DUMP_FILENAME"
|
||||||
|
)
|
||||||
|
|
||||||
def has_content(self):
|
def has_content(self):
|
||||||
return bool(self.profiler)
|
return bool(self.profiler)
|
||||||
@@ -73,7 +77,7 @@ class ProfilerDebugPanel(DebugPanel):
|
|||||||
# Cumulative time
|
# Cumulative time
|
||||||
current['cumtime'] = info[3] * 1000
|
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.
|
# primitive calls.
|
||||||
if info[0]:
|
if info[0]:
|
||||||
current['percall_cum'] = info[3] * 1000 / info[0]
|
current['percall_cum'] = info[3] * 1000 / info[0]
|
||||||
@@ -88,13 +92,20 @@ class ProfilerDebugPanel(DebugPanel):
|
|||||||
|
|
||||||
self.stats = stats
|
self.stats = stats
|
||||||
self.function_calls = function_calls
|
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
|
return response
|
||||||
|
|
||||||
def title(self):
|
def title(self):
|
||||||
if not self.is_active:
|
if not self.is_active:
|
||||||
return "Profiler not 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):
|
def nav_title(self):
|
||||||
return 'Profiler'
|
return 'Profiler'
|
||||||
@@ -102,7 +113,7 @@ class ProfilerDebugPanel(DebugPanel):
|
|||||||
def nav_subtitle(self):
|
def nav_subtitle(self):
|
||||||
if not self.is_active:
|
if not self.is_active:
|
||||||
return "in-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):
|
def url(self):
|
||||||
return ''
|
return ''
|
||||||
@@ -1,9 +1,23 @@
|
|||||||
try:
|
try:
|
||||||
from flask_sqlalchemy import get_debug_queries, SQLAlchemy
|
from flask_sqlalchemy import SQLAlchemy
|
||||||
except ImportError:
|
except ImportError:
|
||||||
sqlalchemy_available = False
|
sqlalchemy_available = False
|
||||||
get_debug_queries = SQLAlchemy = None
|
get_recorded_queries = SQLAlchemy = None
|
||||||
else:
|
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'
|
||||||
sqlalchemy_available = True
|
sqlalchemy_available = True
|
||||||
|
|
||||||
from flask import request, current_app, abort, g
|
from flask import request, current_app, abort, g
|
||||||
@@ -12,7 +26,6 @@ from flask_debugtoolbar.panels import DebugPanel
|
|||||||
from flask_debugtoolbar.utils import format_fname, format_sql
|
from flask_debugtoolbar.utils import format_fname, format_sql
|
||||||
import itsdangerous
|
import itsdangerous
|
||||||
|
|
||||||
|
|
||||||
_ = lambda x: x
|
_ = lambda x: x
|
||||||
|
|
||||||
|
|
||||||
@@ -54,8 +67,10 @@ def extension_used():
|
|||||||
|
|
||||||
|
|
||||||
def recording_enabled():
|
def recording_enabled():
|
||||||
return (current_app.debug
|
return (
|
||||||
or current_app.config.get('SQLALCHEMY_RECORD_QUERIES'))
|
(debug_enables_record_queries and current_app.debug) or
|
||||||
|
current_app.config.get('SQLALCHEMY_RECORD_QUERIES')
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def is_available():
|
def is_available():
|
||||||
@@ -63,8 +78,8 @@ def is_available():
|
|||||||
|
|
||||||
|
|
||||||
def get_queries():
|
def get_queries():
|
||||||
if get_debug_queries:
|
if get_recorded_queries:
|
||||||
return get_debug_queries()
|
return get_recorded_queries()
|
||||||
else:
|
else:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
@@ -118,11 +133,12 @@ class SQLAlchemyDebugPanel(DebugPanel):
|
|||||||
'duration': query.duration,
|
'duration': query.duration,
|
||||||
'sql': format_sql(query.statement, query.parameters),
|
'sql': format_sql(query.statement, query.parameters),
|
||||||
'signed_query': dump_query(query.statement, query.parameters),
|
'signed_query': dump_query(query.statement, query.parameters),
|
||||||
'context_long': query.context,
|
'location_long': getattr(query, location_property),
|
||||||
'context': format_fname(query.context)
|
'location': format_fname(getattr(query, location_property))
|
||||||
})
|
})
|
||||||
return self.render('panels/sqlalchemy.html', {'queries': data})
|
return self.render('panels/sqlalchemy.html', {'queries': data})
|
||||||
|
|
||||||
|
|
||||||
# Panel views
|
# Panel views
|
||||||
|
|
||||||
|
|
||||||
@@ -52,8 +52,7 @@ class TimerDebugPanel(DebugPanel):
|
|||||||
return ''
|
return ''
|
||||||
|
|
||||||
def _elapsed_ru(self, name):
|
def _elapsed_ru(self, name):
|
||||||
return (getattr(self._end_rusage, name)
|
return (getattr(self._end_rusage, name) - getattr(self._start_rusage, name))
|
||||||
- getattr(self._start_rusage, name))
|
|
||||||
|
|
||||||
def content(self):
|
def content(self):
|
||||||
|
|
||||||
@@ -1,22 +1,22 @@
|
|||||||
import os
|
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
|
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
|
_ = 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):
|
class VersionDebugPanel(DebugPanel):
|
||||||
"""
|
"""
|
||||||
Panel that displays the Flask version.
|
Panel that displays the Flask version.
|
||||||
@@ -38,15 +38,14 @@ class VersionDebugPanel(DebugPanel):
|
|||||||
|
|
||||||
def content(self):
|
def content(self):
|
||||||
try:
|
try:
|
||||||
import pkg_resources
|
import importlib.metadata
|
||||||
except ImportError:
|
except ImportError:
|
||||||
packages = []
|
packages = []
|
||||||
else:
|
else:
|
||||||
packages = sorted(pkg_resources.working_set,
|
packages_metadata = [p.metadata for p in importlib.metadata.distributions()]
|
||||||
key=lambda p: p.project_name.lower())
|
packages = sorted(packages_metadata, key=lambda p: p['Name'].lower())
|
||||||
|
|
||||||
return self.render('panels/versions.html', {
|
return self.render('panels/versions.html', {
|
||||||
'packages': packages,
|
'packages': packages,
|
||||||
'python_lib': os.path.normpath(get_python_lib()),
|
'python_lib_dir': os.path.normpath(get_path('platlib')),
|
||||||
'relpath': relpath,
|
|
||||||
})
|
})
|
||||||
@@ -183,7 +183,7 @@ CodeMirror.defineMode('rst', function(config, options) {
|
|||||||
setState(state, inline, {
|
setState(state, inline, {
|
||||||
ch: orig, // inline() has to know what to search for
|
ch: orig, // inline() has to know what to search for
|
||||||
wide: wide, // are we looking for `ch` or `chch`
|
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
|
token: token // I don't want to recompute this all the time
|
||||||
});
|
});
|
||||||
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user