pyramid-debugtoolbar-api-sqlalchemy 0.3.0__tar.gz → 1.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. pyramid_debugtoolbar_api_sqlalchemy-1.0.0/CHANGES.txt +47 -0
  2. pyramid_debugtoolbar_api_sqlalchemy-1.0.0/LICENSE +22 -0
  3. pyramid_debugtoolbar_api_sqlalchemy-1.0.0/MANIFEST.in +10 -0
  4. pyramid_debugtoolbar_api_sqlalchemy-1.0.0/PKG-INFO +112 -0
  5. pyramid_debugtoolbar_api_sqlalchemy-1.0.0/TODO.txt +0 -0
  6. pyramid_debugtoolbar_api_sqlalchemy-1.0.0/pyproject.toml +7 -0
  7. pyramid_debugtoolbar_api_sqlalchemy-1.0.0/setup.cfg +68 -0
  8. {pyramid_debugtoolbar_api_sqlalchemy-0.3.0 → pyramid_debugtoolbar_api_sqlalchemy-1.0.0/src}/pyramid_debugtoolbar_api_sqlalchemy/__init__.py +4 -5
  9. pyramid_debugtoolbar_api_sqlalchemy-1.0.0/src/pyramid_debugtoolbar_api_sqlalchemy/_version.py +3 -0
  10. pyramid_debugtoolbar_api_sqlalchemy-1.0.0/src/pyramid_debugtoolbar_api_sqlalchemy/spreadsheet_utils.py +14 -0
  11. pyramid_debugtoolbar_api_sqlalchemy-1.0.0/src/pyramid_debugtoolbar_api_sqlalchemy/views.py +60 -0
  12. pyramid_debugtoolbar_api_sqlalchemy-1.0.0/src/pyramid_debugtoolbar_api_sqlalchemy.egg-info/PKG-INFO +112 -0
  13. pyramid_debugtoolbar_api_sqlalchemy-1.0.0/src/pyramid_debugtoolbar_api_sqlalchemy.egg-info/SOURCES.txt +22 -0
  14. pyramid_debugtoolbar_api_sqlalchemy-1.0.0/src/pyramid_debugtoolbar_api_sqlalchemy.egg-info/requires.txt +11 -0
  15. pyramid_debugtoolbar_api_sqlalchemy-1.0.0/tests/__init__.py +0 -0
  16. pyramid_debugtoolbar_api_sqlalchemy-1.0.0/tests/test_config.py +197 -0
  17. pyramid_debugtoolbar_api_sqlalchemy-0.3.0/MANIFEST.in +0 -2
  18. pyramid_debugtoolbar_api_sqlalchemy-0.3.0/PKG-INFO +0 -93
  19. pyramid_debugtoolbar_api_sqlalchemy-0.3.0/pyproject.toml +0 -3
  20. pyramid_debugtoolbar_api_sqlalchemy-0.3.0/pyramid_debugtoolbar_api_sqlalchemy/views.py +0 -65
  21. pyramid_debugtoolbar_api_sqlalchemy-0.3.0/pyramid_debugtoolbar_api_sqlalchemy.egg-info/PKG-INFO +0 -93
  22. pyramid_debugtoolbar_api_sqlalchemy-0.3.0/pyramid_debugtoolbar_api_sqlalchemy.egg-info/SOURCES.txt +0 -16
  23. pyramid_debugtoolbar_api_sqlalchemy-0.3.0/pyramid_debugtoolbar_api_sqlalchemy.egg-info/requires.txt +0 -7
  24. pyramid_debugtoolbar_api_sqlalchemy-0.3.0/setup.cfg +0 -7
  25. pyramid_debugtoolbar_api_sqlalchemy-0.3.0/setup.py +0 -58
  26. {pyramid_debugtoolbar_api_sqlalchemy-0.3.0 → pyramid_debugtoolbar_api_sqlalchemy-1.0.0}/README.rst +0 -0
  27. {pyramid_debugtoolbar_api_sqlalchemy-0.3.0 → pyramid_debugtoolbar_api_sqlalchemy-1.0.0/src}/pyramid_debugtoolbar_api_sqlalchemy/panels.py +0 -0
  28. {pyramid_debugtoolbar_api_sqlalchemy-0.3.0 → pyramid_debugtoolbar_api_sqlalchemy-1.0.0/src}/pyramid_debugtoolbar_api_sqlalchemy/templates/sqlalchemy_csv.dbtmako +0 -0
  29. {pyramid_debugtoolbar_api_sqlalchemy-0.3.0 → pyramid_debugtoolbar_api_sqlalchemy-1.0.0/src}/pyramid_debugtoolbar_api_sqlalchemy/utils.py +0 -0
  30. {pyramid_debugtoolbar_api_sqlalchemy-0.3.0 → pyramid_debugtoolbar_api_sqlalchemy-1.0.0/src}/pyramid_debugtoolbar_api_sqlalchemy.egg-info/dependency_links.txt +0 -0
  31. {pyramid_debugtoolbar_api_sqlalchemy-0.3.0 → pyramid_debugtoolbar_api_sqlalchemy-1.0.0/src}/pyramid_debugtoolbar_api_sqlalchemy.egg-info/not-zip-safe +0 -0
  32. {pyramid_debugtoolbar_api_sqlalchemy-0.3.0 → pyramid_debugtoolbar_api_sqlalchemy-1.0.0/src}/pyramid_debugtoolbar_api_sqlalchemy.egg-info/top_level.txt +0 -0
