pyramid-debugtoolbar-api-performance 0.3.1__tar.gz → 1.1.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_performance-1.1.0/CHANGES.txt +35 -0
  2. {pyramid_debugtoolbar_api_performance-0.3.1 → pyramid_debugtoolbar_api_performance-1.1.0}/MANIFEST.in +0 -1
  3. pyramid_debugtoolbar_api_performance-1.1.0/PKG-INFO +108 -0
  4. pyramid_debugtoolbar_api_performance-1.1.0/pyproject.toml +7 -0
  5. pyramid_debugtoolbar_api_performance-1.1.0/setup.cfg +67 -0
  6. {pyramid_debugtoolbar_api_performance-0.3.1 → pyramid_debugtoolbar_api_performance-1.1.0}/src/pyramid_debugtoolbar_api_performance/__init__.py +7 -5
  7. pyramid_debugtoolbar_api_performance-1.1.0/src/pyramid_debugtoolbar_api_performance/_version.py +3 -0
  8. pyramid_debugtoolbar_api_performance-1.1.0/src/pyramid_debugtoolbar_api_performance/spreadsheet_utils.py +14 -0
  9. pyramid_debugtoolbar_api_performance-1.1.0/src/pyramid_debugtoolbar_api_performance/views.py +108 -0
  10. pyramid_debugtoolbar_api_performance-1.1.0/src/pyramid_debugtoolbar_api_performance.egg-info/PKG-INFO +108 -0
  11. {pyramid_debugtoolbar_api_performance-0.3.1 → pyramid_debugtoolbar_api_performance-1.1.0}/src/pyramid_debugtoolbar_api_performance.egg-info/SOURCES.txt +3 -2
  12. pyramid_debugtoolbar_api_performance-1.1.0/src/pyramid_debugtoolbar_api_performance.egg-info/requires.txt +10 -0
  13. pyramid_debugtoolbar_api_performance-1.1.0/tests/__init__.py +0 -0
  14. {pyramid_debugtoolbar_api_performance-0.3.1 → pyramid_debugtoolbar_api_performance-1.1.0}/tests/test_config.py +74 -1
  15. pyramid_debugtoolbar_api_performance-0.3.1/CHANGES.txt +0 -28
  16. pyramid_debugtoolbar_api_performance-0.3.1/PKG-INFO +0 -91
  17. pyramid_debugtoolbar_api_performance-0.3.1/pyproject.toml +0 -3
  18. pyramid_debugtoolbar_api_performance-0.3.1/setup.cfg +0 -7
  19. pyramid_debugtoolbar_api_performance-0.3.1/setup.py +0 -61
  20. pyramid_debugtoolbar_api_performance-0.3.1/src/pyramid_debugtoolbar_api_performance/views.py +0 -103
  21. pyramid_debugtoolbar_api_performance-0.3.1/src/pyramid_debugtoolbar_api_performance.egg-info/PKG-INFO +0 -91
  22. pyramid_debugtoolbar_api_performance-0.3.1/src/pyramid_debugtoolbar_api_performance.egg-info/requires.txt +0 -6
  23. pyramid_debugtoolbar_api_performance-0.3.1/tox.ini +0 -12
  24. {pyramid_debugtoolbar_api_performance-0.3.1 → pyramid_debugtoolbar_api_performance-1.1.0}/LICENSE +0 -0
  25. {pyramid_debugtoolbar_api_performance-0.3.1 → pyramid_debugtoolbar_api_performance-1.1.0}/README.rst +0 -0
  26. {pyramid_debugtoolbar_api_performance-0.3.1 → pyramid_debugtoolbar_api_performance-1.1.0}/TODO.txt +0 -0
  27. {pyramid_debugtoolbar_api_performance-0.3.1 → pyramid_debugtoolbar_api_performance-1.1.0}/src/pyramid_debugtoolbar_api_performance/panels.py +0 -0
  28. {pyramid_debugtoolbar_api_performance-0.3.1 → pyramid_debugtoolbar_api_performance-1.1.0}/src/pyramid_debugtoolbar_api_performance/templates/performance_csv.dbtmako +0 -0
  29. {pyramid_debugtoolbar_api_performance-0.3.1 → pyramid_debugtoolbar_api_performance-1.1.0}/src/pyramid_debugtoolbar_api_performance/utils.py +0 -0
  30. {pyramid_debugtoolbar_api_performance-0.3.1 → pyramid_debugtoolbar_api_performance-1.1.0}/src/pyramid_debugtoolbar_api_performance.egg-info/dependency_links.txt +0 -0
  31. {pyramid_debugtoolbar_api_performance-0.3.1 → pyramid_debugtoolbar_api_performance-1.1.0}/src/pyramid_debugtoolbar_api_performance.egg-info/not-zip-safe +0 -0
  32. {pyramid_debugtoolbar_api_performance-0.3.1 → pyramid_debugtoolbar_api_performance-1.1.0}/src/pyramid_debugtoolbar_api_performance.egg-info/top_level.txt +0 -0
