1from .constants import MISSING
2
3try:
4 from collections.abc import Callable
5 from typing import Any, TypeAlias
6
7 from .constants import MissingLiteral
8
9 DefaultFactory: TypeAlias = Callable[[], Any]
10except ImportError:
11 pass
12
13
[docs]
14class FrozenInstanceError(AttributeError):
15 """Exception raised when attempting to mutate a frozen dataclass instance."""
16
17 pass
18
19
[docs]
20def field(
21 *,
22 default: Any | MissingLiteral = MISSING,
23 default_factory: DefaultFactory | MissingLiteral = MISSING,
24 init: bool = True,
25 repr: bool = True,
26 hash: bool | None = None,
27 compare: bool = True,
28) -> "Field":
29 """Function for explicitly declaring a field."""
30 return Field(
31 default=default,
32 default_factory=default_factory,
33 init=init,
34 repr=repr,
35 hash=hash,
36 compare=compare,
37 )
38
39
[docs]
40class Field:
41 """
42 Internal representation of a field provided by introspection routines.
43 Users should not directly instantiate this class.
44 """
45
46 name: str
47 type: type = object
48 default: Any | MissingLiteral
49 default_factory: DefaultFactory | MissingLiteral
50 init: bool
51 repr: bool
52 hash: bool | None
53 compare: bool
54
55 init_only: bool
56
57 def __init__(
58 self,
59 name: str = "<UNSET>",
60 default: Any = MISSING,
61 default_factory: DefaultFactory | MissingLiteral = MISSING,
62 init: bool = True,
63 repr: bool = True,
64 hash: bool | None = None,
65 compare: bool = True,
66 init_only: bool = False,
67 ) -> None:
68 self.name = name
69 self.default = default
70 self.default_factory = default_factory
71 self.init = init
72 self.repr = repr
73 self.hash = hash
74 self.compare = compare
75 self.init_only = init_only
76
77 def __eq__(self, other: object) -> bool:
78 if isinstance(other, Field):
79 return self.name == other.name
80 return False
81
82 def __repr__(self) -> str:
83 return f"Field({self.name!r}, {self.default!r})"
84
85 @property
86 def _name(self) -> str:
87 return f"_{self.name}"
88
89 @property
90 def default_value_name(self) -> str:
91 """Name to use for storing the default value as a global."""
92 return f"__dataclass_default_{self.name}"
93
94 @property
95 def contributes_to_hash(self) -> bool:
96 """True if this field should contribute to generated __hash__() method."""
97 if self.hash is None:
98 return self.compare
99 return self.hash