blob: fb279cd30517db1d202ae63a4296cacdb1c24d40 [file] [log] [blame]
Eric V. Smithf0db54a2017-12-04 16:58:55 -05001import sys
2import types
3from copy import deepcopy
Eric V. Smithf0db54a2017-12-04 16:58:55 -05004import inspect
5
6__all__ = ['dataclass',
7 'field',
8 'FrozenInstanceError',
9 'InitVar',
Eric V. Smith03220fd2017-12-29 13:59:58 -050010 'MISSING',
Eric V. Smithf0db54a2017-12-04 16:58:55 -050011
12 # Helper functions.
13 'fields',
14 'asdict',
15 'astuple',
16 'make_dataclass',
17 'replace',
Eric V. Smithe7ba0132018-01-06 12:41:53 -050018 'is_dataclass',
Eric V. Smithf0db54a2017-12-04 16:58:55 -050019 ]
20
Eric V. Smithea8fc522018-01-27 19:07:40 -050021# Conditions for adding methods. The boxes indicate what action the
22# dataclass decorator takes. For all of these tables, when I talk
23# about init=, repr=, eq=, order=, hash=, or frozen=, I'm referring
24# to the arguments to the @dataclass decorator. When checking if a
25# dunder method already exists, I mean check for an entry in the
26# class's __dict__. I never check to see if an attribute is defined
27# in a base class.
28
29# Key:
30# +=========+=========================================+
31# + Value | Meaning |
32# +=========+=========================================+
33# | <blank> | No action: no method is added. |
34# +---------+-----------------------------------------+
35# | add | Generated method is added. |
36# +---------+-----------------------------------------+
37# | add* | Generated method is added only if the |
38# | | existing attribute is None and if the |
39# | | user supplied a __eq__ method in the |
40# | | class definition. |
41# +---------+-----------------------------------------+
42# | raise | TypeError is raised. |
43# +---------+-----------------------------------------+
44# | None | Attribute is set to None. |
45# +=========+=========================================+
46
47# __init__
48#
49# +--- init= parameter
50# |
51# v | | |
52# | no | yes | <--- class has __init__ in __dict__?
53# +=======+=======+=======+
54# | False | | |
55# +-------+-------+-------+
56# | True | add | | <- the default
57# +=======+=======+=======+
58
59# __repr__
60#
61# +--- repr= parameter
62# |
63# v | | |
64# | no | yes | <--- class has __repr__ in __dict__?
65# +=======+=======+=======+
66# | False | | |
67# +-------+-------+-------+
68# | True | add | | <- the default
69# +=======+=======+=======+
70
71
72# __setattr__
73# __delattr__
74#
75# +--- frozen= parameter
76# |
77# v | | |
78# | no | yes | <--- class has __setattr__ or __delattr__ in __dict__?
79# +=======+=======+=======+
80# | False | | | <- the default
81# +-------+-------+-------+
82# | True | add | raise |
83# +=======+=======+=======+
84# Raise because not adding these methods would break the "frozen-ness"
85# of the class.
86
87# __eq__
88#
89# +--- eq= parameter
90# |
91# v | | |
92# | no | yes | <--- class has __eq__ in __dict__?
93# +=======+=======+=======+
94# | False | | |
95# +-------+-------+-------+
96# | True | add | | <- the default
97# +=======+=======+=======+
98
99# __lt__
100# __le__
101# __gt__
102# __ge__
103#
104# +--- order= parameter
105# |
106# v | | |
107# | no | yes | <--- class has any comparison method in __dict__?
108# +=======+=======+=======+
109# | False | | | <- the default
110# +-------+-------+-------+
111# | True | add | raise |
112# +=======+=======+=======+
113# Raise because to allow this case would interfere with using
114# functools.total_ordering.
115
116# __hash__
117
118# +------------------- hash= parameter
119# | +----------- eq= parameter
120# | | +--- frozen= parameter
121# | | |
122# v v v | | |
123# | no | yes | <--- class has __hash__ in __dict__?
124# +=========+=======+=======+========+========+
125# | 1 None | False | False | | | No __eq__, use the base class __hash__
126# +---------+-------+-------+--------+--------+
127# | 2 None | False | True | | | No __eq__, use the base class __hash__
128# +---------+-------+-------+--------+--------+
129# | 3 None | True | False | None | | <-- the default, not hashable
130# +---------+-------+-------+--------+--------+
131# | 4 None | True | True | add | add* | Frozen, so hashable
132# +---------+-------+-------+--------+--------+
133# | 5 False | False | False | | |
134# +---------+-------+-------+--------+--------+
135# | 6 False | False | True | | |
136# +---------+-------+-------+--------+--------+
137# | 7 False | True | False | | |
138# +---------+-------+-------+--------+--------+
139# | 8 False | True | True | | |
140# +---------+-------+-------+--------+--------+
141# | 9 True | False | False | add | add* | Has no __eq__, but hashable
142# +---------+-------+-------+--------+--------+
143# |10 True | False | True | add | add* | Has no __eq__, but hashable
144# +---------+-------+-------+--------+--------+
145# |11 True | True | False | add | add* | Not frozen, but hashable
146# +---------+-------+-------+--------+--------+
147# |12 True | True | True | add | add* | Frozen, so hashable
148# +=========+=======+=======+========+========+
149# For boxes that are blank, __hash__ is untouched and therefore
150# inherited from the base class. If the base is object, then
151# id-based hashing is used.
152# Note that a class may have already __hash__=None if it specified an
153# __eq__ method in the class body (not one that was created by
154# @dataclass).
155
156
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500157# Raised when an attempt is made to modify a frozen class.
158class FrozenInstanceError(AttributeError): pass
159
160# A sentinel object for default values to signal that a
161# default-factory will be used.
162# This is given a nice repr() which will appear in the function
163# signature of dataclasses' constructors.
164class _HAS_DEFAULT_FACTORY_CLASS:
165 def __repr__(self):
166 return '<factory>'
167_HAS_DEFAULT_FACTORY = _HAS_DEFAULT_FACTORY_CLASS()
168
Eric V. Smith03220fd2017-12-29 13:59:58 -0500169# A sentinel object to detect if a parameter is supplied or not. Use
170# a class to give it a better repr.
171class _MISSING_TYPE:
172 pass
173MISSING = _MISSING_TYPE()
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500174
175# Since most per-field metadata will be unused, create an empty
176# read-only proxy that can be shared among all fields.
177_EMPTY_METADATA = types.MappingProxyType({})
178
179# Markers for the various kinds of fields and pseudo-fields.
180_FIELD = object() # An actual field.
181_FIELD_CLASSVAR = object() # Not a field, but a ClassVar.
182_FIELD_INITVAR = object() # Not a field, but an InitVar.
183
184# The name of an attribute on the class where we store the Field
185# objects. Also used to check if a class is a Data Class.
186_MARKER = '__dataclass_fields__'
187
188# The name of the function, that if it exists, is called at the end of
189# __init__.
190_POST_INIT_NAME = '__post_init__'
191
192
193class _InitVarMeta(type):
194 def __getitem__(self, params):
195 return self
196
197class InitVar(metaclass=_InitVarMeta):
198 pass
199
200
201# Instances of Field are only ever created from within this module,
202# and only from the field() function, although Field instances are
203# exposed externally as (conceptually) read-only objects.
204# name and type are filled in after the fact, not in __init__. They're
205# not known at the time this class is instantiated, but it's
206# convenient if they're available later.
207# When cls._MARKER is filled in with a list of Field objects, the name
208# and type fields will have been populated.
209class Field:
210 __slots__ = ('name',
211 'type',
212 'default',
213 'default_factory',
214 'repr',
215 'hash',
216 'init',
217 'compare',
218 'metadata',
219 '_field_type', # Private: not to be used by user code.
220 )
221
222 def __init__(self, default, default_factory, init, repr, hash, compare,
223 metadata):
224 self.name = None
225 self.type = None
226 self.default = default
227 self.default_factory = default_factory
228 self.init = init
229 self.repr = repr
230 self.hash = hash
231 self.compare = compare
232 self.metadata = (_EMPTY_METADATA
233 if metadata is None or len(metadata) == 0 else
234 types.MappingProxyType(metadata))
235 self._field_type = None
236
237 def __repr__(self):
238 return ('Field('
239 f'name={self.name!r},'
240 f'type={self.type},'
241 f'default={self.default},'
242 f'default_factory={self.default_factory},'
243 f'init={self.init},'
244 f'repr={self.repr},'
245 f'hash={self.hash},'
246 f'compare={self.compare},'
247 f'metadata={self.metadata}'
248 ')')
249
250
251# This function is used instead of exposing Field creation directly,
252# so that a type checker can be told (via overloads) that this is a
253# function whose type depends on its parameters.
Eric V. Smith03220fd2017-12-29 13:59:58 -0500254def field(*, default=MISSING, default_factory=MISSING, init=True, repr=True,
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500255 hash=None, compare=True, metadata=None):
256 """Return an object to identify dataclass fields.
257
258 default is the default value of the field. default_factory is a
259 0-argument function called to initialize a field's value. If init
260 is True, the field will be a parameter to the class's __init__()
261 function. If repr is True, the field will be included in the
262 object's repr(). If hash is True, the field will be included in
263 the object's hash(). If compare is True, the field will be used in
264 comparison functions. metadata, if specified, must be a mapping
265 which is stored but not otherwise examined by dataclass.
266
267 It is an error to specify both default and default_factory.
268 """
269
Eric V. Smith03220fd2017-12-29 13:59:58 -0500270 if default is not MISSING and default_factory is not MISSING:
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500271 raise ValueError('cannot specify both default and default_factory')
272 return Field(default, default_factory, init, repr, hash, compare,
273 metadata)
274
275
276def _tuple_str(obj_name, fields):
277 # Return a string representing each field of obj_name as a tuple
278 # member. So, if fields is ['x', 'y'] and obj_name is "self",
279 # return "(self.x,self.y)".
280
281 # Special case for the 0-tuple.
Eric V. Smithea8fc522018-01-27 19:07:40 -0500282 if not fields:
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500283 return '()'
284 # Note the trailing comma, needed if this turns out to be a 1-tuple.
285 return f'({",".join([f"{obj_name}.{f.name}" for f in fields])},)'
286
287
Eric V. Smithea8fc522018-01-27 19:07:40 -0500288def _create_fn(name, args, body, *, globals=None, locals=None,
Eric V. Smith03220fd2017-12-29 13:59:58 -0500289 return_type=MISSING):
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500290 # Note that we mutate locals when exec() is called. Caller beware!
291 if locals is None:
292 locals = {}
293 return_annotation = ''
Eric V. Smith03220fd2017-12-29 13:59:58 -0500294 if return_type is not MISSING:
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500295 locals['_return_type'] = return_type
296 return_annotation = '->_return_type'
297 args = ','.join(args)
298 body = '\n'.join(f' {b}' for b in body)
299
300 txt = f'def {name}({args}){return_annotation}:\n{body}'
301
302 exec(txt, globals, locals)
303 return locals[name]
304
305
306def _field_assign(frozen, name, value, self_name):
307 # If we're a frozen class, then assign to our fields in __init__
308 # via object.__setattr__. Otherwise, just use a simple
309 # assignment.
310 # self_name is what "self" is called in this function: don't
311 # hard-code "self", since that might be a field name.
312 if frozen:
313 return f'object.__setattr__({self_name},{name!r},{value})'
314 return f'{self_name}.{name}={value}'
315
316
317def _field_init(f, frozen, globals, self_name):
318 # Return the text of the line in the body of __init__ that will
319 # initialize this field.
320
321 default_name = f'_dflt_{f.name}'
Eric V. Smith03220fd2017-12-29 13:59:58 -0500322 if f.default_factory is not MISSING:
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500323 if f.init:
324 # This field has a default factory. If a parameter is
325 # given, use it. If not, call the factory.
326 globals[default_name] = f.default_factory
327 value = (f'{default_name}() '
328 f'if {f.name} is _HAS_DEFAULT_FACTORY '
329 f'else {f.name}')
330 else:
331 # This is a field that's not in the __init__ params, but
332 # has a default factory function. It needs to be
333 # initialized here by calling the factory function,
334 # because there's no other way to initialize it.
335
336 # For a field initialized with a default=defaultvalue, the
337 # class dict just has the default value
338 # (cls.fieldname=defaultvalue). But that won't work for a
339 # default factory, the factory must be called in __init__
340 # and we must assign that to self.fieldname. We can't
341 # fall back to the class dict's value, both because it's
342 # not set, and because it might be different per-class
343 # (which, after all, is why we have a factory function!).
344
345 globals[default_name] = f.default_factory
346 value = f'{default_name}()'
347 else:
348 # No default factory.
349 if f.init:
Eric V. Smith03220fd2017-12-29 13:59:58 -0500350 if f.default is MISSING:
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500351 # There's no default, just do an assignment.
352 value = f.name
Eric V. Smith03220fd2017-12-29 13:59:58 -0500353 elif f.default is not MISSING:
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500354 globals[default_name] = f.default
355 value = f.name
356 else:
357 # This field does not need initialization. Signify that to
358 # the caller by returning None.
359 return None
360
361 # Only test this now, so that we can create variables for the
362 # default. However, return None to signify that we're not going
363 # to actually do the assignment statement for InitVars.
364 if f._field_type == _FIELD_INITVAR:
365 return None
366
367 # Now, actually generate the field assignment.
368 return _field_assign(frozen, f.name, value, self_name)
369
370
371def _init_param(f):
372 # Return the __init__ parameter string for this field.
373 # For example, the equivalent of 'x:int=3' (except instead of 'int',
374 # reference a variable set to int, and instead of '3', reference a
375 # variable set to 3).
Eric V. Smith03220fd2017-12-29 13:59:58 -0500376 if f.default is MISSING and f.default_factory is MISSING:
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500377 # There's no default, and no default_factory, just
378 # output the variable name and type.
379 default = ''
Eric V. Smith03220fd2017-12-29 13:59:58 -0500380 elif f.default is not MISSING:
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500381 # There's a default, this will be the name that's used to look it up.
382 default = f'=_dflt_{f.name}'
Eric V. Smith03220fd2017-12-29 13:59:58 -0500383 elif f.default_factory is not MISSING:
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500384 # There's a factory function. Set a marker.
385 default = '=_HAS_DEFAULT_FACTORY'
386 return f'{f.name}:_type_{f.name}{default}'
387
388
389def _init_fn(fields, frozen, has_post_init, self_name):
390 # fields contains both real fields and InitVar pseudo-fields.
391
392 # Make sure we don't have fields without defaults following fields
393 # with defaults. This actually would be caught when exec-ing the
394 # function source code, but catching it here gives a better error
395 # message, and future-proofs us in case we build up the function
396 # using ast.
397 seen_default = False
398 for f in fields:
399 # Only consider fields in the __init__ call.
400 if f.init:
Eric V. Smith03220fd2017-12-29 13:59:58 -0500401 if not (f.default is MISSING and f.default_factory is MISSING):
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500402 seen_default = True
403 elif seen_default:
404 raise TypeError(f'non-default argument {f.name!r} '
405 'follows default argument')
406
Eric V. Smith03220fd2017-12-29 13:59:58 -0500407 globals = {'MISSING': MISSING,
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500408 '_HAS_DEFAULT_FACTORY': _HAS_DEFAULT_FACTORY}
409
410 body_lines = []
411 for f in fields:
412 # Do not initialize the pseudo-fields, only the real ones.
413 line = _field_init(f, frozen, globals, self_name)
414 if line is not None:
415 # line is None means that this field doesn't require
416 # initialization. Just skip it.
417 body_lines.append(line)
418
419 # Does this class have a post-init function?
420 if has_post_init:
421 params_str = ','.join(f.name for f in fields
422 if f._field_type is _FIELD_INITVAR)
423 body_lines += [f'{self_name}.{_POST_INIT_NAME}({params_str})']
424
425 # If no body lines, use 'pass'.
Eric V. Smithea8fc522018-01-27 19:07:40 -0500426 if not body_lines:
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500427 body_lines = ['pass']
428
429 locals = {f'_type_{f.name}': f.type for f in fields}
430 return _create_fn('__init__',
431 [self_name] +[_init_param(f) for f in fields if f.init],
432 body_lines,
433 locals=locals,
434 globals=globals,
435 return_type=None)
436
437
438def _repr_fn(fields):
439 return _create_fn('__repr__',
440 ['self'],
441 ['return self.__class__.__qualname__ + f"(' +
442 ', '.join([f"{f.name}={{self.{f.name}!r}}"
443 for f in fields]) +
444 ')"'])
445
446
447def _frozen_setattr(self, name, value):
448 raise FrozenInstanceError(f'cannot assign to field {name!r}')
449
450
451def _frozen_delattr(self, name):
452 raise FrozenInstanceError(f'cannot delete field {name!r}')
453
454
455def _cmp_fn(name, op, self_tuple, other_tuple):
456 # Create a comparison function. If the fields in the object are
457 # named 'x' and 'y', then self_tuple is the string
458 # '(self.x,self.y)' and other_tuple is the string
459 # '(other.x,other.y)'.
460
461 return _create_fn(name,
462 ['self', 'other'],
463 [ 'if other.__class__ is self.__class__:',
464 f' return {self_tuple}{op}{other_tuple}',
465 'return NotImplemented'])
466
467
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500468def _hash_fn(fields):
469 self_tuple = _tuple_str('self', fields)
470 return _create_fn('__hash__',
471 ['self'],
472 [f'return hash({self_tuple})'])
473
474
475def _get_field(cls, a_name, a_type):
476 # Return a Field object, for this field name and type. ClassVars
477 # and InitVars are also returned, but marked as such (see
478 # f._field_type).
479
480 # If the default value isn't derived from field, then it's
481 # only a normal default value. Convert it to a Field().
Eric V. Smith03220fd2017-12-29 13:59:58 -0500482 default = getattr(cls, a_name, MISSING)
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500483 if isinstance(default, Field):
484 f = default
485 else:
486 f = field(default=default)
487
488 # Assume it's a normal field until proven otherwise.
489 f._field_type = _FIELD
490
491 # Only at this point do we know the name and the type. Set them.
492 f.name = a_name
493 f.type = a_type
494
495 # If typing has not been imported, then it's impossible for
496 # any annotation to be a ClassVar. So, only look for ClassVar
497 # if typing has been imported.
498 typing = sys.modules.get('typing')
499 if typing is not None:
500 # This test uses a typing internal class, but it's the best
501 # way to test if this is a ClassVar.
Ivan Levkivskyid911e402018-01-20 11:23:59 +0000502 if (type(a_type) is typing._GenericAlias and
503 a_type.__origin__ is typing.ClassVar):
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500504 # This field is a ClassVar, so it's not a field.
505 f._field_type = _FIELD_CLASSVAR
506
507 if f._field_type is _FIELD:
508 # Check if this is an InitVar.
509 if a_type is InitVar:
510 # InitVars are not fields, either.
511 f._field_type = _FIELD_INITVAR
512
513 # Validations for fields. This is delayed until now, instead of
514 # in the Field() constructor, since only here do we know the field
515 # name, which allows better error reporting.
516
517 # Special restrictions for ClassVar and InitVar.
518 if f._field_type in (_FIELD_CLASSVAR, _FIELD_INITVAR):
Eric V. Smith03220fd2017-12-29 13:59:58 -0500519 if f.default_factory is not MISSING:
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500520 raise TypeError(f'field {f.name} cannot have a '
521 'default factory')
522 # Should I check for other field settings? default_factory
523 # seems the most serious to check for. Maybe add others. For
524 # example, how about init=False (or really,
525 # init=<not-the-default-init-value>)? It makes no sense for
526 # ClassVar and InitVar to specify init=<anything>.
527
528 # For real fields, disallow mutable defaults for known types.
529 if f._field_type is _FIELD and isinstance(f.default, (list, dict, set)):
530 raise ValueError(f'mutable default {type(f.default)} for field '
531 f'{f.name} is not allowed: use default_factory')
532
533 return f
534
535
536def _find_fields(cls):
537 # Return a list of Field objects, in order, for this class (and no
538 # base classes). Fields are found from __annotations__ (which is
539 # guaranteed to be ordered). Default values are from class
540 # attributes, if a field has a default. If the default value is
541 # a Field(), then it contains additional info beyond (and
542 # possibly including) the actual default value. Pseudo-fields
543 # ClassVars and InitVars are included, despite the fact that
Eric V. Smithea8fc522018-01-27 19:07:40 -0500544 # they're not real fields. That's dealt with later.
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500545
546 annotations = getattr(cls, '__annotations__', {})
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500547 return [_get_field(cls, a_name, a_type)
548 for a_name, a_type in annotations.items()]
549
550
Eric V. Smithea8fc522018-01-27 19:07:40 -0500551def _set_new_attribute(cls, name, value):
552 # Never overwrites an existing attribute. Returns True if the
553 # attribute already exists.
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500554 if name in cls.__dict__:
Eric V. Smithea8fc522018-01-27 19:07:40 -0500555 return True
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500556 setattr(cls, name, value)
Eric V. Smithea8fc522018-01-27 19:07:40 -0500557 return False
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500558
559
560def _process_class(cls, repr, eq, order, hash, init, frozen):
Eric V. Smithd1388922018-01-07 14:30:17 -0500561 # Now that dicts retain insertion order, there's no reason to use
562 # an ordered dict. I am leveraging that ordering here, because
563 # derived class fields overwrite base class fields, but the order
564 # is defined by the base class, which is found first.
565 fields = {}
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500566
567 # Find our base classes in reverse MRO order, and exclude
568 # ourselves. In reversed order so that more derived classes
569 # override earlier field definitions in base classes.
570 for b in cls.__mro__[-1:0:-1]:
571 # Only process classes that have been processed by our
572 # decorator. That is, they have a _MARKER attribute.
573 base_fields = getattr(b, _MARKER, None)
574 if base_fields:
575 for f in base_fields.values():
576 fields[f.name] = f
577
578 # Now find fields in our class. While doing so, validate some
579 # things, and set the default values (as class attributes)
580 # where we can.
581 for f in _find_fields(cls):
582 fields[f.name] = f
583
584 # If the class attribute (which is the default value for
585 # this field) exists and is of type 'Field', replace it
586 # with the real default. This is so that normal class
587 # introspection sees a real default value, not a Field.
588 if isinstance(getattr(cls, f.name, None), Field):
Eric V. Smith03220fd2017-12-29 13:59:58 -0500589 if f.default is MISSING:
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500590 # If there's no default, delete the class attribute.
591 # This happens if we specify field(repr=False), for
592 # example (that is, we specified a field object, but
593 # no default value). Also if we're using a default
594 # factory. The class attribute should not be set at
595 # all in the post-processed class.
596 delattr(cls, f.name)
597 else:
598 setattr(cls, f.name, f.default)
599
600 # Remember all of the fields on our class (including bases). This
601 # marks this class as being a dataclass.
602 setattr(cls, _MARKER, fields)
603
604 # We also need to check if a parent class is frozen: frozen has to
605 # be inherited down.
606 is_frozen = frozen or cls.__setattr__ is _frozen_setattr
607
Eric V. Smithea8fc522018-01-27 19:07:40 -0500608 # Was this class defined with an __eq__? Used in __hash__ logic.
609 auto_hash_test= '__eq__' in cls.__dict__ and getattr(cls.__dict__, '__hash__', MISSING) is None
610
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500611 # If we're generating ordering methods, we must be generating
612 # the eq methods.
613 if order and not eq:
614 raise ValueError('eq must be true if order is true')
615
616 if init:
617 # Does this class have a post-init function?
618 has_post_init = hasattr(cls, _POST_INIT_NAME)
619
620 # Include InitVars and regular fields (so, not ClassVars).
Eric V. Smithea8fc522018-01-27 19:07:40 -0500621 flds = [f for f in fields.values()
622 if f._field_type in (_FIELD, _FIELD_INITVAR)]
623 _set_new_attribute(cls, '__init__',
624 _init_fn(flds,
625 is_frozen,
626 has_post_init,
627 # The name to use for the "self" param
628 # in __init__. Use "self" if possible.
629 '__dataclass_self__' if 'self' in fields
630 else 'self',
631 ))
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500632
633 # Get the fields as a list, and include only real fields. This is
634 # used in all of the following methods.
Eric V. Smithea8fc522018-01-27 19:07:40 -0500635 field_list = [f for f in fields.values() if f._field_type is _FIELD]
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500636
637 if repr:
Eric V. Smithea8fc522018-01-27 19:07:40 -0500638 flds = [f for f in field_list if f.repr]
639 _set_new_attribute(cls, '__repr__', _repr_fn(flds))
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500640
641 if eq:
Eric V. Smithea8fc522018-01-27 19:07:40 -0500642 # Create _eq__ method. There's no need for a __ne__ method,
643 # since python will call __eq__ and negate it.
644 flds = [f for f in field_list if f.compare]
645 self_tuple = _tuple_str('self', flds)
646 other_tuple = _tuple_str('other', flds)
647 _set_new_attribute(cls, '__eq__',
648 _cmp_fn('__eq__', '==',
649 self_tuple, other_tuple))
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500650
651 if order:
Eric V. Smithea8fc522018-01-27 19:07:40 -0500652 # Create and set the ordering methods.
653 flds = [f for f in field_list if f.compare]
654 self_tuple = _tuple_str('self', flds)
655 other_tuple = _tuple_str('other', flds)
656 for name, op in [('__lt__', '<'),
657 ('__le__', '<='),
658 ('__gt__', '>'),
659 ('__ge__', '>='),
660 ]:
661 if _set_new_attribute(cls, name,
662 _cmp_fn(name, op, self_tuple, other_tuple)):
663 raise TypeError(f'Cannot overwrite attribute {name} '
664 f'in {cls.__name__}. Consider using '
665 'functools.total_ordering')
666
667 if is_frozen:
668 for name, fn in [('__setattr__', _frozen_setattr),
669 ('__delattr__', _frozen_delattr)]:
670 if _set_new_attribute(cls, name, fn):
671 raise TypeError(f'Cannot overwrite attribute {name} '
672 f'in {cls.__name__}')
673
674 # Decide if/how we're going to create a hash function.
675 # TODO: Move this table to module scope, so it's not recreated
676 # all the time.
677 generate_hash = {(None, False, False): ('', ''),
678 (None, False, True): ('', ''),
679 (None, True, False): ('none', ''),
680 (None, True, True): ('fn', 'fn-x'),
681 (False, False, False): ('', ''),
682 (False, False, True): ('', ''),
683 (False, True, False): ('', ''),
684 (False, True, True): ('', ''),
685 (True, False, False): ('fn', 'fn-x'),
686 (True, False, True): ('fn', 'fn-x'),
687 (True, True, False): ('fn', 'fn-x'),
688 (True, True, True): ('fn', 'fn-x'),
689 }[None if hash is None else bool(hash), # Force bool() if not None.
690 bool(eq),
691 bool(frozen)]['__hash__' in cls.__dict__]
692 # No need to call _set_new_attribute here, since we already know if
693 # we're overwriting a __hash__ or not.
694 if generate_hash == '':
695 # Do nothing.
696 pass
697 elif generate_hash == 'none':
698 cls.__hash__ = None
699 elif generate_hash in ('fn', 'fn-x'):
700 if generate_hash == 'fn' or auto_hash_test:
701 flds = [f for f in field_list
702 if (f.compare if f.hash is None else f.hash)]
703 cls.__hash__ = _hash_fn(flds)
704 else:
705 assert False, f"can't get here: {generate_hash}"
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500706
707 if not getattr(cls, '__doc__'):
708 # Create a class doc-string.
709 cls.__doc__ = (cls.__name__ +
710 str(inspect.signature(cls)).replace(' -> None', ''))
711
712 return cls
713
714
715# _cls should never be specified by keyword, so start it with an
Raymond Hettingerd55209d2018-01-10 20:56:41 -0800716# underscore. The presence of _cls is used to detect if this
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500717# decorator is being called with parameters or not.
718def dataclass(_cls=None, *, init=True, repr=True, eq=True, order=False,
719 hash=None, frozen=False):
720 """Returns the same class as was passed in, with dunder methods
721 added based on the fields defined in the class.
722
723 Examines PEP 526 __annotations__ to determine fields.
724
725 If init is true, an __init__() method is added to the class. If
726 repr is true, a __repr__() method is added. If order is true, rich
727 comparison dunder methods are added. If hash is true, a __hash__()
728 method function is added. If frozen is true, fields may not be
729 assigned to after instance creation.
730 """
731
732 def wrap(cls):
733 return _process_class(cls, repr, eq, order, hash, init, frozen)
734
735 # See if we're being called as @dataclass or @dataclass().
736 if _cls is None:
737 # We're called with parens.
738 return wrap
739
740 # We're called as @dataclass without parens.
741 return wrap(_cls)
742
743
744def fields(class_or_instance):
745 """Return a tuple describing the fields of this dataclass.
746
747 Accepts a dataclass or an instance of one. Tuple elements are of
748 type Field.
749 """
750
751 # Might it be worth caching this, per class?
752 try:
753 fields = getattr(class_or_instance, _MARKER)
754 except AttributeError:
755 raise TypeError('must be called with a dataclass type or instance')
756
Eric V. Smithd1388922018-01-07 14:30:17 -0500757 # Exclude pseudo-fields. Note that fields is sorted by insertion
758 # order, so the order of the tuple is as the fields were defined.
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500759 return tuple(f for f in fields.values() if f._field_type is _FIELD)
760
761
Eric V. Smithe7ba0132018-01-06 12:41:53 -0500762def _is_dataclass_instance(obj):
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500763 """Returns True if obj is an instance of a dataclass."""
764 return not isinstance(obj, type) and hasattr(obj, _MARKER)
765
766
Eric V. Smithe7ba0132018-01-06 12:41:53 -0500767def is_dataclass(obj):
768 """Returns True if obj is a dataclass or an instance of a
769 dataclass."""
770 return hasattr(obj, _MARKER)
771
772
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500773def asdict(obj, *, dict_factory=dict):
774 """Return the fields of a dataclass instance as a new dictionary mapping
775 field names to field values.
776
777 Example usage:
778
779 @dataclass
780 class C:
781 x: int
782 y: int
783
784 c = C(1, 2)
785 assert asdict(c) == {'x': 1, 'y': 2}
786
787 If given, 'dict_factory' will be used instead of built-in dict.
788 The function applies recursively to field values that are
789 dataclass instances. This will also look into built-in containers:
790 tuples, lists, and dicts.
791 """
Eric V. Smithe7ba0132018-01-06 12:41:53 -0500792 if not _is_dataclass_instance(obj):
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500793 raise TypeError("asdict() should be called on dataclass instances")
794 return _asdict_inner(obj, dict_factory)
795
796def _asdict_inner(obj, dict_factory):
Eric V. Smithe7ba0132018-01-06 12:41:53 -0500797 if _is_dataclass_instance(obj):
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500798 result = []
799 for f in fields(obj):
800 value = _asdict_inner(getattr(obj, f.name), dict_factory)
801 result.append((f.name, value))
802 return dict_factory(result)
803 elif isinstance(obj, (list, tuple)):
804 return type(obj)(_asdict_inner(v, dict_factory) for v in obj)
805 elif isinstance(obj, dict):
806 return type(obj)((_asdict_inner(k, dict_factory), _asdict_inner(v, dict_factory))
807 for k, v in obj.items())
808 else:
809 return deepcopy(obj)
810
811
812def astuple(obj, *, tuple_factory=tuple):
813 """Return the fields of a dataclass instance as a new tuple of field values.
814
815 Example usage::
816
817 @dataclass
818 class C:
819 x: int
820 y: int
821
822 c = C(1, 2)
Raymond Hettingerd55209d2018-01-10 20:56:41 -0800823 assert astuple(c) == (1, 2)
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500824
825 If given, 'tuple_factory' will be used instead of built-in tuple.
826 The function applies recursively to field values that are
827 dataclass instances. This will also look into built-in containers:
828 tuples, lists, and dicts.
829 """
830
Eric V. Smithe7ba0132018-01-06 12:41:53 -0500831 if not _is_dataclass_instance(obj):
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500832 raise TypeError("astuple() should be called on dataclass instances")
833 return _astuple_inner(obj, tuple_factory)
834
835def _astuple_inner(obj, tuple_factory):
Eric V. Smithe7ba0132018-01-06 12:41:53 -0500836 if _is_dataclass_instance(obj):
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500837 result = []
838 for f in fields(obj):
839 value = _astuple_inner(getattr(obj, f.name), tuple_factory)
840 result.append(value)
841 return tuple_factory(result)
842 elif isinstance(obj, (list, tuple)):
843 return type(obj)(_astuple_inner(v, tuple_factory) for v in obj)
844 elif isinstance(obj, dict):
845 return type(obj)((_astuple_inner(k, tuple_factory), _astuple_inner(v, tuple_factory))
846 for k, v in obj.items())
847 else:
848 return deepcopy(obj)
849
850
Eric V. Smithd80b4432018-01-06 17:09:58 -0500851def make_dataclass(cls_name, fields, *, bases=(), namespace=None, init=True,
852 repr=True, eq=True, order=False, hash=None, frozen=False):
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500853 """Return a new dynamically created dataclass.
854
Eric V. Smithed7d4292018-01-06 16:14:03 -0500855 The dataclass name will be 'cls_name'. 'fields' is an iterable
856 of either (name), (name, type) or (name, type, Field) objects. If type is
857 omitted, use the string 'typing.Any'. Field objects are created by
Eric V. Smithd327ae62018-01-07 08:19:45 -0500858 the equivalent of calling 'field(name, type [, Field-info])'.
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500859
Raymond Hettingerd55209d2018-01-10 20:56:41 -0800860 C = make_dataclass('C', ['x', ('y', int), ('z', int, field(init=False))], bases=(Base,))
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500861
862 is equivalent to:
863
864 @dataclass
865 class C(Base):
Raymond Hettingerd55209d2018-01-10 20:56:41 -0800866 x: 'typing.Any'
867 y: int
868 z: int = field(init=False)
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500869
Raymond Hettingerd55209d2018-01-10 20:56:41 -0800870 For the bases and namespace parameters, see the builtin type() function.
Eric V. Smithd80b4432018-01-06 17:09:58 -0500871
872 The parameters init, repr, eq, order, hash, and frozen are passed to
873 dataclass().
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500874 """
875
876 if namespace is None:
877 namespace = {}
878 else:
879 # Copy namespace since we're going to mutate it.
880 namespace = namespace.copy()
881
Eric V. Smithd1388922018-01-07 14:30:17 -0500882 anns = {}
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500883 for item in fields:
Eric V. Smithed7d4292018-01-06 16:14:03 -0500884 if isinstance(item, str):
885 name = item
886 tp = 'typing.Any'
887 elif len(item) == 2:
888 name, tp, = item
889 elif len(item) == 3:
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500890 name, tp, spec = item
891 namespace[name] = spec
Eric V. Smithed7d4292018-01-06 16:14:03 -0500892 anns[name] = tp
893
894 namespace['__annotations__'] = anns
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500895 cls = type(cls_name, bases, namespace)
Eric V. Smithd80b4432018-01-06 17:09:58 -0500896 return dataclass(cls, init=init, repr=repr, eq=eq, order=order,
897 hash=hash, frozen=frozen)
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500898
899def replace(obj, **changes):
900 """Return a new object replacing specified fields with new values.
901
902 This is especially useful for frozen classes. Example usage:
903
904 @dataclass(frozen=True)
905 class C:
906 x: int
907 y: int
908
909 c = C(1, 2)
910 c1 = replace(c, x=3)
911 assert c1.x == 3 and c1.y == 2
912 """
913
914 # We're going to mutate 'changes', but that's okay because it's a new
915 # dict, even if called with 'replace(obj, **my_changes)'.
916
Eric V. Smithe7ba0132018-01-06 12:41:53 -0500917 if not _is_dataclass_instance(obj):
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500918 raise TypeError("replace() should be called on dataclass instances")
919
920 # It's an error to have init=False fields in 'changes'.
921 # If a field is not in 'changes', read its value from the provided obj.
922
923 for f in getattr(obj, _MARKER).values():
924 if not f.init:
925 # Error if this field is specified in changes.
926 if f.name in changes:
927 raise ValueError(f'field {f.name} is declared with '
928 'init=False, it cannot be specified with '
929 'replace()')
930 continue
931
932 if f.name not in changes:
933 changes[f.name] = getattr(obj, f.name)
934
935 # Create the new object, which calls __init__() and __post_init__
936 # (if defined), using all of the init fields we've added and/or
937 # left in 'changes'.
938 # If there are values supplied in changes that aren't fields, this
939 # will correctly raise a TypeError.
940 return obj.__class__(**changes)