1
1
import dataclasses
2
+ import datetime
3
+ import os
4
+ import pathlib
2
5
import uuid
3
- from datetime import datetime
4
6
5
7
import pydantic
6
8
import pytest
9
11
from temporalio .client import Client
10
12
from temporalio .contrib .pydantic import pydantic_data_converter
11
13
from temporalio .worker import Worker
14
+ from temporalio .worker .workflow_sandbox ._restrictions import (
15
+ RestrictionContext ,
16
+ SandboxMatcher ,
17
+ _RestrictedProxy ,
18
+ )
12
19
from tests .contrib .pydantic .models import (
13
20
PydanticModels ,
14
21
PydanticModelWithStrictField ,
@@ -103,7 +110,7 @@ async def test_round_trip_misc_objects(client: Client):
103
110
{"7" : 7.0 },
104
111
[{"7" : 7.0 }],
105
112
({"7" : 7.0 },),
106
- datetime (2025 , 1 , 2 , 3 , 4 , 5 ),
113
+ datetime . datetime (2025 , 1 , 2 , 3 , 4 , 5 ),
107
114
uuid .uuid4 (),
108
115
)
109
116
@@ -262,7 +269,9 @@ async def test_datetime_usage_in_workflow(client: Client):
262
269
263
270
def test_pydantic_model_with_strict_field_outside_sandbox ():
264
271
_test_pydantic_model_with_strict_field (
265
- PydanticModelWithStrictField (strict_field = datetime (2025 , 1 , 2 , 3 , 4 , 5 ))
272
+ PydanticModelWithStrictField (
273
+ strict_field = datetime .datetime (2025 , 1 , 2 , 3 , 4 , 5 )
274
+ )
266
275
)
267
276
268
277
@@ -276,7 +285,9 @@ async def test_pydantic_model_with_strict_field_inside_sandbox(client: Client):
276
285
workflows = [PydanticModelWithStrictFieldWorkflow ],
277
286
task_queue = tq ,
278
287
):
279
- orig = PydanticModelWithStrictField (strict_field = datetime (2025 , 1 , 2 , 3 , 4 , 5 ))
288
+ orig = PydanticModelWithStrictField (
289
+ strict_field = datetime .datetime (2025 , 1 , 2 , 3 , 4 , 5 )
290
+ )
280
291
result = await client .execute_workflow (
281
292
PydanticModelWithStrictFieldWorkflow .run ,
282
293
orig ,
@@ -324,3 +335,48 @@ async def test_validation_error(client: Client):
324
335
task_queue = task_queue_name ,
325
336
result_type = tuple [int ],
326
337
)
338
+
339
+
340
+ class RestrictedProxyFieldsModel (BaseModel ):
341
+ path_field : pathlib .Path
342
+ uuid_field : uuid .UUID
343
+ # A datetime.datetime field does not pass this test. See note in
344
+ # temporalio.worker.workflow_sandbox._restrictions._is_restrictable
345
+ datetime_field : datetime .datetime
346
+
347
+
348
+ def test_model_instantiation_from_restricted_proxy_values ():
349
+ restricted_path_cls = _RestrictedProxy (
350
+ "Path" ,
351
+ pathlib .Path ,
352
+ RestrictionContext (),
353
+ SandboxMatcher (),
354
+ )
355
+ restricted_uuid_cls = _RestrictedProxy (
356
+ "uuid" ,
357
+ uuid .UUID ,
358
+ RestrictionContext (),
359
+ SandboxMatcher (),
360
+ )
361
+ restricted_datetime_cls = _RestrictedProxy (
362
+ "datetime" ,
363
+ datetime .datetime ,
364
+ RestrictionContext (),
365
+ SandboxMatcher (),
366
+ )
367
+
368
+ restricted_path = restricted_path_cls ("test/path" )
369
+ restricted_uuid = restricted_uuid_cls (bytes = os .urandom (16 ), version = 4 )
370
+ restricted_datetime = restricted_datetime_cls (2025 , 1 , 2 , 3 , 4 , 5 )
371
+
372
+ assert type (restricted_path ) is _RestrictedProxy
373
+ assert type (restricted_uuid ) is _RestrictedProxy
374
+ assert type (restricted_datetime ) is not _RestrictedProxy
375
+ p = RestrictedProxyFieldsModel (
376
+ path_field = restricted_path , # type: ignore
377
+ uuid_field = restricted_uuid , # type: ignore
378
+ datetime_field = restricted_datetime , # type: ignore
379
+ )
380
+ assert p .path_field == restricted_path
381
+ assert p .uuid_field == restricted_uuid
382
+ assert p .datetime_field == restricted_datetime
0 commit comments