9 | The Flask Debug Toolbar has intercepted a redirect to the above URL for
10 | debug viewing purposes. You can click the above link to continue with the
11 | redirect as normal. If you'd like to disable this feature, you can set the
12 | config variable DEBUG_TB_INTERCEPT_REDIRECTS to False.
13 |
37 |
--------------------------------------------------------------------------------
/requirements/tests.txt:
--------------------------------------------------------------------------------
1 | #
2 | # This file is autogenerated by pip-compile with Python 3.8
3 | # by the following command:
4 | #
5 | # pip-compile tests.in
6 | #
7 | blinker==1.8.1
8 | # via flask
9 | click==8.1.7
10 | # via flask
11 | exceptiongroup==1.2.1
12 | # via pytest
13 | flask==3.0.3
14 | # via flask-sqlalchemy
15 | flask-sqlalchemy==3.1.1
16 | # via -r tests.in
17 | greenlet==3.0.3
18 | # via sqlalchemy
19 | importlib-metadata==7.1.0
20 | # via flask
21 | iniconfig==2.0.0
22 | # via pytest
23 | itsdangerous==2.2.0
24 | # via flask
25 | jinja2==3.1.4
26 | # via flask
27 | markupsafe==2.1.5
28 | # via
29 | # jinja2
30 | # werkzeug
31 | packaging==24.0
32 | # via pytest
33 | pluggy==1.5.0
34 | # via pytest
35 | pygments==2.18.0
36 | # via -r tests.in
37 | pytest==8.3.3
38 | # via -r tests.in
39 | sqlalchemy==2.0.29
40 | # via flask-sqlalchemy
41 | tomli==2.0.1
42 | # via pytest
43 | typing-extensions==4.11.0
44 | # via sqlalchemy
45 | werkzeug==3.0.3
46 | # via flask
47 | zipp==3.19.1
48 | # via importlib-metadata
49 |
--------------------------------------------------------------------------------
/src/flask_debugtoolbar/static/codemirror/mode/pascal/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2011 souceLair
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4 |
5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6 |
7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
8 |
--------------------------------------------------------------------------------
/src/flask_debugtoolbar/static/codemirror/theme/cobalt.css:
--------------------------------------------------------------------------------
1 | .cm-s-cobalt { background: #002240; color: white; }
2 | .cm-s-cobalt div.CodeMirror-selected { background: #b36539 !important; }
3 | .cm-s-cobalt .CodeMirror-gutter { background: #002240; border-right: 1px solid #aaa; }
4 | .cm-s-cobalt .CodeMirror-gutter-text { color: #d0d0d0; }
5 | .cm-s-cobalt .CodeMirror-cursor { border-left: 1px solid white !important; }
6 |
7 | .cm-s-cobalt span.cm-comment { color: #08f; }
8 | .cm-s-cobalt span.cm-atom { color: #845dc4; }
9 | .cm-s-cobalt span.cm-number, .cm-s-cobalt span.cm-attribute { color: #ff80e1; }
10 | .cm-s-cobalt span.cm-keyword { color: #ffee80; }
11 | .cm-s-cobalt span.cm-string { color: #3ad900; }
12 | .cm-s-cobalt span.cm-meta { color: #ff9d00; }
13 | .cm-s-cobalt span.cm-variable-2, .cm-s-cobalt span.cm-tag { color: #9effff; }
14 | .cm-s-cobalt span.cm-variable-3, .cm-s-cobalt span.cm-def { color: white; }
15 | .cm-s-cobalt span.cm-error { color: #9d1e15; }
16 | .cm-s-cobalt span.cm-bracket { color: #d8d8d8; }
17 | .cm-s-cobalt span.cm-builtin, .cm-s-cobalt span.cm-special { color: #ff9e59; }
18 | .cm-s-cobalt span.cm-link { color: #845dc4; }
19 |
--------------------------------------------------------------------------------
/src/flask_debugtoolbar/panels/versions.py:
--------------------------------------------------------------------------------
1 | from __future__ import annotations
2 |
3 | import importlib.metadata
4 | import os
5 | from sysconfig import get_path
6 |
7 | from . import DebugPanel
8 |
9 | flask_version: str = importlib.metadata.version("flask")
10 |
11 |
12 | class VersionDebugPanel(DebugPanel):
13 | """Panel that displays the Flask version."""
14 |
15 | name = "Version"
16 | has_content = True
17 |
18 | def nav_title(self) -> str:
19 | return "Versions"
20 |
21 | def nav_subtitle(self) -> str:
22 | return f"Flask {flask_version}"
23 |
24 | def url(self) -> str:
25 | return ""
26 |
27 | def title(self) -> str:
28 | return "Versions"
29 |
30 | def content(self) -> str:
31 | packages_metadata = [p.metadata for p in importlib.metadata.distributions()]
32 | packages = sorted(packages_metadata, key=lambda p: p["Name"].lower())
33 | return self.render(
34 | "panels/versions.html",
35 | {
36 | "packages": packages,
37 | "python_lib_dir": os.path.normpath(get_path("platlib")),
38 | },
39 | )
40 |
--------------------------------------------------------------------------------
/src/flask_debugtoolbar/static/codemirror/mode/ntriples/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | CodeMirror: NTriples mode
5 |
6 |
7 |
8 |
9 |
14 |
15 |
16 |
CodeMirror: NTriples mode
17 |
26 |
27 |
30 |
MIME types defined:text/n-triples.
31 |
32 |
33 |
--------------------------------------------------------------------------------
/src/flask_debugtoolbar/static/codemirror/mode/xquery/test/testQuotes.js:
--------------------------------------------------------------------------------
1 | $(document).ready(function(){
2 | module("testQuoteEscape");
3 | test("testQuoteEscapeDouble", function() {
4 | expect(1);
5 |
6 | var input = 'let $rootfolder := "c:\\builds\\winnt\\HEAD\\qa\\scripts\\"\
7 | let $keysfolder := concat($rootfolder, "keys\\")\
8 | return\
9 | $keysfolder';
10 | var expected = 'let$rootfolder:="c:\\builds\\winnt\\HEAD\\qa\\scripts\\"let$keysfolder:=concat($rootfolder, "keys\\")return$keysfolder';
11 |
12 | $("#sandbox").html('');
13 | var editor = CodeMirror.fromTextArea($("#editor")[0]);
14 | var result = $(".CodeMirror-lines div div pre")[0].innerHTML;
15 |
16 | equal(result, expected);
17 | $("#editor").html("");
18 | });
19 | });
20 |
--------------------------------------------------------------------------------
/src/flask_debugtoolbar/static/codemirror/theme/eclipse.css:
--------------------------------------------------------------------------------
1 | .cm-s-eclipse span.cm-meta {color: #FF1717;}
2 | .cm-s-eclipse span.cm-keyword { line-height: 1em; font-weight: bold; color: #7F0055; }
3 | .cm-s-eclipse span.cm-atom {color: #219;}
4 | .cm-s-eclipse span.cm-number {color: #164;}
5 | .cm-s-eclipse span.cm-def {color: #00f;}
6 | .cm-s-eclipse span.cm-variable {color: black;}
7 | .cm-s-eclipse span.cm-variable-2 {color: #0000C0;}
8 | .cm-s-eclipse span.cm-variable-3 {color: #0000C0;}
9 | .cm-s-eclipse span.cm-property {color: black;}
10 | .cm-s-eclipse span.cm-operator {color: black;}
11 | .cm-s-eclipse span.cm-comment {color: #3F7F5F;}
12 | .cm-s-eclipse span.cm-string {color: #2A00FF;}
13 | .cm-s-eclipse span.cm-string-2 {color: #f50;}
14 | .cm-s-eclipse span.cm-error {color: #f00;}
15 | .cm-s-eclipse span.cm-qualifier {color: #555;}
16 | .cm-s-eclipse span.cm-builtin {color: #30a;}
17 | .cm-s-eclipse span.cm-bracket {color: #cc7;}
18 | .cm-s-eclipse span.cm-tag {color: #170;}
19 | .cm-s-eclipse span.cm-attribute {color: #00c;}
20 | .cm-s-eclipse span.cm-link {color: #219;}
21 |
22 | .cm-s-eclipse .CodeMirror-matchingbracket {
23 | border:1px solid grey;
24 | color:black !important;;
25 | }
26 |
--------------------------------------------------------------------------------
/src/flask_debugtoolbar/static/codemirror/mode/python/LICENSE.txt:
--------------------------------------------------------------------------------
1 | The MIT License
2 |
3 | Copyright (c) 2010 Timothy Farrell
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
--------------------------------------------------------------------------------
/tests/basic_app.py:
--------------------------------------------------------------------------------
1 | from __future__ import annotations
2 |
3 | from flask import Flask
4 | from flask import render_template
5 | from flask_sqlalchemy import SQLAlchemy
6 |
7 | from flask_debugtoolbar import DebugToolbarExtension
8 |
9 | app = Flask("basic_app")
10 | app.config["DEBUG"] = True
11 | app.config["SECRET_KEY"] = "abc123"
12 | app.config["SQLALCHEMY_RECORD_QUERIES"] = True
13 | app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///:memory:"
14 | # This is no longer needed for Flask-SQLAlchemy 3.0+,
15 | # if you're using 2.X you'll want to define this:
16 | # app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
17 |
18 | # make sure these are printable in the config panel
19 | app.config["BYTES_VALUE"] = b"\x00"
20 | app.config["UNICODE_VALUE"] = "\uffff"
21 |
22 | toolbar = DebugToolbarExtension(app)
23 | db = SQLAlchemy(app)
24 |
25 |
26 | class Foo(db.Model): # type: ignore[name-defined, misc]
27 | __tablename__ = "foo"
28 | id = db.Column(db.Integer, primary_key=True)
29 |
30 |
31 | @app.route("/")
32 | def index() -> str:
33 | Foo.query.filter_by(id=1).all()
34 | return render_template("basic_app.html")
35 |
36 |
37 | with app.app_context():
38 | db.create_all()
39 |
--------------------------------------------------------------------------------
/src/flask_debugtoolbar/static/codemirror/mode/perl/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (C) 2011 by Sabaca under the MIT license.
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy
4 | of this software and associated documentation files (the "Software"), to deal
5 | in the Software without restriction, including without limitation the rights
6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | copies of the Software, and to permit persons to whom the Software is
8 | furnished to do so, subject to the following conditions:
9 |
10 | The above copyright notice and this permission notice shall be included in
11 | all copies or substantial portions of the Software.
12 |
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | THE SOFTWARE.
20 |
--------------------------------------------------------------------------------
/src/flask_debugtoolbar/static/codemirror/mode/xquery/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (C) 2011 by MarkLogic Corporation
2 | Author: Mike Brevoort
3 |
4 | Permission is hereby granted, free of charge, to any person obtaining a copy
5 | of this software and associated documentation files (the "Software"), to deal
6 | in the Software without restriction, including without limitation the rights
7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | copies of the Software, and to permit persons to whom the Software is
9 | furnished to do so, subject to the following conditions:
10 |
11 | The above copyright notice and this permission notice shall be included in
12 | all copies or substantial portions of the Software.
13 |
14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | THE SOFTWARE.
--------------------------------------------------------------------------------
/src/flask_debugtoolbar/static/codemirror/theme/night.css:
--------------------------------------------------------------------------------
1 | /* Loosely based on the Midnight Textmate theme */
2 |
3 | .cm-s-night { background: #0a001f; color: #f8f8f8; }
4 | .cm-s-night div.CodeMirror-selected { background: #a8f !important; }
5 | .cm-s-night .CodeMirror-gutter { background: #0a001f; border-right: 1px solid #aaa; }
6 | .cm-s-night .CodeMirror-gutter-text { color: #f8f8f8; }
7 | .cm-s-night .CodeMirror-cursor { border-left: 1px solid white !important; }
8 |
9 | .cm-s-night span.cm-comment { color: #6900a1; }
10 | .cm-s-night span.cm-atom { color: #845dc4; }
11 | .cm-s-night span.cm-number, .cm-s-night span.cm-attribute { color: #ffd500; }
12 | .cm-s-night span.cm-keyword { color: #599eff; }
13 | .cm-s-night span.cm-string { color: #37f14a; }
14 | .cm-s-night span.cm-meta { color: #7678e2; }
15 | .cm-s-night span.cm-variable-2, .cm-s-night span.cm-tag { color: #99b2ff; }
16 | .cm-s-night span.cm-variable-3, .cm-s-night span.cm-def { color: white; }
17 | .cm-s-night span.cm-error { color: #9d1e15; }
18 | .cm-s-night span.cm-bracket { color: #8da6ce; }
19 | .cm-s-night span.cm-comment { color: #6900a1; }
20 | .cm-s-night span.cm-builtin, .cm-s-night span.cm-special { color: #ff9e59; }
21 | .cm-s-night span.cm-link { color: #845dc4; }
22 |
--------------------------------------------------------------------------------
/src/flask_debugtoolbar/templates/panels/sqlalchemy.html:
--------------------------------------------------------------------------------
1 |
4 | The toolbar was unable to fetch the SQLAlchemy queries for this request.
5 | To enable the SQLAlchemy query display, please:
6 |
7 |
8 |
9 | {% if not sqlalchemy_available %}
10 |
11 |
Install required libraries:
12 |
13 |
Flask-SQLAlchemy
14 |
15 |
16 | {% endif %}
17 |
18 | {% if not extension_used %}
19 |
20 |
Configure Flask-SQLAlchemy:
21 |
22 | The Flask-SQLAlchemy extension needs to be configured for this application.
23 | Please see the
24 | Flask-SQLAlchemy documentation for details.
25 |
26 |
27 | {% endif %}
28 |
29 | {% if not recording_enabled %}
30 |
31 |
Enable query recording:
32 |
33 | Since this app is not currently running in DEBUG mode, Flask-SQLAlchemy will not record queries by default. To enable query recording in non-debug mode, set the following configuration value:
34 |
43 | {% endif %}
44 |
45 |
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | Copyright 2011 Pallets Community Ecosystem
2 |
3 | Redistribution and use in source and binary forms, with or without modification,
4 | are permitted provided that the following conditions are met:
5 |
6 | 1. Redistributions of source code must retain the above copyright notice, this
7 | list of conditions and the following disclaimer.
8 | 2. Redistributions in binary form must reproduce the above copyright notice,
9 | this list of conditions and the following disclaimer in the documentation
10 | and/or other materials provided with the distribution.
11 | 3. Neither the name of the copyright holder nor the names of its contributors
12 | may be used to endorse or promote products derived from this software
13 | without specific prior written permission.
14 |
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
19 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
22 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 |
--------------------------------------------------------------------------------
/src/flask_debugtoolbar/static/codemirror/mode/r/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2011, Ubalo, Inc.
2 | All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without
5 | modification, are permitted provided that the following conditions are met:
6 | * Redistributions of source code must retain the above copyright
7 | notice, this list of conditions and the following disclaimer.
8 | * Redistributions in binary form must reproduce the above copyright
9 | notice, this list of conditions and the following disclaimer in the
10 | documentation and/or other materials provided with the distribution.
11 | * Neither the name of the Ubalo, Inc nor the names of its
12 | contributors may be used to endorse or promote products derived
13 | from this software without specific prior written permission.
14 |
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 | DISCLAIMED. IN NO EVENT SHALL UBALO, INC BE LIABLE FOR ANY
19 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 |
--------------------------------------------------------------------------------
/src/flask_debugtoolbar/static/codemirror/mode/ruby/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2011, Ubalo, Inc.
2 | All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without
5 | modification, are permitted provided that the following conditions are met:
6 | * Redistributions of source code must retain the above copyright
7 | notice, this list of conditions and the following disclaimer.
8 | * Redistributions in binary form must reproduce the above copyright
9 | notice, this list of conditions and the following disclaimer in the
10 | documentation and/or other materials provided with the distribution.
11 | * Neither the name of the Ubalo, Inc. nor the names of its
12 | contributors may be used to endorse or promote products derived
13 | from this software without specific prior written permission.
14 |
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 | DISCLAIMED. IN NO EVENT SHALL UBALO, INC BE LIABLE FOR ANY
19 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 |
--------------------------------------------------------------------------------
/example/app.py:
--------------------------------------------------------------------------------
1 | # Run using: `FLASK_DEBUG=True flask run`
2 |
3 | from flask import Flask
4 | from flask import redirect
5 | from flask import render_template
6 | from flask import url_for
7 | from flask_sqlalchemy import SQLAlchemy
8 |
9 | from flask_debugtoolbar import DebugToolbarExtension
10 |
11 | app = Flask(__name__)
12 | app.config["DEBUG_TB_INTERCEPT_REDIRECTS"] = True
13 | # app.config['DEBUG_TB_PANELS'] = (
14 | # 'flask_debugtoolbar.panels.headers.HeaderDebugPanel',
15 | # 'flask_debugtoolbar.panels.logger.LoggingPanel',
16 | # 'flask_debugtoolbar.panels.timer.TimerDebugPanel',
17 | # )
18 | # app.config['DEBUG_TB_HOSTS'] = ('127.0.0.1', '::1' )
19 | app.config["SECRET_KEY"] = "asd"
20 | app.config["SQLALCHEMY_RECORD_QUERIES"] = True
21 | app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:////tmp/test.db"
22 | # This is no longer needed for Flask-SQLAlchemy 3.0+, if you're using 2.X you'll
23 | # want to define this:
24 | # app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
25 |
26 | db = SQLAlchemy(app)
27 | toolbar = DebugToolbarExtension(app)
28 |
29 |
30 | class ExampleModel(db.Model):
31 | __tablename__ = "examples"
32 | value = db.Column(db.String(100), primary_key=True)
33 |
34 |
35 | @app.route("/")
36 | def index():
37 | app.logger.info("Hello there")
38 | ExampleModel.query.get(1)
39 | return render_template("index.html")
40 |
41 |
42 | @app.route("/redirect")
43 | def redirect_example():
44 | response = redirect(url_for("index"))
45 | response.set_cookie("test_cookie", "1")
46 | return response
47 |
48 |
49 | with app.app_context():
50 | db.create_all()
51 |
--------------------------------------------------------------------------------
/requirements/typing.txt:
--------------------------------------------------------------------------------
1 | #
2 | # This file is autogenerated by pip-compile with Python 3.8
3 | # by the following command:
4 | #
5 | # pip-compile typing.in
6 | #
7 | blinker==1.8.1
8 | # via flask
9 | click==8.1.7
10 | # via flask
11 | exceptiongroup==1.2.1
12 | # via pytest
13 | flask==3.0.3
14 | # via flask-sqlalchemy
15 | flask-sqlalchemy==3.1.1
16 | # via -r typing.in
17 | greenlet==3.0.3
18 | # via sqlalchemy
19 | importlib-metadata==7.1.0
20 | # via flask
21 | iniconfig==2.0.0
22 | # via pytest
23 | itsdangerous==2.2.0
24 | # via flask
25 | jinja2==3.1.4
26 | # via flask
27 | markupsafe==2.1.5
28 | # via
29 | # jinja2
30 | # werkzeug
31 | mypy==1.11.2
32 | # via -r typing.in
33 | mypy-extensions==1.0.0
34 | # via mypy
35 | nodeenv==1.8.0
36 | # via pyright
37 | packaging==24.0
38 | # via pytest
39 | pluggy==1.5.0
40 | # via pytest
41 | pyright==1.1.382.post1
42 | # via -r typing.in
43 | pytest==8.3.3
44 | # via -r typing.in
45 | sqlalchemy==2.0.29
46 | # via flask-sqlalchemy
47 | tomli==2.0.1
48 | # via
49 | # mypy
50 | # pytest
51 | types-docutils==0.21.0.20240423
52 | # via types-pygments
53 | types-pygments==2.18.0.20240506
54 | # via -r typing.in
55 | types-setuptools==69.5.0.20240423
56 | # via types-pygments
57 | typing-extensions==4.11.0
58 | # via
59 | # mypy
60 | # pyright
61 | # sqlalchemy
62 | werkzeug==3.0.3
63 | # via flask
64 | zipp==3.19.1
65 | # via importlib-metadata
66 |
67 | # The following packages are considered to be unsafe in a requirements file:
68 | # setuptools
69 |
--------------------------------------------------------------------------------
/src/flask_debugtoolbar/panels/headers.py:
--------------------------------------------------------------------------------
1 | from __future__ import annotations
2 |
3 | import typing as t
4 |
5 | from werkzeug import Request
6 |
7 | from . import DebugPanel
8 |
9 |
10 | class HeaderDebugPanel(DebugPanel):
11 | """A panel to display HTTP headers."""
12 |
13 | name = "Header"
14 | has_content = True
15 | # List of headers we want to display
16 | header_filter: tuple[str, ...] = (
17 | "CONTENT_TYPE",
18 | "HTTP_ACCEPT",
19 | "HTTP_ACCEPT_CHARSET",
20 | "HTTP_ACCEPT_ENCODING",
21 | "HTTP_ACCEPT_LANGUAGE",
22 | "HTTP_CACHE_CONTROL",
23 | "HTTP_CONNECTION",
24 | "HTTP_HOST",
25 | "HTTP_KEEP_ALIVE",
26 | "HTTP_REFERER",
27 | "HTTP_USER_AGENT",
28 | "QUERY_STRING",
29 | "REMOTE_ADDR",
30 | "REMOTE_HOST",
31 | "REQUEST_METHOD",
32 | "SCRIPT_NAME",
33 | "SERVER_NAME",
34 | "SERVER_PORT",
35 | "SERVER_PROTOCOL",
36 | "SERVER_SOFTWARE",
37 | )
38 |
39 | def nav_title(self) -> str:
40 | return "HTTP Headers"
41 |
42 | def title(self) -> str:
43 | return "HTTP Headers"
44 |
45 | def url(self) -> str:
46 | return ""
47 |
48 | def process_request(self, request: Request) -> None:
49 | self.headers: dict[str, t.Any] = {
50 | k: request.environ[k] for k in self.header_filter if k in request.environ
51 | }
52 |
53 | def content(self) -> str:
54 | context = self.context.copy()
55 | context.update({"headers": self.headers})
56 | return self.render("panels/headers.html", context)
57 |
--------------------------------------------------------------------------------
/src/flask_debugtoolbar/static/codemirror/mode/php/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | CodeMirror: PHP mode
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
CodeMirror: PHP mode
17 |
18 |
29 |
30 |
41 |
42 |
Simple HTML/PHP mode based on
43 | the C-like mode. Depends on XML,
44 | JavaScript, CSS, and C-like modes.
The XML mode supports two configuration parameters:
32 |
33 |
htmlMode (boolean)
34 |
This switches the mode to parse HTML instead of XML. This
35 | means attributes do not have to be quoted, and some elements
36 | (such as br) do not require a closing tag.
37 |
alignCDATA (boolean)
38 |
Setting this to true will force the opening tag of CDATA
39 | blocks to not be indented.
40 |
41 |
42 |
MIME types defined:application/xml, text/html.
43 |
44 |
45 |
--------------------------------------------------------------------------------
/src/flask_debugtoolbar/static/codemirror/util/runmode.js:
--------------------------------------------------------------------------------
1 | CodeMirror.runMode = function(string, modespec, callback, options) {
2 | var mode = CodeMirror.getMode(CodeMirror.defaults, modespec);
3 | var isNode = callback.nodeType == 1;
4 | var tabSize = (options && options.tabSize) || CodeMirror.defaults.tabSize;
5 | if (isNode) {
6 | var node = callback, accum = [], col = 0;
7 | callback = function(text, style) {
8 | if (text == "\n") {
9 | accum.push(" ");
10 | col = 0;
11 | return;
12 | }
13 | var escaped = "";
14 | // HTML-escape and replace tabs
15 | for (var pos = 0;;) {
16 | var idx = text.indexOf("\t", pos);
17 | if (idx == -1) {
18 | escaped += CodeMirror.htmlEscape(text.slice(pos));
19 | col += text.length - pos;
20 | break;
21 | } else {
22 | col += idx - pos;
23 | escaped += CodeMirror.htmlEscape(text.slice(pos, idx));
24 | var size = tabSize - col % tabSize;
25 | col += size;
26 | for (var i = 0; i < size; ++i) escaped += " ";
27 | pos = idx + 1;
28 | }
29 | }
30 |
31 | if (style)
32 | accum.push("" + escaped + "");
33 | else
34 | accum.push(escaped);
35 | }
36 | }
37 | var lines = CodeMirror.splitLines(string), state = CodeMirror.startState(mode);
38 | for (var i = 0, e = lines.length; i < e; ++i) {
39 | if (i) callback("\n");
40 | var stream = new CodeMirror.StringStream(lines[i]);
41 | while (!stream.eol()) {
42 | var style = mode.token(stream, state);
43 | callback(stream.current(), style, i, stream.start);
44 | stream.start = stream.pos;
45 | }
46 | }
47 | if (isNode)
48 | node.innerHTML = accum.join("");
49 | };
50 |
--------------------------------------------------------------------------------
/src/flask_debugtoolbar/static/codemirror/mode/plsql/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | CodeMirror: Oracle PL/SQL mode
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
CodeMirror: Oracle PL/SQL mode
13 |
14 |
46 |
47 |
55 |
56 |
57 | Simple mode that handles Oracle PL/SQL language (and Oracle SQL, of course).
58 |
Mode for html embedded scripts like JSP and ASP.NET. Depends on HtmlMixed which in turn depends on
44 | JavaScript, CSS and XML. Other dependancies include those of the scriping language chosen.
Loosely based on Franciszek
64 | Wawrzak's CodeMirror
65 | 1 mode. One configuration parameter is
66 | supported, specials, to which you can provide an
67 | array of strings to have those identifiers highlighted with
68 | the lua-special style.
62 |
63 |
64 |
65 |
--------------------------------------------------------------------------------
/src/flask_debugtoolbar/static/codemirror/theme/xq-dark.css:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (C) 2011 by MarkLogic Corporation
3 | Author: Mike Brevoort
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
22 | */
23 | .cm-s-xq-dark { background: #0a001f; color: #f8f8f8; }
24 | .cm-s-xq-dark span.CodeMirror-selected { background: #a8f !important; }
25 | .cm-s-xq-dark .CodeMirror-gutter { background: #0a001f; border-right: 1px solid #aaa; }
26 | .cm-s-xq-dark .CodeMirror-gutter-text { color: #f8f8f8; }
27 | .cm-s-xq-dark .CodeMirror-cursor { border-left: 1px solid white !important; }
28 |
29 | .cm-s-xq-dark span.cm-keyword {color: #FFBD40;}
30 | .cm-s-xq-dark span.cm-atom {color: #6C8CD5;}
31 | .cm-s-xq-dark span.cm-number {color: #164;}
32 | .cm-s-xq-dark span.cm-def {color: #FFF; text-decoration:underline;}
33 | .cm-s-xq-dark span.cm-variable {color: #FFF;}
34 | .cm-s-xq-dark span.cm-variable-2 {color: #EEE;}
35 | .cm-s-xq-dark span.cm-variable-3 {color: #DDD;}
36 | .cm-s-xq-dark span.cm-property {}
37 | .cm-s-xq-dark span.cm-operator {}
38 | .cm-s-xq-dark span.cm-comment {color: gray;}
39 | .cm-s-xq-dark span.cm-string {color: #9FEE00;}
40 | .cm-s-xq-dark span.cm-meta {color: yellow;}
41 | .cm-s-xq-dark span.cm-error {color: #f00;}
42 | .cm-s-xq-dark span.cm-qualifier {color: #FFF700;}
43 | .cm-s-xq-dark span.cm-builtin {color: #30a;}
44 | .cm-s-xq-dark span.cm-bracket {color: #cc7;}
45 | .cm-s-xq-dark span.cm-tag {color: #FFBD40;}
46 | .cm-s-xq-dark span.cm-attribute {color: #FFF700;}
47 |
--------------------------------------------------------------------------------
/src/flask_debugtoolbar/templates/base.html:
--------------------------------------------------------------------------------
1 |
76 |
77 |
78 |
--------------------------------------------------------------------------------
/src/flask_debugtoolbar/static/codemirror/mode/rpm/spec/spec.js:
--------------------------------------------------------------------------------
1 | // Quick and dirty spec file highlighting
2 |
3 | CodeMirror.defineMode("spec", function(config, modeConfig) {
4 | var arch = /^(i386|i586|i686|x86_64|ppc64|ppc|ia64|s390x|s390|sparc64|sparcv9|sparc|noarch|alphaev6|alpha|hppa|mipsel)/;
5 |
6 | var preamble = /^(Name|Version|Release|License|Summary|Url|Group|Source|BuildArch|BuildRequires|BuildRoot|AutoReqProv|Provides|Requires(\(\w+\))?|Obsoletes|Conflicts|Recommends|Source\d*|Patch\d*|ExclusiveArch|NoSource|Supplements):/;
7 | var section = /^%(debug_package|package|description|prep|build|install|files|clean|changelog|preun|postun|pre|post|triggerin|triggerun|pretrans|posttrans|verifyscript|check|triggerpostun|triggerprein|trigger)/;
8 | var control_flow_complex = /^%(ifnarch|ifarch|if)/; // rpm control flow macros
9 | var control_flow_simple = /^%(else|endif)/; // rpm control flow macros
10 | var operators = /^(\!|\?|\<\=|\<|\>\=|\>|\=\=|\&\&|\|\|)/; // operators in control flow macros
11 |
12 | return {
13 | startState: function () {
14 | return {
15 | controlFlow: false,
16 | macroParameters: false,
17 | section: false
18 | };
19 | },
20 | token: function (stream, state) {
21 | var ch = stream.peek();
22 | if (ch == "#") { stream.skipToEnd(); return "comment"; }
23 |
24 | if (stream.sol()) {
25 | if (stream.match(preamble)) { return "preamble"; }
26 | if (stream.match(section)) { return "section"; }
27 | }
28 |
29 | if (stream.match(/^\$\w+/)) { return "def"; } // Variables like '$RPM_BUILD_ROOT'
30 | if (stream.match(/^\$\{\w+\}/)) { return "def"; } // Variables like '${RPM_BUILD_ROOT}'
31 |
32 | if (stream.match(control_flow_simple)) { return "keyword"; }
33 | if (stream.match(control_flow_complex)) {
34 | state.controlFlow = true;
35 | return "keyword";
36 | }
37 | if (state.controlFlow) {
38 | if (stream.match(operators)) { return "operator"; }
39 | if (stream.match(/^(\d+)/)) { return "number"; }
40 | if (stream.eol()) { state.controlFlow = false; }
41 | }
42 |
43 | if (stream.match(arch)) { return "number"; }
44 |
45 | // Macros like '%make_install' or '%attr(0775,root,root)'
46 | if (stream.match(/^%[\w]+/)) {
47 | if (stream.match(/^\(/)) { state.macroParameters = true; }
48 | return "macro";
49 | }
50 | if (state.macroParameters) {
51 | if (stream.match(/^\d+/)) { return "number";}
52 | if (stream.match(/^\)/)) {
53 | state.macroParameters = false;
54 | return "macro";
55 | }
56 | }
57 | if (stream.match(/^%\{\??[\w \-]+\}/)) { return "macro"; } // Macros like '%{defined fedora}'
58 |
59 | //TODO: Include bash script sub-parser (CodeMirror supports that)
60 | stream.next();
61 | return null;
62 | }
63 | };
64 | });
65 |
66 | CodeMirror.defineMIME("text/x-rpm-spec", "spec");
67 |
--------------------------------------------------------------------------------
/src/flask_debugtoolbar/static/codemirror/mode/pascal/pascal.js:
--------------------------------------------------------------------------------
1 | CodeMirror.defineMode("pascal", function(config) {
2 | function words(str) {
3 | var obj = {}, words = str.split(" ");
4 | for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
5 | return obj;
6 | }
7 | var keywords = words("and array begin case const div do downto else end file for forward integer " +
8 | "boolean char function goto if in label mod nil not of or packed procedure " +
9 | "program record repeat set string then to type until var while with");
10 | var atoms = {"null": true};
11 |
12 | var isOperatorChar = /[+\-*&%=<>!?|\/]/;
13 |
14 | function tokenBase(stream, state) {
15 | var ch = stream.next();
16 | if (ch == "#" && state.startOfLine) {
17 | stream.skipToEnd();
18 | return "meta";
19 | }
20 | if (ch == '"' || ch == "'") {
21 | state.tokenize = tokenString(ch);
22 | return state.tokenize(stream, state);
23 | }
24 | if (ch == "(" && stream.eat("*")) {
25 | state.tokenize = tokenComment;
26 | return tokenComment(stream, state);
27 | }
28 | if (/[\[\]{}\(\),;\:\.]/.test(ch)) {
29 | return null
30 | }
31 | if (/\d/.test(ch)) {
32 | stream.eatWhile(/[\w\.]/);
33 | return "number";
34 | }
35 | if (ch == "/") {
36 | if (stream.eat("/")) {
37 | stream.skipToEnd();
38 | return "comment";
39 | }
40 | }
41 | if (isOperatorChar.test(ch)) {
42 | stream.eatWhile(isOperatorChar);
43 | return "operator";
44 | }
45 | stream.eatWhile(/[\w\$_]/);
46 | var cur = stream.current();
47 | if (keywords.propertyIsEnumerable(cur)) return "keyword";
48 | if (atoms.propertyIsEnumerable(cur)) return "atom";
49 | return "word";
50 | }
51 |
52 | function tokenString(quote) {
53 | return function(stream, state) {
54 | var escaped = false, next, end = false;
55 | while ((next = stream.next()) != null) {
56 | if (next == quote && !escaped) {end = true; break;}
57 | escaped = !escaped && next == "\\";
58 | }
59 | if (end || !escaped) state.tokenize = null;
60 | return "string";
61 | };
62 | }
63 |
64 | function tokenComment(stream, state) {
65 | var maybeEnd = false, ch;
66 | while (ch = stream.next()) {
67 | if (ch == ")" && maybeEnd) {
68 | state.tokenize = null;
69 | break;
70 | }
71 | maybeEnd = (ch == "*");
72 | }
73 | return "comment";
74 | }
75 |
76 | // Interface
77 |
78 | return {
79 | startState: function(basecolumn) {
80 | return {tokenize: null};
81 | },
82 |
83 | token: function(stream, state) {
84 | if (stream.eatSpace()) return null;
85 | var style = (state.tokenize || tokenBase)(stream, state);
86 | if (style == "comment" || style == "meta") return style;
87 | return style;
88 | },
89 |
90 | electricChars: "{}"
91 | };
92 | });
93 |
94 | CodeMirror.defineMIME("text/x-pascal", "pascal");
95 |
--------------------------------------------------------------------------------
/src/flask_debugtoolbar/static/codemirror/mode/yaml/yaml.js:
--------------------------------------------------------------------------------
1 | CodeMirror.defineMode("yaml", function() {
2 |
3 | var cons = ['true', 'false', 'on', 'off', 'yes', 'no'];
4 | var keywordRegex = new RegExp("\\b(("+cons.join(")|(")+"))$", 'i');
5 |
6 | return {
7 | token: function(stream, state) {
8 | var ch = stream.peek();
9 | var esc = state.escaped;
10 | state.escaped = false;
11 | /* comments */
12 | if (ch == "#") { stream.skipToEnd(); return "comment"; }
13 | if (state.literal && stream.indentation() > state.keyCol) {
14 | stream.skipToEnd(); return "string";
15 | } else if (state.literal) { state.literal = false; }
16 | if (stream.sol()) {
17 | state.keyCol = 0;
18 | state.pair = false;
19 | state.pairStart = false;
20 | /* document start */
21 | if(stream.match(/---/)) { return "def"; }
22 | /* document end */
23 | if (stream.match(/\.\.\./)) { return "def"; }
24 | /* array list item */
25 | if (stream.match(/\s*-\s+/)) { return 'meta'; }
26 | }
27 | /* pairs (associative arrays) -> key */
28 | if (!state.pair && stream.match(/^\s*([a-z0-9\._-])+(?=\s*:)/i)) {
29 | state.pair = true;
30 | state.keyCol = stream.indentation();
31 | return "atom";
32 | }
33 | if (state.pair && stream.match(/^:\s*/)) { state.pairStart = true; return 'meta'; }
34 |
35 | /* inline pairs/lists */
36 | if (stream.match(/^(\{|\}|\[|\])/)) {
37 | if (ch == '{')
38 | state.inlinePairs++;
39 | else if (ch == '}')
40 | state.inlinePairs--;
41 | else if (ch == '[')
42 | state.inlineList++;
43 | else
44 | state.inlineList--;
45 | return 'meta';
46 | }
47 |
48 | /* list seperator */
49 | if (state.inlineList > 0 && !esc && ch == ',') {
50 | stream.next();
51 | return 'meta';
52 | }
53 | /* pairs seperator */
54 | if (state.inlinePairs > 0 && !esc && ch == ',') {
55 | state.keyCol = 0;
56 | state.pair = false;
57 | state.pairStart = false;
58 | stream.next();
59 | return 'meta';
60 | }
61 |
62 | /* start of value of a pair */
63 | if (state.pairStart) {
64 | /* block literals */
65 | if (stream.match(/^\s*(\||\>)\s*/)) { state.literal = true; return 'meta'; };
66 | /* references */
67 | if (stream.match(/^\s*(\&|\*)[a-z0-9\._-]+\b/i)) { return 'variable-2'; }
68 | /* numbers */
69 | if (state.inlinePairs == 0 && stream.match(/^\s*-?[0-9\.\,]+\s?$/)) { return 'number'; }
70 | if (state.inlinePairs > 0 && stream.match(/^\s*-?[0-9\.\,]+\s?(?=(,|}))/)) { return 'number'; }
71 | /* keywords */
72 | if (stream.match(keywordRegex)) { return 'keyword'; }
73 | }
74 |
75 | /* nothing found, continue */
76 | state.pairStart = false;
77 | state.escaped = (ch == '\\');
78 | stream.next();
79 | return null;
80 | },
81 | startState: function() {
82 | return {
83 | pair: false,
84 | pairStart: false,
85 | keyCol: 0,
86 | inlinePairs: 0,
87 | inlineList: 0,
88 | literal: false,
89 | escaped: false
90 | };
91 | }
92 | };
93 | });
94 |
95 | CodeMirror.defineMIME("text/x-yaml", "yaml");
96 |
--------------------------------------------------------------------------------
/src/flask_debugtoolbar/static/codemirror/mode/htmlmixed/htmlmixed.js:
--------------------------------------------------------------------------------
1 | CodeMirror.defineMode("htmlmixed", function(config, parserConfig) {
2 | var htmlMode = CodeMirror.getMode(config, {name: "xml", htmlMode: true});
3 | var jsMode = CodeMirror.getMode(config, "javascript");
4 | var cssMode = CodeMirror.getMode(config, "css");
5 |
6 | function html(stream, state) {
7 | var style = htmlMode.token(stream, state.htmlState);
8 | if (style == "tag" && stream.current() == ">" && state.htmlState.context) {
9 | if (/^script$/i.test(state.htmlState.context.tagName)) {
10 | state.token = javascript;
11 | state.localState = jsMode.startState(htmlMode.indent(state.htmlState, ""));
12 | state.mode = "javascript";
13 | }
14 | else if (/^style$/i.test(state.htmlState.context.tagName)) {
15 | state.token = css;
16 | state.localState = cssMode.startState(htmlMode.indent(state.htmlState, ""));
17 | state.mode = "css";
18 | }
19 | }
20 | return style;
21 | }
22 | function maybeBackup(stream, pat, style) {
23 | var cur = stream.current();
24 | var close = cur.search(pat);
25 | if (close > -1) stream.backUp(cur.length - close);
26 | return style;
27 | }
28 | function javascript(stream, state) {
29 | if (stream.match(/^<\/\s*script\s*>/i, false)) {
30 | state.token = html;
31 | state.localState = null;
32 | state.mode = "html";
33 | return html(stream, state);
34 | }
35 | return maybeBackup(stream, /<\/\s*script\s*>/,
36 | jsMode.token(stream, state.localState));
37 | }
38 | function css(stream, state) {
39 | if (stream.match(/^<\/\s*style\s*>/i, false)) {
40 | state.token = html;
41 | state.localState = null;
42 | state.mode = "html";
43 | return html(stream, state);
44 | }
45 | return maybeBackup(stream, /<\/\s*style\s*>/,
46 | cssMode.token(stream, state.localState));
47 | }
48 |
49 | return {
50 | startState: function() {
51 | var state = htmlMode.startState();
52 | return {token: html, localState: null, mode: "html", htmlState: state};
53 | },
54 |
55 | copyState: function(state) {
56 | if (state.localState)
57 | var local = CodeMirror.copyState(state.token == css ? cssMode : jsMode, state.localState);
58 | return {token: state.token, localState: local, mode: state.mode,
59 | htmlState: CodeMirror.copyState(htmlMode, state.htmlState)};
60 | },
61 |
62 | token: function(stream, state) {
63 | return state.token(stream, state);
64 | },
65 |
66 | indent: function(state, textAfter) {
67 | if (state.token == html || /^\s*<\//.test(textAfter))
68 | return htmlMode.indent(state.htmlState, textAfter);
69 | else if (state.token == javascript)
70 | return jsMode.indent(state.localState, textAfter);
71 | else
72 | return cssMode.indent(state.localState, textAfter);
73 | },
74 |
75 | compareStates: function(a, b) {
76 | return htmlMode.compareStates(a.htmlState, b.htmlState);
77 | },
78 |
79 | electricChars: "/{}:"
80 | }
81 | });
82 |
83 | CodeMirror.defineMIME("text/html", "htmlmixed");
84 |
--------------------------------------------------------------------------------
/src/flask_debugtoolbar/static/codemirror/util/simple-hint.js:
--------------------------------------------------------------------------------
1 | (function() {
2 | CodeMirror.simpleHint = function(editor, getHints) {
3 | // We want a single cursor position.
4 | if (editor.somethingSelected()) return;
5 | var result = getHints(editor);
6 | if (!result || !result.list.length) return;
7 | var completions = result.list;
8 | function insert(str) {
9 | editor.replaceRange(str, result.from, result.to);
10 | }
11 | // When there is only one completion, use it directly.
12 | if (completions.length == 1) {insert(completions[0]); return true;}
13 |
14 | // Build the select widget
15 | var complete = document.createElement("div");
16 | complete.className = "CodeMirror-completions";
17 | var sel = complete.appendChild(document.createElement("select"));
18 | // Opera doesn't move the selection when pressing up/down in a
19 | // multi-select, but it does properly support the size property on
20 | // single-selects, so no multi-select is necessary.
21 | if (!window.opera) sel.multiple = true;
22 | for (var i = 0; i < completions.length; ++i) {
23 | var opt = sel.appendChild(document.createElement("option"));
24 | opt.appendChild(document.createTextNode(completions[i]));
25 | }
26 | sel.firstChild.selected = true;
27 | sel.size = Math.min(10, completions.length);
28 | var pos = editor.cursorCoords();
29 | complete.style.left = pos.x + "px";
30 | complete.style.top = pos.yBot + "px";
31 | document.body.appendChild(complete);
32 | // If we're at the edge of the screen, then we want the menu to appear on the left of the cursor.
33 | var winW = window.innerWidth || Math.max(document.body.offsetWidth, document.documentElement.offsetWidth);
34 | if(winW - pos.x < sel.clientWidth)
35 | complete.style.left = (pos.x - sel.clientWidth) + "px";
36 | // Hack to hide the scrollbar.
37 | if (completions.length <= 10)
38 | complete.style.width = (sel.clientWidth - 1) + "px";
39 |
40 | var done = false;
41 | function close() {
42 | if (done) return;
43 | done = true;
44 | complete.parentNode.removeChild(complete);
45 | }
46 | function pick() {
47 | insert(completions[sel.selectedIndex]);
48 | close();
49 | setTimeout(function(){editor.focus();}, 50);
50 | }
51 | CodeMirror.connect(sel, "blur", close);
52 | CodeMirror.connect(sel, "keydown", function(event) {
53 | var code = event.keyCode;
54 | // Enter
55 | if (code == 13) {CodeMirror.e_stop(event); pick();}
56 | // Escape
57 | else if (code == 27) {CodeMirror.e_stop(event); close(); editor.focus();}
58 | else if (code != 38 && code != 40) {
59 | close(); editor.focus();
60 | // Pass the event to the CodeMirror instance so that it can handle things like backspace properly.
61 | editor.triggerOnKeyDown(event);
62 | setTimeout(function(){CodeMirror.simpleHint(editor, getHints);}, 50);
63 | }
64 | });
65 | CodeMirror.connect(sel, "dblclick", pick);
66 |
67 | sel.focus();
68 | // Opera sometimes ignores focusing a freshly created node
69 | if (window.opera) setTimeout(function(){if (!done) sel.focus();}, 100);
70 | return true;
71 | };
72 | })();
73 |
--------------------------------------------------------------------------------
/src/flask_debugtoolbar/panels/__init__.py:
--------------------------------------------------------------------------------
1 | from __future__ import annotations
2 |
3 | import collections.abc as c
4 | import typing as t
5 |
6 | from flask import Flask
7 | from jinja2 import Environment
8 | from werkzeug import Request
9 | from werkzeug import Response
10 |
11 |
12 | class DebugPanel:
13 | """Base class for debug panels."""
14 |
15 | name: str
16 |
17 | # If content returns something, set to true in subclass
18 | has_content = False
19 |
20 | # If the client is able to activate/de-activate the panel
21 | user_enable = False
22 |
23 | # We'll maintain a local context instance so we can expose our template
24 | # context variables to panels which need them:
25 | context: dict[str, t.Any] = {}
26 |
27 | # Panel methods
28 | def __init__(
29 | self, jinja_env: Environment, context: dict[str, t.Any] | None = None
30 | ) -> None:
31 | if context is not None:
32 | self.context.update(context)
33 |
34 | self.jinja_env = jinja_env
35 | # If the client enabled the panel
36 | self.is_active = False
37 |
38 | @classmethod
39 | def init_app(cls, app: Flask) -> None:
40 | """Method that can be overridden by child classes.
41 | Can be used for setting up additional URL-rules/routes.
42 |
43 | Example::
44 |
45 | class UMLDiagramPanel(DebugPanel):
46 |
47 | @classmethod
48 | def init_app(cls, app):
49 | app.add_url_rule(
50 | '/_flask_debugtoolbar_umldiagram/',
51 | '_flask_debugtoolbar_umldiagram.serve_generated_image',
52 | cls.serve_generated_image
53 | )
54 |
55 | @classmethod
56 | def serve_generated_image(cls, app):
57 | return Response(...)
58 | """
59 | pass
60 |
61 | def render(self, template_name: str, context: dict[str, t.Any]) -> str:
62 | template = self.jinja_env.get_template(template_name)
63 | return template.render(**context)
64 |
65 | def dom_id(self) -> str:
66 | return f"flDebug{self.name.replace(' ', '')}Panel"
67 |
68 | def nav_title(self) -> str:
69 | """Title showing in toolbar"""
70 | raise NotImplementedError
71 |
72 | def nav_subtitle(self) -> str:
73 | """Subtitle showing until title in toolbar"""
74 | return ""
75 |
76 | def title(self) -> str:
77 | """Title showing in panel"""
78 | raise NotImplementedError
79 |
80 | def url(self) -> str:
81 | raise NotImplementedError
82 |
83 | def content(self) -> str:
84 | raise NotImplementedError
85 |
86 | # Standard middleware methods
87 | def process_request(self, request: Request) -> None:
88 | pass
89 |
90 | def process_view(
91 | self,
92 | request: Request,
93 | view_func: c.Callable[..., t.Any],
94 | view_kwargs: dict[str, t.Any],
95 | ) -> c.Callable[..., t.Any] | None:
96 | pass
97 |
98 | def process_response(self, request: Request, response: Response) -> None:
99 | pass
100 |
--------------------------------------------------------------------------------
/src/flask_debugtoolbar/static/codemirror/mode/velocity/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | CodeMirror: Velocity mode
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
CodeMirror: Velocity mode
14 |
89 |
99 |
100 |
MIME types defined:text/velocity.
101 |
102 |
103 |
104 |
--------------------------------------------------------------------------------
/docs/panels.rst:
--------------------------------------------------------------------------------
1 | Built-In Panels
2 | ===============
3 |
4 | Versions
5 | --------
6 | flask_debugtoolbar.panels.versions.VersionDebugPanel
7 |
8 | Shows the installed Flask version. The expanded view displays all installed packages and their versions as detected by ``setuptools``.
9 |
10 |
11 | Time
12 | ----
13 |
14 | flask_debugtoolbar.panels.timer.TimerDebugPanel
15 |
16 | Shows the time taken to process the current request. The expanded view includes the breakdown of CPU time, by user and system, wall clock time, and context switches.
17 |
18 | .. image:: _static/screenshot-time-panel.png
19 |
20 |
21 | HTTP Headers
22 | ------------
23 |
24 | flask_debugtoolbar.panels.headers.HeaderDebugPanel
25 |
26 | Displays the HTTP headers for the current request.
27 |
28 | .. image:: _static/screenshot-headers-panel.png
29 |
30 |
31 | Request Vars
32 | ------------
33 |
34 | flask_debugtoolbar.panels.request_vars.RequestVarsDebugPanel
35 |
36 | Displays details of the Flask request-related variables, including the view function parameters, cookies, session variables, and GET and POST variables.
37 |
38 | .. image:: _static/screenshot-request-vars-panel.png
39 |
40 |
41 | Config
42 | ------
43 |
44 | flask_debugtoolbar.panels.config_vars.ConfigVarsDebugPanel
45 |
46 | Shows the contents of the Flask application's config dict ``app.config``.
47 |
48 | .. image:: _static/screenshot-config-panel.png
49 |
50 |
51 | Templates
52 | ---------
53 |
54 | flask_debugtoolbar.panels.template.TemplateDebugPanel
55 |
56 | Shows information about the templates rendered for this request, and the value of the template parameters provided.
57 |
58 | .. image:: _static/screenshot-template-panel.png
59 |
60 |
61 | SQLAlchemy
62 | ----------
63 |
64 | flask_debugtoolbar.panels.sqlalchemy.SQLAlchemyDebugPanel
65 |
66 | Shows SQL queries run during the current request.
67 |
68 | .. note:: This panel requires using the `Flask-SQLAlchemy`_ extension in order
69 | to record the queries. See the Flask-SQLAlchemy
70 | :ref:`flasksqlalchemy:quickstart` section to configure it.
71 |
72 | For additional details on query recording see the
73 | :py:func:`~flask_sqlalchemy.get_debug_queries` documentation.
74 |
75 | .. note:: SQL syntax highlighting requires `Pygments`_ to be installed.
76 |
77 | .. image:: _static/screenshot-sqlalchemy-panel.png
78 |
79 | .. _Flask-SQLAlchemy: https://flask-sqlalchemy.palletsprojects.com/
80 |
81 | .. _Pygments: https://pygments.org/
82 |
83 |
84 | Logging
85 | -------
86 |
87 | flask_debugtoolbar.panels.logger.LoggingPanel
88 |
89 | Displays log messages recorded during the current request.
90 |
91 | .. image:: _static/screenshot-logger-panel.png
92 |
93 |
94 | Route List
95 | ----------
96 |
97 | flask_debugtoolbar.panels.route_list.RouteListDebugPanel
98 |
99 |
100 | Displays the Flask URL routing rules.
101 |
102 |
103 | Profiler
104 | --------
105 |
106 | flask_debugtoolbar.panels.profiler.ProfilerDebugPanel
107 |
108 | Reports profiling data for the current request. Due to the performance overhead, profiling is disabled by default. Click the checkmark to toggle profiling on or off. After enabling the profiler, refresh the page to re-run it with profiling.
109 |
110 | .. image:: _static/screenshot-profiler-panel.png
111 |
--------------------------------------------------------------------------------
/src/flask_debugtoolbar/static/codemirror/mode/python/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | CodeMirror: Python mode
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
CodeMirror: Python mode
13 |
14 |
103 |
114 |
Configuration Options:
115 |
116 |
version - 2/3 - The version of Python to recognize. Default is 2.
117 |
singleLineStringErrors - true/false - If you have a single-line string that is not terminated at the end of the line, this will show subsequent lines as errors if true, otherwise it will consider the newline as the end of the string. Default is false.
Simple mode that tries to handle C-like languages as well as it
91 | can. Takes two configuration parameters: keywords, an
92 | object whose property names are the keywords in the language,
93 | and useCPP, which determines whether C preprocessor
94 | directives are recognized.