tywrap 0.8.0 → 0.9.0
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.
- package/README.md +22 -7
- package/SECURITY.md +39 -0
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/index.js +8 -0
- package/dist/config/index.js.map +1 -1
- package/dist/core/annotation-parser.d.ts +2 -1
- package/dist/core/annotation-parser.d.ts.map +1 -1
- package/dist/core/annotation-parser.js +6 -3
- package/dist/core/annotation-parser.js.map +1 -1
- package/dist/core/generator.d.ts +23 -4
- package/dist/core/generator.d.ts.map +1 -1
- package/dist/core/generator.js +243 -170
- package/dist/core/generator.js.map +1 -1
- package/dist/core/mapper.d.ts +3 -2
- package/dist/core/mapper.d.ts.map +1 -1
- package/dist/core/mapper.js +5 -5
- package/dist/core/mapper.js.map +1 -1
- package/dist/index.d.ts +7 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -4
- package/dist/index.js.map +1 -1
- package/dist/runtime/base-bridge.d.ts +3 -7
- package/dist/runtime/base-bridge.d.ts.map +1 -1
- package/dist/runtime/base-bridge.js +4 -17
- package/dist/runtime/base-bridge.js.map +1 -1
- package/dist/runtime/bounded-context.d.ts +3 -22
- package/dist/runtime/bounded-context.d.ts.map +1 -1
- package/dist/runtime/bounded-context.js +13 -53
- package/dist/runtime/bounded-context.js.map +1 -1
- package/dist/runtime/bridge-codec.d.ts +1 -1
- package/dist/runtime/bridge-codec.d.ts.map +1 -1
- package/dist/runtime/bridge-codec.js +78 -55
- package/dist/runtime/bridge-codec.js.map +1 -1
- package/dist/runtime/errors.d.ts +16 -0
- package/dist/runtime/errors.d.ts.map +1 -1
- package/dist/runtime/errors.js +17 -0
- package/dist/runtime/errors.js.map +1 -1
- package/dist/runtime/http-transport.d.ts +1 -1
- package/dist/runtime/http-transport.d.ts.map +1 -1
- package/dist/runtime/http-transport.js +1 -1
- package/dist/runtime/http-transport.js.map +1 -1
- package/dist/runtime/index.d.ts +1 -0
- package/dist/runtime/index.d.ts.map +1 -1
- package/dist/runtime/index.js +1 -0
- package/dist/runtime/index.js.map +1 -1
- package/dist/runtime/node.d.ts +7 -36
- package/dist/runtime/node.d.ts.map +1 -1
- package/dist/runtime/node.js +2 -80
- package/dist/runtime/node.js.map +1 -1
- package/dist/runtime/pooled-transport.d.ts +120 -59
- package/dist/runtime/pooled-transport.d.ts.map +1 -1
- package/dist/runtime/pooled-transport.js +345 -78
- package/dist/runtime/pooled-transport.js.map +1 -1
- package/dist/runtime/pyodide-bootstrap-core.generated.d.ts.map +1 -1
- package/dist/runtime/pyodide-bootstrap-core.generated.js +1 -1
- package/dist/runtime/pyodide-bootstrap-core.generated.js.map +1 -1
- package/dist/runtime/pyodide-transport.d.ts +1 -1
- package/dist/runtime/pyodide-transport.d.ts.map +1 -1
- package/dist/runtime/pyodide-transport.js +2 -3
- package/dist/runtime/pyodide-transport.js.map +1 -1
- package/dist/runtime/rpc-client.d.ts +7 -36
- package/dist/runtime/rpc-client.d.ts.map +1 -1
- package/dist/runtime/rpc-client.js +20 -102
- package/dist/runtime/rpc-client.js.map +1 -1
- package/dist/runtime/subprocess-transport.d.ts +30 -69
- package/dist/runtime/subprocess-transport.d.ts.map +1 -1
- package/dist/runtime/subprocess-transport.js +179 -236
- package/dist/runtime/subprocess-transport.js.map +1 -1
- package/dist/runtime/timed-out-request-tracker.d.ts +2 -1
- package/dist/runtime/timed-out-request-tracker.d.ts.map +1 -1
- package/dist/runtime/transport.d.ts +9 -19
- package/dist/runtime/transport.d.ts.map +1 -1
- package/dist/runtime/transport.js +1 -1
- package/dist/runtime/transport.js.map +1 -1
- package/dist/runtime/validators.d.ts +49 -0
- package/dist/runtime/validators.d.ts.map +1 -1
- package/dist/runtime/validators.js +152 -0
- package/dist/runtime/validators.js.map +1 -1
- package/dist/types/index.d.ts +14 -39
- package/dist/types/index.d.ts.map +1 -1
- package/dist/tywrap.d.ts +3 -2
- package/dist/tywrap.d.ts.map +1 -1
- package/dist/tywrap.js +140 -13
- package/dist/tywrap.js.map +1 -1
- package/dist/utils/cache.d.ts +3 -16
- package/dist/utils/cache.d.ts.map +1 -1
- package/dist/utils/codec.d.ts +1 -0
- package/dist/utils/codec.d.ts.map +1 -1
- package/dist/utils/codec.js +13 -13
- package/dist/utils/codec.js.map +1 -1
- package/dist/utils/ir-cache.d.ts +2 -1
- package/dist/utils/ir-cache.d.ts.map +1 -1
- package/dist/utils/runtime.d.ts +0 -29
- package/dist/utils/runtime.d.ts.map +1 -1
- package/dist/utils/runtime.js +16 -107
- package/dist/utils/runtime.js.map +1 -1
- package/dist/version.js +1 -1
- package/package.json +7 -6
- package/runtime/frame_codec.py +7 -1
- package/runtime/python_bridge.py +85 -125
- package/runtime/tywrap_bridge_core.py +133 -150
- package/src/config/index.ts +11 -0
- package/src/core/annotation-parser.ts +7 -4
- package/src/core/generator.ts +315 -205
- package/src/core/mapper.ts +8 -8
- package/src/index.ts +7 -4
- package/src/runtime/base-bridge.ts +5 -30
- package/src/runtime/bounded-context.ts +12 -67
- package/src/runtime/bridge-codec.ts +94 -65
- package/src/runtime/errors.ts +21 -0
- package/src/runtime/http-transport.ts +6 -1
- package/src/runtime/index.ts +6 -0
- package/src/runtime/node.ts +9 -120
- package/src/runtime/pooled-transport.ts +424 -90
- package/src/runtime/pyodide-bootstrap-core.generated.ts +1 -1
- package/src/runtime/pyodide-transport.ts +7 -3
- package/src/runtime/rpc-client.ts +37 -139
- package/src/runtime/subprocess-transport.ts +210 -285
- package/src/runtime/timed-out-request-tracker.ts +1 -1
- package/src/runtime/transport.ts +15 -23
- package/src/runtime/validators.ts +204 -0
- package/src/types/index.ts +21 -60
- package/src/tywrap.ts +157 -22
- package/src/utils/cache.ts +3 -3
- package/src/utils/codec.ts +21 -13
- package/src/utils/ir-cache.ts +1 -1
- package/src/utils/runtime.ts +17 -128
- package/src/version.ts +1 -1
- package/dist/core/discovery.d.ts +0 -103
- package/dist/core/discovery.d.ts.map +0 -1
- package/dist/core/discovery.js +0 -380
- package/dist/core/discovery.js.map +0 -1
- package/dist/core/validation.d.ts +0 -102
- package/dist/core/validation.d.ts.map +0 -1
- package/dist/core/validation.js +0 -490
- package/dist/core/validation.js.map +0 -1
- package/dist/runtime/base.d.ts +0 -22
- package/dist/runtime/base.d.ts.map +0 -1
- package/dist/runtime/base.js +0 -23
- package/dist/runtime/base.js.map +0 -1
- package/dist/runtime/transport-pool.d.ts +0 -196
- package/dist/runtime/transport-pool.d.ts.map +0 -1
- package/dist/runtime/transport-pool.js +0 -418
- package/dist/runtime/transport-pool.js.map +0 -1
- package/runtime/__pycache__/_tywrap_conformance_chunking_fixtures.cpython-311.pyc +0 -0
- package/runtime/__pycache__/_tywrap_member_fixtures.cpython-311.pyc +0 -0
- package/runtime/__pycache__/_tywrap_w4_chunking_fixture.cpython-311.pyc +0 -0
- package/runtime/__pycache__/_tywrap_w5_request_chunking_fixture.cpython-311.pyc +0 -0
- package/runtime/__pycache__/_tywrap_w6_pool_chunking_fixture.cpython-311.pyc +0 -0
- package/runtime/__pycache__/frame_codec.cpython-311.pyc +0 -0
- package/runtime/__pycache__/safe_codec.cpython-311.pyc +0 -0
- package/runtime/__pycache__/tywrap_bridge_core.cpython-311.pyc +0 -0
- package/runtime/safe_codec.py +0 -352
- package/src/core/discovery.ts +0 -477
- package/src/core/validation.ts +0 -729
- package/src/runtime/base.ts +0 -24
- package/src/runtime/transport-pool.ts +0 -538
package/runtime/safe_codec.py
DELETED
|
@@ -1,352 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Safe JSON codec with explicit edge case handling.
|
|
3
|
-
|
|
4
|
-
Provides bidirectional validation and serialization for the JS<->Python bridge.
|
|
5
|
-
This module handles special Python types and enforces payload size limits to
|
|
6
|
-
ensure predictable behavior at the language boundary.
|
|
7
|
-
"""
|
|
8
|
-
|
|
9
|
-
import base64
|
|
10
|
-
import json
|
|
11
|
-
import math
|
|
12
|
-
from datetime import date, datetime, time, timedelta
|
|
13
|
-
from decimal import Decimal
|
|
14
|
-
from pathlib import Path, PurePath
|
|
15
|
-
from typing import Any, Optional, Union
|
|
16
|
-
from uuid import UUID
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
class CodecError(Exception):
|
|
20
|
-
"""Raised when encoding/decoding fails."""
|
|
21
|
-
|
|
22
|
-
pass
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
def _is_nan_or_inf(value: Any) -> bool:
|
|
26
|
-
"""
|
|
27
|
-
Check if a numeric value is NaN or Infinity.
|
|
28
|
-
|
|
29
|
-
Args:
|
|
30
|
-
value: The value to check.
|
|
31
|
-
|
|
32
|
-
Returns:
|
|
33
|
-
True if the value is NaN, positive infinity, or negative infinity.
|
|
34
|
-
"""
|
|
35
|
-
if not isinstance(value, (int, float)):
|
|
36
|
-
return False
|
|
37
|
-
try:
|
|
38
|
-
return math.isnan(value) or math.isinf(value)
|
|
39
|
-
except (TypeError, ValueError):
|
|
40
|
-
return False
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
def _is_numpy_scalar(obj: Any) -> bool:
|
|
44
|
-
"""
|
|
45
|
-
Detect numpy scalar types when NumPy is installed.
|
|
46
|
-
|
|
47
|
-
Why: numpy scalars have an `.item()` method to extract Python primitives,
|
|
48
|
-
which is needed for JSON serialization.
|
|
49
|
-
"""
|
|
50
|
-
try:
|
|
51
|
-
import numpy as np
|
|
52
|
-
except ImportError:
|
|
53
|
-
return False
|
|
54
|
-
return isinstance(obj, (np.generic, np.ndarray)) and obj.ndim == 0
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
def _is_pandas_scalar(obj: Any) -> bool:
|
|
58
|
-
"""
|
|
59
|
-
Detect pandas scalar types (Timestamp, Timedelta, etc.).
|
|
60
|
-
|
|
61
|
-
Why: pandas wraps numpy scalars with additional metadata; extracting the
|
|
62
|
-
underlying value ensures clean JSON serialization.
|
|
63
|
-
"""
|
|
64
|
-
try:
|
|
65
|
-
import pandas as pd
|
|
66
|
-
except ImportError:
|
|
67
|
-
return False
|
|
68
|
-
# Check for pandas Timestamp, Timedelta, NaT, etc.
|
|
69
|
-
return isinstance(
|
|
70
|
-
obj,
|
|
71
|
-
(
|
|
72
|
-
pd.Timestamp,
|
|
73
|
-
pd.Timedelta,
|
|
74
|
-
type(pd.NaT),
|
|
75
|
-
),
|
|
76
|
-
)
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
def _has_pydantic_model_dump(obj: Any) -> bool:
|
|
80
|
-
"""
|
|
81
|
-
Check if object is a Pydantic v2 model with model_dump method.
|
|
82
|
-
|
|
83
|
-
Why: Pydantic models should be serialized via their built-in mechanism
|
|
84
|
-
to respect field aliases and serialization modes.
|
|
85
|
-
"""
|
|
86
|
-
model_dump = getattr(obj, 'model_dump', None)
|
|
87
|
-
return callable(model_dump)
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
class BridgeCodec:
|
|
91
|
-
"""
|
|
92
|
-
Safe JSON codec with explicit edge case handling.
|
|
93
|
-
|
|
94
|
-
This codec provides:
|
|
95
|
-
- Rejection of NaN/Infinity by default (configurable)
|
|
96
|
-
- Payload size limits to prevent memory exhaustion
|
|
97
|
-
- Automatic handling of common Python types (datetime, Decimal, UUID, etc.)
|
|
98
|
-
- Support for numpy/pandas scalars
|
|
99
|
-
- Pydantic model serialization
|
|
100
|
-
|
|
101
|
-
Args:
|
|
102
|
-
allow_nan: If False (default), reject NaN/Infinity values.
|
|
103
|
-
max_payload_bytes: Maximum payload size in bytes (default 10MB).
|
|
104
|
-
|
|
105
|
-
Example:
|
|
106
|
-
>>> codec = BridgeCodec()
|
|
107
|
-
>>> codec.encode({"key": "value"})
|
|
108
|
-
'{"key": "value"}'
|
|
109
|
-
>>> codec.decode('{"key": "value"}')
|
|
110
|
-
{'key': 'value'}
|
|
111
|
-
"""
|
|
112
|
-
|
|
113
|
-
def __init__(
|
|
114
|
-
self,
|
|
115
|
-
allow_nan: bool = False,
|
|
116
|
-
max_payload_bytes: int = 10 * 1024 * 1024,
|
|
117
|
-
) -> None:
|
|
118
|
-
"""
|
|
119
|
-
Initialize the codec with configuration.
|
|
120
|
-
|
|
121
|
-
Args:
|
|
122
|
-
allow_nan: If False (default), reject NaN/Infinity values.
|
|
123
|
-
max_payload_bytes: Maximum payload size in bytes (default 10MB).
|
|
124
|
-
"""
|
|
125
|
-
self.allow_nan = allow_nan
|
|
126
|
-
self.max_payload_bytes = max_payload_bytes
|
|
127
|
-
|
|
128
|
-
def encode(self, value: Any) -> str:
|
|
129
|
-
"""
|
|
130
|
-
Encode a Python value to a JSON string.
|
|
131
|
-
|
|
132
|
-
Args:
|
|
133
|
-
value: The Python value to encode.
|
|
134
|
-
|
|
135
|
-
Returns:
|
|
136
|
-
A JSON string representation of the value.
|
|
137
|
-
|
|
138
|
-
Raises:
|
|
139
|
-
CodecError: If encoding fails due to:
|
|
140
|
-
- NaN/Infinity values when allow_nan is False
|
|
141
|
-
- Payload exceeds max_payload_bytes
|
|
142
|
-
- Value contains non-serializable types
|
|
143
|
-
"""
|
|
144
|
-
try:
|
|
145
|
-
result = json.dumps(
|
|
146
|
-
value,
|
|
147
|
-
default=self._default_encoder,
|
|
148
|
-
allow_nan=self.allow_nan,
|
|
149
|
-
)
|
|
150
|
-
except ValueError as exc:
|
|
151
|
-
# json.dumps raises ValueError for NaN/Infinity when allow_nan=False.
|
|
152
|
-
# The wording is Python-version dependent (3.12+ appends ": nan";
|
|
153
|
-
# 3.10/3.11 emit only "Out of range float values are not JSON
|
|
154
|
-
# compliant"), so match that canonical phrase too for a stable message.
|
|
155
|
-
error_msg = str(exc).lower()
|
|
156
|
-
if (
|
|
157
|
-
'nan' in error_msg
|
|
158
|
-
or 'infinity' in error_msg
|
|
159
|
-
or 'inf' in error_msg
|
|
160
|
-
or 'out of range float' in error_msg
|
|
161
|
-
):
|
|
162
|
-
raise CodecError(
|
|
163
|
-
'Cannot serialize NaN - NaN/Infinity not allowed in JSON'
|
|
164
|
-
) from exc
|
|
165
|
-
raise CodecError(f'JSON encoding failed: {exc}') from exc
|
|
166
|
-
except TypeError as exc:
|
|
167
|
-
raise CodecError(f'JSON encoding failed: {exc}') from exc
|
|
168
|
-
|
|
169
|
-
# Check payload size
|
|
170
|
-
payload_bytes = len(result.encode('utf-8'))
|
|
171
|
-
if payload_bytes > self.max_payload_bytes:
|
|
172
|
-
raise CodecError(f'Payload exceeds {self.max_payload_bytes} bytes')
|
|
173
|
-
|
|
174
|
-
return result
|
|
175
|
-
|
|
176
|
-
def decode(self, payload: str) -> Any:
|
|
177
|
-
"""
|
|
178
|
-
Decode a JSON string to a Python value.
|
|
179
|
-
|
|
180
|
-
Args:
|
|
181
|
-
payload: The JSON string to decode.
|
|
182
|
-
|
|
183
|
-
Returns:
|
|
184
|
-
The decoded Python value.
|
|
185
|
-
|
|
186
|
-
Raises:
|
|
187
|
-
CodecError: If decoding fails due to:
|
|
188
|
-
- Payload exceeds max_payload_bytes
|
|
189
|
-
- Invalid JSON syntax
|
|
190
|
-
"""
|
|
191
|
-
# Check payload size first
|
|
192
|
-
payload_bytes = len(payload.encode('utf-8'))
|
|
193
|
-
if payload_bytes > self.max_payload_bytes:
|
|
194
|
-
raise CodecError(f'Payload exceeds {self.max_payload_bytes} bytes')
|
|
195
|
-
|
|
196
|
-
try:
|
|
197
|
-
return json.loads(payload)
|
|
198
|
-
except json.JSONDecodeError as exc:
|
|
199
|
-
raise CodecError(f'JSON decoding failed: {exc}') from exc
|
|
200
|
-
|
|
201
|
-
def _default_encoder(self, obj: Any) -> Any:
|
|
202
|
-
"""
|
|
203
|
-
Handle special Python types during JSON encoding.
|
|
204
|
-
|
|
205
|
-
This method is called by json.dumps for objects that are not natively
|
|
206
|
-
JSON serializable.
|
|
207
|
-
|
|
208
|
-
Args:
|
|
209
|
-
obj: The object to encode.
|
|
210
|
-
|
|
211
|
-
Returns:
|
|
212
|
-
A JSON-serializable representation of the object.
|
|
213
|
-
|
|
214
|
-
Raises:
|
|
215
|
-
TypeError: If the object cannot be serialized.
|
|
216
|
-
CodecError: If the object contains NaN/Infinity when not allowed.
|
|
217
|
-
"""
|
|
218
|
-
# Handle numpy/pandas scalars first (they need .item() extraction)
|
|
219
|
-
if _is_numpy_scalar(obj):
|
|
220
|
-
extracted = obj.item()
|
|
221
|
-
# Check for NaN/Infinity in extracted value
|
|
222
|
-
if not self.allow_nan and _is_nan_or_inf(extracted):
|
|
223
|
-
raise CodecError(
|
|
224
|
-
'Cannot serialize NaN - NaN/Infinity not allowed in JSON'
|
|
225
|
-
)
|
|
226
|
-
return extracted
|
|
227
|
-
|
|
228
|
-
if _is_pandas_scalar(obj):
|
|
229
|
-
try:
|
|
230
|
-
import pandas as pd
|
|
231
|
-
except ImportError:
|
|
232
|
-
pass
|
|
233
|
-
else:
|
|
234
|
-
# Handle NaT (Not a Time)
|
|
235
|
-
if obj is pd.NaT or (hasattr(pd, 'isna') and pd.isna(obj)):
|
|
236
|
-
return None
|
|
237
|
-
# Pandas Timestamp -> ISO string
|
|
238
|
-
if isinstance(obj, pd.Timestamp):
|
|
239
|
-
return obj.isoformat()
|
|
240
|
-
# Pandas Timedelta -> total seconds
|
|
241
|
-
if isinstance(obj, pd.Timedelta):
|
|
242
|
-
return obj.total_seconds()
|
|
243
|
-
|
|
244
|
-
# datetime types
|
|
245
|
-
if isinstance(obj, datetime):
|
|
246
|
-
return obj.isoformat()
|
|
247
|
-
|
|
248
|
-
if isinstance(obj, date):
|
|
249
|
-
return obj.isoformat()
|
|
250
|
-
|
|
251
|
-
if isinstance(obj, time):
|
|
252
|
-
return obj.isoformat()
|
|
253
|
-
|
|
254
|
-
# timedelta -> total seconds (consistent with python_bridge.py)
|
|
255
|
-
if isinstance(obj, timedelta):
|
|
256
|
-
return obj.total_seconds()
|
|
257
|
-
|
|
258
|
-
# Decimal -> string (preserves precision)
|
|
259
|
-
if isinstance(obj, Decimal):
|
|
260
|
-
return str(obj)
|
|
261
|
-
|
|
262
|
-
# UUID -> string
|
|
263
|
-
if isinstance(obj, UUID):
|
|
264
|
-
return str(obj)
|
|
265
|
-
|
|
266
|
-
# Path -> string
|
|
267
|
-
if isinstance(obj, (Path, PurePath)):
|
|
268
|
-
return str(obj)
|
|
269
|
-
|
|
270
|
-
# bytes/bytearray -> base64 with type marker
|
|
271
|
-
if isinstance(obj, (bytes, bytearray)):
|
|
272
|
-
return {
|
|
273
|
-
'__type__': 'bytes',
|
|
274
|
-
'encoding': 'base64',
|
|
275
|
-
'data': base64.b64encode(obj).decode('ascii'),
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
# Pydantic models
|
|
279
|
-
if _has_pydantic_model_dump(obj):
|
|
280
|
-
try:
|
|
281
|
-
return obj.model_dump(by_alias=True, mode='json')
|
|
282
|
-
except TypeError:
|
|
283
|
-
# Older Pydantic versions may not support mode='json'
|
|
284
|
-
return obj.model_dump(by_alias=True)
|
|
285
|
-
|
|
286
|
-
# Sets -> lists (common conversion)
|
|
287
|
-
if isinstance(obj, (set, frozenset)):
|
|
288
|
-
return list(obj)
|
|
289
|
-
|
|
290
|
-
# Complex numbers (rejected by default as they contain floats)
|
|
291
|
-
if isinstance(obj, complex):
|
|
292
|
-
raise TypeError(
|
|
293
|
-
f'Object of type {type(obj).__name__} is not JSON serializable'
|
|
294
|
-
)
|
|
295
|
-
|
|
296
|
-
# Fallback: raise TypeError with clear message
|
|
297
|
-
raise TypeError(
|
|
298
|
-
f'Object of type {type(obj).__name__} is not JSON serializable'
|
|
299
|
-
)
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
# Module-level convenience instance with default settings
|
|
303
|
-
_default_codec: Optional[BridgeCodec] = None
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
def get_default_codec() -> BridgeCodec:
|
|
307
|
-
"""
|
|
308
|
-
Get or create the default BridgeCodec instance.
|
|
309
|
-
|
|
310
|
-
Returns:
|
|
311
|
-
The default BridgeCodec instance with standard settings.
|
|
312
|
-
"""
|
|
313
|
-
global _default_codec
|
|
314
|
-
if _default_codec is None:
|
|
315
|
-
_default_codec = BridgeCodec()
|
|
316
|
-
return _default_codec
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
def encode(value: Any, *, allow_nan: bool = False) -> str:
|
|
320
|
-
"""
|
|
321
|
-
Convenience function to encode a value using default settings.
|
|
322
|
-
|
|
323
|
-
Args:
|
|
324
|
-
value: The Python value to encode.
|
|
325
|
-
allow_nan: If True, allow NaN/Infinity values.
|
|
326
|
-
|
|
327
|
-
Returns:
|
|
328
|
-
A JSON string representation of the value.
|
|
329
|
-
|
|
330
|
-
Raises:
|
|
331
|
-
CodecError: If encoding fails.
|
|
332
|
-
"""
|
|
333
|
-
if allow_nan:
|
|
334
|
-
codec = BridgeCodec(allow_nan=True)
|
|
335
|
-
return codec.encode(value)
|
|
336
|
-
return get_default_codec().encode(value)
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
def decode(payload: str) -> Any:
|
|
340
|
-
"""
|
|
341
|
-
Convenience function to decode a JSON string using default settings.
|
|
342
|
-
|
|
343
|
-
Args:
|
|
344
|
-
payload: The JSON string to decode.
|
|
345
|
-
|
|
346
|
-
Returns:
|
|
347
|
-
The decoded Python value.
|
|
348
|
-
|
|
349
|
-
Raises:
|
|
350
|
-
CodecError: If decoding fails.
|
|
351
|
-
"""
|
|
352
|
-
return get_default_codec().decode(payload)
|