py4web-debug-tools 1.3.3__tar.gz → 1.4.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.
- {py4web_debug_tools-1.3.3 → py4web_debug_tools-1.4.0}/PKG-INFO +14 -14
- {py4web_debug_tools-1.3.3 → py4web_debug_tools-1.4.0}/README.md +1 -3
- py4web_debug_tools-1.4.0/pyproject.toml +179 -0
- py4web_debug_tools-1.3.3/pyproject.toml → py4web_debug_tools-1.4.0/pyproject.toml.orig +49 -20
- py4web_debug_tools-1.4.0/src/py4web_debug/__about__.py +3 -0
- {py4web_debug_tools-1.3.3 → py4web_debug_tools-1.4.0}/src/py4web_debug/core.py +2 -1
- {py4web_debug_tools-1.3.3 → py4web_debug_tools-1.4.0}/src/py4web_debug/dumping.py +24 -2
- {py4web_debug_tools-1.3.3 → py4web_debug_tools-1.4.0}/src/py4web_debug/internals.py +11 -1
- py4web_debug_tools-1.3.3/.gitignore +0 -8
- py4web_debug_tools-1.3.3/CHANGELOG.md +0 -79
- py4web_debug_tools-1.3.3/src/py4web_debug/__about__.py +0 -1
- py4web_debug_tools-1.3.3/tests/test_dumping.py +0 -99
- {py4web_debug_tools-1.3.3 → py4web_debug_tools-1.4.0}/src/py4web_debug/__init__.py +0 -0
- {py4web_debug_tools-1.3.3 → py4web_debug_tools-1.4.0}/src/py4web_debug/_internals.py +0 -0
- {py4web_debug_tools-1.3.3 → py4web_debug_tools-1.4.0}/src/py4web_debug/debugbar.py +0 -0
- {py4web_debug_tools-1.3.3 → py4web_debug_tools-1.4.0}/src/py4web_debug/env.py +0 -0
- {py4web_debug_tools-1.3.3 → py4web_debug_tools-1.4.0}/src/py4web_debug/py.typed +0 -0
- {py4web_debug_tools-1.3.3 → py4web_debug_tools-1.4.0}/src/py4web_debug/templates/debugbar.html +0 -0
- {py4web_debug_tools-1.3.3 → py4web_debug_tools-1.4.0}/src/py4web_debug/templates/dumpdie.html +0 -0
- {py4web_debug_tools-1.3.3 → py4web_debug_tools-1.4.0}/src/py4web_debug/templates/error_default.html +0 -0
- {py4web_debug_tools-1.3.3 → py4web_debug_tools-1.4.0}/src/py4web_debug/templates/fancy_dumpdie.html +0 -0
- {py4web_debug_tools-1.3.3 → py4web_debug_tools-1.4.0}/src/py4web_debug/types.py +0 -0
- {py4web_debug_tools-1.3.3 → py4web_debug_tools-1.4.0}/src/py4web_debug/wsgi.py +0 -0
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: py4web-debug-tools
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.4.0
|
|
4
4
|
Summary: Debug Tools for py4web
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
Project-URL: Source, https://github.com/trialandsuccess/py4web-debug-tools
|
|
5
|
+
Keywords:
|
|
6
|
+
Author: Robin van der Noord
|
|
8
7
|
Author-email: Robin van der Noord <contact@trialandsuccess.nl>
|
|
9
8
|
License-Expression: MIT
|
|
10
9
|
Classifier: Development Status :: 4 - Beta
|
|
@@ -12,19 +11,22 @@ Classifier: Programming Language :: Python
|
|
|
12
11
|
Classifier: Programming Language :: Python :: 3.10
|
|
13
12
|
Classifier: Programming Language :: Python :: 3.11
|
|
14
13
|
Classifier: Programming Language :: Python :: 3.12
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
15
15
|
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
16
16
|
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
|
17
|
-
Requires-Python: >=3.10
|
|
18
|
-
Requires-Dist: configurable-json>=1.1
|
|
19
17
|
Requires-Dist: py4web
|
|
18
|
+
Requires-Dist: yatl
|
|
20
19
|
Requires-Dist: pydal
|
|
20
|
+
Requires-Dist: configurable-json>=1.1
|
|
21
21
|
Requires-Dist: typing-extensions
|
|
22
|
-
Requires-Dist:
|
|
22
|
+
Requires-Dist: su6[all] ; extra == 'dev'
|
|
23
|
+
Requires-Dist: pytest ; extra == 'dev'
|
|
24
|
+
Requires-Dist: dotmap ; extra == 'dev'
|
|
25
|
+
Requires-Python: >=3.10
|
|
26
|
+
Project-URL: Documentation, https://github.com/trialandsuccess/py4web-debug-tools#readme
|
|
27
|
+
Project-URL: Issues, https://github.com/trialandsuccess/py4web-debug-tools/issues
|
|
28
|
+
Project-URL: Source, https://github.com/trialandsuccess/py4web-debug-tools
|
|
23
29
|
Provides-Extra: dev
|
|
24
|
-
Requires-Dist: dotmap; extra == 'dev'
|
|
25
|
-
Requires-Dist: hatch; extra == 'dev'
|
|
26
|
-
Requires-Dist: pytest; extra == 'dev'
|
|
27
|
-
Requires-Dist: su6[all]; extra == 'dev'
|
|
28
30
|
Description-Content-Type: text/markdown
|
|
29
31
|
|
|
30
32
|
# py4web debug tools
|
|
@@ -109,9 +111,7 @@ You can modify your `py4web_uwsgi.py` file:
|
|
|
109
111
|
# yes:
|
|
110
112
|
from py4web_debug import wsgi
|
|
111
113
|
|
|
112
|
-
application = wsgi(apps_folder="apps",
|
|
113
|
-
password_file='password.txt',
|
|
114
|
-
dashboard_mode="full")
|
|
114
|
+
application = wsgi(apps_folder="apps", password_file="password.txt", dashboard_mode="full")
|
|
115
115
|
```
|
|
116
116
|
|
|
117
117
|
After this, you can `tools.enable` as before.
|
|
@@ -80,9 +80,7 @@ You can modify your `py4web_uwsgi.py` file:
|
|
|
80
80
|
# yes:
|
|
81
81
|
from py4web_debug import wsgi
|
|
82
82
|
|
|
83
|
-
application = wsgi(apps_folder="apps",
|
|
84
|
-
password_file='password.txt',
|
|
85
|
-
dashboard_mode="full")
|
|
83
|
+
application = wsgi(apps_folder="apps", password_file="password.txt", dashboard_mode="full")
|
|
86
84
|
```
|
|
87
85
|
|
|
88
86
|
After this, you can `tools.enable` as before.
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["uv_build>=0.12.4,<0.13"]
|
|
3
|
+
build-backend = "uv_build"
|
|
4
|
+
|
|
5
|
+
[template.plugins.default]
|
|
6
|
+
src-layout = true
|
|
7
|
+
|
|
8
|
+
[tool.setuptools.package-data]
|
|
9
|
+
py4web_debug = ["py.typed"]
|
|
10
|
+
|
|
11
|
+
[tool.uv.build-backend]
|
|
12
|
+
module-name = "py4web_debug"
|
|
13
|
+
|
|
14
|
+
[tool.vommit]
|
|
15
|
+
allow_breaking_bang = true
|
|
16
|
+
allow_breaking_footer = true
|
|
17
|
+
prerelease_token = "beta"
|
|
18
|
+
confirm = true
|
|
19
|
+
ignore = []
|
|
20
|
+
|
|
21
|
+
[tool.vommit.git]
|
|
22
|
+
enabled = true
|
|
23
|
+
origin = "origin"
|
|
24
|
+
branch = "master"
|
|
25
|
+
on_wrong_branch = "error"
|
|
26
|
+
tag_format = "v{version}"
|
|
27
|
+
commit_format = "{version}"
|
|
28
|
+
|
|
29
|
+
[tool.vommit.changelog]
|
|
30
|
+
enabled = true
|
|
31
|
+
file = "CHANGELOG.md"
|
|
32
|
+
include_prereleases = false
|
|
33
|
+
placeholder = "<!--next-version-placeholder-->"
|
|
34
|
+
placeholder_regex = "<auto>"
|
|
35
|
+
entry_title_format = "## v{version} ({date:%Y-%m-%d})"
|
|
36
|
+
|
|
37
|
+
[tool.vommit.changelog.levels]
|
|
38
|
+
feat = "Feature{s}"
|
|
39
|
+
fix = "Fix{es}"
|
|
40
|
+
break = "Breaking Change{s}"
|
|
41
|
+
docs = "Documentation"
|
|
42
|
+
perf = "Performance"
|
|
43
|
+
|
|
44
|
+
[tool.vommit.pypi]
|
|
45
|
+
enabled = true
|
|
46
|
+
use_keyring = true
|
|
47
|
+
|
|
48
|
+
[tool.vommit.commands]
|
|
49
|
+
clean = "rm -rf ./dist"
|
|
50
|
+
build = "uv build"
|
|
51
|
+
publish = "uv publish"
|
|
52
|
+
post_publish = ""
|
|
53
|
+
|
|
54
|
+
[tool.vommit.version_bump_map]
|
|
55
|
+
break = "major"
|
|
56
|
+
feat = "minor"
|
|
57
|
+
fix = "patch"
|
|
58
|
+
perf = "patch"
|
|
59
|
+
|
|
60
|
+
[tool.pytest.ini_options]
|
|
61
|
+
testpaths = ["tests"]
|
|
62
|
+
pythonpath = ["."]
|
|
63
|
+
|
|
64
|
+
[tool.su6]
|
|
65
|
+
directory = "src"
|
|
66
|
+
include = []
|
|
67
|
+
exclude = ["pytest"]
|
|
68
|
+
stop-after-first-failure = true
|
|
69
|
+
|
|
70
|
+
[tool.black]
|
|
71
|
+
target-version = ["py311"]
|
|
72
|
+
line-length = 120
|
|
73
|
+
extend-exclude = '''
|
|
74
|
+
# A regex preceded with ^/ will apply only to files and directories
|
|
75
|
+
# in the root of the project.
|
|
76
|
+
(
|
|
77
|
+
^.*\.bak\/.+ # ignore every .bak directory
|
|
78
|
+
^.*venv.+\/.+ # ignore every venv directory
|
|
79
|
+
venv.+|.+\.bak # idk why it suddenly works, let's not touch it
|
|
80
|
+
)
|
|
81
|
+
'''
|
|
82
|
+
|
|
83
|
+
[tool.mypy]
|
|
84
|
+
python_version = "3.11"
|
|
85
|
+
no_implicit_optional = false
|
|
86
|
+
ignore_missing_imports = true
|
|
87
|
+
strict = true
|
|
88
|
+
exclude = [
|
|
89
|
+
"venv",
|
|
90
|
+
".bak",
|
|
91
|
+
]
|
|
92
|
+
|
|
93
|
+
[tool.ruff]
|
|
94
|
+
target-version = "py311"
|
|
95
|
+
line-length = 120
|
|
96
|
+
extend-exclude = [
|
|
97
|
+
"*.bak/",
|
|
98
|
+
"venv*/",
|
|
99
|
+
]
|
|
100
|
+
|
|
101
|
+
[tool.ruff.lint]
|
|
102
|
+
select = [
|
|
103
|
+
"F",
|
|
104
|
+
"E",
|
|
105
|
+
"W",
|
|
106
|
+
"Q",
|
|
107
|
+
"A",
|
|
108
|
+
"SIM",
|
|
109
|
+
"ARG",
|
|
110
|
+
"RUF",
|
|
111
|
+
]
|
|
112
|
+
unfixable = ["F401"]
|
|
113
|
+
ignore = ["RUF013"]
|
|
114
|
+
|
|
115
|
+
[tool.bandit]
|
|
116
|
+
exclude_dirs = [
|
|
117
|
+
".bak",
|
|
118
|
+
"venv",
|
|
119
|
+
]
|
|
120
|
+
skips = ["B108"]
|
|
121
|
+
|
|
122
|
+
[tool.isort]
|
|
123
|
+
profile = "black"
|
|
124
|
+
extend_skip_glob = ["*.bak/*"]
|
|
125
|
+
|
|
126
|
+
[tool.pydocstyle]
|
|
127
|
+
convention = "google"
|
|
128
|
+
match-dir = '(?!venv)[^\.].*'
|
|
129
|
+
add_select = [
|
|
130
|
+
"D213",
|
|
131
|
+
"D416",
|
|
132
|
+
"D417",
|
|
133
|
+
]
|
|
134
|
+
add_ignore = [
|
|
135
|
+
"D200",
|
|
136
|
+
"D212",
|
|
137
|
+
]
|
|
138
|
+
|
|
139
|
+
[project]
|
|
140
|
+
name = "py4web-debug-tools"
|
|
141
|
+
description = "Debug Tools for py4web"
|
|
142
|
+
readme = "README.md"
|
|
143
|
+
requires-python = ">=3.10"
|
|
144
|
+
license = "MIT"
|
|
145
|
+
keywords = []
|
|
146
|
+
classifiers = [
|
|
147
|
+
"Development Status :: 4 - Beta",
|
|
148
|
+
"Programming Language :: Python",
|
|
149
|
+
"Programming Language :: Python :: 3.10",
|
|
150
|
+
"Programming Language :: Python :: 3.11",
|
|
151
|
+
"Programming Language :: Python :: 3.12",
|
|
152
|
+
"Programming Language :: Python :: 3.14",
|
|
153
|
+
"Programming Language :: Python :: Implementation :: CPython",
|
|
154
|
+
"Programming Language :: Python :: Implementation :: PyPy",
|
|
155
|
+
]
|
|
156
|
+
dependencies = [
|
|
157
|
+
"py4web",
|
|
158
|
+
"yatl",
|
|
159
|
+
"pydal",
|
|
160
|
+
"configurable-json >= 1.1",
|
|
161
|
+
"typing-extensions",
|
|
162
|
+
]
|
|
163
|
+
version = "1.4.0"
|
|
164
|
+
|
|
165
|
+
[[project.authors]]
|
|
166
|
+
name = "Robin van der Noord"
|
|
167
|
+
email = "contact@trialandsuccess.nl"
|
|
168
|
+
|
|
169
|
+
[project.urls]
|
|
170
|
+
Documentation = "https://github.com/trialandsuccess/py4web-debug-tools#readme"
|
|
171
|
+
Issues = "https://github.com/trialandsuccess/py4web-debug-tools/issues"
|
|
172
|
+
Source = "https://github.com/trialandsuccess/py4web-debug-tools"
|
|
173
|
+
|
|
174
|
+
[project.optional-dependencies]
|
|
175
|
+
dev = [
|
|
176
|
+
"su6[all]",
|
|
177
|
+
"pytest",
|
|
178
|
+
"dotmap",
|
|
179
|
+
]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[build-system]
|
|
2
|
-
requires = ["
|
|
3
|
-
build-backend = "
|
|
2
|
+
requires = ["uv_build>=0.12.4,<0.13"]
|
|
3
|
+
build-backend = "uv_build"
|
|
4
4
|
|
|
5
5
|
[template.plugins.default]
|
|
6
6
|
src-layout = true
|
|
@@ -8,17 +8,11 @@ src-layout = true
|
|
|
8
8
|
[tool.setuptools.package-data]
|
|
9
9
|
"py4web_debug" = ["py.typed"]
|
|
10
10
|
|
|
11
|
-
[tool.
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
[tool.hatch.build]
|
|
15
|
-
artifacts = [
|
|
16
|
-
"src/py4web_debug/templates/*.html"
|
|
17
|
-
]
|
|
11
|
+
[tool.uv.build-backend]
|
|
12
|
+
module-name = "py4web_debug"
|
|
18
13
|
|
|
19
14
|
[project]
|
|
20
15
|
name = "py4web-debug-tools"
|
|
21
|
-
dynamic = ["version"]
|
|
22
16
|
description = 'Debug Tools for py4web'
|
|
23
17
|
readme = "README.md"
|
|
24
18
|
requires-python = ">=3.10"
|
|
@@ -33,6 +27,7 @@ classifiers = [
|
|
|
33
27
|
"Programming Language :: Python :: 3.10",
|
|
34
28
|
"Programming Language :: Python :: 3.11",
|
|
35
29
|
"Programming Language :: Python :: 3.12",
|
|
30
|
+
"Programming Language :: Python :: 3.14",
|
|
36
31
|
"Programming Language :: Python :: Implementation :: CPython",
|
|
37
32
|
"Programming Language :: Python :: Implementation :: PyPy",
|
|
38
33
|
]
|
|
@@ -43,6 +38,7 @@ dependencies = [
|
|
|
43
38
|
"configurable-json >= 1.1",
|
|
44
39
|
"typing-extensions",
|
|
45
40
|
]
|
|
41
|
+
version = "1.4.0"
|
|
46
42
|
|
|
47
43
|
|
|
48
44
|
[project.urls]
|
|
@@ -53,23 +49,56 @@ Source = "https://github.com/trialandsuccess/py4web-debug-tools"
|
|
|
53
49
|
[project.optional-dependencies]
|
|
54
50
|
dev = [
|
|
55
51
|
"su6[all]",
|
|
56
|
-
"hatch",
|
|
57
52
|
"pytest",
|
|
58
53
|
"dotmap",
|
|
59
54
|
]
|
|
60
55
|
|
|
61
56
|
|
|
62
|
-
[tool.
|
|
63
|
-
|
|
57
|
+
[tool.vommit]
|
|
58
|
+
allow_breaking_bang = true
|
|
59
|
+
allow_breaking_footer = true
|
|
60
|
+
prerelease_token = "beta"
|
|
61
|
+
confirm = true
|
|
62
|
+
ignore = []
|
|
64
63
|
|
|
65
|
-
[tool.
|
|
64
|
+
[tool.vommit.git]
|
|
65
|
+
enabled = true
|
|
66
|
+
origin = "origin"
|
|
66
67
|
branch = "master"
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
68
|
+
on_wrong_branch = "error"
|
|
69
|
+
tag_format = "v{version}"
|
|
70
|
+
commit_format = "{version}"
|
|
71
|
+
|
|
72
|
+
[tool.vommit.changelog]
|
|
73
|
+
enabled = true
|
|
74
|
+
file = "CHANGELOG.md"
|
|
75
|
+
include_prereleases = false
|
|
76
|
+
placeholder = "<!--next-version-placeholder-->"
|
|
77
|
+
placeholder_regex = "<auto>"
|
|
78
|
+
entry_title_format = "## v{version} ({date:%Y-%m-%d})"
|
|
79
|
+
|
|
80
|
+
[tool.vommit.changelog.levels]
|
|
81
|
+
feat = "Feature{s}"
|
|
82
|
+
fix = "Fix{es}"
|
|
83
|
+
break = "Breaking Change{s}"
|
|
84
|
+
docs = "Documentation"
|
|
85
|
+
perf = "Performance"
|
|
86
|
+
|
|
87
|
+
[tool.vommit.pypi]
|
|
88
|
+
enabled = true
|
|
89
|
+
use_keyring = true
|
|
90
|
+
|
|
91
|
+
[tool.vommit.commands]
|
|
92
|
+
clean = "rm -rf ./dist"
|
|
93
|
+
build = "uv build"
|
|
94
|
+
publish = "uv publish"
|
|
95
|
+
post_publish = ""
|
|
96
|
+
|
|
97
|
+
[tool.vommit.version_bump_map]
|
|
98
|
+
break = "major"
|
|
99
|
+
feat = "minor"
|
|
100
|
+
fix = "patch"
|
|
101
|
+
perf = "patch"
|
|
73
102
|
|
|
74
103
|
[tool.pytest.ini_options]
|
|
75
104
|
testpaths = ["tests"]
|
|
@@ -52,6 +52,7 @@ class DebugTools:
|
|
|
52
52
|
debugbar_fancy_rendering: bool = True,
|
|
53
53
|
debugbar_style: typing.Literal["bootstrap"] = "bootstrap",
|
|
54
54
|
debugbar_slow_threshold_ms: int = 10,
|
|
55
|
+
errorpage_json_renderer: T_Renderer = None,
|
|
55
56
|
) -> None:
|
|
56
57
|
"""
|
|
57
58
|
By default, on_off looks at PY4WEB_DEBUG_MODE in the env
|
|
@@ -73,7 +74,7 @@ class DebugTools:
|
|
|
73
74
|
|
|
74
75
|
if enabled:
|
|
75
76
|
if self.config.errorpage.enabled:
|
|
76
|
-
patch_py4(errorpage_renderer, error_logger)
|
|
77
|
+
patch_py4(errorpage_renderer, error_logger, json_renderer=errorpage_json_renderer)
|
|
77
78
|
|
|
78
79
|
if self.config.debugbar.enabled:
|
|
79
80
|
if not db:
|
|
@@ -102,8 +102,30 @@ def dump(data: typing.Iterable[typing.Any], with_headers: bool = True) -> str:
|
|
|
102
102
|
if with_headers:
|
|
103
103
|
response.headers["Content-Type"] = "application/json"
|
|
104
104
|
|
|
105
|
-
|
|
106
|
-
|
|
105
|
+
try:
|
|
106
|
+
return json.dumps(data, indent=2, cls=DDJsonEncoder)
|
|
107
|
+
# return json.dumps(data, indent=2, default=DDJsonEncoder._default)
|
|
108
|
+
except Exception as e:
|
|
109
|
+
raise DumpSerializationError(data, e) from e
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
class DumpSerializationError(TypeError):
|
|
113
|
+
"""
|
|
114
|
+
Raised by dump() when the data (or something nested inside it) could not be
|
|
115
|
+
JSON-serialized, even with DDJsonEncoder's custom object-to-dict fallback rules.
|
|
116
|
+
|
|
117
|
+
Wraps the original error (still available via `__cause__`/`.original`) with
|
|
118
|
+
context about what was being dumped, so this is actionable instead of a bare
|
|
119
|
+
stdlib error surfacing from deep inside json.dumps()/DDJsonEncoder internals.
|
|
120
|
+
"""
|
|
121
|
+
|
|
122
|
+
def __init__(self, data: typing.Any, original: Exception) -> None:
|
|
123
|
+
self.data = data
|
|
124
|
+
self.original = original
|
|
125
|
+
super().__init__(
|
|
126
|
+
f"dump() could not JSON-serialize this data (top-level type: {type(data).__name__}): "
|
|
127
|
+
f"{original.__class__.__name__}: {original}"
|
|
128
|
+
)
|
|
107
129
|
|
|
108
130
|
|
|
109
131
|
class DumpDieError(Exception):
|
|
@@ -51,6 +51,7 @@ def custom_error_page(
|
|
|
51
51
|
err_type: str | typing.Type[Exception] | None = None,
|
|
52
52
|
bare_exception: typing.Optional[Exception | str] = None,
|
|
53
53
|
renderer: T_Renderer = None,
|
|
54
|
+
json_renderer: T_Renderer = None,
|
|
54
55
|
) -> str:
|
|
55
56
|
if err_type and not isinstance(err_type, str):
|
|
56
57
|
err_type = err_type.__name__
|
|
@@ -78,6 +79,10 @@ def custom_error_page(
|
|
|
78
79
|
# if client accepts 'application/json' - return json
|
|
79
80
|
if re.search(REGEX_APPJSON, request.headers.get("accept", "")):
|
|
80
81
|
response.status = code
|
|
82
|
+
response.headers["Content-Type"] = "application/json"
|
|
83
|
+
if json_renderer:
|
|
84
|
+
return json_renderer(context)
|
|
85
|
+
|
|
81
86
|
return dump(context)
|
|
82
87
|
# else - return html error-page
|
|
83
88
|
|
|
@@ -119,9 +124,12 @@ T_Logger = typing.Callable[[ErrorSnapshot], None]
|
|
|
119
124
|
class patch_py4:
|
|
120
125
|
# THIS IS ONLY CALLED ONCE, WHEN tools.enable IS CALLED OR py4web_debug.wsgi IS USED!
|
|
121
126
|
renderer: T_Renderer | None = None
|
|
127
|
+
json_renderer: T_Renderer | None = None
|
|
122
128
|
logger: T_Logger | typing.Literal[False] | None = None
|
|
123
129
|
|
|
124
|
-
def __init__(
|
|
130
|
+
def __init__(
|
|
131
|
+
_, renderer: T_Renderer = None, logger: T_Logger | bool | None = None, json_renderer: T_Renderer = None
|
|
132
|
+
):
|
|
125
133
|
# note: don't use self, use patch_py4 instead
|
|
126
134
|
if logger is True:
|
|
127
135
|
# use default logger:
|
|
@@ -169,6 +177,7 @@ class patch_py4:
|
|
|
169
177
|
err_type=type(e),
|
|
170
178
|
bare_exception=e,
|
|
171
179
|
renderer=getattr(patch_py4, "renderer", None),
|
|
180
|
+
json_renderer=getattr(patch_py4, "json_renderer", None),
|
|
172
181
|
),
|
|
173
182
|
status=500,
|
|
174
183
|
)
|
|
@@ -181,5 +190,6 @@ class patch_py4:
|
|
|
181
190
|
|
|
182
191
|
# allows swapping renderer on the fly with tools.set_renderer():
|
|
183
192
|
patch_py4.renderer = renderer
|
|
193
|
+
patch_py4.json_renderer = json_renderer
|
|
184
194
|
_logger = getattr(patch_py4, "logger", None) or logger
|
|
185
195
|
patch_py4.logger = staticmethod(_logger) if callable(_logger) else _logger
|
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
# Changelog
|
|
2
|
-
|
|
3
|
-
<!--next-version-placeholder-->
|
|
4
|
-
|
|
5
|
-
## v1.3.3 (2026-08-06)
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
## v1.3.2 (2025-12-12)
|
|
10
|
-
|
|
11
|
-
### Fix
|
|
12
|
-
|
|
13
|
-
* Use existing debug-tools `dump` instead of py4web's `dumps`, hopefully to prevent circular import error ([`0d5afad`](https://github.com/trialandsuccess/py4web-debug-tools/commit/0d5afad2904834cf80d9252b89816b7ae360249a))
|
|
14
|
-
|
|
15
|
-
## v1.3.1 (2025-04-01)
|
|
16
|
-
|
|
17
|
-
### Fix
|
|
18
|
-
|
|
19
|
-
* **dbg:** Detect more variable names ([`a80556c`](https://github.com/trialandsuccess/py4web-debug-tools/commit/a80556c2d35f89a5c0f900518074b7800dfeb844))
|
|
20
|
-
|
|
21
|
-
## v1.3.0 (2025-04-01)
|
|
22
|
-
|
|
23
|
-
### Feature
|
|
24
|
-
|
|
25
|
-
* Add `dbg` helper ([`b7529e3`](https://github.com/trialandsuccess/py4web-debug-tools/commit/b7529e32bcaa88a237fa505d26afe3f013d0bdf2))
|
|
26
|
-
|
|
27
|
-
## v1.2.2 (2024-11-20)
|
|
28
|
-
|
|
29
|
-
### Fix
|
|
30
|
-
|
|
31
|
-
* Replace 'self' with 'patch_py4' for better stability ([`6987942`](https://github.com/trialandsuccess/py4web-debug-tools/commit/6987942347b993cf767166b6f3dac90e75989130))
|
|
32
|
-
|
|
33
|
-
## v1.2.1 (2024-11-20)
|
|
34
|
-
|
|
35
|
-
### Fix
|
|
36
|
-
|
|
37
|
-
* Allow logger to be set to False in case you're using py4webs default logger (PY4WEB_ERRORLOG=:stderr) ([`43639f3`](https://github.com/trialandsuccess/py4web-debug-tools/commit/43639f377d92b2f8b96bbdb31f61251fde95f831))
|
|
38
|
-
|
|
39
|
-
## v1.2.0 (2023-11-06)
|
|
40
|
-
### Feature
|
|
41
|
-
* Allow custom `error_logger` for tools.enable ([`a8301bc`](https://github.com/trialandsuccess/py4web-debug-tools/commit/a8301bc1762984fc5af420075acdc09e97bcc378))
|
|
42
|
-
|
|
43
|
-
## v1.1.4 (2023-07-19)
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
## v1.1.3 (2023-07-19)
|
|
47
|
-
### Fix
|
|
48
|
-
* Error page renderer can also be False (in addition to None or a method) ([`41d33aa`](https://github.com/trialandsuccess/py4web-debug-tools/commit/41d33aae9e307034b2818641c041f1dd6c8364fc))
|
|
49
|
-
|
|
50
|
-
## v1.1.2 (2023-07-19)
|
|
51
|
-
### Fix
|
|
52
|
-
* Wrapper can also return an HTTP response! ([`4431d80`](https://github.com/trialandsuccess/py4web-debug-tools/commit/4431d8094162dc9100aab2798571b87e5a076ed4))
|
|
53
|
-
|
|
54
|
-
## v1.1.1 (2023-07-19)
|
|
55
|
-
### Fix
|
|
56
|
-
* Bump `configurable-json` to new typed version ([`52fa55a`](https://github.com/trialandsuccess/py4web-debug-tools/commit/52fa55a3eb0d8e95064ddb9ecae820a2fa229a9a))
|
|
57
|
-
|
|
58
|
-
### Documentation
|
|
59
|
-
* Updated changelog ([`15a9517`](https://github.com/trialandsuccess/py4web-debug-tools/commit/15a9517f149b9bff272306c64165e9e62845e8d0))
|
|
60
|
-
|
|
61
|
-
## v1.1.0 (2023-07-19)
|
|
62
|
-
|
|
63
|
-
Moved to hatch build system.
|
|
64
|
-
|
|
65
|
-
## v1.0.0 (2023-07-17)
|
|
66
|
-
### Feature
|
|
67
|
-
* **config:** Multiple minor changes: ([`bb14fec`](https://github.com/trialandsuccess/py4web-debug-tools/commit/bb14fec07780826eb7f550cb9c5d0ed24df1f8b3))
|
|
68
|
-
* **debugbar:** Added required files ([`afc690f`](https://github.com/trialandsuccess/py4web-debug-tools/commit/afc690fb96ec2c9d54547434caffe7c1469302b1))
|
|
69
|
-
* **p4w-debug:** Initial module setup ([`b36c53c`](https://github.com/trialandsuccess/py4web-debug-tools/commit/b36c53c30206189bfcfcbea1c7236f12ae8becab))
|
|
70
|
-
|
|
71
|
-
### Fix
|
|
72
|
-
* Expose `is_debug` from the top-level library ([`dd73055`](https://github.com/trialandsuccess/py4web-debug-tools/commit/dd7305596a90db3b5902dcaa7d4e5f5c22c693c6))
|
|
73
|
-
* Expose `is_debug` from the top-level library ([`ee835e8`](https://github.com/trialandsuccess/py4web-debug-tools/commit/ee835e84983e74aa03825b346074469563e58fe6))
|
|
74
|
-
* **tools:** 'db' is only required when debugbar is used (debugbar_enabled=True) ([`dba49b8`](https://github.com/trialandsuccess/py4web-debug-tools/commit/dba49b85149b8aa8cf5992529be6942cd9b08de4))
|
|
75
|
-
|
|
76
|
-
### Documentation
|
|
77
|
-
* **readme:** Updated for style and missing `wsgi` ([`9394747`](https://github.com/trialandsuccess/py4web-debug-tools/commit/9394747b2e48a30c1902f5852955f85f9524c6b3))
|
|
78
|
-
* **tools:** Include all parameters of .enable() ([`90ccffc`](https://github.com/trialandsuccess/py4web-debug-tools/commit/90ccffcf6342b68434ad64ad945aea4c7c516cf1))
|
|
79
|
-
* **README:** Updated explaination ([`3f3b6b3`](https://github.com/trialandsuccess/py4web-debug-tools/commit/3f3b6b3f2f2fca29f4ac15851082e2e49ae288f8))
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "1.3.3"
|
|
@@ -1,99 +0,0 @@
|
|
|
1
|
-
from types import SimpleNamespace
|
|
2
|
-
|
|
3
|
-
from dotmap import DotMap
|
|
4
|
-
from pytest import MonkeyPatch
|
|
5
|
-
|
|
6
|
-
from src.py4web_debug.dumping import DDJsonEncoder, DumpDieError, dd, dump
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
def _sample_dotmap() -> DotMap:
|
|
10
|
-
data = DotMap()
|
|
11
|
-
data.a = 1
|
|
12
|
-
data.b.c = "nested"
|
|
13
|
-
return data
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
def test_dump_handles_dotmap():
|
|
17
|
-
# dump() should serialize a DotMap without crashing.
|
|
18
|
-
result = dump(_sample_dotmap(), with_headers=False)
|
|
19
|
-
|
|
20
|
-
assert '"a": 1' in result
|
|
21
|
-
assert '"c": "nested"' in result
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
def test_dd_handles_dotmap(monkeypatch: MonkeyPatch):
|
|
25
|
-
# dd() should not crash on a DotMap; in debug mode it raises a DumpDieError
|
|
26
|
-
# (by design) instead of letting json serialization blow up.
|
|
27
|
-
monkeypatch.setenv("PY4WEB_DEBUG_MODE", "1")
|
|
28
|
-
|
|
29
|
-
try:
|
|
30
|
-
dd(_sample_dotmap(), fancy=False)
|
|
31
|
-
except DumpDieError as e:
|
|
32
|
-
assert '"a": 1' in str(e)
|
|
33
|
-
else:
|
|
34
|
-
raise AssertionError("dd() should raise DumpDieError in debug mode")
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
def test_default_crashes_on_bare_dotmap():
|
|
38
|
-
"""
|
|
39
|
-
DotMap's __getattr__ returns an empty DotMap for ANY missing attribute
|
|
40
|
-
instead of raising AttributeError, so hasattr(dotmap, "as_list") is
|
|
41
|
-
always True even though `as_list` isn't a real method on it.
|
|
42
|
-
|
|
43
|
-
Note: dump()/dd() never hit this for a *bare* DotMap in practice, because
|
|
44
|
-
DotMap is a dict subclass and gets recognized (and recursed into) by
|
|
45
|
-
configurablejson's encoder before _default() is ever called - see
|
|
46
|
-
test_dump_handles_dotmap above, which passes fine. This test instead
|
|
47
|
-
calls DDJsonEncoder._default() directly, to pin the underlying flaw that
|
|
48
|
-
both this and the TypeDAL-model-class crash below share.
|
|
49
|
-
|
|
50
|
-
FAILS until DDJsonEncoder._default() is fixed:
|
|
51
|
-
TypeError: 'DotMap' object is not callable
|
|
52
|
-
"""
|
|
53
|
-
d = DotMap({"label": "Dashboard"})
|
|
54
|
-
|
|
55
|
-
DDJsonEncoder._default(d)
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
class _TableMetaLike(type):
|
|
59
|
-
"""
|
|
60
|
-
Reproduces TypeDAL's `TableMeta.__getattr__`: for an unbound model class,
|
|
61
|
-
any attribute that isn't a real column falls through to `return None`
|
|
62
|
-
instead of raising AttributeError (see typedal/tables.py TableMeta.__getattr__).
|
|
63
|
-
"""
|
|
64
|
-
|
|
65
|
-
def __getattr__(cls, name: str) -> None:
|
|
66
|
-
return None
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
class Offering(metaclass=_TableMetaLike):
|
|
70
|
-
"""Stand-in for a real TypeDAL model class, e.g. used as menu["model"]."""
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
def test_dump_reproduces_as_list_crash_on_model_class_value():
|
|
74
|
-
"""
|
|
75
|
-
Real-world crash reproduction (whitelabel AdminMenuFixture):
|
|
76
|
-
admin nav menu entries are plain dicts that carry a `"model"` key holding
|
|
77
|
-
the *model class itself* (e.g. `Offering`, not an instance). Wrapping such
|
|
78
|
-
an entry in a DotMap (for dot-access in templates) doesn't cause this —
|
|
79
|
-
a plain dict crashes identically, see test below.
|
|
80
|
-
|
|
81
|
-
FAILS until DDJsonEncoder._default() is fixed: it does
|
|
82
|
-
`if hasattr(o, "as_list"): o.as_list()` without checking it's callable.
|
|
83
|
-
TypeDAL's TableMeta.__getattr__ returns None for unknown attributes on a
|
|
84
|
-
model class instead of raising AttributeError, so hasattr() lies and
|
|
85
|
-
`o.as_list()` becomes `None()`. Matches production traceback exactly:
|
|
86
|
-
dumping.py:42 in _default -> TypeError: 'NoneType' object is not callable.
|
|
87
|
-
"""
|
|
88
|
-
entry = DotMap({"label": "Aanbod beheren", "icon": "fas fa-masks-theater", "model": Offering})
|
|
89
|
-
|
|
90
|
-
dump(entry, with_headers=False)
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
def test_dump_reproduces_as_list_crash_without_dotmap():
|
|
94
|
-
# Same crash with a plain dict: DotMap is incidental, not the cause.
|
|
95
|
-
entry1 = {"label": "Aanbod beheren", "model": Offering}
|
|
96
|
-
dump(entry1, with_headers=False)
|
|
97
|
-
|
|
98
|
-
entry2 = SimpleNamespace(label="Aanbod beheren", model=Offering)
|
|
99
|
-
dump(entry2, with_headers=False)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{py4web_debug_tools-1.3.3 → py4web_debug_tools-1.4.0}/src/py4web_debug/templates/debugbar.html
RENAMED
|
File without changes
|
{py4web_debug_tools-1.3.3 → py4web_debug_tools-1.4.0}/src/py4web_debug/templates/dumpdie.html
RENAMED
|
File without changes
|
{py4web_debug_tools-1.3.3 → py4web_debug_tools-1.4.0}/src/py4web_debug/templates/error_default.html
RENAMED
|
File without changes
|
{py4web_debug_tools-1.3.3 → py4web_debug_tools-1.4.0}/src/py4web_debug/templates/fancy_dumpdie.html
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|