@@ -0,0 +1,35 @@
1
+ v1.1.0
2
+ * Add spreadsheet=1 to both performance CSV routes to prefix formula-like text.
3
+
4
+ v1.0.0
5
+ * Explicitly package the CSV template as data to avoid setuptools package discovery warnings.
6
+ * Keep runtime dependencies out of version discovery on legacy setuptools.
7
+ * Consolidate package and tox configuration and extend CI through Python 3.15.
8
+ * Harden CSV download headers and disable caching for profiling exports.
9
+ * Return 404 when a request or its performance data is unavailable.
10
+ * added tests/__init__.py
11
+
12
+ v0.3.1
13
+ * packaging
14
+
15
+ v0.3.0
16
+ * updated debugtoolbar includes
17
+
18
+ v0.2.2dev unreleased
19
+ * black
20
+ * upgraded black; 20.8b1
21
+ * integrated with pre-commit
22
+
23
+ v0.2.1
24
+ * bugfixes
25
+ * includeme registers the panel via the api method `config.add_debugtoolbar_panel()`
26
+
27
+ v0.2.0 | 2019.04.29
28
+ * python3 support
29
+
30
+ v0.1.1 | 2017.12.06
31
+ * ported a functionality to current debugtoolbar api
32
+ * store version as __VERSION__ in /__init__.py
33
+
34
+ v0.1.0 | 2017.05.10
35
+ * initial
@@ -2,7 +2,6 @@ graft src
2
2
  graft tests
3
3
 
4
4
  include setup.cfg pyproject.toml
5
- include tox.ini
6
5
  include CHANGES.txt
7
6
  include LICENSE
8
7
  include README.rst
