· 4 years ago · Feb 28, 2021, 11:10 AM
1#!/usr/bin/env python3
2# -*- coding: utf-8 -*-
3import re
4import sys
5import copy
6import types
7import inspect
8import keyword
9import builtins
10import functools
11import _thread
12
13
14
15
16
17# A sentinel object for default values to signal that a default
18# factory will be used. This is given a nice repr() which will appear
19# in the function signature of dataclasses' constructors.
20class _HAS_DEFAULT_FACTORY_CLASS:
21 def __repr__(self):
22 return '<factory>'
23_HAS_DEFAULT_FACTORY = _HAS_DEFAULT_FACTORY_CLASS()
24
25# A sentinel object to detect if a parameter is supplied or not. Use
26# a class to give it a better repr.
27class _MISSING_TYPE:
28 pass
29MISSING = _MISSING_TYPE()
30
31# Since most per-field metadata will be unused, create an empty
32# read-only proxy that can be shared among all fields.
33_EMPTY_METADATA = types.MappingProxyType({})
34
35# Markers for the various kinds of fields and pseudo-fields.
36class _FIELD_BASE:
37 def __init__(self, name):
38 self.name = name
39 def __repr__(self):
40 return self.name
41_FIELD = _FIELD_BASE('_FIELD')
42_FIELD_CLASSVAR = _FIELD_BASE('_FIELD_CLASSVAR')
43_FIELD_INITVAR = _FIELD_BASE('_FIELD_INITVAR')
44
45# The name of an attribute on the class where we store the Field
46# objects. Also used to check if a class is a Data Class.
47_FIELDS = '__dataclass_fields__'
48
49# The name of an attribute on the class that stores the parameters to
50# @dataclass.
51_PARAMS = '__dataclass_params__'
52
53# The name of the function, that if it exists, is called at the end of
54# __init__.
55_POST_INIT_NAME = '__post_init__'
56
57# String regex that string annotations for ClassVar or InitVar must match.
58# Allows "identifier.identifier[" or "identifier[".
59# https://bugs.python.org/issue33453 for details.
60_MODULE_IDENTIFIER_RE = re.compile(r'^(?:\s*(\w+)\s*\.)?\s*(\w+)')
61
62class _InitVarMeta(type):
63 def __getitem__(self, params):
64 return InitVar(params)
65
66class InitVar(metaclass=_InitVarMeta):
67 __slots__ = ('type', )
68
69 def __init__(self, type):
70 self.type = type
71
72 def __repr__(self):
73 if isinstance(self.type, type):
74 type_name = self.type.__name__
75 else:
76 # typing objects, e.g. List[int]
77 type_name = repr(self.type)
78 return f'dataclasses.InitVar[{type_name}]'
79
80
81# Instances of Field are only ever created from within this module,
82# and only from the field() function, although Field instances are
83# exposed externally as (conceptually) read-only objects.
84#
85# name and type are filled in after the fact, not in __init__.
86# They're not known at the time this class is instantiated, but it's
87# convenient if they're available later.
88#
89# When cls._FIELDS is filled in with a list of Field objects, the name
90# and type fields will have been populated.
91class Field:
92 __slots__ = ('name',
93 'type',
94 'default',
95 'default_factory',
96 'repr',
97 'hash',
98 'init',
99 'compare',
100 'metadata',
101 '_field_type', # Private: not to be used by user code.
102 )
103
104 def __init__(self, default, default_factory, init, repr, hash, compare,
105 metadata):
106 self.name = None
107 self.type = None
108 self.default = default
109 self.default_factory = default_factory
110 self.init = init
111 self.repr = repr
112 self.hash = hash
113 self.compare = compare
114 self.metadata = (_EMPTY_METADATA
115 if metadata is None else
116 types.MappingProxyType(metadata))
117 self._field_type = None
118
119 def __repr__(self):
120 return ('Field('
121 f'name={self.name!r},'
122 f'type={self.type!r},'
123 f'default={self.default!r},'
124 f'default_factory={self.default_factory!r},'
125 f'init={self.init!r},'
126 f'repr={self.repr!r},'
127 f'hash={self.hash!r},'
128 f'compare={self.compare!r},'
129 f'metadata={self.metadata!r},'
130 f'_field_type={self._field_type}'
131 ')')
132
133 # This is used to support the PEP 487 __set_name__ protocol in the
134 # case where we're using a field that contains a descriptor as a
135 # default value. For details on __set_name__, see
136 # https://www.python.org/dev/peps/pep-0487/#implementation-details.
137 #
138 # Note that in _process_class, this Field object is overwritten
139 # with the default value, so the end result is a descriptor that
140 # had __set_name__ called on it at the right time.
141 def __set_name__(self, owner, name):
142 func = getattr(type(self.default), '__set_name__', None)
143 if func:
144 # There is a __set_name__ method on the descriptor, call
145 # it.
146 func(self.default, owner, name)
147
148
149class _DataclassParams:
150 __slots__ = ('init',
151 'repr',
152 'eq',
153 'order',
154 'unsafe_hash',
155 'frozen',
156 )
157
158 def __init__(self, init, repr, eq, order, unsafe_hash, frozen):
159 self.init = init
160 self.repr = repr
161 self.eq = eq
162 self.order = order
163 self.unsafe_hash = unsafe_hash
164 self.frozen = frozen
165
166 def __repr__(self):
167 return ('_DataclassParams('
168 f'init={self.init!r},'
169 f'repr={self.repr!r},'
170 f'eq={self.eq!r},'
171 f'order={self.order!r},'
172 f'unsafe_hash={self.unsafe_hash!r},'
173 f'frozen={self.frozen!r}'
174 ')')
175
176
177# This function is used instead of exposing Field creation directly,
178# so that a type checker can be told (via overloads) that this is a
179# function whose type depends on its parameters.
180def field(*, default=MISSING, default_factory=MISSING, init=True, repr=True,
181 hash=None, compare=True, metadata=None):
182 """Return an object to identify dataclass fields.
183 default is the default value of the field. default_factory is a
184 0-argument function called to initialize a field's value. If init
185 is True, the field will be a parameter to the class's __init__()
186 function. If repr is True, the field will be included in the
187 object's repr(). If hash is True, the field will be included in
188 the object's hash(). If compare is True, the field will be used
189 in comparison functions. metadata, if specified, must be a
190 mapping which is stored but not otherwise examined by dataclass.
191 It is an error to specify both default and default_factory.
192 """
193
194 if default is not MISSING and default_factory is not MISSING:
195 raise ValueError('cannot specify both default and default_factory')
196 return Field(default, default_factory, init, repr, hash, compare,
197 metadata)
198
199
200def _tuple_str(obj_name, fields):
201 # Return a string representing each field of obj_name as a tuple
202 # member. So, if fields is ['x', 'y'] and obj_name is "self",
203 # return "(self.x,self.y)".
204
205 # Special case for the 0-tuple.
206 if not fields:
207 return '()'
208 # Note the trailing comma, needed if this turns out to be a 1-tuple.
209 return f'({",".join([f"{obj_name}.{f.name}" for f in fields])},)'
210
211
212# This function's logic is copied from "recursive_repr" function in
213# reprlib module to avoid dependency.
214def _recursive_repr(user_function):
215 # Decorator to make a repr function return "..." for a recursive
216 # call.
217 repr_running = set()
218
219 @functools.wraps(user_function)
220 def wrapper(self):
221 key = id(self), _thread.get_ident()
222 if key in repr_running:
223 return '...'
224 repr_running.add(key)
225 try:
226 result = user_function(self)
227 finally:
228 repr_running.discard(key)
229 return result
230 return wrapper
231
232
233def _create_fn(name, args, body, *, globals=None, locals=None,
234 return_type=MISSING):
235 # Note that we mutate locals when exec() is called. Caller
236 # beware! The only callers are internal to this module, so no
237 # worries about external callers.
238 if locals is None:
239 locals = {}
240 if 'BUILTINS' not in locals:
241 locals['BUILTINS'] = builtins
242 return_annotation = ''
243 if return_type is not MISSING:
244 locals['_return_type'] = return_type
245 return_annotation = '->_return_type'
246 args = ','.join(args)
247 body = '\n'.join(f' {b}' for b in body)
248
249 # Compute the text of the entire function.
250 txt = f' def {name}({args}){return_annotation}:\n{body}'
251
252 local_vars = ', '.join(locals.keys())
253 txt = f"def __create_fn__({local_vars}):\n{txt}\n return {name}"
254
255 ns = {}
256 exec(txt, globals, ns)
257 return ns['__create_fn__'](**locals)
258
259
260def _field_assign(frozen, name, value, self_name):
261 # If we're a frozen class, then assign to our fields in __init__
262 # via object.__setattr__. Otherwise, just use a simple
263 # assignment.
264 #
265 # self_name is what "self" is called in this function: don't
266 # hard-code "self", since that might be a field name.
267 if frozen:
268 return f'BUILTINS.object.__setattr__({self_name},{name!r},{value})'
269 return f'{self_name}.{name}={value}'
270
271
272def _field_init(f, frozen, globals, self_name):
273 # Return the text of the line in the body of __init__ that will
274 # initialize this field.
275
276 default_name = f'_dflt_{f.name}'
277 if f.default_factory is not MISSING:
278 if f.init:
279 # This field has a default factory. If a parameter is
280 # given, use it. If not, call the factory.
281 globals[default_name] = f.default_factory
282 value = (f'{default_name}() '
283 f'if {f.name} is _HAS_DEFAULT_FACTORY '
284 f'else {f.name}')
285 else:
286 # This is a field that's not in the __init__ params, but
287 # has a default factory function. It needs to be
288 # initialized here by calling the factory function,
289 # because there's no other way to initialize it.
290
291 # For a field initialized with a default=defaultvalue, the
292 # class dict just has the default value
293 # (cls.fieldname=defaultvalue). But that won't work for a
294 # default factory, the factory must be called in __init__
295 # and we must assign that to self.fieldname. We can't
296 # fall back to the class dict's value, both because it's
297 # not set, and because it might be different per-class
298 # (which, after all, is why we have a factory function!).
299
300 globals[default_name] = f.default_factory
301 value = f'{default_name}()'
302 else:
303 # No default factory.
304 if f.init:
305 if f.default is MISSING:
306 # There's no default, just do an assignment.
307 value = f.name
308 elif f.default is not MISSING:
309 globals[default_name] = f.default
310 value = f.name
311 else:
312 # This field does not need initialization. Signify that
313 # to the caller by returning None.
314 return None
315
316 # Only test this now, so that we can create variables for the
317 # default. However, return None to signify that we're not going
318 # to actually do the assignment statement for InitVars.
319 if f._field_type is _FIELD_INITVAR:
320 return None
321
322 # Now, actually generate the field assignment.
323 return _field_assign(frozen, f.name, value, self_name)
324
325
326def _init_param(f):
327 # Return the __init__ parameter string for this field. For
328 # example, the equivalent of 'x:int=3' (except instead of 'int',
329 # reference a variable set to int, and instead of '3', reference a
330 # variable set to 3).
331 if f.default is MISSING and f.default_factory is MISSING:
332 # There's no default, and no default_factory, just output the
333 # variable name and type.
334 default = ''
335 elif f.default is not MISSING:
336 # There's a default, this will be the name that's used to look
337 # it up.
338 default = f'=_dflt_{f.name}'
339 elif f.default_factory is not MISSING:
340 # There's a factory function. Set a marker.
341 default = '=_HAS_DEFAULT_FACTORY'
342 return f'{f.name}:_type_{f.name}{default}'
343
344
345def _init_fn(fields, frozen, has_post_init, self_name, globals):
346 # fields contains both real fields and InitVar pseudo-fields.
347
348 # Make sure we don't have fields without defaults following fields
349 # with defaults. This actually would be caught when exec-ing the
350 # function source code, but catching it here gives a better error
351 # message, and future-proofs us in case we build up the function
352 # using ast.
353 seen_default = False
354 for f in fields:
355 # Only consider fields in the __init__ call.
356 if f.init:
357 if not (f.default is MISSING and f.default_factory is MISSING):
358 seen_default = True
359 elif seen_default:
360 raise TypeError(f'non-default argument {f.name!r} '
361 'follows default argument')
362
363 locals = {f'_type_{f.name}': f.type for f in fields}
364 locals.update({
365 'MISSING': MISSING,
366 '_HAS_DEFAULT_FACTORY': _HAS_DEFAULT_FACTORY,
367 })
368
369 body_lines = []
370 for f in fields:
371 line = _field_init(f, frozen, locals, self_name)
372 # line is None means that this field doesn't require
373 # initialization (it's a pseudo-field). Just skip it.
374 if line:
375 body_lines.append(line)
376
377 # Does this class have a post-init function?
378 if has_post_init:
379 params_str = ','.join(f.name for f in fields
380 if f._field_type is _FIELD_INITVAR)
381 body_lines.append(f'{self_name}.{_POST_INIT_NAME}({params_str})')
382
383 # If no body lines, use 'pass'.
384 if not body_lines:
385 body_lines = ['pass']
386
387 return _create_fn('__init__',
388 [self_name] + [_init_param(f) for f in fields if f.init],
389 body_lines,
390 locals=locals,
391 globals=globals,
392 return_type=None)
393
394
395def _repr_fn(fields, globals):
396 fn = _create_fn('__repr__',
397 ('self',),
398 ['return self.__class__.__name__ + f"(' +
399 ', '.join([f"{f.name}={{self.{f.name}!r}}"
400 for f in fields]) +
401 ')"'],
402 globals=globals)
403 return _recursive_repr(fn)
404
405
406def _frozen_get_del_attr(cls, fields, globals):
407 locals = {'cls': cls,
408 'ReadonlyAttributeError': ReadonlyAttributeError}
409 if fields:
410 fields_str = '(' + ','.join(repr(f.name) for f in fields) + ',)'
411 else:
412 # Special case for the zero-length tuple.
413 fields_str = '()'
414 return (_create_fn('__setattr__',
415 ('self', 'name', 'value'),
416 (f'if type(self) is cls or name in {fields_str}:',
417 ' raise ReadonlyAttributeError(f"cannot assign to field {name!r}")',
418 f'super(cls, self).__setattr__(name, value)'),
419 locals=locals,
420 globals=globals),
421 _create_fn('__delattr__',
422 ('self', 'name'),
423 (f'if type(self) is cls or name in {fields_str}:',
424 ' raise ReadonlyAttributeError(f"cannot delete field {name!r}")',
425 f'super(cls, self).__delattr__(name)'),
426 locals=locals,
427 globals=globals),
428 )
429
430
431def _cmp_fn(name, op, self_tuple, other_tuple, globals):
432 # Create a comparison function. If the fields in the object are
433 # named 'x' and 'y', then self_tuple is the string
434 # '(self.x,self.y)' and other_tuple is the string
435 # '(other.x,other.y)'.
436
437 return _create_fn(name,
438 ('self', 'other'),
439 [ 'if other.__class__ is self.__class__:',
440 f' return {self_tuple}{op}{other_tuple}',
441 'return NotImplemented'],
442 globals=globals)
443
444
445def _hash_fn(fields, globals):
446 self_tuple = _tuple_str('self', fields)
447 return _create_fn('__hash__',
448 ('self',),
449 [f'return hash({self_tuple})'],
450 globals=globals)
451
452
453def _is_classvar(a_type, typing):
454 # This test uses a typing internal class, but it's the best way to
455 # test if this is a ClassVar.
456 return (a_type is typing.ClassVar
457 or (type(a_type) is typing._GenericAlias
458 and a_type.__origin__ is typing.ClassVar))
459
460
461def _is_initvar(a_type, dataclasses):
462 # The module we're checking against is the module we're
463 # currently in (dataclasses.py).
464 return (a_type is dataclasses.InitVar
465 or type(a_type) is dataclasses.InitVar)
466
467
468def _is_type(annotation, cls, a_module, a_type, is_type_predicate):
469 # Given a type annotation string, does it refer to a_type in
470 # a_module? For example, when checking that annotation denotes a
471 # ClassVar, then a_module is typing, and a_type is
472 # typing.ClassVar.
473
474 # It's possible to look up a_module given a_type, but it involves
475 # looking in sys.modules (again!), and seems like a waste since
476 # the caller already knows a_module.
477
478 # - annotation is a string type annotation
479 # - cls is the class that this annotation was found in
480 # - a_module is the module we want to match
481 # - a_type is the type in that module we want to match
482 # - is_type_predicate is a function called with (obj, a_module)
483 # that determines if obj is of the desired type.
484
485 # Since this test does not do a local namespace lookup (and
486 # instead only a module (global) lookup), there are some things it
487 # gets wrong.
488
489 # With string annotations, cv0 will be detected as a ClassVar:
490 # CV = ClassVar
491 # @dataclass
492 # class C0:
493 # cv0: CV
494
495 # But in this example cv1 will not be detected as a ClassVar:
496 # @dataclass
497 # class C1:
498 # CV = ClassVar
499 # cv1: CV
500
501 # In C1, the code in this function (_is_type) will look up "CV" in
502 # the module and not find it, so it will not consider cv1 as a
503 # ClassVar. This is a fairly obscure corner case, and the best
504 # way to fix it would be to eval() the string "CV" with the
505 # correct global and local namespaces. However that would involve
506 # a eval() penalty for every single field of every dataclass
507 # that's defined. It was judged not worth it.
508
509 match = _MODULE_IDENTIFIER_RE.match(annotation)
510 if match:
511 ns = None
512 module_name = match.group(1)
513 if not module_name:
514 # No module name, assume the class's module did
515 # "from dataclasses import InitVar".
516 ns = sys.modules.get(cls.__module__).__dict__
517 else:
518 # Look up module_name in the class's module.
519 module = sys.modules.get(cls.__module__)
520 if module and module.__dict__.get(module_name) is a_module:
521 ns = sys.modules.get(a_type.__module__).__dict__
522 if ns and is_type_predicate(ns.get(match.group(2)), a_module):
523 return True
524 return False
525
526
527def _get_field(cls, a_name, a_type):
528 # Return a Field object for this field name and type. ClassVars
529 # and InitVars are also returned, but marked as such (see
530 # f._field_type).
531
532 # If the default value isn't derived from Field, then it's only a
533 # normal default value. Convert it to a Field().
534 default = getattr(cls, a_name, MISSING)
535 if isinstance(default, Field):
536 f = default
537 else:
538 if isinstance(default, types.MemberDescriptorType):
539 # This is a field in __slots__, so it has no default value.
540 default = MISSING
541 f = field(default=default)
542
543 # Only at this point do we know the name and the type. Set them.
544 f.name = a_name
545 f.type = a_type
546
547 # Assume it's a normal field until proven otherwise. We're next
548 # going to decide if it's a ClassVar or InitVar, everything else
549 # is just a normal field.
550 f._field_type = _FIELD
551
552 # In addition to checking for actual types here, also check for
553 # string annotations. get_type_hints() won't always work for us
554 # (see https://github.com/python/typing/issues/508 for example),
555 # plus it's expensive and would require an eval for every stirng
556 # annotation. So, make a best effort to see if this is a ClassVar
557 # or InitVar using regex's and checking that the thing referenced
558 # is actually of the correct type.
559
560 # For the complete discussion, see https://bugs.python.org/issue33453
561
562 # If typing has not been imported, then it's impossible for any
563 # annotation to be a ClassVar. So, only look for ClassVar if
564 # typing has been imported by any module (not necessarily cls's
565 # module).
566 typing = sys.modules.get('typing')
567 if typing:
568 if (_is_classvar(a_type, typing)
569 or (isinstance(f.type, str)
570 and _is_type(f.type, cls, typing, typing.ClassVar,
571 _is_classvar))):
572 f._field_type = _FIELD_CLASSVAR
573
574 # If the type is InitVar, or if it's a matching string annotation,
575 # then it's an InitVar.
576 if f._field_type is _FIELD:
577 # The module we're checking against is the module we're
578 # currently in (dataclasses.py).
579 dataclasses = sys.modules[__name__]
580 if (_is_initvar(a_type, dataclasses)
581 or (isinstance(f.type, str)
582 and _is_type(f.type, cls, dataclasses, dataclasses.InitVar,
583 _is_initvar))):
584 f._field_type = _FIELD_INITVAR
585
586 # Validations for individual fields. This is delayed until now,
587 # instead of in the Field() constructor, since only here do we
588 # know the field name, which allows for better error reporting.
589
590 # Special restrictions for ClassVar and InitVar.
591 if f._field_type in (_FIELD_CLASSVAR, _FIELD_INITVAR):
592 if f.default_factory is not MISSING:
593 raise TypeError(f'field {f.name} cannot have a '
594 'default factory')
595 # Should I check for other field settings? default_factory
596 # seems the most serious to check for. Maybe add others. For
597 # example, how about init=False (or really,
598 # init=<not-the-default-init-value>)? It makes no sense for
599 # ClassVar and InitVar to specify init=<anything>.
600
601 # For real fields, disallow mutable defaults for known types.
602 if f._field_type is _FIELD and isinstance(f.default, (list, dict, set)):
603 raise ValueError(f'mutable default {type(f.default)} for field '
604 f'{f.name} is not allowed: use default_factory')
605
606 return f
607
608
609def _set_new_attribute(cls, name, value):
610 # Never overwrites an existing attribute. Returns True if the
611 # attribute already exists.
612 if name in cls.__dict__:
613 return True
614 setattr(cls, name, value)
615 return False
616
617
618# Decide if/how we're going to create a hash function. Key is
619# (unsafe_hash, eq, frozen, does-hash-exist). Value is the action to
620# take. The common case is to do nothing, so instead of providing a
621# function that is a no-op, use None to signify that.
622
623def _hash_set_none(cls, fields, globals):
624 return None
625
626def _hash_add(cls, fields, globals):
627 flds = [f for f in fields if (f.compare if f.hash is None else f.hash)]
628 return _hash_fn(flds, globals)
629
630def _hash_exception(cls, fields, globals):
631 # Raise an exception.
632 raise TypeError(f'Cannot overwrite attribute __hash__ '
633 f'in class {cls.__name__}')
634
635#
636# +-------------------------------------- unsafe_hash?
637# | +------------------------------- eq?
638# | | +------------------------ frozen?
639# | | | +---------------- has-explicit-hash?
640# | | | |
641# | | | | +------- action
642# | | | | |
643# v v v v v
644_hash_action = {(False, False, False, False): None,
645 (False, False, False, True ): None,
646 (False, False, True, False): None,
647 (False, False, True, True ): None,
648 (False, True, False, False): _hash_set_none,
649 (False, True, False, True ): None,
650 (False, True, True, False): _hash_add,
651 (False, True, True, True ): None,
652 (True, False, False, False): _hash_add,
653 (True, False, False, True ): _hash_exception,
654 (True, False, True, False): _hash_add,
655 (True, False, True, True ): _hash_exception,
656 (True, True, False, False): _hash_add,
657 (True, True, False, True ): _hash_exception,
658 (True, True, True, False): _hash_add,
659 (True, True, True, True ): _hash_exception,
660 }
661# See https://bugs.python.org/issue32929#msg312829 for an if-statement
662# version of this table.
663
664
665def _process_class(cls, init, repr, eq, order, unsafe_hash, frozen):
666 # Now that dicts retain insertion order, there's no reason to use
667 # an ordered dict. I am leveraging that ordering here, because
668 # derived class fields overwrite base class fields, but the order
669 # is defined by the base class, which is found first.
670 fields = {}
671
672 if cls.__module__ in sys.modules:
673 globals = sys.modules[cls.__module__].__dict__
674 else:
675 # Theoretically this can happen if someone writes
676 # a custom string to cls.__module__. In which case
677 # such dataclass won't be fully introspectable
678 # (w.r.t. typing.get_type_hints) but will still function
679 # correctly.
680 globals = {}
681
682 setattr(cls, _PARAMS, _DataclassParams(init, repr, eq, order,
683 unsafe_hash, frozen))
684
685 # Find our base classes in reverse MRO order, and exclude
686 # ourselves. In reversed order so that more derived classes
687 # override earlier field definitions in base classes. As long as
688 # we're iterating over them, see if any are frozen.
689 any_frozen_base = False
690 has_dataclass_bases = False
691 for b in cls.__mro__[-1:0:-1]:
692 # Only process classes that have been processed by our
693 # decorator. That is, they have a _FIELDS attribute.
694 base_fields = getattr(b, _FIELDS, None)
695 if base_fields:
696 has_dataclass_bases = True
697 for f in base_fields.values():
698 fields[f.name] = f
699 if getattr(b, _PARAMS).frozen:
700 any_frozen_base = True
701
702 # Annotations that are defined in this class (not in base
703 # classes). If __annotations__ isn't present, then this class
704 # adds no new annotations. We use this to compute fields that are
705 # added by this class.
706 #
707 # Fields are found from cls_annotations, which is guaranteed to be
708 # ordered. Default values are from class attributes, if a field
709 # has a default. If the default value is a Field(), then it
710 # contains additional info beyond (and possibly including) the
711 # actual default value. Pseudo-fields ClassVars and InitVars are
712 # included, despite the fact that they're not real fields. That's
713 # dealt with later.
714 cls_annotations = cls.__dict__.get('__annotations__', {})
715
716 # Now find fields in our class. While doing so, validate some
717 # things, and set the default values (as class attributes) where
718 # we can.
719 cls_fields = [_get_field(cls, name, type)
720 for name, type in cls_annotations.items()]
721 for f in cls_fields:
722 fields[f.name] = f
723
724 # If the class attribute (which is the default value for this
725 # field) exists and is of type 'Field', replace it with the
726 # real default. This is so that normal class introspection
727 # sees a real default value, not a Field.
728 if isinstance(getattr(cls, f.name, None), Field):
729 if f.default is MISSING:
730 # If there's no default, delete the class attribute.
731 # This happens if we specify field(repr=False), for
732 # example (that is, we specified a field object, but
733 # no default value). Also if we're using a default
734 # factory. The class attribute should not be set at
735 # all in the post-processed class.
736 delattr(cls, f.name)
737 else:
738 setattr(cls, f.name, f.default)
739
740 # Do we have any Field members that don't also have annotations?
741 for name, value in cls.__dict__.items():
742 if isinstance(value, Field) and not name in cls_annotations:
743 raise TypeError(f'{name!r} is a field but has no type annotation')
744
745 # Check rules that apply if we are derived from any dataclasses.
746 if has_dataclass_bases:
747 # Raise an exception if any of our bases are frozen, but we're not.
748 if any_frozen_base and not frozen:
749 raise TypeError('cannot inherit non-frozen dataclass from a '
750 'frozen one')
751
752 # Raise an exception if we're frozen, but none of our bases are.
753 if not any_frozen_base and frozen:
754 raise TypeError('cannot inherit frozen dataclass from a '
755 'non-frozen one')
756
757 # Remember all of the fields on our class (including bases). This
758 # also marks this class as being a dataclass.
759 setattr(cls, _FIELDS, fields)
760
761 # Was this class defined with an explicit __hash__? Note that if
762 # __eq__ is defined in this class, then python will automatically
763 # set __hash__ to None. This is a heuristic, as it's possible
764 # that such a __hash__ == None was not auto-generated, but it
765 # close enough.
766 class_hash = cls.__dict__.get('__hash__', MISSING)
767 has_explicit_hash = not (class_hash is MISSING or
768 (class_hash is None and '__eq__' in cls.__dict__))
769
770 # If we're generating ordering methods, we must be generating the
771 # eq methods.
772 if order and not eq:
773 raise ValueError('eq must be true if order is true')
774
775 if init:
776 # Does this class have a post-init function?
777 has_post_init = hasattr(cls, _POST_INIT_NAME)
778
779 # Include InitVars and regular fields (so, not ClassVars).
780 flds = [f for f in fields.values()
781 if f._field_type in (_FIELD, _FIELD_INITVAR)]
782 _set_new_attribute(cls, '__init__',
783 _init_fn(flds,
784 frozen,
785 has_post_init,
786 # The name to use for the "self"
787 # param in __init__. Use "self"
788 # if possible.
789 '__dataclass_self__' if 'self' in fields
790 else 'self',
791 globals,
792 ))
793
794 # Get the fields as a list, and include only real fields. This is
795 # used in all of the following methods.
796 field_list = [f for f in fields.values() if f._field_type is _FIELD]
797
798 if repr:
799 flds = [f for f in field_list if f.repr]
800 _set_new_attribute(cls, '__repr__', _repr_fn(flds, globals))
801
802 if eq:
803 # Create _eq__ method. There's no need for a __ne__ method,
804 # since python will call __eq__ and negate it.
805 flds = [f for f in field_list if f.compare]
806 self_tuple = _tuple_str('self', flds)
807 other_tuple = _tuple_str('other', flds)
808 _set_new_attribute(cls, '__eq__',
809 _cmp_fn('__eq__', '==',
810 self_tuple, other_tuple,
811 globals=globals))
812
813 if order:
814 # Create and set the ordering methods.
815 flds = [f for f in field_list if f.compare]
816 self_tuple = _tuple_str('self', flds)
817 other_tuple = _tuple_str('other', flds)
818 for name, op in [('__lt__', '<'),
819 ('__le__', '<='),
820 ('__gt__', '>'),
821 ('__ge__', '>='),
822 ]:
823 if _set_new_attribute(cls, name,
824 _cmp_fn(name, op, self_tuple, other_tuple,
825 globals=globals)):
826 raise TypeError(f'Cannot overwrite attribute {name} '
827 f'in class {cls.__name__}. Consider using '
828 'functools.total_ordering')
829
830 if frozen:
831 for fn in _frozen_get_del_attr(cls, field_list, globals):
832 if _set_new_attribute(cls, fn.__name__, fn):
833 raise TypeError(f'Cannot overwrite attribute {fn.__name__} '
834 f'in class {cls.__name__}')
835
836 # Decide if/how we're going to create a hash function.
837 hash_action = _hash_action[bool(unsafe_hash),
838 bool(eq),
839 bool(frozen),
840 has_explicit_hash]
841 if hash_action:
842 # No need to call _set_new_attribute here, since by the time
843 # we're here the overwriting is unconditional.
844 cls.__hash__ = hash_action(cls, field_list, globals)
845
846 if not getattr(cls, '__doc__'):
847 # Create a class doc-string.
848 cls.__doc__ = (cls.__name__ +
849 str(inspect.signature(cls)).replace(' -> None', ''))
850
851 return cls
852
853
854
855def attrclass(cls=None, /, *, init=True, repr=True, eq=True, order=False,
856 unsafe_hash=False, readonly=False):
857
858
859 def wrap(cls):
860 return _process_class(cls, init, repr, eq, order, unsafe_hash, readonly)
861
862 # See if we're being called as @dataclass or @dataclass().
863 if cls is None:
864 # We're called with parens.
865 return wrap
866
867 # We're called as @dataclass without parens.
868 return wrap(cls)
869
870
871class ReadonlyAttributeError(AttributeError):
872 pass
873
874
875if __name__ == "__main__":
876 pass
877