|
16 | 16 |
|
17 | 17 | """Test convert_if_exist_pydantic_model.""" |
18 | 18 |
|
| 19 | +import datetime |
19 | 20 | import inspect |
| 21 | +import sys |
20 | 22 | from typing import Optional, Union |
| 23 | +import uuid |
21 | 24 | import pydantic |
22 | 25 | import pytest |
23 | | -import sys |
24 | 26 | from ... import errors |
25 | 27 | from ..._extra_utils import convert_if_exist_pydantic_model |
26 | 28 |
|
@@ -307,3 +309,113 @@ def test_incompatible_value_and_annotation(): |
307 | 309 | 'param_name', |
308 | 310 | 'func_name', |
309 | 311 | ) |
| 312 | + |
| 313 | + |
| 314 | +def test_string_encoded_types(): |
| 315 | + """Strings for date, time, duration and UUID annotations are parsed.""" |
| 316 | + assert convert_if_exist_pydantic_model( |
| 317 | + '2026-11-10T09:30:00Z', datetime.datetime, 'param_name', 'func_name' |
| 318 | + ) == datetime.datetime(2026, 11, 10, 9, 30, tzinfo=datetime.timezone.utc) |
| 319 | + assert convert_if_exist_pydantic_model( |
| 320 | + '2026-11-10T09:30:00', datetime.datetime, 'param_name', 'func_name' |
| 321 | + ) == datetime.datetime(2026, 11, 10, 9, 30) |
| 322 | + assert convert_if_exist_pydantic_model( |
| 323 | + '12345678-1234-5678-1234-567812345678', |
| 324 | + uuid.UUID, |
| 325 | + 'param_name', |
| 326 | + 'func_name', |
| 327 | + ) == uuid.UUID('12345678-1234-5678-1234-567812345678') |
| 328 | + assert convert_if_exist_pydantic_model( |
| 329 | + '2026-11-10', datetime.date, 'param_name', 'func_name' |
| 330 | + ) == datetime.date(2026, 11, 10) |
| 331 | + assert convert_if_exist_pydantic_model( |
| 332 | + '09:30:00', datetime.time, 'param_name', 'func_name' |
| 333 | + ) == datetime.time(9, 30) |
| 334 | + assert convert_if_exist_pydantic_model( |
| 335 | + 'PT1H', datetime.timedelta, 'param_name', 'func_name' |
| 336 | + ) == datetime.timedelta(hours=1) |
| 337 | + value = datetime.datetime(2026, 11, 10, 9, 30) |
| 338 | + assert ( |
| 339 | + convert_if_exist_pydantic_model( |
| 340 | + value, datetime.datetime, 'param_name', 'func_name' |
| 341 | + ) |
| 342 | + is value |
| 343 | + ) |
| 344 | + |
| 345 | + |
| 346 | +def test_string_encoded_types_in_containers_and_unions(): |
| 347 | + """Parsing applies inside list, dict and union annotations.""" |
| 348 | + assert convert_if_exist_pydantic_model( |
| 349 | + '2026-11-10T09:30:00Z', |
| 350 | + Optional[datetime.datetime], |
| 351 | + 'param_name', |
| 352 | + 'func_name', |
| 353 | + ) == datetime.datetime(2026, 11, 10, 9, 30, tzinfo=datetime.timezone.utc) |
| 354 | + assert ( |
| 355 | + convert_if_exist_pydantic_model( |
| 356 | + None, Optional[uuid.UUID], 'param_name', 'func_name' |
| 357 | + ) |
| 358 | + is None |
| 359 | + ) |
| 360 | + if sys.version_info >= (3, 10): |
| 361 | + assert convert_if_exist_pydantic_model( |
| 362 | + '12345678-1234-5678-1234-567812345678', |
| 363 | + uuid.UUID | None, |
| 364 | + 'param_name', |
| 365 | + 'func_name', |
| 366 | + ) == uuid.UUID('12345678-1234-5678-1234-567812345678') |
| 367 | + assert convert_if_exist_pydantic_model( |
| 368 | + ['2026-11-10', '2026-11-11'], |
| 369 | + list[datetime.date], |
| 370 | + 'param_name', |
| 371 | + 'func_name', |
| 372 | + ) == [datetime.date(2026, 11, 10), datetime.date(2026, 11, 11)] |
| 373 | + assert convert_if_exist_pydantic_model( |
| 374 | + {'a': '12345678-1234-5678-1234-567812345678'}, |
| 375 | + dict[str, uuid.UUID], |
| 376 | + 'param_name', |
| 377 | + 'func_name', |
| 378 | + ) == {'a': uuid.UUID('12345678-1234-5678-1234-567812345678')} |
| 379 | + assert ( |
| 380 | + convert_if_exist_pydantic_model( |
| 381 | + 'not a date', |
| 382 | + Union[datetime.datetime, str], |
| 383 | + 'param_name', |
| 384 | + 'func_name', |
| 385 | + ) |
| 386 | + == 'not a date' |
| 387 | + ) |
| 388 | + assert ( |
| 389 | + convert_if_exist_pydantic_model( |
| 390 | + '2026-11-10', Union[str, datetime.date], 'param_name', 'func_name' |
| 391 | + ) |
| 392 | + == '2026-11-10' |
| 393 | + ) |
| 394 | + |
| 395 | + |
| 396 | +def test_invalid_string_encoded_value_raises(): |
| 397 | + """Unparseable or non-string values for these annotations raise.""" |
| 398 | + with pytest.raises( |
| 399 | + errors.UnknownFunctionCallArgumentError, match='due to error' |
| 400 | + ): |
| 401 | + convert_if_exist_pydantic_model( |
| 402 | + 'not a date', datetime.datetime, 'param_name', 'func_name' |
| 403 | + ) |
| 404 | + with pytest.raises( |
| 405 | + errors.UnknownFunctionCallArgumentError, match='due to error' |
| 406 | + ): |
| 407 | + convert_if_exist_pydantic_model( |
| 408 | + 'nope', uuid.UUID, 'param_name', 'func_name' |
| 409 | + ) |
| 410 | + with pytest.raises( |
| 411 | + errors.UnknownFunctionCallArgumentError, match='not compatible' |
| 412 | + ): |
| 413 | + convert_if_exist_pydantic_model( |
| 414 | + 1700000000, datetime.datetime, 'param_name', 'func_name' |
| 415 | + ) |
| 416 | + with pytest.raises( |
| 417 | + errors.UnknownFunctionCallArgumentError, match='cannot be converted' |
| 418 | + ): |
| 419 | + convert_if_exist_pydantic_model( |
| 420 | + 'bad', Optional[uuid.UUID], 'param_name', 'func_name' |
| 421 | + ) |
0 commit comments