py4web-debug-tools 1.3.3__tar.gz → 1.3.4__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 (22) hide show
  1. {py4web_debug_tools-1.3.3 → py4web_debug_tools-1.3.4}/CHANGELOG.md +10 -0
  2. {py4web_debug_tools-1.3.3 → py4web_debug_tools-1.3.4}/PKG-INFO +1 -1
  3. py4web_debug_tools-1.3.4/src/py4web_debug/__about__.py +1 -0
  4. {py4web_debug_tools-1.3.3 → py4web_debug_tools-1.3.4}/src/py4web_debug/dumping.py +24 -2
  5. {py4web_debug_tools-1.3.3 → py4web_debug_tools-1.3.4}/tests/test_dumping.py +22 -1
  6. py4web_debug_tools-1.3.3/src/py4web_debug/__about__.py +0 -1
  7. {py4web_debug_tools-1.3.3 → py4web_debug_tools-1.3.4}/.gitignore +0 -0
  8. {py4web_debug_tools-1.3.3 → py4web_debug_tools-1.3.4}/README.md +0 -0
  9. {py4web_debug_tools-1.3.3 → py4web_debug_tools-1.3.4}/pyproject.toml +0 -0
  10. {py4web_debug_tools-1.3.3 → py4web_debug_tools-1.3.4}/src/py4web_debug/__init__.py +0 -0
  11. {py4web_debug_tools-1.3.3 → py4web_debug_tools-1.3.4}/src/py4web_debug/_internals.py +0 -0
  12. {py4web_debug_tools-1.3.3 → py4web_debug_tools-1.3.4}/src/py4web_debug/core.py +0 -0
  13. {py4web_debug_tools-1.3.3 → py4web_debug_tools-1.3.4}/src/py4web_debug/debugbar.py +0 -0
  14. {py4web_debug_tools-1.3.3 → py4web_debug_tools-1.3.4}/src/py4web_debug/env.py +0 -0
  15. {py4web_debug_tools-1.3.3 → py4web_debug_tools-1.3.4}/src/py4web_debug/internals.py +0 -0
  16. {py4web_debug_tools-1.3.3 → py4web_debug_tools-1.3.4}/src/py4web_debug/py.typed +0 -0
  17. {py4web_debug_tools-1.3.3 → py4web_debug_tools-1.3.4}/src/py4web_debug/templates/debugbar.html +0 -0
  18. {py4web_debug_tools-1.3.3 → py4web_debug_tools-1.3.4}/src/py4web_debug/templates/dumpdie.html +0 -0
  19. {py4web_debug_tools-1.3.3 → py4web_debug_tools-1.3.4}/src/py4web_debug/templates/error_default.html +0 -0
  20. {py4web_debug_tools-1.3.3 → py4web_debug_tools-1.3.4}/src/py4web_debug/templates/fancy_dumpdie.html +0 -0
  21. {py4web_debug_tools-1.3.3 → py4web_debug_tools-1.3.4}/src/py4web_debug/types.py +0 -0
  22. {py4web_debug_tools-1.3.3 → py4web_debug_tools-1.3.4}/src/py4web_debug/wsgi.py +0 -0
@@ -2,8 +2,18 @@
2
2
 
3
3
  <!--next-version-placeholder-->
4
4
 
5
+ ## v1.3.4 (2026-08-06)
6
+
7
+ ### Fix
8
+
9
+ * Improved error message if json failed to `dump()` ([`920b786`](https://github.com/trialandsuccess/py4web-debug-tools/commit/920b78685cfc89cf27269972326562da7c4d05f6))
10
+
5
11
  ## v1.3.3 (2026-08-06)
6
12
 
13
+ ### Fix
14
+
15
+ * Fix JSON dumping for TypeDAL model classes and DotMap-like objects whose dynamic attribute lookup makes hasattr()
16
+ return misleading results. ([PR 2](https://github.com/trialandsuccess/py4web-debug-tools/pull/2))
7
17
 
8
18
 
9
19
  ## v1.3.2 (2025-12-12)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: py4web-debug-tools
3
- Version: 1.3.3
3
+ Version: 1.3.4
4
4
  Summary: Debug Tools for py4web
5
5
  Project-URL: Documentation, https://github.com/trialandsuccess/py4web-debug-tools#readme
6
6
  Project-URL: Issues, https://github.com/trialandsuccess/py4web-debug-tools/issues
@@ -0,0 +1 @@
1
+ __version__ = "1.3.4"
@@ -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
- return json.dumps(data, indent=2, cls=DDJsonEncoder)
106
- # return json.dumps(data, indent=2, default=DDJsonEncoder._default)
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):
@@ -1,9 +1,10 @@
1
1
  from types import SimpleNamespace
2
2
 
3
+ import pytest
3
4
  from dotmap import DotMap
4
5
  from pytest import MonkeyPatch
5
6
 
6
- from src.py4web_debug.dumping import DDJsonEncoder, DumpDieError, dd, dump
7
+ from src.py4web_debug.dumping import DDJsonEncoder, DumpDieError, DumpSerializationError, dd, dump
7
8
 
8
9
 
9
10
  def _sample_dotmap() -> DotMap:
@@ -97,3 +98,23 @@ def test_dump_reproduces_as_list_crash_without_dotmap():
97
98
 
98
99
  entry2 = SimpleNamespace(label="Aanbod beheren", model=Offering)
99
100
  dump(entry2, with_headers=False)
101
+
102
+
103
+ def test_dump_wraps_unexpected_errors_with_context():
104
+ """
105
+ Force *some other* JSON-serialization failure (a plain circular reference,
106
+ nothing to do with DotMap/permissive __getattr__) to prove dump() wraps
107
+ whatever goes wrong with a nicer, actionable error instead of leaking a
108
+ bare exception from deep inside json.dumps()/DDJsonEncoder.
109
+ """
110
+ circular: dict = {}
111
+ circular["self"] = circular
112
+
113
+ with pytest.raises(DumpSerializationError) as exc_info:
114
+ dump(circular, with_headers=False)
115
+
116
+ err = exc_info.value
117
+ assert "could not JSON-serialize" in str(err)
118
+ assert "dict" in str(err) # names the top-level type that was being dumped
119
+ assert isinstance(err.__cause__, ValueError) # original error is preserved/chained
120
+ assert "circular" in str(err.__cause__).lower()
@@ -1 +0,0 @@
1
- __version__ = "1.3.3"