Skip to content

Commit 1c79c84

Browse files
committed
ensure_type: supports complex types
like TypeDict Signed-off-by: Gaëtan Lehmann <[email protected]>
1 parent d0300bc commit 1c79c84

File tree

2 files changed

+18
-4
lines changed

2 files changed

+18
-4
lines changed

lib/common.py

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
from contextlib import suppress
12
import getpass
23
import inspect
34
import itertools
@@ -7,6 +8,7 @@
78
import time
89
import traceback
910
from enum import Enum
11+
from pydantic import TypeAdapter, ValidationError
1012
from typing import Any, Dict, Literal, Optional, Type, TypeVar, overload, TYPE_CHECKING, Union
1113
from uuid import UUID
1214

@@ -70,10 +72,21 @@ def expand_scope_relative_nodeid(scoped_nodeid, scope, ref_nodeid):
7072
T = TypeVar("T")
7173

7274
def ensure_type(typ: Type[T], value: Any) -> T:
73-
"""Converts a value to the specified type. Also performs a runtime check."""
74-
if not isinstance(value, typ):
75-
raise TypeError(f"'{type(value).__name__}' object is not of the expected type '{typ.__name__}'")
76-
return value
75+
"""
76+
Converts a value to the specified type.
77+
78+
Unlike typing.cast, it also performs a runtime check.
79+
Unlike isinstance, it also supports complex types.
80+
"""
81+
try:
82+
if isinstance(value, typ):
83+
return value
84+
except TypeError:
85+
# not just a simple type, lets try with pydantic
86+
with suppress(ValidationError):
87+
ta = TypeAdapter(typ)
88+
return ta.validate_python(value)
89+
raise TypeError(f"'{type(value).__name__}' object is not of the expected type '{typ.__name__}'")
7790

7891
def callable_marker(value, request):
7992
"""

requirements/base.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,4 @@ pluggy>=1.1.0
66
requests
77
legacycrypt
88
pytest-dependency
9+
pydantic

0 commit comments

Comments
 (0)