Skip to content

pydantic_graph.util

Utility types and functions for type manipulation and introspection.

This module provides helper classes and functions for working with Python's type system, including workarounds for type checker limitations and utilities for runtime type inspection.

T module-attribute

T = TypeVar('T', infer_variance=True)

Generic type variable with inferred variance.

TypeExpression

Bases: Generic[T]

A workaround for type checker limitations when using complex type expressions.

This class serves as a wrapper for types that cannot normally be used in positions

requiring type[T], such as Any, Union[...], or Literal[...]. It provides a way to pass these complex type expressions to functions expecting concrete types.

Example

Instead of output_type=Union[str, int] (which may cause type errors), use output_type=TypeExpression[Union[str, int]].

Note

This is a workaround for the lack of TypeForm in the Python type system.

Source code in pydantic_graph/pydantic_graph/util.py
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
class TypeExpression(Generic[T]):
    """A workaround for type checker limitations when using complex type expressions.

        This class serves as a wrapper for types that cannot normally be used in positions
    requiring `type[T]`, such as `Any`, `Union[...]`, or `Literal[...]`. It provides a
        way to pass these complex type expressions to functions expecting concrete types.

    Example:
            Instead of `output_type=Union[str, int]` (which may cause type errors),
            use `output_type=TypeExpression[Union[str, int]]`.

    Note:
            This is a workaround for the lack of TypeForm in the Python type system.
    """

    pass

TypeOrTypeExpression module-attribute

TypeOrTypeExpression = TypeAliasType(
    "TypeOrTypeExpression",
    type[TypeExpression[T]] | type[T],
    type_params=(T,),
)

Type alias allowing both direct types and TypeExpression wrappers.

This alias enables functions to accept either regular types (when compatible with type checkers) or TypeExpression wrappers for complex type expressions. The correct type should be inferred automatically in either case.

unpack_type_expression

unpack_type_expression(
    type_: TypeOrTypeExpression[T],
) -> type[T]

Extract the actual type from a TypeExpression wrapper or return the type directly.

Parameters:

Name Type Description Default
type_ TypeOrTypeExpression[T]

Either a direct type or a TypeExpression wrapper.

required

Returns:

Type Description
type[T]

The unwrapped type, ready for use in runtime type operations.

Source code in pydantic_graph/pydantic_graph/util.py
43
44
45
46
47
48
49
50
51
52
53
54
def unpack_type_expression(type_: TypeOrTypeExpression[T]) -> type[T]:
    """Extract the actual type from a TypeExpression wrapper or return the type directly.

    Args:
        type_: Either a direct type or a TypeExpression wrapper.

    Returns:
        The unwrapped type, ready for use in runtime type operations.
    """
    if get_origin(type_) is TypeExpression:
        return get_args(type_)[0]
    return cast(type[T], type_)

Some dataclass

Bases: Generic[T]

Container for explicitly present values in Maybe type pattern.

This class represents a value that is definitely present, as opposed to None. It's part of the Maybe pattern, similar to Option/Maybe in functional programming, allowing distinction between "no value" (None) and "value is None" (Some(None)).

Source code in pydantic_graph/pydantic_graph/util.py
57
58
59
60
61
62
63
64
65
66
67
@dataclass
class Some(Generic[T]):
    """Container for explicitly present values in Maybe type pattern.

    This class represents a value that is definitely present, as opposed to None.
    It's part of the Maybe pattern, similar to Option/Maybe in functional programming,
    allowing distinction between "no value" (None) and "value is None" (Some(None)).
    """

    value: T
    """The wrapped value."""

value instance-attribute

value: T

The wrapped value.

Maybe module-attribute

Maybe = TypeAliasType(
    "Maybe", Some[T] | None, type_params=(T,)
)

Optional-like type that distinguishes between absence and None values.

Unlike Optional[T], Maybe[T] can differentiate between: - No value present: represented as None - Value is None: represented as Some(None)

This is particularly useful when None is a valid value in your domain.

get_callable_name

get_callable_name(callable_: Any) -> str

Extract a human-readable name from a callable object.

Parameters:

Name Type Description Default
callable_ Any

Any callable object (function, method, class, etc.).

required

Returns:

Type Description
str

The callable's name attribute if available, otherwise its string representation.

Source code in pydantic_graph/pydantic_graph/util.py
81
82
83
84
85
86
87
88
89
90
def get_callable_name(callable_: Any) -> str:
    """Extract a human-readable name from a callable object.

    Args:
        callable_: Any callable object (function, method, class, etc.).

    Returns:
        The callable's __name__ attribute if available, otherwise its string representation.
    """
    return getattr(callable_, '__name__', str(callable_))