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

39 statements  

1from __future__ import annotations 

2 

3from typing import Any 

4 

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 

16 

17__all__ = ( 

18 "FieldInfo", 

19 "StructConfig", 

20 "asdict", 

21 "astuple", 

22 "fields", 

23 "force_setattr", 

24 "replace", 

25) 

26 

27 

28def __dir__(): 

29 return __all__ 

30 

31 

32class FieldInfo(Struct): 

33 """A record describing a field in a struct type. 

34 

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 """ 

51 

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) 

57 

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 

62 

63 

64def fields(type_or_instance: Struct | type[Struct]) -> tuple[FieldInfo]: 

65 """Get information about the fields in a Struct. 

66 

67 Parameters 

68 ---------- 

69 type_or_instance: 

70 A struct type or instance. 

71 

72 Returns 

73 ------- 

74 tuple[FieldInfo] 

75 """ 

76 obj = type_or_instance 

77 

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") 

90 

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 

104 

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) 

113 

114 return tuple(fields)