Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/msgspec/structs.py: 41%
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1from __future__ import annotations
3from typing import Any
5from . import NODEFAULT, Struct, field
6from ._core import ( # noqa
7 Factory as _Factory,
8 StructConfig,
9 StructMeta,
10 asdict,
11 astuple,
12 force_setattr,
13 replace,
14)
15from ._utils import get_class_annotations as _get_class_annotations
17__all__ = (
18 "FieldInfo",
19 "StructConfig",
20 "asdict",
21 "astuple",
22 "fields",
23 "force_setattr",
24 "replace",
25)
28def __dir__():
29 return __all__
32class FieldInfo(Struct):
33 """A record describing a field in a struct type.
35 Parameters
36 ----------
37 name: str
38 The field name as seen by Python code (e.g. ``field_one``).
39 encode_name: str
40 The name used when encoding/decoding the field. This may differ if
41 the field is renamed (e.g. ``fieldOne``).
42 type: Any
43 The full field type annotation.
44 default: Any, optional
45 A default value for the field. Will be `NODEFAULT` if no default value
46 is set.
47 default_factory: Any, optional
48 A callable that creates a default value for the field. Will be
49 `NODEFAULT` if no ``default_factory`` is set.
50 """
52 name: str
53 encode_name: str
54 type: Any
55 default: Any = field(default_factory=lambda: NODEFAULT)
56 default_factory: Any = field(default_factory=lambda: NODEFAULT)
58 @property
59 def required(self) -> bool:
60 """A helper for checking whether a field is required"""
61 return self.default is NODEFAULT and self.default_factory is NODEFAULT
64def fields(type_or_instance: Struct | type[Struct]) -> tuple[FieldInfo]:
65 """Get information about the fields in a Struct.
67 Parameters
68 ----------
69 type_or_instance:
70 A struct type or instance.
72 Returns
73 -------
74 tuple[FieldInfo]
75 """
76 obj = type_or_instance
78 # Struct class
79 if isinstance(obj, StructMeta):
80 annotated_cls = cls = obj
81 # Struct instance
82 elif isinstance(type(obj), StructMeta):
83 annotated_cls = cls = type(obj)
84 # Generic alias
85 else:
86 annotated_cls = obj
87 cls = getattr(obj, "__origin__", obj)
88 if not isinstance(cls, StructMeta):
89 raise TypeError("Must be called with a struct type or instance")
91 hints = _get_class_annotations(annotated_cls)
92 npos = len(cls.__struct_fields__) - len(cls.__struct_defaults__)
93 fields = []
94 for name, encode_name, default_obj in zip(
95 cls.__struct_fields__,
96 cls.__struct_encode_fields__,
97 (NODEFAULT,) * npos + cls.__struct_defaults__,
98 ):
99 default = default_factory = NODEFAULT
100 if isinstance(default_obj, _Factory):
101 default_factory = default_obj.factory
102 elif default_obj is not NODEFAULT:
103 default = default_obj
105 field = FieldInfo(
106 name=name,
107 encode_name=encode_name,
108 type=hints[name],
109 default=default,
110 default_factory=default_factory,
111 )
112 fields.append(field)
114 return tuple(fields)