33
33
from typing_extensions import Literal
34
34
35
35
from iwf .iwf_api .models import EncodedObject
36
- from iwf .iwf_api .types import Unset
36
+ from iwf .iwf_api .types import UNSET , Unset
37
37
38
38
# StrEnum is available in 3.11+
39
39
if sys .version_info >= (3 , 11 ):
@@ -50,14 +50,15 @@ class PayloadConverter(ABC):
50
50
def to_payload (
51
51
self ,
52
52
value : Any ,
53
- ) -> EncodedObject :
53
+ ) -> Union [ EncodedObject , Unset ] :
54
54
"""Encode values into payloads.
55
55
56
56
Args:
57
57
value: value to be converted
58
58
59
59
Returns:
60
- Converted payload.
60
+ A boolean to indicate if the payload was converted and the converted value
61
+ or Unset
61
62
62
63
Raises:
63
64
Exception: Any issue during conversion.
@@ -90,19 +91,20 @@ class EncodingPayloadConverter(ABC):
90
91
91
92
@property
92
93
@abstractmethod
93
- def encoding (self ) -> str :
94
+ def encoding (self ) -> Union [ str , Unset ] :
94
95
"""Encoding for the payload this converter works with."""
95
96
raise NotImplementedError
96
97
97
98
@abstractmethod
98
- def to_payload (self , value : Any ) -> Optional [ EncodedObject ]:
99
+ def to_payload (self , value : Any ) -> tuple [ bool , Union [ EncodedObject , Unset ] ]:
99
100
"""Encode a single value to a payload or None.
100
101
101
102
Args:
102
103
value: Value to be converted.
103
104
104
105
Returns:
105
- Payload of the value or None if unable to convert.
106
+ A boolean to indicate if the payload was converted and the converted value
107
+ or Unset
106
108
107
109
Raises:
108
110
TypeError: Value is not the expected type.
@@ -145,7 +147,7 @@ class CompositePayloadConverter(PayloadConverter):
145
147
converters: List of payload converters to delegate to, in order.
146
148
"""
147
149
148
- converters : Mapping [str , EncodingPayloadConverter ]
150
+ converters : Mapping [Union [ str , Unset ] , EncodingPayloadConverter ]
149
151
150
152
def __init__ (self , * converters : EncodingPayloadConverter ) -> None :
151
153
"""Initializes the data converter.
@@ -159,7 +161,7 @@ def __init__(self, *converters: EncodingPayloadConverter) -> None:
159
161
def to_payload (
160
162
self ,
161
163
value : Any ,
162
- ) -> EncodedObject :
164
+ ) -> Union [ EncodedObject , Unset ] :
163
165
"""Encode values trying each converter.
164
166
165
167
See base class. Always returns the same number of payloads as values.
@@ -169,12 +171,13 @@ def to_payload(
169
171
"""
170
172
# We intentionally attempt these serially just in case a stateful
171
173
# converter may rely on the previous values
172
- payload = None
174
+ payload : Union [EncodedObject , Unset ] = Unset ()
175
+ is_encoded = False
173
176
for converter in self .converters .values ():
174
- payload = converter .to_payload (value )
175
- if payload is not None :
177
+ is_encoded , payload = converter .to_payload (value )
178
+ if is_encoded :
176
179
break
177
- if payload is None :
180
+ if not is_encoded :
178
181
raise RuntimeError (
179
182
f"Value of type { type (value )} has no known converter" ,
180
183
)
@@ -194,7 +197,7 @@ def from_payload(
194
197
RuntimeError: Error during decode
195
198
"""
196
199
encoding = payload .encoding
197
- assert isinstance (encoding , str )
200
+ assert isinstance (encoding , ( str , Unset ) )
198
201
converter = self .converters .get (encoding )
199
202
if converter is None :
200
203
raise KeyError (f"Unknown payload encoding { encoding } " )
@@ -229,17 +232,15 @@ class BinaryNullPayloadConverter(EncodingPayloadConverter):
229
232
"""Converter for 'binary/null' payloads supporting None values."""
230
233
231
234
@property
232
- def encoding (self ) -> str :
235
+ def encoding (self ) -> Union [ str , Unset ] :
233
236
"""See base class."""
234
- return "binary/null"
237
+ return UNSET
235
238
236
- def to_payload (self , value : Any ) -> Optional [ EncodedObject ]:
239
+ def to_payload (self , value : Any ) -> tuple [ bool , Union [ EncodedObject , Unset ] ]:
237
240
"""See base class."""
238
241
if value is None :
239
- return EncodedObject (
240
- encoding = self .encoding ,
241
- )
242
- return None
242
+ return (True , UNSET )
243
+ return (False , UNSET )
243
244
244
245
def from_payload (
245
246
self ,
@@ -256,18 +257,21 @@ class BinaryPlainPayloadConverter(EncodingPayloadConverter):
256
257
"""Converter for 'binary/plain' payloads supporting bytes values."""
257
258
258
259
@property
259
- def encoding (self ) -> str :
260
+ def encoding (self ) -> Union [ str , Unset ] :
260
261
"""See base class."""
261
262
return "binary/plain"
262
263
263
- def to_payload (self , value : Any ) -> Optional [ EncodedObject ]:
264
+ def to_payload (self , value : Any ) -> tuple [ bool , Union [ EncodedObject , Unset ] ]:
264
265
"""See base class."""
265
266
if isinstance (value , bytes ):
266
- return EncodedObject (
267
- encoding = self .encoding ,
268
- data = str (value ),
267
+ return (
268
+ True ,
269
+ EncodedObject (
270
+ encoding = self .encoding ,
271
+ data = str (value ),
272
+ ),
269
273
)
270
- return None
274
+ return ( False , UNSET )
271
275
272
276
def from_payload (
273
277
self ,
@@ -345,11 +349,11 @@ def __init__(
345
349
self ._custom_type_converters = custom_type_converters
346
350
347
351
@property
348
- def encoding (self ) -> str :
352
+ def encoding (self ) -> Union [ str , Unset ] :
349
353
"""See base class."""
350
354
return self ._encoding
351
355
352
- def to_payload (self , value : Any ) -> Optional [ EncodedObject ]:
356
+ def to_payload (self , value : Any ) -> tuple [ bool , Union [ EncodedObject , Unset ] ]:
353
357
"""See base class."""
354
358
# Check for pydantic then send warning
355
359
if hasattr (value , "parse_obj" ):
@@ -358,13 +362,16 @@ def to_payload(self, value: Any) -> Optional[EncodedObject]:
358
362
"https://github.com/temporalio/samples-python/tree/main/pydantic_converter for better support" ,
359
363
)
360
364
# We let JSON conversion errors be thrown to caller
361
- return EncodedObject (
362
- encoding = self .encoding ,
363
- data = json .dumps (
364
- value ,
365
- cls = self ._encoder ,
366
- separators = ("," , ":" ),
367
- sort_keys = True ,
365
+ return (
366
+ True ,
367
+ EncodedObject (
368
+ encoding = self .encoding ,
369
+ data = json .dumps (
370
+ value ,
371
+ cls = self ._encoder ,
372
+ separators = ("," , ":" ),
373
+ sort_keys = True ,
374
+ ),
368
375
),
369
376
)
370
377
@@ -428,7 +435,7 @@ class PayloadCodec(ABC):
428
435
@abstractmethod
429
436
def encode (
430
437
self ,
431
- payload : EncodedObject ,
438
+ payload : Union [ EncodedObject , Unset ] ,
432
439
) -> EncodedObject :
433
440
"""Encode the given payloads.
434
441
@@ -486,7 +493,7 @@ def __post_init__(self) -> None: # noqa: D105
486
493
def encode (
487
494
self ,
488
495
value : Any ,
489
- ) -> EncodedObject :
496
+ ) -> Union [ EncodedObject , Unset ] :
490
497
"""Encode values into payloads.
491
498
492
499
First converts values to payload then encodes payload using codec.
0 commit comments