@@ -0,0 +1,47 @@
1
+ v1.0.0
2
+ * Add a spreadsheet=1 CSV option that prefixes formula-like text fields.
3
+ * Harden CSV download headers and preserve Unicode SQL in Python 3 exports.
4
+ * Consolidate packaging and tox settings and extend CI through Python 3.15.
5
+ * add tests/__init__.py
6
+
7
+ v0.3.1
8
+ * packaging
9
+
10
+ v0.3.0
11
+ * updated debugtoolbar includes
12
+ * improved tests
13
+ * black & upgraded black; 20.8b1
14
+ * integrated with pre-commit
15
+ * tox and tests
16
+ * migrated README to rst
17
+
18
+
19
+ v0.2.1 | 2019.05.01
20
+ includeme registers the panel via the api method `config.add_debugtoolbar_panel()`
21
+
22
+ v0.2.0 | 2019.04.29
23
+ * python3 support
24
+
25
+ v0.1.2 | 2017.12.06
26
+ * ported a functionality to current debugtoolbar api
27
+ * store version as __VERSION__ in /__init__.py
28
+
29
+ v0.1.1 | 2017.05.10
30
+ * changes after making a performance version of this panel
31
+ * renamed the route
32
+ * making data visible to the template
33
+ * packaging fix, the templates weren't distributing
34
+
35
+ v0.1.0 | 2017.05.10
36
+ * this works off the new pyramid_debutoolbar>=4.0 api. no longer a dirty hack!
37
+ * please use `debugtoolbar.includes`
38
+ * changed the url for queries
39
+ * renamed to pyramid_debugtoolbar_api_sqlalchemy
40
+
41
+ v0.0.2 | 2014.12.16
42
+ * fixed namings to `pyramid_debugtoolbar_api_sqla`
43
+
44
+ v0.0.1 | 2014.12.16
45
+ * initial import
46
+
47
+
@@ -0,0 +1,22 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2014 jvanasco
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 all
13
+ 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 THE
21
+ SOFTWARE.
22
+
@@ -0,0 +1,10 @@
1
+ graft src
2
+ graft tests
3
+
4
+ include setup.cfg pyproject.toml
5
+ include CHANGES.txt
6
+ include LICENSE
7
+ include README.rst
8
+ include TODO.txt
9
+
10
+ recursive-exclude * __pycache__ *.py[cod] .DS_Store
@@ -0,0 +1,112 @@
1
+ Metadata-Version: 2.4
2
+ Name: pyramid_debugtoolbar_api_sqlalchemy
3
+ Version: 1.0.0
4
+ Summary: SQLAlchemy CSV exporting for pyramid_debugtoolbar
5
+ Home-page: https://github.com/jvanasco/pyramid_debugtoolbar_api_sqlalchemy
6
+ Author: Jonathan Vanasco
7
+ Author-email: jvanasco@2xlp.com
8
+ License: MIT
9
+ Keywords: web,pyramid,sqlalchemy
10
+ Classifier: Intended Audience :: Developers
11
+ Classifier: Framework :: Pyramid
12
+ Classifier: Programming Language :: Python
13
+ Classifier: Programming Language :: Python :: 2.7
14
+ Classifier: Programming Language :: Python :: 3.5
15
+ Classifier: Programming Language :: Python :: 3.6
16
+ Classifier: Programming Language :: Python :: 3.7
17
+ Classifier: Programming Language :: Python :: 3.8
18
+ Classifier: Programming Language :: Python :: 3.9
19
+ Classifier: Programming Language :: Python :: 3.10
20
+ Classifier: Programming Language :: Python :: 3.11
21
+ Classifier: Programming Language :: Python :: 3.12
22
+ Classifier: Programming Language :: Python :: 3.13
23
+ Classifier: Programming Language :: Python :: 3.14
24
+ Classifier: Programming Language :: Python :: 3.15
25
+ Requires-Python: !=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7
26
+ Description-Content-Type: text/x-rst
27
+ License-File: LICENSE
28
+ Requires-Dist: pyramid
29
+ Requires-Dist: pyramid_debugtoolbar>=4.0
30
+ Requires-Dist: six
31
+ Requires-Dist: sqlalchemy
32
+ Requires-Dist: setuptools<82; python_version >= "3.7" and python_version < "3.10"
33
+ Provides-Extra: testing
34
+ Requires-Dist: coverage; extra == "testing"
35
+ Requires-Dist: pytest; extra == "testing"
36
+ Dynamic: license-file
37
+
38
+ pyramid_debugtoolbar_api_sqlalchemy
39
+ ===================================
40
+
41
+ .. image:: https://github.com/jvanasco/pyramid_debugtoolbar_api_sqlalchemy/workflows/Python%20package/badge.svg
42
+ :alt: Build Status
43
+
44
+ `pyramid_debugtoolbar_api_sqlalchemy` extends the existing `pyramid_debugtoolbar`
45
+ SQLAlchemy Panel to support downloadable CSV files of profiling data.
46
+
47
+ This package does not replace the default panel, and requires it to be active.
48
+
49
+ This package is designed for application profile and to be a useful part of test
50
+ suites, allowing developers to run a series of tests and log the SQLAlchemy
51
+ performance.
52
+
53
+ If you are using the debugtoolbar directly:
54
+
55
+ * If SQLAlchemy queries exist on the request, a "SQLAlchemy CSV" tab will appear.
56
+ That will prompt you for queries.
57
+
58
+ If you are scripting:
59
+
60
+ * The urls are generated in a machine-friendly format, so you can regex the
61
+ `request_id` off a page and pull it from the API. this is explained below:
62
+
63
+
64
+ NOTES:
65
+ ======
66
+
67
+ This packages requires pyramid_debugtoolbar 4.0 or newer
68
+
69
+
70
+ How to use this package
71
+ =======================
72
+
73
+
74
+ Update your ENVIRONMENT.ini file
75
+
76
+ .. code-block:: python
77
+
78
+ debugtoolbar.includes = pyramid_debugtoolbar_api_sqlalchemy
79
+
80
+ You MUST be using `pyramid_debugtoolbar` with the SQLAlchemy panel enabled.
81
+ This just piggybacks on the existing module's work to log queries.
82
+
83
+ You MUST use `debugtoolbar.includes`. This will not work properly via `pyramid.includes`
84
+
85
+ You can access a csv of the SQLAlchemy report via the following url hack:
86
+
87
+ .. code-block:: python
88
+
89
+ url_html = '/_debug_toolbar/{request_id}'
90
+ url_api = '/_debug_toolbar/api-sqlalchemy/sqlalchemy-{request_id}.csv'
91
+
92
+ The file will be downloaded and offer a content-disposition as:
93
+
94
+ sqlalchemy-{request_id}.csv
95
+
96
+ The CSV columns are:
97
+
98
+ * execution timing
99
+ * SQLAlchemy query
100
+ * query params (json encoded)
101
+
102
+
103
+ Configuration
104
+ =======================
105
+
106
+ By default, this package writes CSV files using "UTF-8" encoding.
107
+
108
+ To change this, use the environment variable `pyramid_debugtoolbar_api_sqlalchemy_encoding`
109
+
110
+ .. code-block:: shell
111
+
112
+ export pyramid_debugtoolbar_api_sqlalchemy_encoding=ascii
File without changes
@@ -0,0 +1,7 @@
1
+ [build-system]
2
+ requires = ["setuptools>=40.8", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [tool.black]
6
+ target-version = ['py35']
7
+
@@ -0,0 +1,68 @@
1
+ [metadata]
2
+ name = pyramid_debugtoolbar_api_sqlalchemy
3
+ version = attr: pyramid_debugtoolbar_api_sqlalchemy._version.__VERSION__
4
+ description = SQLAlchemy CSV exporting for pyramid_debugtoolbar
5
+ long_description = file: README.rst
6
+ long_description_content_type = text/x-rst
7
+ author = Jonathan Vanasco
8
+ author_email = jvanasco@2xlp.com
9
+ url = https://github.com/jvanasco/pyramid_debugtoolbar_api_sqlalchemy
10
+ keywords = web, pyramid, sqlalchemy
11
+ license = MIT
12
+ license_file = LICENSE
13
+ classifiers =
14
+ Intended Audience :: Developers
15
+ Framework :: Pyramid
16
+ Programming Language :: Python
17
+ Programming Language :: Python :: 2.7
18
+ Programming Language :: Python :: 3.5
19
+ Programming Language :: Python :: 3.6
20
+ Programming Language :: Python :: 3.7
21
+ Programming Language :: Python :: 3.8
22
+ Programming Language :: Python :: 3.9
23
+ Programming Language :: Python :: 3.10
24
+ Programming Language :: Python :: 3.11
25
+ Programming Language :: Python :: 3.12
26
+ Programming Language :: Python :: 3.13
27
+ Programming Language :: Python :: 3.14
28
+ Programming Language :: Python :: 3.15
29
+
30
+ [options]
31
+ packages = find:
32
+ package_dir =
33
+ = src
34
+ include_package_data = False
35
+ zip_safe = False
36
+ python_requires = >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*
37
+ install_requires =
38
+ pyramid
39
+ pyramid_debugtoolbar>=4.0
40
+ six
41
+ sqlalchemy
42
+ setuptools<82; python_version >= "3.7" and python_version < "3.10"
43
+
44
+ [options.packages.find]
45
+ where = src
46
+
47
+ [options.package_data]
48
+ pyramid_debugtoolbar_api_sqlalchemy = templates/*.dbtmako
49
+
50
+ [options.extras_require]
51
+ testing =
52
+ coverage
53
+ pytest
54
+
55
+ [tox:tox]
56
+ envlist = py27, py35, py36, py37, py38, py39, py310, py311, py312, py313, py314, py315
57
+
58
+ [testenv]
59
+ extras = testing
60
+ commands =
61
+ python --version
62
+ python -m coverage run --source=pyramid_debugtoolbar_api_sqlalchemy -m pytest {posargs:}
63
+ python -m coverage html -d {envtmpdir}/coverage
64
+
65
+ [egg_info]
66
+ tag_build =
67
+ tag_date = 0
68
+
@@ -1,8 +1,4 @@
1
- # local
2
- from .panels import SqlalchemyCsvDebugPanel
3
-
4
-
5
- __VERSION__ = "0.3.0"
1
+ from ._version import __VERSION__
6
2
 
7
3
 
8
4
  # ==============================================================================
@@ -16,6 +12,9 @@ def includeme(config):
16
12
 
17
13
  debugtoolbar.includes = pyramid_debugtoolbar_api_sqlalchemy
18
14
  """
15
+ # Legacy setuptools imports this package to discover the version.
16
+ from .panels import SqlalchemyCsvDebugPanel
17
+
19
18
  config.add_debugtoolbar_panel(SqlalchemyCsvDebugPanel)
20
19
  config.add_route(
21
20
  "debugtoolbar.api_sqlalchemy.queries.csv",
@@ -0,0 +1,3 @@
1
+ """Package version shared by runtime and build metadata."""
2
+
3
+ __VERSION__ = "1.0.0"
@@ -0,0 +1,14 @@
1
+ """Helpers for exporting text fields to spreadsheet CSV files."""
2
+
3
+ from six import text_type
4
+
5
+
6
+ def sanitize_spreadsheet_cell(value):
7
+ # type: (text_type) -> text_type
8
+ """Prefix formula-like text with a spreadsheet text marker."""
9
+ stripped = value.lstrip()
10
+ if value.startswith((u"\t", u"\r", u"\n")) or stripped.startswith(
11
+ (u"=", u"+", u"-", u"@", u"\uff1d", u"\uff0b", u"\uff0d", u"\uff20")
12
+ ):
13
+ return u"'" + value
14
+ return value
@@ -0,0 +1,60 @@
1
+ import csv
2
+ import os
3
+ import re
4
+
5
+ from pyramid.exceptions import NotFound
6
+ from pyramid.request import Request
7
+ from pyramid.response import Response
8
+ from pyramid.view import view_config
9
+ from six import PY2, StringIO, binary_type, text_type
10
+
11
+ from .spreadsheet_utils import sanitize_spreadsheet_cell
12
+ from .utils import get_sqlalchemy_panel
13
+
14
+
15
+ ENCODING = os.environ.get("pyramid_debugtoolbar_api_sqlalchemy_encoding", "utf-8")
16
+
17
+
18
+ @view_config(route_name="debugtoolbar.api_sqlalchemy.queries.csv")
19
+ def queries_api_csv(request):
20
+ # type: (Request) -> Response
21
+ """Export the recorded SQL queries for the requested toolbar entry."""
22
+ request_id = request.matchdict["request_id"]
23
+ toolbar = request.pdtb_history.get(request_id, None)
24
+ if toolbar is None:
25
+ raise NotFound
26
+
27
+ panel = get_sqlalchemy_panel(toolbar.panels)
28
+ if panel is None:
29
+ raise NotFound
30
+
31
+ spreadsheet = request.GET.get("spreadsheet") == "1"
32
+ csvfile = StringIO()
33
+ writer = csv.writer(csvfile)
34
+ for query in panel.data.get("queries", ()):
35
+ sql = query["raw_sql"]
36
+ parameters = query["parameters"]
37
+ if spreadsheet:
38
+ sql = sanitize_spreadsheet_cell(sql)
39
+ if parameters is not None:
40
+ if isinstance(parameters, binary_type):
41
+ parameters = parameters.decode(ENCODING, "replace")
42
+ else:
43
+ parameters = text_type(parameters)
44
+ parameters = sanitize_spreadsheet_cell(parameters)
45
+ if PY2:
46
+ parameters = parameters.encode(ENCODING)
47
+ if PY2:
48
+ sql = sql.encode(ENCODING)
49
+ writer.writerow((query["duration"], sql, parameters))
50
+
51
+ response = Response(
52
+ content_type="text/csv", body=csvfile.getvalue(), charset=ENCODING
53
+ )
54
+ safe_id = re.sub(r"[^a-zA-Z0-9_-]", "_", request_id)
55
+ suffix = "-spreadsheet" if spreadsheet else ""
56
+ response.headers["Content-Disposition"] = str(
57
+ 'attachment; filename="sqlalchemy-%s%s.csv"' % (safe_id, suffix)
58
+ )
59
+ response.cache_control.no_store = True
60
+ return response
@@ -0,0 +1,112 @@
1
+ Metadata-Version: 2.4
2
+ Name: pyramid_debugtoolbar_api_sqlalchemy
3
+ Version: 1.0.0
4
+ Summary: SQLAlchemy CSV exporting for pyramid_debugtoolbar
5
+ Home-page: https://github.com/jvanasco/pyramid_debugtoolbar_api_sqlalchemy
6
+ Author: Jonathan Vanasco
7
+ Author-email: jvanasco@2xlp.com
8
+ License: MIT
9
+ Keywords: web,pyramid,sqlalchemy
10
+ Classifier: Intended Audience :: Developers
11
+ Classifier: Framework :: Pyramid
12
+ Classifier: Programming Language :: Python
13
+ Classifier: Programming Language :: Python :: 2.7
14
+ Classifier: Programming Language :: Python :: 3.5
15
+ Classifier: Programming Language :: Python :: 3.6
16
+ Classifier: Programming Language :: Python :: 3.7
17
+ Classifier: Programming Language :: Python :: 3.8
18
+ Classifier: Programming Language :: Python :: 3.9
19
+ Classifier: Programming Language :: Python :: 3.10
20
+ Classifier: Programming Language :: Python :: 3.11
21
+ Classifier: Programming Language :: Python :: 3.12
22
+ Classifier: Programming Language :: Python :: 3.13
23
+ Classifier: Programming Language :: Python :: 3.14
24
+ Classifier: Programming Language :: Python :: 3.15
25
+ Requires-Python: !=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7
26
+ Description-Content-Type: text/x-rst
27
+ License-File: LICENSE
28
+ Requires-Dist: pyramid
29
+ Requires-Dist: pyramid_debugtoolbar>=4.0
30
+ Requires-Dist: six
31
+ Requires-Dist: sqlalchemy
32
+ Requires-Dist: setuptools<82; python_version >= "3.7" and python_version < "3.10"
33
+ Provides-Extra: testing
34
+ Requires-Dist: coverage; extra == "testing"
35
+ Requires-Dist: pytest; extra == "testing"
36
+ Dynamic: license-file
37
+
38
+ pyramid_debugtoolbar_api_sqlalchemy
39
+ ===================================
40
+
41
+ .. image:: https://github.com/jvanasco/pyramid_debugtoolbar_api_sqlalchemy/workflows/Python%20package/badge.svg
42
+ :alt: Build Status
43
+
44
+ `pyramid_debugtoolbar_api_sqlalchemy` extends the existing `pyramid_debugtoolbar`
45
+ SQLAlchemy Panel to support downloadable CSV files of profiling data.
46
+
47
+ This package does not replace the default panel, and requires it to be active.
48
+
49
+ This package is designed for application profile and to be a useful part of test
50
+ suites, allowing developers to run a series of tests and log the SQLAlchemy
51
+ performance.
52
+
53
+ If you are using the debugtoolbar directly:
54
+
55
+ * If SQLAlchemy queries exist on the request, a "SQLAlchemy CSV" tab will appear.
56
+ That will prompt you for queries.
57
+
58
+ If you are scripting:
59
+
60
+ * The urls are generated in a machine-friendly format, so you can regex the
61
+ `request_id` off a page and pull it from the API. this is explained below:
62
+
63
+
64
+ NOTES:
65
+ ======
66
+
67
+ This packages requires pyramid_debugtoolbar 4.0 or newer
68
+
69
+
70
+ How to use this package
71
+ =======================
72
+
73
+
74
+ Update your ENVIRONMENT.ini file
75
+
76
+ .. code-block:: python
77
+
78
+ debugtoolbar.includes = pyramid_debugtoolbar_api_sqlalchemy
79
+
80
+ You MUST be using `pyramid_debugtoolbar` with the SQLAlchemy panel enabled.
81
+ This just piggybacks on the existing module's work to log queries.
82
+
83
+ You MUST use `debugtoolbar.includes`. This will not work properly via `pyramid.includes`
84
+
85
+ You can access a csv of the SQLAlchemy report via the following url hack:
86
+
87
+ .. code-block:: python
88
+
89
+ url_html = '/_debug_toolbar/{request_id}'
90
+ url_api = '/_debug_toolbar/api-sqlalchemy/sqlalchemy-{request_id}.csv'
91
+
92
+ The file will be downloaded and offer a content-disposition as:
93
+
94
+ sqlalchemy-{request_id}.csv
95
+
96
+ The CSV columns are:
97
+
98
+ * execution timing
99
+ * SQLAlchemy query
100
+ * query params (json encoded)
101
+
102
+
103
+ Configuration
104
+ =======================
105
+
106
+ By default, this package writes CSV files using "UTF-8" encoding.
107
+
108
+ To change this, use the environment variable `pyramid_debugtoolbar_api_sqlalchemy_encoding`
109
+
110
+ .. code-block:: shell
111
+
112
+ export pyramid_debugtoolbar_api_sqlalchemy_encoding=ascii
@@ -0,0 +1,22 @@
1
+ CHANGES.txt
2
+ LICENSE
3
+ MANIFEST.in
4
+ README.rst
5
+ TODO.txt
6
+ pyproject.toml
7
+ setup.cfg
8
+ src/pyramid_debugtoolbar_api_sqlalchemy/__init__.py
9
+ src/pyramid_debugtoolbar_api_sqlalchemy/_version.py
10
+ src/pyramid_debugtoolbar_api_sqlalchemy/panels.py
11
+ src/pyramid_debugtoolbar_api_sqlalchemy/spreadsheet_utils.py
12
+ src/pyramid_debugtoolbar_api_sqlalchemy/utils.py
13
+ src/pyramid_debugtoolbar_api_sqlalchemy/views.py
14
+ src/pyramid_debugtoolbar_api_sqlalchemy.egg-info/PKG-INFO
15
+ src/pyramid_debugtoolbar_api_sqlalchemy.egg-info/SOURCES.txt
16
+ src/pyramid_debugtoolbar_api_sqlalchemy.egg-info/dependency_links.txt
17
+ src/pyramid_debugtoolbar_api_sqlalchemy.egg-info/not-zip-safe
18
+ src/pyramid_debugtoolbar_api_sqlalchemy.egg-info/requires.txt
19
+ src/pyramid_debugtoolbar_api_sqlalchemy.egg-info/top_level.txt
20
+ src/pyramid_debugtoolbar_api_sqlalchemy/templates/sqlalchemy_csv.dbtmako
21
+ tests/__init__.py
22
+ tests/test_config.py
@@ -0,0 +1,11 @@
1
+ pyramid
2
+ pyramid_debugtoolbar>=4.0
3
+ six
4
+ sqlalchemy
5
+
6
+ [:python_version >= "3.7" and python_version < "3.10"]
7
+ setuptools<82
8
+
9
+ [testing]
10
+ coverage
11
+ pytest
@@ -0,0 +1,197 @@
1
+ # coding=utf-8
2
+ from __future__ import print_function
3
+ from __future__ import unicode_literals
4
+
5
+ # stdlib
6
+ import re
7
+ import unittest
8
+
9
+ # pyramid testing requirements
10
+ from pyramid import testing
11
+ from pyramid.exceptions import ConfigurationError
12
+ from pyramid.response import Response
13
+ from pyramid.request import Request
14
+
15
+ import sqlalchemy
16
+
17
+
18
+ # ------------------------------------------------------------------------------
19
+
20
+
21
+ # used to ensure the toolbar link is injected into requests
22
+ re_toolbar_link = re.compile(r'(?:href="http://localhost)(/_debug_toolbar/[\d]+)"')
23
+ re_csv_link = re.compile(
24
+ r'href="(/_debug_toolbar/api-sqlalchemy/sqlalchemy-([\d]+).csv)"'
25
+ )
26
+
27
+
28
+ class TestDebugtoolbarPanel_NoSqlAlchemy(unittest.TestCase):
29
+ def setUp(self):
30
+ def view_no_sqlalchemy(request):
31
+ return Response(
32
+ "<html><head></head><body>OK</body></html>", content_type="text/html"
33
+ )
34
+
35
+ self.config = config = testing.setUp()
36
+ config.add_settings(
37
+ {"debugtoolbar.includes": ["pyramid_debugtoolbar_api_sqlalchemy"]}
38
+ )
39
+ config.include("pyramid_debugtoolbar")
40
+ self.settings = config.registry.settings
41
+
42
+ config.add_view(view_no_sqlalchemy)
43
+
44
+ def tearDown(self):
45
+ testing.tearDown()
46
+
47
+ def test_panel_injected(self):
48
+
49
+ # make the app
50
+ app = self.config.make_wsgi_app()
51
+ # make a request
52
+ req1 = Request.blank("/")
53
+ req1.remote_addr = "127.0.0.1"
54
+ resp1 = req1.get_response(app)
55
+ self.assertEqual(resp1.status_code, 200)
56
+ self.assertIn("http://localhost/_debug_toolbar/", resp1.text)
57
+
58
+ # check the toolbar
59
+ links = re_toolbar_link.findall(resp1.text)
60
+ self.assertIsNotNone(links)
61
+ self.assertIsInstance(links, list)
62
+ self.assertEqual(len(links), 1)
63
+ toolbar_link = links[0]
64
+
65
+ req2 = Request.blank(toolbar_link)
66
+ req2.remote_addr = "127.0.0.1"
67
+ resp2 = req2.get_response(app)
68
+ self.assertEqual(resp2.status_code, 200)
69
+
70
+ self.assertIn(
71
+ '<li class="disabled" id="pDebugPanel-sqlalchemy-csv">', resp2.text
72
+ )
73
+ self.assertNotIn(
74
+ '<div id="pDebugPanel-sqlalchemy-csv-content"',
75
+ resp2.text,
76
+ )
77
+
78
+
79
+ class TestDebugtoolbarPanel_HasSqlAlchemy(unittest.TestCase):
80
+ def setUp(self):
81
+ def view_has_sqlalchemy(request):
82
+
83
+ engine = sqlalchemy.create_engine("sqlite://")
84
+ conn = engine.connect()
85
+ result = conn.execute(sqlalchemy.sql.text("-- CSV marker\nSELECT NULL;"))
86
+ # toss in another select statement with a unicode party hat
87
+ result = conn.execute(sqlalchemy.sql.text("SELECT NULL; -- 🎉"))
88
+ # make sure we encode bindparams correctly
89
+ stmt = sqlalchemy.sql.text(
90
+ "SELECT NULL = :party_hat or :int or :float or :text or :bool;"
91
+ )
92
+ stmt = stmt.bindparams(
93
+ party_hat="🎉",
94
+ int=1,
95
+ float=1.0,
96
+ text="text",
97
+ bool=False,
98
+ )
99
+ result = conn.execute(stmt)
100
+ return Response(
101
+ "<html><head></head><body>OK</body></html>", content_type="text/html"
102
+ )
103
+
104
+ self.config = config = testing.setUp()
105
+ config.add_settings(
106
+ {"debugtoolbar.includes": ["pyramid_debugtoolbar_api_sqlalchemy"]}
107
+ )
108
+ config.include("pyramid_debugtoolbar")
109
+ self.settings = config.registry.settings
110
+
111
+ config.add_view(view_has_sqlalchemy)
112
+ config.add_notfound_view(lambda request: Response(status=404))
113
+
114
+ def tearDown(self):
115
+ testing.tearDown()
116
+
117
+ def test_panel_injected(self):
118
+
119
+ # make the app
120
+ app = self.config.make_wsgi_app()
121
+ # make a request
122
+ req1 = Request.blank("/")
123
+ req1.remote_addr = "127.0.0.1"
124
+ resp1 = req1.get_response(app)
125
+ self.assertEqual(resp1.status_code, 200)
126
+ self.assertIn("http://localhost/_debug_toolbar/", resp1.text)
127
+
128
+ # check the toolbar
129
+ links = re_toolbar_link.findall(resp1.text)
130
+ self.assertIsNotNone(links)
131
+ self.assertIsInstance(links, list)
132
+ self.assertEqual(len(links), 1)
133
+ toolbar_link = links[0]
134
+
135
+ req2 = Request.blank(toolbar_link)
136
+ req2.remote_addr = "127.0.0.1"
137
+ resp2 = req2.get_response(app)
138
+ self.assertEqual(resp2.status_code, 200)
139
+ self.assertIn('<li class="" id="pDebugPanel-sqlalchemy-csv">', resp2.text)
140
+ self.assertIn(
141
+ '<div id="pDebugPanel-sqlalchemy-csv-content"',
142
+ resp2.text,
143
+ )
144
+ self.assertIn(
145
+ "SqlAclhemy queries are available for this request as a CSV via the link below:",
146
+ resp2.text,
147
+ )
148
+
149
+ # csv
150
+ match = re_csv_link.search(resp2.text)
151
+ self.assertTrue(match)
152
+ (_csv_link, _id) = match.groups()
153
+ req3 = Request.blank(_csv_link)
154
+ req3.remote_addr = "127.0.0.1"
155
+ resp3 = req3.get_response(app)
156
+ self.assertEqual(resp3.status_code, 200)
157
+ self.assertIn("SELECT NULL;", resp3.text)
158
+ self.assertIn("SELECT NULL; -- 🎉", resp3.text)
159
+ self.assertEqual(
160
+ resp3.headers["Content-Disposition"],
161
+ 'attachment; filename="sqlalchemy-%s.csv"' % _id,
162
+ )
163
+ self.assertTrue(resp3.cache_control.no_store)
164
+ spreadsheet = Request.blank(_csv_link + "?spreadsheet=1")
165
+ spreadsheet.remote_addr = "127.0.0.1"
166
+ exported = spreadsheet.get_response(app)
167
+ self.assertEqual(exported.status_code, 200)
168
+ self.assertTrue(exported.cache_control.no_store)
169
+ self.assertIn("-spreadsheet.csv", exported.headers["Content-Disposition"])
170
+ self.assertIn(',"-- CSV marker', resp3.text)
171
+ self.assertIn(",\"'-- CSV marker", exported.text)
172
+ self.assertIn("SELECT NULL; -- 🎉", exported.text)
173
+
174
+ denied = Request.blank(_csv_link)
175
+ denied.remote_addr = "192.0.2.1"
176
+ self.assertEqual(denied.get_response(app).status_code, 404)
177
+
178
+ def test_csv_missing_history(self):
179
+ # type: () -> None
180
+ """Return 404 for a request absent from toolbar history."""
181
+ app = self.config.make_wsgi_app()
182
+ request = Request.blank("/_debug_toolbar/api-sqlalchemy/sqlalchemy-missing.csv")
183
+ request.remote_addr = "127.0.0.1"
184
+ self.assertEqual(request.get_response(app).status_code, 404)
185
+
186
+
187
+ class TestSpreadsheetCell(unittest.TestCase):
188
+ def test_formula_like_text(self):
189
+ """Prefix formula-like text while preserving ordinary SQL."""
190
+ from pyramid_debugtoolbar_api_sqlalchemy.spreadsheet_utils import (
191
+ sanitize_spreadsheet_cell,
192
+ )
193
+
194
+ for value in ("=1", " +1", "-1", "@x", "\ttext", "\rtext", "\ntext", "\uff1d1"):
195
+ self.assertEqual(sanitize_spreadsheet_cell(value), "'" + value)
196
+ for value in ("", "SELECT 1", 'SELECT "a,b"'):
197
+ self.assertEqual(sanitize_spreadsheet_cell(value), value)
@@ -1,2 +0,0 @@
1
- include README.md
2
- include pyramid_debugtoolbar_api_sqlalchemy/templates/*
@@ -1,93 +0,0 @@
1
- Metadata-Version: 2.1
2
- Name: pyramid_debugtoolbar_api_sqlalchemy
3
- Version: 0.3.0
4
- Summary: SQLAlchemy CSV exporting for pyramid_debugtoolbar
5
- Home-page: https://github.com/jvanasco/pyramid_debugtoolbar_api_sqlalchemy
6
- Author: Jonathan Vanasco
7
- Author-email: jonathan@findmeon.com
8
- License: MIT
9
- Description: pyramid_debugtoolbar_api_sqlalchemy
10
- ===================================
11
-
12
- .. image:: https://github.com/jvanasco/pyramid_debugtoolbar_api_sqlalchemy/workflows/Python%20package/badge.svg
13
- :alt: Build Status
14
-
15
- `pyramid_debugtoolbar_api_sqlalchemy` extends the existing `pyramid_debugtoolbar`
16
- SQLAlchemy Panel to support downloadable CSV files of profiling data.
17
-
18
- This package does not replace the default panel, and requires it to be active.
19
-
20
- This package is designed for application profile and to be a useful part of test
21
- suites, allowing developers to run a series of tests and log the SQLAlchemy
22
- performance.
23
-
24
- If you are using the debugtoolbar directly:
25
-
26
- * If SQLAlchemy queries exist on the request, a "SQLAlchemy CSV" tab will appear.
27
- That will prompt you for queries.
28
-
29
- If you are scripting:
30
-
31
- * The urls are generated in a machine-friendly format, so you can regex the
32
- `request_id` off a page and pull it from the API. this is explained below:
33
-
34
-
35
- NOTES:
36
- ======
37
-
38
- This packages requires pyramid_debugtoolbar 4.0 or newer
39
-
40
-
41
- How to use this package
42
- =======================
43
-
44
-
45
- Update your ENVIRONMENT.ini file
46
-
47
- .. code-block:: python
48
-
49
- debugtoolbar.includes = pyramid_debugtoolbar_api_sqlalchemy
50
-
51
- You MUST be using `pyramid_debugtoolbar` with the SQLAlchemy panel enabled.
52
- This just piggybacks on the existing module's work to log queries.
53
-
54
- You MUST use `debugtoolbar.includes`. This will not work properly via `pyramid.includes`
55
-
56
- You can access a csv of the SQLAlchemy report via the following url hack:
57
-
58
- .. code-block:: python
59
-
60
- url_html = '/_debug_toolbar/{request_id}'
61
- url_api = '/_debug_toolbar/api-sqlalchemy/sqlalchemy-{request_id}.csv'
62
-
63
- The file will be downloaded and offer a content-disposition as:
64
-
65
- sqlalchemy-{request_id}.csv
66
-
67
- The CSV columns are:
68
-
69
- * execution timing
70
- * SQLAlchemy query
71
- * query params (json encoded)
72
-
73
-
74
- Configuration
75
- =======================
76
-
77
- By default, this package writes CSV files using "UTF-8" encoding.
78
-
79
- To change this, use the environment variable `pyramid_debugtoolbar_api_sqlalchemy_encoding`
80
-
81
- .. code-block:: shell
82
-
83
- export pyramid_debugtoolbar_api_sqlalchemy_encoding=ascii
84
-
85
- Keywords: web pyramid sqlalchemy
86
- Platform: UNKNOWN
87
- Classifier: Intended Audience :: Developers
88
- Classifier: Framework :: Pyramid
89
- Classifier: Programming Language :: Python
90
- Classifier: Programming Language :: Python :: 2
91
- Classifier: Programming Language :: Python :: 3
92
- Classifier: License :: OSI Approved :: MIT License
93
- Provides-Extra: testing
@@ -1,3 +0,0 @@
1
- [tool.black]
2
- target-version = ['py27', 'py38']
3
-
@@ -1,65 +0,0 @@
1
- # stdlib
2
- import csv
3
-
4
- # pyramid
5
- from pyramid.response import Response
6
- from pyramid.view import view_config
7
- from pyramid.exceptions import NotFound
8
-
9
- # pypi
10
- import six
11
-
12
- # from six import BytesIO
13
- from six import StringIO
14
-
15
- import os
16
-
17
- # lcoal
18
- from .utils import get_sqlalchemy_panel
19
-
20
-
21
- # encoding used to write filedata
22
- ENCODING = os.environ.get("pyramid_debugtoolbar_api_sqlalchemy_encoding", "utf-8")
23
-
24
-
25
- # ==============================================================================
26
-
27
-
28
- @view_config(route_name="debugtoolbar.api_sqlalchemy.queries.csv")
29
- def queries_api_csv(request):
30
-
31
- history = request.pdtb_history
32
- try:
33
- last_request_pair = history.last(1)[0]
34
- except IndexError:
35
- last_request_pair = None
36
- last_request_id = None
37
- else:
38
- last_request_id = last_request_pair[0]
39
-
40
- request_id = request.matchdict.get("request_id", last_request_id)
41
- toolbar = history.get(request_id, None)
42
-
43
- if not toolbar:
44
- raise NotFound
45
-
46
- sqla_panel = get_sqlalchemy_panel(toolbar.panels)
47
- if not sqla_panel:
48
- raise NotFound
49
-
50
- csvfile = StringIO()
51
- csvwriter = csv.writer(csvfile)
52
- for query in sqla_panel.data["queries"]:
53
- # we need to encode the query in Python2 if we use StringIO
54
- # we need to encode them in Python3 if we use BytesIO
55
- csvwriter.writerow(
56
- (query["duration"], query["raw_sql"].encode(ENCODING), query["parameters"])
57
- )
58
- csvfile.seek(0)
59
- as_csv = Response(
60
- content_type="text/csv", body=csvfile.read(), status=200, charset=ENCODING
61
- )
62
- as_csv.headers["Content-Disposition"] = str(
63
- "attachment; filename= sqlalchemy-%s.csv" % request_id
64
- )
65
- return as_csv
@@ -1,93 +0,0 @@
1
- Metadata-Version: 2.1
2
- Name: pyramid-debugtoolbar-api-sqlalchemy
3
- Version: 0.3.0
4
- Summary: SQLAlchemy CSV exporting for pyramid_debugtoolbar
5
- Home-page: https://github.com/jvanasco/pyramid_debugtoolbar_api_sqlalchemy
6
- Author: Jonathan Vanasco
7
- Author-email: jonathan@findmeon.com
8
- License: MIT
9
- Description: pyramid_debugtoolbar_api_sqlalchemy
10
- ===================================
11
-
12
- .. image:: https://github.com/jvanasco/pyramid_debugtoolbar_api_sqlalchemy/workflows/Python%20package/badge.svg
13
- :alt: Build Status
14
-
15
- `pyramid_debugtoolbar_api_sqlalchemy` extends the existing `pyramid_debugtoolbar`
16
- SQLAlchemy Panel to support downloadable CSV files of profiling data.
17
-
18
- This package does not replace the default panel, and requires it to be active.
19
-
20
- This package is designed for application profile and to be a useful part of test
21
- suites, allowing developers to run a series of tests and log the SQLAlchemy
22
- performance.
23
-
24
- If you are using the debugtoolbar directly:
25
-
26
- * If SQLAlchemy queries exist on the request, a "SQLAlchemy CSV" tab will appear.
27
- That will prompt you for queries.
28
-
29
- If you are scripting:
30
-
31
- * The urls are generated in a machine-friendly format, so you can regex the
32
- `request_id` off a page and pull it from the API. this is explained below:
33
-
34
-
35
- NOTES:
36
- ======
37
-
38
- This packages requires pyramid_debugtoolbar 4.0 or newer
39
-
40
-
41
- How to use this package
42
- =======================
43
-
44
-
45
- Update your ENVIRONMENT.ini file
46
-
47
- .. code-block:: python
48
-
49
- debugtoolbar.includes = pyramid_debugtoolbar_api_sqlalchemy
50
-
51
- You MUST be using `pyramid_debugtoolbar` with the SQLAlchemy panel enabled.
52
- This just piggybacks on the existing module's work to log queries.
53
-
54
- You MUST use `debugtoolbar.includes`. This will not work properly via `pyramid.includes`
55
-
56
- You can access a csv of the SQLAlchemy report via the following url hack:
57
-
58
- .. code-block:: python
59
-
60
- url_html = '/_debug_toolbar/{request_id}'
61
- url_api = '/_debug_toolbar/api-sqlalchemy/sqlalchemy-{request_id}.csv'
62
-
63
- The file will be downloaded and offer a content-disposition as:
64
-
65
- sqlalchemy-{request_id}.csv
66
-
67
- The CSV columns are:
68
-
69
- * execution timing
70
- * SQLAlchemy query
71
- * query params (json encoded)
72
-
73
-
74
- Configuration
75
- =======================
76
-
77
- By default, this package writes CSV files using "UTF-8" encoding.
78
-
79
- To change this, use the environment variable `pyramid_debugtoolbar_api_sqlalchemy_encoding`
80
-
81
- .. code-block:: shell
82
-
83
- export pyramid_debugtoolbar_api_sqlalchemy_encoding=ascii
84
-
85
- Keywords: web pyramid sqlalchemy
86
- Platform: UNKNOWN
87
- Classifier: Intended Audience :: Developers
88
- Classifier: Framework :: Pyramid
89
- Classifier: Programming Language :: Python
90
- Classifier: Programming Language :: Python :: 2
91
- Classifier: Programming Language :: Python :: 3
92
- Classifier: License :: OSI Approved :: MIT License
93
- Provides-Extra: testing
@@ -1,16 +0,0 @@
1
- MANIFEST.in
2
- README.rst
3
- pyproject.toml
4
- setup.cfg
5
- setup.py
6
- pyramid_debugtoolbar_api_sqlalchemy/__init__.py
7
- pyramid_debugtoolbar_api_sqlalchemy/panels.py
8
- pyramid_debugtoolbar_api_sqlalchemy/utils.py
9
- pyramid_debugtoolbar_api_sqlalchemy/views.py
10
- pyramid_debugtoolbar_api_sqlalchemy.egg-info/PKG-INFO
11
- pyramid_debugtoolbar_api_sqlalchemy.egg-info/SOURCES.txt
12
- pyramid_debugtoolbar_api_sqlalchemy.egg-info/dependency_links.txt
13
- pyramid_debugtoolbar_api_sqlalchemy.egg-info/not-zip-safe
14
- pyramid_debugtoolbar_api_sqlalchemy.egg-info/requires.txt
15
- pyramid_debugtoolbar_api_sqlalchemy.egg-info/top_level.txt
16
- pyramid_debugtoolbar_api_sqlalchemy/templates/sqlalchemy_csv.dbtmako
@@ -1,7 +0,0 @@
1
- pyramid
2
- pyramid_debugtoolbar>=4.0
3
- six
4
- sqlalchemy
5
-
6
- [testing]
7
- pytest
@@ -1,7 +0,0 @@
1
- [easy_install]
2
- zip_ok = false
3
-
4
- [egg_info]
5
- tag_build =
6
- tag_date = 0
7
-
@@ -1,58 +0,0 @@
1
- """pyramid_debugtoolbar_api_sqlalchemy installation script.
2
- """
3
- import os
4
- from setuptools import setup
5
- from setuptools import find_packages
6
-
7
- # store version in the init.py
8
- import re
9
-
10
- with open(
11
- os.path.join(
12
- os.path.dirname(__file__), "pyramid_debugtoolbar_api_sqlalchemy", "__init__.py"
13
- )
14
- ) as v_file:
15
- VERSION = re.compile(r'.*__VERSION__ = "(.*?)"', re.S).match(v_file.read()).group(1)
16
-
17
- here = os.path.abspath(os.path.dirname(__file__))
18
- README = open(os.path.join(here, "README.rst")).read()
19
-
20
- requires = [
21
- "pyramid",
22
- "pyramid_debugtoolbar>=4.0",
23
- "six",
24
- "sqlalchemy",
25
- ]
26
- tests_require = [
27
- "pytest",
28
- ]
29
- testing_extras = tests_require + []
30
-
31
- setup(
32
- name="pyramid_debugtoolbar_api_sqlalchemy",
33
- author="Jonathan Vanasco",
34
- author_email="jonathan@findmeon.com",
35
- url="https://github.com/jvanasco/pyramid_debugtoolbar_api_sqlalchemy",
36
- version=VERSION,
37
- description="SQLAlchemy CSV exporting for pyramid_debugtoolbar",
38
- long_description=README,
39
- keywords="web pyramid sqlalchemy",
40
- license="MIT",
41
- classifiers=[
42
- "Intended Audience :: Developers",
43
- "Framework :: Pyramid",
44
- "Programming Language :: Python",
45
- "Programming Language :: Python :: 2",
46
- "Programming Language :: Python :: 3",
47
- "License :: OSI Approved :: MIT License",
48
- ],
49
- packages=find_packages(),
50
- include_package_data=True,
51
- zip_safe=False,
52
- install_requires=requires,
53
- tests_require=tests_require,
54
- extras_require={
55
- "testing": testing_extras,
56
- },
57
- test_suite="tests",
58
- )