Inspecting Types¶
Warning
This module is experimental. While we don’t expect any breaking changes, we also don’t promise not to break things between releases while this interface stabilizes.
msgspec
provides type-introspection support, which can be used to build
tooling on top of msgspec-compatible types. Possible use cases include:
Generating OpenAPI specifications from msgspec-compatible types (note that the builtin JSON Schema support may be a better starting point for this).
Generating example instances of types for testing or documentation purposes
Integration with hypothesis for testing
The main function here is msgspec.inspect.type_info
for converting a type
annotation into a corresponding msgspec.inspect.Type
object. There’s also
msgspec.inspect.multi_type_info
which converts an iterable of annotations;
this function is more efficient than calling type_info
in a loop.
>>> import msgspec
>>> msgspec.inspect.type_info(bool)
BoolType()
>>> msgspec.inspect.type_info(int)
IntType(gt=None, ge=None, lt=None, le=None, multiple_of=None)
>>> msgspec.inspect.type_info(list[int]) # nested types are traversed
ListType(
item_type=IntType(gt=None, ge=None, lt=None, le=None, multiple_of=None),
min_length=None,
max_length=None
)
>>> msgspec.inspect.multi_type_info([bool, int]) # inspect multiple types
(BoolType(), IntType(gt=None, ge=None, lt=None, le=None, multiple_of=None))
Types with Constraints will include the constraint information as well:
>>> from typing import Annotated
>>> from msgspec import Meta
>>> PositiveInt = Annotated[int, Meta(gt=0)]
>>> msgspec.inspect.type_info(PositiveInt)
IntType(gt=0, ge=None, lt=None, le=None, multiple_of=None)
Compound types like Structs are also supported:
>>> class User(msgspec.Struct):
... name: str
... groups: list[str] = []
... email: str | None = None
>>> msgspec.inspect.type_info(User)
StructType(
cls=User,
fields=(
Field(
name='name',
encode_name='name',
type=StrType(min_length=None, max_length=None, pattern=None),
required=True,
default=UNSET,
default_factory=UNSET
),
Field(
name='groups',
encode_name='groups',
type=ListType(
item_type=StrType(min_length=None, max_length=None, pattern=None),
min_length=None,
max_length=None
),
required=False,
default=[],
default_factory=UNSET
),
Field(
name='email',
encode_name='email',
type=UnionType(
types=(
StrType(min_length=None, max_length=None, pattern=None),
NoneType()
)
),
required=False,
default=None,
default_factory=UNSET
)
),
tag_field=None,
tag=None,
array_like=False,
forbid_unknown_fields=False
)
Types with additional metadata like extra_json_schema
or title
will be
wrapped in a msgspec.inspect.Metadata
object. Note that all JSON schema
specific fields are merged into a single extra_json_schema
dict.
>>> UnixName = Annotated[
... str,
... Meta(
... min_length=1,
... max_length=32,
... pattern="^[a-z_][a-z0-9_-]*$",
... description="A valid UNIX username"
... )
... ]
>>> msgspec.inspect.type_info(UnixName)
Metadata(
type=StrType(
min_length=1,
max_length=32,
pattern='^[a-z_][a-z0-9_-]*$'
),
extra_json_schema={'description': 'A valid UNIX username'}
)
Every type supported by msgspec
has a corresponding msgspec.inspect.Type
subclass. See the API docs for a complete list of types.
For an example of using these functions, you might find our builtin
JSON Schema generator implementation useful - the code for this can be
found here. In
particular, take a look at the large if-else statement in _to_schema
.