@@ -0,0 +1,108 @@
1
+ Metadata-Version: 2.4
2
+ Name: pyramid_debugtoolbar_api_performance
3
+ Version: 1.1.0
4
+ Summary: performance csv exporting for pyramid_debugtoolbar
5
+ Home-page: https://github.com/jvanasco/pyramid_debugtoolbar_api_performance
6
+ Author: Jonathan Vanasco
7
+ Author-email: jvanasco@2xlp.com
8
+ License: MIT
9
+ Keywords: web,pyramid
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: setuptools<82; python_version >= "3.7" and python_version < "3.10"
32
+ Provides-Extra: testing
33
+ Requires-Dist: coverage; extra == "testing"
34
+ Requires-Dist: pytest; extra == "testing"
35
+ Dynamic: license-file
36
+
37
+ pyramid_debugtoolbar_api_performance
38
+ ====================================
39
+
40
+ .. image:: https://github.com/jvanasco/pyramid_debugtoolbar_api_performance/workflows/Python%20package/badge.svg
41
+ :alt: Build Status
42
+
43
+ `pyramid_debugtoolbar_api_performance` extends the existing `pyramid_debugtoolbar`
44
+ Performance Panel to support downloadable CSV files of profiling data.
45
+
46
+ This package does not replace the default panel, and requires it to be active.
47
+
48
+ This package is designed for application profile and to be a useful part of test
49
+ suites, allowing developers to run a series of tests and log the Performance
50
+ performance.
51
+
52
+ The package exposes two routes for CSV data:
53
+
54
+ * timing
55
+ * function_calls
56
+
57
+ Both correlate to the official Performance panel data.
58
+
59
+ The urls are generated in a machine-friendly format, so you can regex the
60
+ `request_id` off a page and pull it from the API. This is explained below...
61
+
62
+
63
+ NOTES:
64
+ ======
65
+
66
+ This packages requires pyramid_debugtoolbar 4.0 or newer
67
+
68
+
69
+ How to use this package
70
+ =======================
71
+
72
+
73
+ Update your ENVIRONMENT.ini file
74
+
75
+ .. code-block:: python
76
+
77
+ debugtoolbar.includes = pyramid_debugtoolbar_api_performance
78
+
79
+ You MUST be using `pyramid_debugtoolbar` with the Performance panel enabled.
80
+ This package simply piggybacks on the existing module's work to log queries.
81
+
82
+ You MUST use `debugtoolbar.includes`. This will not work properly via `pyramid.includes`
83
+
84
+ You can access a csv of the Profiling report via the following url hack:
85
+
86
+ .. code-block:: python
87
+
88
+ url_html = '/_debug_toolbar/{request_id}'
89
+ url_api = '/_debug_toolbar/api-performance/timing-{request_id}.csv'
90
+ url_api = '/_debug_toolbar/api-performance/function_calls-{request_id}.csv'
91
+
92
+
93
+ The file will be downloaded and offer a content-disposition as:
94
+
95
+ .. code-block:: shell
96
+
97
+ performance-{request_id}.csv
98
+
99
+ Configuration
100
+ =======================
101
+
102
+ By default, this package writes CSV files using "UTF-8" encoding.
103
+
104
+ To change this, use the environment variable `pyramid_debugtoolbar_api_performance_encoding`
105
+
106
+ .. code-block:: shell
107
+
108
+ export pyramid_debugtoolbar_api_performance_encoding=ascii
@@ -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 = ['py27', 'py38']
7
+
@@ -0,0 +1,67 @@
1
+ [metadata]
2
+ name = pyramid_debugtoolbar_api_performance
3
+ version = attr: pyramid_debugtoolbar_api_performance._version.__VERSION__
4
+ description = performance 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_performance
10
+ keywords = web, pyramid
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
+ setuptools<82; python_version >= "3.7" and python_version < "3.10"
42
+
43
+ [options.packages.find]
44
+ where = src
45
+
46
+ [options.package_data]
47
+ pyramid_debugtoolbar_api_performance = templates/*.dbtmako
48
+
49
+ [options.extras_require]
50
+ testing =
51
+ coverage
52
+ pytest
53
+
54
+ [tox:tox]
55
+ envlist = py27, py35, py36, py37, py38, py39, py310, py311, py312, py313, py314, py315
56
+
57
+ [testenv]
58
+ extras = testing
59
+ commands =
60
+ python --version
61
+ python -m coverage run --source=pyramid_debugtoolbar_api_performance -m pytest {posargs:}
62
+ python -m coverage html -d {envtmpdir}/coverage
63
+
64
+ [egg_info]
65
+ tag_build =
66
+ tag_date = 0
67
+
@@ -1,14 +1,16 @@
1
- # local
2
- from .panels import PerformanceCsvDebugPanel
3
-
4
-
5
- __VERSION__ = "0.3.1"
1
+ # type: from pyramid.config import Configurator
2
+ from ._version import __VERSION__
6
3
 
7
4
 
8
5
  # ==============================================================================
9
6
 
10
7
 
11
8
  def includeme(config):
9
+ # type: (Configurator) -> None
10
+ """Register the CSV panel and routes with the debug toolbar."""
11
+ # Older setuptools imports this package to read its version at build time.
12
+ from .panels import PerformanceCsvDebugPanel
13
+
12
14
  config.add_debugtoolbar_panel(PerformanceCsvDebugPanel)
13
15
  config.add_route(
14
16
  "debugtoolbar.api_performance_csv.function_calls",
@@ -0,0 +1,3 @@
1
+ """Package version shared by runtime and build metadata."""
2
+
3
+ __VERSION__ = "1.1.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,108 @@
1
+ # stdlib
2
+ import csv
3
+ import os
4
+ import re
5
+
6
+ # pyramid
7
+ from pyramid.response import Response
8
+
9
+ from pyramid.request import Request
10
+ from pyramid_debugtoolbar.panels.performance import PerformanceDebugPanel
11
+ from pyramid.view import view_config
12
+ from pyramid.exceptions import NotFound
13
+
14
+ # Python 2's csv module requires a byte buffer.
15
+ from six import PY2, StringIO, binary_type
16
+
17
+ # local
18
+ from .spreadsheet_utils import sanitize_spreadsheet_cell
19
+ from .utils import get_performance_panel
20
+
21
+
22
+ # encoding used to write filedata
23
+ ENCODING = os.environ.get("pyramid_debugtoolbar_api_sqlalchemy_encoding", "utf-8")
24
+
25
+
26
+ # ==============================================================================
27
+
28
+
29
+ def _standardized_setup(request):
30
+ # type: (Request) -> tuple[str, PerformanceDebugPanel]
31
+ """Resolve the performance panel for the requested history entry."""
32
+ request_id = request.matchdict["request_id"]
33
+ toolbar = request.pdtb_history.get(request_id, None)
34
+ if toolbar is None:
35
+ raise NotFound
36
+
37
+ panel = get_performance_panel(toolbar.panels)
38
+ if panel is None or not panel.data:
39
+ raise NotFound
40
+
41
+ return request_id, panel
42
+
43
+
44
+ def _spreadsheet_text(value):
45
+ # type: (str) -> str
46
+ """Sanitize a CSV text field using the export's encoding."""
47
+ if isinstance(value, binary_type):
48
+ value = value.decode(ENCODING)
49
+ value = sanitize_spreadsheet_cell(value)
50
+ return value.encode(ENCODING) if PY2 else value
51
+
52
+
53
+ def _csv_response(csvfile, report, request_id, spreadsheet):
54
+ # type: (StringIO, str, str, bool) -> Response
55
+ """Return a CSV attachment with a header-safe filename."""
56
+ safe_id = re.sub(r"[^a-zA-Z0-9_-]", "_", request_id)
57
+ suffix = "-spreadsheet" if spreadsheet else ""
58
+ filename = "performance-%s-%s%s.csv" % (report, safe_id, suffix)
59
+ response = Response(
60
+ content_type="text/csv", body=csvfile.getvalue(), charset=ENCODING
61
+ )
62
+ response.headers["Content-Disposition"] = str('attachment; filename="%s"' % filename)
63
+ response.cache_control.no_store = True
64
+ return response
65
+
66
+
67
+ @view_config(route_name="debugtoolbar.api_performance_csv.timing")
68
+ def csv_timing(request):
69
+ # type: (Request) -> Response
70
+ """Export timing rows for a recorded request."""
71
+ (request_id, panel) = _standardized_setup(request)
72
+
73
+ spreadsheet = request.GET.get("spreadsheet") == "1"
74
+ csvfile = StringIO()
75
+ csvwriter = csv.writer(csvfile)
76
+ for label, timing in panel.data["timing_rows"]:
77
+ if spreadsheet:
78
+ label = _spreadsheet_text(label)
79
+ csvwriter.writerow((label, timing))
80
+ return _csv_response(csvfile, "timing", request_id, spreadsheet)
81
+
82
+
83
+ @view_config(route_name="debugtoolbar.api_performance_csv.function_calls")
84
+ def csv_function_calls(request):
85
+ # type: (Request) -> Response
86
+ """Export profiler rows for a recorded request."""
87
+ (request_id, panel) = _standardized_setup(request)
88
+
89
+ spreadsheet = request.GET.get("spreadsheet") == "1"
90
+ csvfile = StringIO()
91
+ csvwriter = csv.writer(csvfile)
92
+ if panel.data["stats"]:
93
+ csvwriter.writerow(("Calls", "Total", "Percall", "Cumu", "CumuPer", "Func"))
94
+ for row in panel.data["function_calls"]:
95
+ filename = row["filename_long"]
96
+ if spreadsheet:
97
+ filename = _spreadsheet_text(filename)
98
+ csvwriter.writerow(
99
+ (
100
+ row["ncalls"],
101
+ row["tottime"],
102
+ row["percall"],
103
+ row["cumtime"],
104
+ row["percall_cum"],
105
+ filename,
106
+ )
107
+ )
108
+ return _csv_response(csvfile, "function_calls", request_id, spreadsheet)
@@ -0,0 +1,108 @@
1
+ Metadata-Version: 2.4
2
+ Name: pyramid_debugtoolbar_api_performance
3
+ Version: 1.1.0
4
+ Summary: performance csv exporting for pyramid_debugtoolbar
5
+ Home-page: https://github.com/jvanasco/pyramid_debugtoolbar_api_performance
6
+ Author: Jonathan Vanasco
7
+ Author-email: jvanasco@2xlp.com
8
+ License: MIT
9
+ Keywords: web,pyramid
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: setuptools<82; python_version >= "3.7" and python_version < "3.10"
32
+ Provides-Extra: testing
33
+ Requires-Dist: coverage; extra == "testing"
34
+ Requires-Dist: pytest; extra == "testing"
35
+ Dynamic: license-file
36
+
37
+ pyramid_debugtoolbar_api_performance
38
+ ====================================
39
+
40
+ .. image:: https://github.com/jvanasco/pyramid_debugtoolbar_api_performance/workflows/Python%20package/badge.svg
41
+ :alt: Build Status
42
+
43
+ `pyramid_debugtoolbar_api_performance` extends the existing `pyramid_debugtoolbar`
44
+ Performance Panel to support downloadable CSV files of profiling data.
45
+
46
+ This package does not replace the default panel, and requires it to be active.
47
+
48
+ This package is designed for application profile and to be a useful part of test
49
+ suites, allowing developers to run a series of tests and log the Performance
50
+ performance.
51
+
52
+ The package exposes two routes for CSV data:
53
+
54
+ * timing
55
+ * function_calls
56
+
57
+ Both correlate to the official Performance panel data.
58
+
59
+ The urls are generated in a machine-friendly format, so you can regex the
60
+ `request_id` off a page and pull it from the API. This is explained below...
61
+
62
+
63
+ NOTES:
64
+ ======
65
+
66
+ This packages requires pyramid_debugtoolbar 4.0 or newer
67
+
68
+
69
+ How to use this package
70
+ =======================
71
+
72
+
73
+ Update your ENVIRONMENT.ini file
74
+
75
+ .. code-block:: python
76
+
77
+ debugtoolbar.includes = pyramid_debugtoolbar_api_performance
78
+
79
+ You MUST be using `pyramid_debugtoolbar` with the Performance panel enabled.
80
+ This package simply piggybacks on the existing module's work to log queries.
81
+
82
+ You MUST use `debugtoolbar.includes`. This will not work properly via `pyramid.includes`
83
+
84
+ You can access a csv of the Profiling report via the following url hack:
85
+
86
+ .. code-block:: python
87
+
88
+ url_html = '/_debug_toolbar/{request_id}'
89
+ url_api = '/_debug_toolbar/api-performance/timing-{request_id}.csv'
90
+ url_api = '/_debug_toolbar/api-performance/function_calls-{request_id}.csv'
91
+
92
+
93
+ The file will be downloaded and offer a content-disposition as:
94
+
95
+ .. code-block:: shell
96
+
97
+ performance-{request_id}.csv
98
+
99
+ Configuration
100
+ =======================
101
+
102
+ By default, this package writes CSV files using "UTF-8" encoding.
103
+
104
+ To change this, use the environment variable `pyramid_debugtoolbar_api_performance_encoding`
105
+
106
+ .. code-block:: shell
107
+
108
+ export pyramid_debugtoolbar_api_performance_encoding=ascii
@@ -5,10 +5,10 @@ README.rst
5
5
  TODO.txt
6
6
  pyproject.toml
7
7
  setup.cfg
8
- setup.py
9
- tox.ini
10
8
  src/pyramid_debugtoolbar_api_performance/__init__.py
9
+ src/pyramid_debugtoolbar_api_performance/_version.py
11
10
  src/pyramid_debugtoolbar_api_performance/panels.py
11
+ src/pyramid_debugtoolbar_api_performance/spreadsheet_utils.py
12
12
  src/pyramid_debugtoolbar_api_performance/utils.py
13
13
  src/pyramid_debugtoolbar_api_performance/views.py
14
14
  src/pyramid_debugtoolbar_api_performance.egg-info/PKG-INFO
@@ -18,4 +18,5 @@ src/pyramid_debugtoolbar_api_performance.egg-info/not-zip-safe
18
18
  src/pyramid_debugtoolbar_api_performance.egg-info/requires.txt
19
19
  src/pyramid_debugtoolbar_api_performance.egg-info/top_level.txt
20
20
  src/pyramid_debugtoolbar_api_performance/templates/performance_csv.dbtmako
21
+ tests/__init__.py
21
22
  tests/test_config.py
@@ -0,0 +1,10 @@
1
+ pyramid
2
+ pyramid_debugtoolbar>=4.0
3
+ six
4
+
5
+ [:python_version >= "3.7" and python_version < "3.10"]
6
+ setuptools<82
7
+
8
+ [testing]
9
+ coverage
10
+ pytest
@@ -7,7 +7,6 @@ import unittest
7
7
 
8
8
  # pyramid testing requirements
9
9
  from pyramid import testing
10
- from pyramid.exceptions import ConfigurationError
11
10
  from pyramid.response import Response
12
11
  from pyramid.request import Request
13
12
 
@@ -41,6 +40,7 @@ class TestDebugtoolbarPanel(unittest.TestCase):
41
40
  )
42
41
 
43
42
  config.add_view(empty_view)
43
+ config.add_notfound_view(lambda request: Response(status=404))
44
44
 
45
45
  def tearDown(self):
46
46
  testing.tearDown()
@@ -132,6 +132,14 @@ class TestDebugtoolbarPanel(unittest.TestCase):
132
132
  req3.remote_addr = "127.0.0.1"
133
133
  resp3 = req3.get_response(app)
134
134
  self.assertEqual(resp3.status_code, 200)
135
+ self.assertEqual(
136
+ resp3.headers["Content-Disposition"],
137
+ 'attachment; filename="performance-timing-%s.csv"' % _id,
138
+ )
139
+ self.assertTrue(resp3.cache_control.no_store)
140
+ denied = Request.blank(_timing_link)
141
+ denied.remote_addr = "192.0.2.1"
142
+ self.assertEqual(denied.get_response(app).status_code, 404)
135
143
  self.assertTrue(resp3.text.startswith("User CPU time,"))
136
144
 
137
145
  # function csv
@@ -142,6 +150,71 @@ class TestDebugtoolbarPanel(unittest.TestCase):
142
150
  req4.remote_addr = "127.0.0.1"
143
151
  resp4 = req4.get_response(app)
144
152
  self.assertEqual(resp4.status_code, 200)
153
+ self.assertEqual(
154
+ resp4.headers["Content-Disposition"],
155
+ 'attachment; filename="performance-function_calls-%s.csv"' % _id,
156
+ )
157
+ self.assertTrue(resp4.cache_control.no_store)
158
+ denied = Request.blank(_function_link)
159
+ denied.remote_addr = "192.0.2.1"
160
+ self.assertEqual(denied.get_response(app).status_code, 404)
145
161
  self.assertTrue(
146
162
  resp4.text.startswith("Calls,Total,Percall,Cumu,CumuPer,Func\r\n")
147
163
  )
164
+
165
+ def test_csv_missing_history(self):
166
+ # type: () -> None
167
+ """Both CSV routes return 404 when the request is absent from history."""
168
+ app = self.config.make_wsgi_app()
169
+ for report in ("timing", "function_calls"):
170
+ request = Request.blank(
171
+ "/_debug_toolbar/api-performance/%s-missing.csv" % report
172
+ )
173
+ request.remote_addr = "127.0.0.1"
174
+ self.assertEqual(request.get_response(app).status_code, 404)
175
+
176
+
177
+ def test_spreadsheet_exports(self):
178
+ # type: () -> None
179
+ """Protect both CSV text fields while preserving default output."""
180
+ from pyramid_debugtoolbar.panels.performance import PerformanceDebugPanel
181
+
182
+ app = self.config.make_wsgi_app()
183
+ initial = Request.blank("/")
184
+ initial.remote_addr = "127.0.0.1"
185
+ initial.get_response(app)
186
+ request_id, toolbar = self.config.registry.pdtb_history.last(1)[0]
187
+ panel = next(p for p in toolbar.panels if isinstance(p, PerformanceDebugPanel))
188
+ panel.data.update(
189
+ timing_rows=[(str("=label"), str("-2 msec"))],
190
+ stats=True,
191
+ function_calls=[
192
+ dict(
193
+ ncalls="1",
194
+ tottime="-2",
195
+ percall="3",
196
+ cumtime="4",
197
+ percall_cum="5",
198
+ filename_long=" @module",
199
+ )
200
+ ],
201
+ )
202
+
203
+ for report, raw, safe in (
204
+ ("timing", "=label,-2 msec", "'=label,-2 msec"),
205
+ ("function_calls", "1,-2,3,4,5, @module", "1,-2,3,4,5,' @module"),
206
+ ):
207
+ path = "/_debug_toolbar/api-performance/%s-%s.csv" % (report, request_id)
208
+ for query, row in (("", raw), ("?spreadsheet=1", safe)):
209
+ request = Request.blank(path + query)
210
+ request.remote_addr = "127.0.0.1"
211
+ response = request.get_response(app)
212
+ self.assertEqual(response.status_code, 200)
213
+ self.assertIn(row + "\r\n", response.text)
214
+ self.assertTrue(response.cache_control.no_store)
215
+ if query:
216
+ self.assertTrue(
217
+ response.headers["Content-Disposition"].endswith(
218
+ '-spreadsheet.csv"'
219
+ )
220
+ )
@@ -1,28 +0,0 @@
1
- v0.3.1
2
- * packaging
3
-
4
- v0.3.0
5
- * updated debugtoolbar includes
6
-
7
- v0.2.2dev unreleased
8
- black
9
- * upgraded black; 20.8b1
10
- * integrated with pre-commit
11
-
12
- v0.2.1
13
- bugfixes
14
- includeme registers the panel via the api method `config.add_debugtoolbar_panel()`
15
-
16
- v0.2.0
17
- 2019.04.29
18
- * python3 support
19
-
20
- v0.1.1
21
- 2017.12.06
22
- * ported a functionality to current debugtoolbar api
23
- * store version as __VERSION__ in /__init__.py
24
-
25
- v0.1.0
26
- 2017.05.10
27
- * initial
28
-
@@ -1,91 +0,0 @@
1
- Metadata-Version: 2.1
2
- Name: pyramid_debugtoolbar_api_performance
3
- Version: 0.3.1
4
- Summary: performance csv exporting for pyramid_debugtoolbar
5
- Home-page: https://github.com/jvanasco/pyramid_debugtoolbar_api_performance
6
- Author: Jonathan Vanasco
7
- Author-email: jonathan@findmeon.com
8
- License: MIT
9
- Description: pyramid_debugtoolbar_api_performance
10
- ====================================
11
-
12
- .. image:: https://github.com/jvanasco/pyramid_debugtoolbar_api_performance/workflows/Python%20package/badge.svg
13
- :alt: Build Status
14
-
15
- `pyramid_debugtoolbar_api_performance` extends the existing `pyramid_debugtoolbar`
16
- Performance 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 Performance
22
- performance.
23
-
24
- The package exposes two routes for CSV data:
25
-
26
- * timing
27
- * function_calls
28
-
29
- Both correlate to the official Performance panel data.
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_performance
50
-
51
- You MUST be using `pyramid_debugtoolbar` with the Performance panel enabled.
52
- This package simply 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 Profiling 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-performance/timing-{request_id}.csv'
62
- url_api = '/_debug_toolbar/api-performance/function_calls-{request_id}.csv'
63
-
64
-
65
- The file will be downloaded and offer a content-disposition as:
66
-
67
- .. code-block:: shell
68
-
69
- performance-{request_id}.csv
70
-
71
- Configuration
72
- =======================
73
-
74
- By default, this package writes CSV files using "UTF-8" encoding.
75
-
76
- To change this, use the environment variable `pyramid_debugtoolbar_api_performance_encoding`
77
-
78
- .. code-block:: shell
79
-
80
- export pyramid_debugtoolbar_api_performance_encoding=ascii
81
-
82
- Keywords: web pyramid
83
- Platform: UNKNOWN
84
- Classifier: Intended Audience :: Developers
85
- Classifier: Framework :: Pyramid
86
- Classifier: Programming Language :: Python
87
- Classifier: Programming Language :: Python :: 2
88
- Classifier: Programming Language :: Python :: 3
89
- Classifier: License :: OSI Approved :: MIT License
90
- Description-Content-Type: text/markdown
91
- Provides-Extra: testing
@@ -1,3 +0,0 @@
1
- [tool.black]
2
- target-version = ['py27', 'py38']
3
-
@@ -1,7 +0,0 @@
1
- [easy_install]
2
- zip_ok = false
3
-
4
- [egg_info]
5
- tag_build =
6
- tag_date = 0
7
-
@@ -1,61 +0,0 @@
1
- """pyramid_debugtoolbar_api_performance installation script.
2
- """
3
- import os
4
- import re
5
- from setuptools import setup
6
- from setuptools import find_packages
7
-
8
- # store version in the init.py
9
- HERE = os.path.abspath(os.path.dirname(__file__))
10
-
11
- with open(
12
- os.path.join(HERE, "src", "pyramid_debugtoolbar_api_performance", "__init__.py")
13
- ) as v_file:
14
- VERSION = re.compile(r'.*__VERSION__ = "(.*?)"', re.S).match(v_file.read()).group(1)
15
-
16
- long_description = description = "performance csv exporting for pyramid_debugtoolbar"
17
- with open(os.path.join(HERE, "README.rst")) as fp:
18
- long_description = fp.read()
19
-
20
- requires = [
21
- "pyramid",
22
- "pyramid_debugtoolbar>=4.0",
23
- "six",
24
- ]
25
- tests_require = [
26
- "pytest",
27
- ]
28
- testing_extras = tests_require + []
29
-
30
- setup(
31
- name="pyramid_debugtoolbar_api_performance",
32
- author="Jonathan Vanasco",
33
- author_email="jonathan@findmeon.com",
34
- url="https://github.com/jvanasco/pyramid_debugtoolbar_api_performance",
35
- version=VERSION,
36
- description=description,
37
- long_description=long_description,
38
- long_description_content_type="text/markdown",
39
- keywords="web pyramid",
40
- packages=find_packages(
41
- where="src",
42
- ),
43
- package_dir={"": "src"},
44
- include_package_data=True,
45
- license="MIT",
46
- classifiers=[
47
- "Intended Audience :: Developers",
48
- "Framework :: Pyramid",
49
- "Programming Language :: Python",
50
- "Programming Language :: Python :: 2",
51
- "Programming Language :: Python :: 3",
52
- "License :: OSI Approved :: MIT License",
53
- ],
54
- zip_safe=False,
55
- install_requires=requires,
56
- tests_require=tests_require,
57
- extras_require={
58
- "testing": testing_extras,
59
- },
60
- test_suite="tests",
61
- )
@@ -1,103 +0,0 @@
1
- # stdlib
2
- import csv
3
- import os
4
-
5
- # pyramid
6
- from pyramid.response import Response
7
- from pyramid.view import view_config
8
- from pyramid.exceptions import NotFound
9
-
10
- # pypi
11
- import six
12
-
13
- # from six import BytesIO
14
- from six import StringIO
15
-
16
- # local
17
- from .utils import get_performance_panel
18
-
19
-
20
- # encoding used to write filedata
21
- ENCODING = os.environ.get("pyramid_debugtoolbar_api_sqlalchemy_encoding", "utf-8")
22
-
23
-
24
- # ==============================================================================
25
-
26
-
27
- def _standardized_setup(request):
28
- """returns panel after some processing"""
29
- history = request.pdtb_history
30
- try:
31
- last_request_pair = history.last(1)[0]
32
- except IndexError:
33
- last_request_pair = None
34
- last_request_id = None
35
- else:
36
- last_request_id = last_request_pair[0]
37
-
38
- request_id = request.matchdict.get("request_id", last_request_id)
39
- toolbar = history.get(request_id, None)
40
-
41
- if not toolbar:
42
- raise NotFound
43
-
44
- panel = get_performance_panel(toolbar.panels)
45
- if not panel:
46
- raise NotFound
47
-
48
- return request_id, panel
49
-
50
-
51
- @view_config(route_name="debugtoolbar.api_performance_csv.timing")
52
- def csv_timing(request):
53
- (request_id, panel) = _standardized_setup(request)
54
-
55
- csvfile = StringIO()
56
- csvwriter = csv.writer(csvfile)
57
- for row in panel.data["timing_rows"]:
58
- # row is `label, timing`
59
- # example:
60
- # 'timing_rows': (('User CPU time', '119.678 msec'),
61
- # ('System CPU time', '64.695 msec'),
62
- # ('Total CPU time', '184.373 msec'),
63
- # ('Elapsed time', '205.099 msec'),
64
- # ('Context switches', '19 voluntary, 1233 involuntary')
65
- # )
66
- csvwriter.writerow(row)
67
- csvfile.seek(0)
68
- as_csv = Response(
69
- content_type="text/csv", body=csvfile.read(), status=200, charset=ENCODING
70
- )
71
- as_csv.headers["Content-Disposition"] = str(
72
- "attachment; filename= performance-timing-%s.csv" % request_id
73
- )
74
- return as_csv
75
-
76
-
77
- @view_config(route_name="debugtoolbar.api_performance_csv.function_calls")
78
- def csv_function_calls(request):
79
- (request_id, panel) = _standardized_setup(request)
80
-
81
- csvfile = StringIO()
82
- csvwriter = csv.writer(csvfile)
83
- if panel.data["stats"]:
84
- csvwriter.writerow(("Calls", "Total", "Percall", "Cumu", "CumuPer", "Func"))
85
- for row in panel.data["function_calls"]:
86
- csvwriter.writerow(
87
- (
88
- row["ncalls"],
89
- row["tottime"],
90
- row["percall"],
91
- row["cumtime"],
92
- row["percall_cum"],
93
- row["filename_long"],
94
- )
95
- )
96
- csvfile.seek(0)
97
- as_csv = Response(
98
- content_type="text/csv", body=csvfile.read(), status=200, charset=ENCODING
99
- )
100
- as_csv.headers["Content-Disposition"] = str(
101
- "attachment; filename= performance-function_calls-%s.csv" % request_id
102
- )
103
- return as_csv
@@ -1,91 +0,0 @@
1
- Metadata-Version: 2.1
2
- Name: pyramid-debugtoolbar-api-performance
3
- Version: 0.3.1
4
- Summary: performance csv exporting for pyramid_debugtoolbar
5
- Home-page: https://github.com/jvanasco/pyramid_debugtoolbar_api_performance
6
- Author: Jonathan Vanasco
7
- Author-email: jonathan@findmeon.com
8
- License: MIT
9
- Description: pyramid_debugtoolbar_api_performance
10
- ====================================
11
-
12
- .. image:: https://github.com/jvanasco/pyramid_debugtoolbar_api_performance/workflows/Python%20package/badge.svg
13
- :alt: Build Status
14
-
15
- `pyramid_debugtoolbar_api_performance` extends the existing `pyramid_debugtoolbar`
16
- Performance 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 Performance
22
- performance.
23
-
24
- The package exposes two routes for CSV data:
25
-
26
- * timing
27
- * function_calls
28
-
29
- Both correlate to the official Performance panel data.
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_performance
50
-
51
- You MUST be using `pyramid_debugtoolbar` with the Performance panel enabled.
52
- This package simply 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 Profiling 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-performance/timing-{request_id}.csv'
62
- url_api = '/_debug_toolbar/api-performance/function_calls-{request_id}.csv'
63
-
64
-
65
- The file will be downloaded and offer a content-disposition as:
66
-
67
- .. code-block:: shell
68
-
69
- performance-{request_id}.csv
70
-
71
- Configuration
72
- =======================
73
-
74
- By default, this package writes CSV files using "UTF-8" encoding.
75
-
76
- To change this, use the environment variable `pyramid_debugtoolbar_api_performance_encoding`
77
-
78
- .. code-block:: shell
79
-
80
- export pyramid_debugtoolbar_api_performance_encoding=ascii
81
-
82
- Keywords: web pyramid
83
- Platform: UNKNOWN
84
- Classifier: Intended Audience :: Developers
85
- Classifier: Framework :: Pyramid
86
- Classifier: Programming Language :: Python
87
- Classifier: Programming Language :: Python :: 2
88
- Classifier: Programming Language :: Python :: 3
89
- Classifier: License :: OSI Approved :: MIT License
90
- Description-Content-Type: text/markdown
91
- Provides-Extra: testing
@@ -1,6 +0,0 @@
1
- pyramid
2
- pyramid_debugtoolbar>=4.0
3
- six
4
-
5
- [testing]
6
- pytest
@@ -1,12 +0,0 @@
1
- [tox]
2
- envlist =
3
- lint,
4
- py27,
5
- py35,py36,py37,py38
6
-
7
- [testenv]
8
- extras =
9
- testing
10
- commands =
11
- python --version
12
- pytest {posargs:}