soia-client 1.1.5__py3-none-any.whl → 1.1.20__py3-none-any.whl

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.
soia/_impl/primitives.py CHANGED
@@ -1,15 +1,30 @@
1
1
  import base64
2
+ import math
3
+ import struct
2
4
  from collections.abc import Callable
3
5
  from dataclasses import dataclass
4
6
  from typing import Any, Final, final
5
7
 
6
8
  from soia import _spec, reflection
9
+ from soia._impl.binary import (
10
+ decode_bool,
11
+ decode_float,
12
+ decode_int32,
13
+ decode_int64,
14
+ decode_uint64,
15
+ encode_float32,
16
+ encode_float64,
17
+ encode_int32,
18
+ encode_int64,
19
+ encode_length_prefix,
20
+ encode_uint64,
21
+ )
7
22
  from soia._impl.function_maker import Expr, ExprLike
8
23
  from soia._impl.timestamp import Timestamp
9
- from soia._impl.type_adapter import TypeAdapter
24
+ from soia._impl.type_adapter import ByteStream, T, TypeAdapter
10
25
 
11
26
 
12
- class AbstractPrimitiveAdapter(TypeAdapter):
27
+ class AbstractPrimitiveAdapter(TypeAdapter[T]):
13
28
  @final
14
29
  def finalize(
15
30
  self,
@@ -29,7 +44,7 @@ class AbstractPrimitiveAdapter(TypeAdapter):
29
44
  return None
30
45
 
31
46
 
32
- class _BoolAdapter(AbstractPrimitiveAdapter):
47
+ class _BoolAdapter(AbstractPrimitiveAdapter[bool]):
33
48
  def default_expr(self) -> ExprLike:
34
49
  return "False"
35
50
 
@@ -49,8 +64,23 @@ class _BoolAdapter(AbstractPrimitiveAdapter):
49
64
  else:
50
65
  return Expr.join("(1 if ", in_expr, " else 0)")
51
66
 
52
- def from_json_expr(self, json_expr: ExprLike) -> Expr:
53
- return Expr.join("(True if ", json_expr, " else False)")
67
+ def from_json_expr(
68
+ self, json_expr: ExprLike, keep_unrecognized_expr: ExprLike
69
+ ) -> Expr:
70
+ return Expr.join("(", json_expr, " not in (0, '0'))")
71
+
72
+ @staticmethod
73
+ def encode(
74
+ value: bool,
75
+ buffer: bytearray,
76
+ ) -> None:
77
+ buffer.append(1 if value else 0)
78
+
79
+ def encode_fn(self) -> Callable[[bool, bytearray], None]:
80
+ return _BoolAdapter.encode
81
+
82
+ def decode_fn(self) -> Callable[[ByteStream], bool]:
83
+ return decode_bool
54
84
 
55
85
  def get_type(self) -> reflection.Type:
56
86
  return reflection.PrimitiveType(
@@ -59,11 +89,11 @@ class _BoolAdapter(AbstractPrimitiveAdapter):
59
89
  )
60
90
 
61
91
 
62
- BOOL_ADAPTER: Final[TypeAdapter] = _BoolAdapter()
92
+ BOOL_ADAPTER: Final[TypeAdapter[bool]] = _BoolAdapter()
63
93
 
64
94
 
65
95
  @dataclass(frozen=True)
66
- class _AbstractIntAdapter(AbstractPrimitiveAdapter):
96
+ class _AbstractIntAdapter(AbstractPrimitiveAdapter[int]):
67
97
  """Type adapter implementation for int32, int64 and uint64."""
68
98
 
69
99
  def default_expr(self) -> ExprLike:
@@ -76,7 +106,9 @@ class _AbstractIntAdapter(AbstractPrimitiveAdapter):
76
106
  def is_not_default_expr(self, arg_expr: ExprLike, attr_expr: ExprLike) -> ExprLike:
77
107
  return arg_expr
78
108
 
79
- def from_json_expr(self, json_expr: ExprLike) -> Expr:
109
+ def from_json_expr(
110
+ self, json_expr: ExprLike, keep_unrecognized_expr: ExprLike
111
+ ) -> Expr:
80
112
  # Must accept float inputs and string inputs and turn them into ints.
81
113
  return Expr.join(
82
114
  "(0).__class__(",
@@ -98,6 +130,12 @@ class _Int32Adapter(_AbstractIntAdapter):
98
130
  " < 2147483647 else 2147483647)",
99
131
  )
100
132
 
133
+ def encode_fn(self) -> Callable[[int, bytearray], None]:
134
+ return encode_int32
135
+
136
+ def decode_fn(self) -> Callable[[ByteStream], int]:
137
+ return decode_int32
138
+
101
139
  def get_type(self) -> reflection.Type:
102
140
  return reflection.PrimitiveType(
103
141
  kind="primitive",
@@ -124,6 +162,12 @@ class _Int64Adapter(_AbstractIntAdapter):
124
162
  def to_json_expr(self, in_expr: ExprLike, readable: bool) -> Expr:
125
163
  return Expr.join(Expr.local("int64_to_json", _int64_to_json), "(", in_expr, ")")
126
164
 
165
+ def encode_fn(self) -> Callable[[int, bytearray], None]:
166
+ return encode_int64
167
+
168
+ def decode_fn(self) -> Callable[[ByteStream], int]:
169
+ return decode_int64
170
+
127
171
  def get_type(self) -> reflection.Type:
128
172
  return reflection.PrimitiveType(
129
173
  kind="primitive",
@@ -149,6 +193,12 @@ class _Uint64Adapter(_AbstractIntAdapter):
149
193
  Expr.local("uint64_to_json", _uint64_to_json), "(", in_expr, ")"
150
194
  )
151
195
 
196
+ def encode_fn(self) -> Callable[[int, bytearray], None]:
197
+ return encode_uint64
198
+
199
+ def decode_fn(self) -> Callable[[ByteStream], int]:
200
+ return decode_uint64
201
+
152
202
  def get_type(self) -> reflection.Type:
153
203
  return reflection.PrimitiveType(
154
204
  kind="primitive",
@@ -156,13 +206,27 @@ class _Uint64Adapter(_AbstractIntAdapter):
156
206
  )
157
207
 
158
208
 
159
- INT32_ADAPTER: Final[TypeAdapter] = _Int32Adapter()
160
- INT64_ADAPTER: Final[TypeAdapter] = _Int64Adapter()
161
- UINT64_ADAPTER: Final[TypeAdapter] = _Uint64Adapter()
209
+ INT32_ADAPTER: Final[TypeAdapter[int]] = _Int32Adapter()
210
+ INT64_ADAPTER: Final[TypeAdapter[int]] = _Int64Adapter()
211
+ UINT64_ADAPTER: Final[TypeAdapter[int]] = _Uint64Adapter()
212
+
213
+
214
+ _SPECIAL_FLOAT_TO_STRING: Final[dict[str, str]] = {
215
+ "nan": "NaN",
216
+ "inf": "Infinity",
217
+ "-inf": "-Infinity",
218
+ }
219
+
220
+
221
+ _STRING_TO_SPECIAL_FLOAT: Final[dict[str, float]] = {
222
+ "NaN": float("nan"),
223
+ "Infinity": float("inf"),
224
+ "-Infinity": float("-inf"),
225
+ }
162
226
 
163
227
 
164
228
  @dataclass(frozen=True)
165
- class _AbstractFloatAdapter(AbstractPrimitiveAdapter):
229
+ class _AbstractFloatAdapter(AbstractPrimitiveAdapter[float]):
166
230
  """Type adapter implementation for float32 and float64."""
167
231
 
168
232
  def default_expr(self) -> ExprLike:
@@ -175,16 +239,52 @@ class _AbstractFloatAdapter(AbstractPrimitiveAdapter):
175
239
  return arg_expr
176
240
 
177
241
  def to_json_expr(self, in_expr: ExprLike, readable: bool) -> ExprLike:
178
- return in_expr
242
+ return Expr.join(
243
+ "(",
244
+ in_expr,
245
+ " if ",
246
+ Expr.local("_isfinite", math.isfinite),
247
+ "(",
248
+ in_expr,
249
+ ") else ",
250
+ Expr.local(
251
+ "_SPECIAL_FLOAT_TO_STRING",
252
+ _SPECIAL_FLOAT_TO_STRING,
253
+ ),
254
+ "[f'{",
255
+ in_expr,
256
+ "}'])",
257
+ )
258
+
259
+ def from_json_expr(
260
+ self, json_expr: ExprLike, keep_unrecognized_expr: ExprLike
261
+ ) -> Expr:
262
+ return Expr.join(
263
+ "(",
264
+ Expr.local(
265
+ "_STRING_TO_SPECIAL_FLOAT",
266
+ _STRING_TO_SPECIAL_FLOAT,
267
+ ),
268
+ "[",
269
+ json_expr,
270
+ "] if ",
271
+ json_expr,
272
+ " in ('NaN', 'Infinity', '-Infinity') else (",
273
+ json_expr,
274
+ " + 0.0))",
275
+ )
179
276
 
180
- def from_json_expr(self, json_expr: ExprLike) -> Expr:
181
- return Expr.join("(", json_expr, " + 0.0)")
277
+ def decode_fn(self) -> Callable[[ByteStream], float]:
278
+ return decode_float
182
279
 
183
280
 
184
281
  @dataclass(frozen=True)
185
282
  class _Float32Adapter(_AbstractFloatAdapter):
186
283
  """Type adapter implementation for float32."""
187
284
 
285
+ def encode_fn(self) -> Callable[[float, bytearray], None]:
286
+ return encode_float32
287
+
188
288
  def get_type(self) -> reflection.Type:
189
289
  return reflection.PrimitiveType(
190
290
  kind="primitive",
@@ -194,7 +294,10 @@ class _Float32Adapter(_AbstractFloatAdapter):
194
294
 
195
295
  @dataclass(frozen=True)
196
296
  class _Float64Adapter(_AbstractFloatAdapter):
197
- """Type adapter implementation for float32."""
297
+ """Type adapter implementation for float64."""
298
+
299
+ def encode_fn(self) -> Callable[[float, bytearray], None]:
300
+ return encode_float64
198
301
 
199
302
  def get_type(self) -> reflection.Type:
200
303
  return reflection.PrimitiveType(
@@ -203,11 +306,16 @@ class _Float64Adapter(_AbstractFloatAdapter):
203
306
  )
204
307
 
205
308
 
206
- FLOAT32_ADAPTER: Final[TypeAdapter] = _Float32Adapter()
207
- FLOAT64_ADAPTER: Final[TypeAdapter] = _Float64Adapter()
309
+ FLOAT32_ADAPTER: Final[TypeAdapter[float]] = _Float32Adapter()
310
+ FLOAT64_ADAPTER: Final[TypeAdapter[float]] = _Float64Adapter()
311
+
208
312
 
313
+ def _clamp_unix_millis(unix_millis: int) -> int:
314
+ """Clamp unix milliseconds to valid range for JavaScript dates."""
315
+ return max(-8640000000000000, min(unix_millis, 8640000000000000))
209
316
 
210
- class _TimestampAdapter(AbstractPrimitiveAdapter):
317
+
318
+ class _TimestampAdapter(AbstractPrimitiveAdapter[Timestamp]):
211
319
  def default_expr(self) -> Expr:
212
320
  return Expr.local("_EPOCH", Timestamp.EPOCH)
213
321
 
@@ -236,10 +344,34 @@ class _TimestampAdapter(AbstractPrimitiveAdapter):
236
344
  else:
237
345
  return Expr.join(in_expr, ".unix_millis")
238
346
 
239
- def from_json_expr(self, json_expr: ExprLike) -> Expr:
347
+ def from_json_expr(
348
+ self, json_expr: ExprLike, keep_unrecognized_expr: ExprLike
349
+ ) -> Expr:
240
350
  fn = Expr.local("_timestamp_from_json", _timestamp_from_json)
241
351
  return Expr.join(fn, "(", json_expr, ")")
242
352
 
353
+ @staticmethod
354
+ def encode(
355
+ value: Timestamp,
356
+ buffer: bytearray,
357
+ ) -> None:
358
+ unix_millis = _clamp_unix_millis(value.unix_millis)
359
+ if unix_millis == 0:
360
+ buffer.append(0)
361
+ else:
362
+ buffer.append(239)
363
+ buffer.extend(struct.pack("<q", unix_millis))
364
+
365
+ def encode_fn(self) -> Callable[[Timestamp, bytearray], None]:
366
+ return _TimestampAdapter.encode
367
+
368
+ @staticmethod
369
+ def decode(stream: ByteStream) -> Timestamp:
370
+ return Timestamp(unix_millis=_clamp_unix_millis(decode_int64(stream)))
371
+
372
+ def decode_fn(self) -> Callable[[ByteStream], Timestamp]:
373
+ return _TimestampAdapter.decode
374
+
243
375
  def get_type(self) -> reflection.Type:
244
376
  return reflection.PrimitiveType(
245
377
  kind="primitive",
@@ -250,14 +382,16 @@ class _TimestampAdapter(AbstractPrimitiveAdapter):
250
382
  def _timestamp_from_json(json: Any) -> Timestamp:
251
383
  if json.__class__ is int or isinstance(json, int):
252
384
  return Timestamp(unix_millis=json)
385
+ elif isinstance(json, float) or isinstance(json, str):
386
+ return Timestamp(unix_millis=int(json))
253
387
  else:
254
388
  return Timestamp(unix_millis=json["unix_millis"])
255
389
 
256
390
 
257
- TIMESTAMP_ADAPTER: Final[TypeAdapter] = _TimestampAdapter()
391
+ TIMESTAMP_ADAPTER: Final[TypeAdapter[Timestamp]] = _TimestampAdapter()
258
392
 
259
393
 
260
- class _StringAdapter(AbstractPrimitiveAdapter):
394
+ class _StringAdapter(AbstractPrimitiveAdapter[str]):
261
395
  def default_expr(self) -> ExprLike:
262
396
  return '""'
263
397
 
@@ -270,9 +404,42 @@ class _StringAdapter(AbstractPrimitiveAdapter):
270
404
  def to_json_expr(self, in_expr: ExprLike, readable: bool) -> ExprLike:
271
405
  return in_expr
272
406
 
273
- def from_json_expr(self, json_expr: ExprLike) -> Expr:
407
+ def from_json_expr(
408
+ self, json_expr: ExprLike, keep_unrecognized_expr: ExprLike
409
+ ) -> Expr:
274
410
  return Expr.join("('' + (", json_expr, " or ''))")
275
411
 
412
+ @staticmethod
413
+ def encode(
414
+ value: str,
415
+ buffer: bytearray,
416
+ ) -> None:
417
+ if not value:
418
+ buffer.append(242)
419
+ else:
420
+ buffer.append(243)
421
+ bytes_data = value.encode("utf-8")
422
+ length = len(bytes_data)
423
+ encode_length_prefix(length, buffer)
424
+ buffer.extend(bytes_data)
425
+
426
+ def encode_fn(self) -> Callable[[str, bytearray], None]:
427
+ return _StringAdapter.encode
428
+
429
+ @staticmethod
430
+ def decode(stream: ByteStream) -> str:
431
+ wire = stream.read(1)[0]
432
+ if wire in (0, 242):
433
+ return ""
434
+ else:
435
+ # Should be wire 243
436
+ length = decode_int64(stream)
437
+ bytes_data = stream.read(length)
438
+ return bytes_data.decode("utf-8")
439
+
440
+ def decode_fn(self) -> Callable[[ByteStream], str]:
441
+ return _StringAdapter.decode
442
+
276
443
  def get_type(self) -> reflection.Type:
277
444
  return reflection.PrimitiveType(
278
445
  kind="primitive",
@@ -283,7 +450,14 @@ class _StringAdapter(AbstractPrimitiveAdapter):
283
450
  STRING_ADAPTER: Final[TypeAdapter] = _StringAdapter()
284
451
 
285
452
 
286
- class _BytesAdapter(AbstractPrimitiveAdapter):
453
+ def _bytes_from_json(json: str) -> bytes:
454
+ if json.startswith("hex:"):
455
+ return bytes.fromhex(json[4:])
456
+ else:
457
+ return base64.b64decode(json)
458
+
459
+
460
+ class _BytesAdapter(AbstractPrimitiveAdapter[bytes]):
287
461
  def default_expr(self) -> ExprLike:
288
462
  return 'b""'
289
463
 
@@ -297,18 +471,56 @@ class _BytesAdapter(AbstractPrimitiveAdapter):
297
471
  self,
298
472
  in_expr: ExprLike,
299
473
  readable: bool,
474
+ ) -> Expr:
475
+ if readable:
476
+ return Expr.join(
477
+ "('hex:' + ",
478
+ in_expr,
479
+ ".hex())",
480
+ )
481
+ else:
482
+ return Expr.join(
483
+ Expr.local("b64encode", base64.b64encode),
484
+ "(",
485
+ in_expr,
486
+ ").decode('utf-8')",
487
+ )
488
+
489
+ def from_json_expr(
490
+ self, json_expr: ExprLike, keep_unrecognized_expr: ExprLike
300
491
  ) -> Expr:
301
492
  return Expr.join(
302
- Expr.local("b64encode", base64.b64encode),
303
- "(",
304
- in_expr,
305
- ").decode('utf-8')",
493
+ Expr.local("bytes_from_json", _bytes_from_json), "(", json_expr, ' or "")'
306
494
  )
307
495
 
308
- def from_json_expr(self, json_expr: ExprLike) -> Expr:
309
- return Expr.join(
310
- Expr.local("b64decode", base64.b64decode), "(", json_expr, ' or "")'
311
- )
496
+ @staticmethod
497
+ def encode(
498
+ value: bytes,
499
+ buffer: bytearray,
500
+ ) -> None:
501
+ if len(value) == 0:
502
+ buffer.append(244)
503
+ else:
504
+ buffer.append(245)
505
+ length = len(value)
506
+ encode_length_prefix(length, buffer)
507
+ buffer.extend(value)
508
+
509
+ def encode_fn(self) -> Callable[[bytes, bytearray], None]:
510
+ return _BytesAdapter.encode
511
+
512
+ @staticmethod
513
+ def decode(stream: ByteStream) -> bytes:
514
+ wire = stream.read_wire()
515
+ if wire in (0, 244):
516
+ return b""
517
+ else:
518
+ # Should be wire 245
519
+ length = decode_int64(stream)
520
+ return stream.read(length)
521
+
522
+ def decode_fn(self) -> Callable[[ByteStream], bytes]:
523
+ return _BytesAdapter.decode
312
524
 
313
525
  def get_type(self) -> reflection.Type:
314
526
  return reflection.PrimitiveType(
@@ -317,4 +529,4 @@ class _BytesAdapter(AbstractPrimitiveAdapter):
317
529
  )
318
530
 
319
531
 
320
- BYTES_ADAPTER: Final[TypeAdapter] = _BytesAdapter()
532
+ BYTES_ADAPTER: Final[TypeAdapter[bytes]] = _BytesAdapter()
soia/_impl/serializer.py CHANGED
@@ -8,7 +8,7 @@ from weakref import WeakValueDictionary
8
8
  from soia import reflection
9
9
  from soia._impl.function_maker import Expr, LineSpan, make_function
10
10
  from soia._impl.never import Never
11
- from soia._impl.type_adapter import TypeAdapter
11
+ from soia._impl.type_adapter import ByteStream, TypeAdapter
12
12
 
13
13
  T = TypeVar("T")
14
14
 
@@ -21,26 +21,33 @@ class Serializer(Generic[T]):
21
21
  "_to_dense_json_fn",
22
22
  "_to_readable_json_fn",
23
23
  "_from_json_fn",
24
+ "_encode_fn",
25
+ "_decode_fn",
24
26
  "__dict__",
25
27
  )
26
28
 
27
- _adapter: TypeAdapter
29
+ _adapter: TypeAdapter[T]
28
30
  _to_dense_json_fn: Callable[[T], Any]
29
31
  _to_readable_json_fn: Callable[[T], Any]
30
- _from_json_fn: Callable[[Any], T]
32
+ _from_json_fn: Callable[[Any, bool], T]
33
+ _encode_fn: Callable[[T, bytearray], None]
34
+ _decode_fn: Callable[[ByteStream], T]
31
35
 
32
36
  def __init__(self, adapter: Never):
33
37
  # Use Never (^) as a trick to make the constructor internal.
34
- object.__setattr__(self, "_adapter", adapter)
38
+ as_adapter = cast(TypeAdapter[T], adapter)
39
+ object.__setattr__(self, "_adapter", as_adapter)
35
40
  object.__setattr__(
36
- self, "_to_dense_json_fn", _make_to_json_fn(adapter, readable=False)
41
+ self, "_to_dense_json_fn", _make_to_json_fn(as_adapter, readable=False)
37
42
  )
38
43
  object.__setattr__(
39
44
  self,
40
45
  "_to_readable_json_fn",
41
- _make_to_json_fn(adapter, readable=True),
46
+ _make_to_json_fn(as_adapter, readable=True),
42
47
  )
43
- object.__setattr__(self, "_from_json_fn", _make_from_json_fn(adapter))
48
+ object.__setattr__(self, "_from_json_fn", _make_from_json_fn(as_adapter))
49
+ object.__setattr__(self, "_encode_fn", as_adapter.encode_fn())
50
+ object.__setattr__(self, "_decode_fn", as_adapter.decode_fn())
44
51
 
45
52
  def to_json(self, input: T, *, readable=False) -> Any:
46
53
  if readable:
@@ -54,11 +61,26 @@ class Serializer(Generic[T]):
54
61
  else:
55
62
  return jsonlib.dumps(self._to_dense_json_fn(input), separators=(",", ":"))
56
63
 
57
- def from_json(self, json: Any) -> T:
58
- return self._from_json_fn(json)
64
+ def from_json(self, json: Any, keep_unrecognized_fields: bool = False) -> T:
65
+ return self._from_json_fn(json, keep_unrecognized_fields)
59
66
 
60
- def from_json_code(self, json_code: str) -> T:
61
- return self._from_json_fn(jsonlib.loads(json_code))
67
+ def from_json_code(
68
+ self, json_code: str, keep_unrecognized_fields: bool = False
69
+ ) -> T:
70
+ return self._from_json_fn(jsonlib.loads(json_code), keep_unrecognized_fields)
71
+
72
+ def to_bytes(self, input: T) -> bytes:
73
+ buffer = bytearray(b"soia")
74
+ self._encode_fn(input, buffer)
75
+ return bytes(buffer)
76
+
77
+ def from_bytes(self, bytes: bytes, keep_unrecognized_fields: bool = False) -> T:
78
+ if bytes.startswith(b"soia"):
79
+ stream = ByteStream(
80
+ bytes, position=4, keep_unrecognized_fields=keep_unrecognized_fields
81
+ )
82
+ return self._decode_fn(stream)
83
+ return self.from_json_code(bytes.decode("utf-8"))
62
84
 
63
85
  @cached_property
64
86
  def type_descriptor(self) -> reflection.TypeDescriptor:
@@ -82,13 +104,13 @@ _type_adapter_to_serializer: WeakValueDictionary[TypeAdapter, Serializer] = (
82
104
  )
83
105
 
84
106
 
85
- def make_serializer(adapter: TypeAdapter) -> Serializer:
107
+ def make_serializer(adapter: TypeAdapter[T]) -> Serializer[T]:
86
108
  return _type_adapter_to_serializer.setdefault(
87
109
  adapter, Serializer(cast(Never, adapter))
88
110
  )
89
111
 
90
112
 
91
- def _make_to_json_fn(adapter: TypeAdapter, readable: bool) -> Callable[[Any], Any]:
113
+ def _make_to_json_fn(adapter: TypeAdapter[T], readable: bool) -> Callable[[T], Any]:
92
114
  return make_function(
93
115
  name="to_json",
94
116
  params=["input"],
@@ -104,11 +126,13 @@ def _make_to_json_fn(adapter: TypeAdapter, readable: bool) -> Callable[[Any], An
104
126
  )
105
127
 
106
128
 
107
- def _make_from_json_fn(adapter: TypeAdapter) -> Callable[[Any], Any]:
129
+ def _make_from_json_fn(adapter: TypeAdapter[T]) -> Callable[[Any, bool], T]:
108
130
  return make_function(
109
131
  name="from_json",
110
- params=["json"],
132
+ params=["json", "keep_unrecognized_fields"],
111
133
  body=[
112
- LineSpan.join("return ", adapter.from_json_expr(Expr.join("json"))),
134
+ LineSpan.join(
135
+ "return ", adapter.from_json_expr("json", "keep_unrecognized_fields")
136
+ ),
113
137
  ],
114
138
  )
soia/_impl/service.py CHANGED
@@ -130,9 +130,7 @@ class _HandleRequestFlow(Generic[Request, Response, RequestHeaders, ResponseHead
130
130
  try:
131
131
  req_body_json = json.loads(self.req_body)
132
132
  except json.JSONDecodeError:
133
- return RawServiceResponse(
134
- "bad request: invalid JSON", "bad-request"
135
- )
133
+ return RawServiceResponse("bad request: invalid JSON", "bad-request")
136
134
  method = req_body_json.get("method", ())
137
135
  if method == ():
138
136
  return RawServiceResponse(