Skip to content

Commit b3f3662

Browse files
authored
Pydantic data converter (#757)
1 parent 77a1502 commit b3f3662

File tree

13 files changed

+1698
-111
lines changed

13 files changed

+1698
-111
lines changed

README.md

Lines changed: 31 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ informal introduction to the features and their implementation.
5252
- [Usage](#usage)
5353
- [Client](#client)
5454
- [Data Conversion](#data-conversion)
55+
- [Pydantic Support](#pydantic-support)
5556
- [Custom Type Data Conversion](#custom-type-data-conversion)
5657
- [Workers](#workers)
5758
- [Workflows](#workflows)
@@ -84,7 +85,6 @@ informal introduction to the features and their implementation.
8485
- [Extending Restricted Classes](#extending-restricted-classes)
8586
- [Certain Standard Library Calls on Restricted Objects](#certain-standard-library-calls-on-restricted-objects)
8687
- [is_subclass of ABC-based Restricted Classes](#is_subclass-of-abc-based-restricted-classes)
87-
- [Compiled Pydantic Sometimes Using Wrong Types](#compiled-pydantic-sometimes-using-wrong-types)
8888
- [Activities](#activities)
8989
- [Definition](#definition-1)
9090
- [Types of Activities](#types-of-activities)
@@ -298,10 +298,10 @@ other_ns_client = Client(**config)
298298
#### Data Conversion
299299

300300
Data converters are used to convert raw Temporal payloads to/from actual Python types. A custom data converter of type
301-
`temporalio.converter.DataConverter` can be set via the `data_converter` client parameter. Data converters are a
302-
combination of payload converters, payload codecs, and failure converters. Payload converters convert Python values
303-
to/from serialized bytes. Payload codecs convert bytes to bytes (e.g. for compression or encryption). Failure converters
304-
convert exceptions to/from serialized failures.
301+
`temporalio.converter.DataConverter` can be set via the `data_converter` parameter of the `Client` constructor. Data
302+
converters are a combination of payload converters, payload codecs, and failure converters. Payload converters convert
303+
Python values to/from serialized bytes. Payload codecs convert bytes to bytes (e.g. for compression or encryption).
304+
Failure converters convert exceptions to/from serialized failures.
305305

306306
The default data converter supports converting multiple types including:
307307

@@ -312,22 +312,39 @@ The default data converter supports converting multiple types including:
312312
* Anything that [`json.dump`](https://docs.python.org/3/library/json.html#json.dump) supports natively
313313
* [dataclasses](https://docs.python.org/3/library/dataclasses.html)
314314
* Iterables including ones JSON dump may not support by default, e.g. `set`
315-
* Any class with a `dict()` method and a static `parse_obj()` method, e.g.
316-
[Pydantic models](https://pydantic-docs.helpmanual.io/usage/models)
317-
* The default data converter is deprecated for Pydantic models and will warn if used since not all fields work.
318-
See [this sample](https://github.com/temporalio/samples-python/tree/main/pydantic_converter) for the recommended
319-
approach.
320315
* [IntEnum, StrEnum](https://docs.python.org/3/library/enum.html) based enumerates
321316
* [UUID](https://docs.python.org/3/library/uuid.html)
322317

323-
This notably doesn't include any `date`, `time`, or `datetime` objects as they may not work across SDKs.
318+
To use pydantic model instances, see [](#pydantic-support).
324319

325-
Users are strongly encouraged to use a single `dataclass` for parameter and return types so fields with defaults can be
326-
easily added without breaking compatibility.
320+
`datetime.date`, `datetime.time`, and `datetime.datetime` can only be used with the Pydantic data converter.
321+
322+
Although workflows, updates, signals, and queries can all be defined with multiple input parameters, users are strongly
323+
encouraged to use a single `dataclass` or Pydantic model parameter, so that fields with defaults can be easily added
324+
without breaking compatibility. Similar advice applies to return values.
327325

328326
Classes with generics may not have the generics properly resolved. The current implementation does not have generic
329327
type resolution. Users should use concrete types.
330328

329+
##### Pydantic Support
330+
331+
To use Pydantic model instances, install Pydantic and set the Pydantic data converter when creating client instances:
332+
333+
```python
334+
from temporalio.contrib.pydantic import pydantic_data_converter
335+
336+
client = Client(data_converter=pydantic_data_converter, ...)
337+
```
338+
339+
This data converter supports conversion of all types supported by Pydantic to and from JSON.
340+
341+
In addition to Pydantic models, these include all `json.dump`-able types, various non-`json.dump`-able standard library
342+
types such as dataclasses, types from the datetime module, sets, UUID, etc, and custom types composed of any of these.
343+
344+
Pydantic v1 is not supported by this data converter. If you are not yet able to upgrade from Pydantic v1, see
345+
https://github.com/temporalio/samples-python/tree/main/pydantic_converter/v1 for limited v1 support.
346+
347+
331348
##### Custom Type Data Conversion
332349

333350
For converting from JSON, the workflow/activity type hint is taken into account to convert to the proper type. Care has
@@ -1133,15 +1150,6 @@ Due to [https://bugs.python.org/issue44847](https://bugs.python.org/issue44847),
11331150
checked to see if they are subclasses of another via `is_subclass` may fail (see also
11341151
[this wrapt issue](https://github.com/GrahamDumpleton/wrapt/issues/130)).
11351152

1136-
###### Compiled Pydantic Sometimes Using Wrong Types
1137-
1138-
If the Pydantic dependency is in compiled form (the default) and you are using a Pydantic model inside a workflow
1139-
sandbox that uses a `datetime` type, it will grab the wrong validator and use `date` instead. This is because our
1140-
patched form of `issubclass` is bypassed by compiled Pydantic.
1141-
1142-
To work around, either don't use `datetime`-based Pydantic model fields in workflows, or mark `datetime` library as
1143-
passthrough (means you lose protection against calling the non-deterministic `now()`), or use non-compiled Pydantic
1144-
dependency.
11451153

11461154
### Activities
11471155

@@ -1341,7 +1349,7 @@ async def check_past_histories(my_client: Client):
13411349
OpenTelemetry support requires the optional `opentelemetry` dependencies which are part of the `opentelemetry` extra.
13421350
When using `pip`, running
13431351

1344-
pip install temporalio[opentelemetry]
1352+
pip install 'temporalio[opentelemetry]'
13451353

13461354
will install needed dependencies. Then the `temporalio.contrib.opentelemetry.TracingInterceptor` can be created and set
13471355
as an interceptor on the `interceptors` argument of `Client.connect`. When set, spans will be created for all client

0 commit comments

Comments
 (0)