blob: 0c4b47564b0605b8820c197704f267d33683d556 [file] [log] [blame]
Eric V. Smith2a7bacb2018-05-15 22:44:27 -04001import re
Eric V. Smithf0db54a2017-12-04 16:58:55 -05002import sys
Eric V. Smithf96ddad2018-03-24 17:20:26 -04003import copy
Eric V. Smithf0db54a2017-12-04 16:58:55 -05004import types
Eric V. Smithf0db54a2017-12-04 16:58:55 -05005import inspect
Eric V. Smith4e812962018-05-16 11:31:29 -04006import keyword
Vadim Pushtaev4d12e4d2018-08-12 14:46:05 +03007import builtins
Srinivas Thatiparthy (శ్రీనివాస్ తాటిపర్తి)dd13c882018-10-19 22:24:50 +05308import functools
Ben Avrahamibef7d292020-10-06 20:40:50 +03009import abc
Srinivas Thatiparthy (శ్రీనివాస్ తాటిపర్తి)dd13c882018-10-19 22:24:50 +053010import _thread
Batuhan Taskayac7437e22020-10-21 16:49:22 +030011from types import FunctionType, GenericAlias
Srinivas Thatiparthy (శ్రీనివాస్ తాటిపర్తి)dd13c882018-10-19 22:24:50 +053012
Eric V. Smithf0db54a2017-12-04 16:58:55 -050013
14__all__ = ['dataclass',
15 'field',
Eric V. Smith8e4560a2018-03-21 17:10:22 -040016 'Field',
Eric V. Smithf0db54a2017-12-04 16:58:55 -050017 'FrozenInstanceError',
18 'InitVar',
Eric V. Smith03220fd2017-12-29 13:59:58 -050019 'MISSING',
Eric V. Smithf0db54a2017-12-04 16:58:55 -050020
21 # Helper functions.
22 'fields',
23 'asdict',
24 'astuple',
25 'make_dataclass',
26 'replace',
Eric V. Smithe7ba0132018-01-06 12:41:53 -050027 'is_dataclass',
Eric V. Smithf0db54a2017-12-04 16:58:55 -050028 ]
29
Eric V. Smithea8fc522018-01-27 19:07:40 -050030# Conditions for adding methods. The boxes indicate what action the
Eric V. Smithf8e75492018-05-16 05:14:53 -040031# dataclass decorator takes. For all of these tables, when I talk
32# about init=, repr=, eq=, order=, unsafe_hash=, or frozen=, I'm
33# referring to the arguments to the @dataclass decorator. When
34# checking if a dunder method already exists, I mean check for an
35# entry in the class's __dict__. I never check to see if an attribute
36# is defined in a base class.
Eric V. Smithea8fc522018-01-27 19:07:40 -050037
38# Key:
39# +=========+=========================================+
40# + Value | Meaning |
41# +=========+=========================================+
42# | <blank> | No action: no method is added. |
43# +---------+-----------------------------------------+
44# | add | Generated method is added. |
45# +---------+-----------------------------------------+
Eric V. Smithea8fc522018-01-27 19:07:40 -050046# | raise | TypeError is raised. |
47# +---------+-----------------------------------------+
48# | None | Attribute is set to None. |
49# +=========+=========================================+
50
51# __init__
52#
53# +--- init= parameter
54# |
55# v | | |
56# | no | yes | <--- class has __init__ in __dict__?
57# +=======+=======+=======+
58# | False | | |
59# +-------+-------+-------+
60# | True | add | | <- the default
61# +=======+=======+=======+
62
63# __repr__
64#
65# +--- repr= parameter
66# |
67# v | | |
68# | no | yes | <--- class has __repr__ in __dict__?
69# +=======+=======+=======+
70# | False | | |
71# +-------+-------+-------+
72# | True | add | | <- the default
73# +=======+=======+=======+
74
75
76# __setattr__
77# __delattr__
78#
79# +--- frozen= parameter
80# |
81# v | | |
82# | no | yes | <--- class has __setattr__ or __delattr__ in __dict__?
83# +=======+=======+=======+
84# | False | | | <- the default
85# +-------+-------+-------+
86# | True | add | raise |
87# +=======+=======+=======+
88# Raise because not adding these methods would break the "frozen-ness"
Eric V. Smithf8e75492018-05-16 05:14:53 -040089# of the class.
Eric V. Smithea8fc522018-01-27 19:07:40 -050090
91# __eq__
92#
93# +--- eq= parameter
94# |
95# v | | |
96# | no | yes | <--- class has __eq__ in __dict__?
97# +=======+=======+=======+
98# | False | | |
99# +-------+-------+-------+
100# | True | add | | <- the default
101# +=======+=======+=======+
102
103# __lt__
104# __le__
105# __gt__
106# __ge__
107#
108# +--- order= parameter
109# |
110# v | | |
111# | no | yes | <--- class has any comparison method in __dict__?
112# +=======+=======+=======+
113# | False | | | <- the default
114# +-------+-------+-------+
115# | True | add | raise |
116# +=======+=======+=======+
117# Raise because to allow this case would interfere with using
Eric V. Smithf8e75492018-05-16 05:14:53 -0400118# functools.total_ordering.
Eric V. Smithea8fc522018-01-27 19:07:40 -0500119
120# __hash__
121
Eric V. Smithdbf9cff2018-02-25 21:30:17 -0500122# +------------------- unsafe_hash= parameter
123# | +----------- eq= parameter
124# | | +--- frozen= parameter
125# | | |
126# v v v | | |
127# | no | yes | <--- class has explicitly defined __hash__
128# +=======+=======+=======+========+========+
129# | False | False | False | | | No __eq__, use the base class __hash__
130# +-------+-------+-------+--------+--------+
131# | False | False | True | | | No __eq__, use the base class __hash__
132# +-------+-------+-------+--------+--------+
133# | False | True | False | None | | <-- the default, not hashable
134# +-------+-------+-------+--------+--------+
135# | False | True | True | add | | Frozen, so hashable, allows override
136# +-------+-------+-------+--------+--------+
137# | True | False | False | add | raise | Has no __eq__, but hashable
138# +-------+-------+-------+--------+--------+
139# | True | False | True | add | raise | Has no __eq__, but hashable
140# +-------+-------+-------+--------+--------+
141# | True | True | False | add | raise | Not frozen, but hashable
142# +-------+-------+-------+--------+--------+
143# | True | True | True | add | raise | Frozen, so hashable
144# +=======+=======+=======+========+========+
Eric V. Smithea8fc522018-01-27 19:07:40 -0500145# For boxes that are blank, __hash__ is untouched and therefore
Eric V. Smithf8e75492018-05-16 05:14:53 -0400146# inherited from the base class. If the base is object, then
147# id-based hashing is used.
148#
Eric V. Smithf96ddad2018-03-24 17:20:26 -0400149# Note that a class may already have __hash__=None if it specified an
Eric V. Smithf8e75492018-05-16 05:14:53 -0400150# __eq__ method in the class body (not one that was created by
151# @dataclass).
152#
Eric V. Smithdbf9cff2018-02-25 21:30:17 -0500153# See _hash_action (below) for a coded version of this table.
Eric V. Smithea8fc522018-01-27 19:07:40 -0500154
155
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500156# Raised when an attempt is made to modify a frozen class.
157class FrozenInstanceError(AttributeError): pass
158
Eric V. Smithf8e75492018-05-16 05:14:53 -0400159# A sentinel object for default values to signal that a default
160# factory will be used. This is given a nice repr() which will appear
161# in the function signature of dataclasses' constructors.
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500162class _HAS_DEFAULT_FACTORY_CLASS:
163 def __repr__(self):
164 return '<factory>'
165_HAS_DEFAULT_FACTORY = _HAS_DEFAULT_FACTORY_CLASS()
166
Eric V. Smith03220fd2017-12-29 13:59:58 -0500167# A sentinel object to detect if a parameter is supplied or not. Use
Eric V. Smithf8e75492018-05-16 05:14:53 -0400168# a class to give it a better repr.
Eric V. Smith03220fd2017-12-29 13:59:58 -0500169class _MISSING_TYPE:
170 pass
171MISSING = _MISSING_TYPE()
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500172
173# Since most per-field metadata will be unused, create an empty
Eric V. Smithf8e75492018-05-16 05:14:53 -0400174# read-only proxy that can be shared among all fields.
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500175_EMPTY_METADATA = types.MappingProxyType({})
176
177# Markers for the various kinds of fields and pseudo-fields.
Eric V. Smith01abc6e2018-05-15 08:36:21 -0400178class _FIELD_BASE:
179 def __init__(self, name):
180 self.name = name
181 def __repr__(self):
182 return self.name
183_FIELD = _FIELD_BASE('_FIELD')
184_FIELD_CLASSVAR = _FIELD_BASE('_FIELD_CLASSVAR')
185_FIELD_INITVAR = _FIELD_BASE('_FIELD_INITVAR')
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500186
187# The name of an attribute on the class where we store the Field
Eric V. Smithf8e75492018-05-16 05:14:53 -0400188# objects. Also used to check if a class is a Data Class.
Eric V. Smithf199bc62018-03-18 20:40:34 -0400189_FIELDS = '__dataclass_fields__'
190
191# The name of an attribute on the class that stores the parameters to
192# @dataclass.
193_PARAMS = '__dataclass_params__'
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500194
195# The name of the function, that if it exists, is called at the end of
196# __init__.
197_POST_INIT_NAME = '__post_init__'
198
Eric V. Smith2a7bacb2018-05-15 22:44:27 -0400199# String regex that string annotations for ClassVar or InitVar must match.
200# Allows "identifier.identifier[" or "identifier[".
201# https://bugs.python.org/issue33453 for details.
202_MODULE_IDENTIFIER_RE = re.compile(r'^(?:\s*(\w+)\s*\.)?\s*(\w+)')
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500203
Serhiy Storchakab4d0b392019-09-22 13:32:41 +0300204class InitVar:
Augusto Hack01ee12b2019-06-02 23:14:48 -0300205 __slots__ = ('type', )
206
207 def __init__(self, type):
208 self.type = type
209
210 def __repr__(self):
Samuel Colvin793cb852019-10-13 12:45:36 +0100211 if isinstance(self.type, type):
212 type_name = self.type.__name__
213 else:
214 # typing objects, e.g. List[int]
215 type_name = repr(self.type)
216 return f'dataclasses.InitVar[{type_name}]'
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500217
Serhiy Storchakab4d0b392019-09-22 13:32:41 +0300218 def __class_getitem__(cls, type):
219 return InitVar(type)
220
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500221
222# Instances of Field are only ever created from within this module,
Eric V. Smithf8e75492018-05-16 05:14:53 -0400223# and only from the field() function, although Field instances are
224# exposed externally as (conceptually) read-only objects.
225#
226# name and type are filled in after the fact, not in __init__.
227# They're not known at the time this class is instantiated, but it's
228# convenient if they're available later.
229#
Eric V. Smithf199bc62018-03-18 20:40:34 -0400230# When cls._FIELDS is filled in with a list of Field objects, the name
Eric V. Smithf8e75492018-05-16 05:14:53 -0400231# and type fields will have been populated.
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500232class Field:
233 __slots__ = ('name',
234 'type',
235 'default',
236 'default_factory',
237 'repr',
238 'hash',
239 'init',
240 'compare',
241 'metadata',
242 '_field_type', # Private: not to be used by user code.
243 )
244
245 def __init__(self, default, default_factory, init, repr, hash, compare,
246 metadata):
247 self.name = None
248 self.type = None
249 self.default = default
250 self.default_factory = default_factory
251 self.init = init
252 self.repr = repr
253 self.hash = hash
254 self.compare = compare
255 self.metadata = (_EMPTY_METADATA
Christopher Huntb01786c2019-02-12 06:50:49 -0500256 if metadata is None else
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500257 types.MappingProxyType(metadata))
258 self._field_type = None
259
260 def __repr__(self):
261 return ('Field('
262 f'name={self.name!r},'
Eric V. Smith2473eea2018-05-14 11:37:28 -0400263 f'type={self.type!r},'
264 f'default={self.default!r},'
265 f'default_factory={self.default_factory!r},'
266 f'init={self.init!r},'
267 f'repr={self.repr!r},'
268 f'hash={self.hash!r},'
269 f'compare={self.compare!r},'
Eric V. Smith01abc6e2018-05-15 08:36:21 -0400270 f'metadata={self.metadata!r},'
271 f'_field_type={self._field_type}'
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500272 ')')
273
Eric V. Smithde7a2f02018-03-26 13:29:16 -0400274 # This is used to support the PEP 487 __set_name__ protocol in the
Eric V. Smithf8e75492018-05-16 05:14:53 -0400275 # case where we're using a field that contains a descriptor as a
Artjome55ca3f2018-07-06 02:09:13 +0300276 # default value. For details on __set_name__, see
Eric V. Smithf8e75492018-05-16 05:14:53 -0400277 # https://www.python.org/dev/peps/pep-0487/#implementation-details.
278 #
279 # Note that in _process_class, this Field object is overwritten
280 # with the default value, so the end result is a descriptor that
281 # had __set_name__ called on it at the right time.
Eric V. Smithde7a2f02018-03-26 13:29:16 -0400282 def __set_name__(self, owner, name):
Eric V. Smith52199522018-03-29 11:07:48 -0400283 func = getattr(type(self.default), '__set_name__', None)
Eric V. Smithde7a2f02018-03-26 13:29:16 -0400284 if func:
Eric V. Smithf8e75492018-05-16 05:14:53 -0400285 # There is a __set_name__ method on the descriptor, call
286 # it.
Eric V. Smith52199522018-03-29 11:07:48 -0400287 func(self.default, owner, name)
Eric V. Smithde7a2f02018-03-26 13:29:16 -0400288
Ethan Smithd01628e2020-04-14 16:14:15 -0700289 __class_getitem__ = classmethod(GenericAlias)
290
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500291
Eric V. Smithf199bc62018-03-18 20:40:34 -0400292class _DataclassParams:
293 __slots__ = ('init',
294 'repr',
295 'eq',
296 'order',
297 'unsafe_hash',
298 'frozen',
299 )
Eric V. Smithf96ddad2018-03-24 17:20:26 -0400300
Eric V. Smithf199bc62018-03-18 20:40:34 -0400301 def __init__(self, init, repr, eq, order, unsafe_hash, frozen):
302 self.init = init
303 self.repr = repr
304 self.eq = eq
305 self.order = order
306 self.unsafe_hash = unsafe_hash
307 self.frozen = frozen
308
309 def __repr__(self):
310 return ('_DataclassParams('
Eric V. Smith30590422018-05-14 17:16:52 -0400311 f'init={self.init!r},'
312 f'repr={self.repr!r},'
313 f'eq={self.eq!r},'
314 f'order={self.order!r},'
315 f'unsafe_hash={self.unsafe_hash!r},'
316 f'frozen={self.frozen!r}'
Eric V. Smithf199bc62018-03-18 20:40:34 -0400317 ')')
318
Eric V. Smithf96ddad2018-03-24 17:20:26 -0400319
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500320# This function is used instead of exposing Field creation directly,
Eric V. Smithf8e75492018-05-16 05:14:53 -0400321# so that a type checker can be told (via overloads) that this is a
322# function whose type depends on its parameters.
Eric V. Smith03220fd2017-12-29 13:59:58 -0500323def field(*, default=MISSING, default_factory=MISSING, init=True, repr=True,
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500324 hash=None, compare=True, metadata=None):
325 """Return an object to identify dataclass fields.
326
Eric V. Smithf8e75492018-05-16 05:14:53 -0400327 default is the default value of the field. default_factory is a
328 0-argument function called to initialize a field's value. If init
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500329 is True, the field will be a parameter to the class's __init__()
Eric V. Smithf8e75492018-05-16 05:14:53 -0400330 function. If repr is True, the field will be included in the
331 object's repr(). If hash is True, the field will be included in
332 the object's hash(). If compare is True, the field will be used
333 in comparison functions. metadata, if specified, must be a
334 mapping which is stored but not otherwise examined by dataclass.
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500335
336 It is an error to specify both default and default_factory.
337 """
338
Eric V. Smith03220fd2017-12-29 13:59:58 -0500339 if default is not MISSING and default_factory is not MISSING:
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500340 raise ValueError('cannot specify both default and default_factory')
341 return Field(default, default_factory, init, repr, hash, compare,
342 metadata)
343
344
345def _tuple_str(obj_name, fields):
346 # Return a string representing each field of obj_name as a tuple
Eric V. Smithf8e75492018-05-16 05:14:53 -0400347 # member. So, if fields is ['x', 'y'] and obj_name is "self",
348 # return "(self.x,self.y)".
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500349
350 # Special case for the 0-tuple.
Eric V. Smithea8fc522018-01-27 19:07:40 -0500351 if not fields:
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500352 return '()'
353 # Note the trailing comma, needed if this turns out to be a 1-tuple.
354 return f'({",".join([f"{obj_name}.{f.name}" for f in fields])},)'
355
356
Srinivas Thatiparthy (శ్రీనివాస్ తాటిపర్తి)dd13c882018-10-19 22:24:50 +0530357# This function's logic is copied from "recursive_repr" function in
358# reprlib module to avoid dependency.
359def _recursive_repr(user_function):
360 # Decorator to make a repr function return "..." for a recursive
361 # call.
362 repr_running = set()
363
364 @functools.wraps(user_function)
365 def wrapper(self):
366 key = id(self), _thread.get_ident()
367 if key in repr_running:
368 return '...'
369 repr_running.add(key)
370 try:
371 result = user_function(self)
372 finally:
373 repr_running.discard(key)
374 return result
375 return wrapper
376
377
Eric V. Smithea8fc522018-01-27 19:07:40 -0500378def _create_fn(name, args, body, *, globals=None, locals=None,
Eric V. Smith03220fd2017-12-29 13:59:58 -0500379 return_type=MISSING):
Eric V. Smithf8e75492018-05-16 05:14:53 -0400380 # Note that we mutate locals when exec() is called. Caller
381 # beware! The only callers are internal to this module, so no
382 # worries about external callers.
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500383 if locals is None:
384 locals = {}
Yury Selivanovd219cc42019-12-09 09:54:20 -0500385 if 'BUILTINS' not in locals:
386 locals['BUILTINS'] = builtins
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500387 return_annotation = ''
Eric V. Smith03220fd2017-12-29 13:59:58 -0500388 if return_type is not MISSING:
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500389 locals['_return_type'] = return_type
390 return_annotation = '->_return_type'
391 args = ','.join(args)
Yury Selivanovd219cc42019-12-09 09:54:20 -0500392 body = '\n'.join(f' {b}' for b in body)
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500393
Eric V. Smithf199bc62018-03-18 20:40:34 -0400394 # Compute the text of the entire function.
Yury Selivanovd219cc42019-12-09 09:54:20 -0500395 txt = f' def {name}({args}){return_annotation}:\n{body}'
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500396
Yury Selivanovd219cc42019-12-09 09:54:20 -0500397 local_vars = ', '.join(locals.keys())
398 txt = f"def __create_fn__({local_vars}):\n{txt}\n return {name}"
399
400 ns = {}
401 exec(txt, globals, ns)
Batuhan Taskaya044a1042020-10-06 23:03:02 +0300402 func = ns['__create_fn__'](**locals)
403 for arg, annotation in func.__annotations__.copy().items():
404 func.__annotations__[arg] = locals[annotation]
405 return func
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500406
407def _field_assign(frozen, name, value, self_name):
408 # If we're a frozen class, then assign to our fields in __init__
Eric V. Smithf8e75492018-05-16 05:14:53 -0400409 # via object.__setattr__. Otherwise, just use a simple
410 # assignment.
411 #
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500412 # self_name is what "self" is called in this function: don't
Eric V. Smithf8e75492018-05-16 05:14:53 -0400413 # hard-code "self", since that might be a field name.
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500414 if frozen:
Yury Selivanovd219cc42019-12-09 09:54:20 -0500415 return f'BUILTINS.object.__setattr__({self_name},{name!r},{value})'
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500416 return f'{self_name}.{name}={value}'
417
418
419def _field_init(f, frozen, globals, self_name):
420 # Return the text of the line in the body of __init__ that will
Eric V. Smithf8e75492018-05-16 05:14:53 -0400421 # initialize this field.
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500422
423 default_name = f'_dflt_{f.name}'
Eric V. Smith03220fd2017-12-29 13:59:58 -0500424 if f.default_factory is not MISSING:
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500425 if f.init:
426 # This field has a default factory. If a parameter is
Eric V. Smithf8e75492018-05-16 05:14:53 -0400427 # given, use it. If not, call the factory.
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500428 globals[default_name] = f.default_factory
429 value = (f'{default_name}() '
430 f'if {f.name} is _HAS_DEFAULT_FACTORY '
431 f'else {f.name}')
432 else:
433 # This is a field that's not in the __init__ params, but
Eric V. Smithf8e75492018-05-16 05:14:53 -0400434 # has a default factory function. It needs to be
435 # initialized here by calling the factory function,
436 # because there's no other way to initialize it.
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500437
438 # For a field initialized with a default=defaultvalue, the
Eric V. Smithf8e75492018-05-16 05:14:53 -0400439 # class dict just has the default value
440 # (cls.fieldname=defaultvalue). But that won't work for a
441 # default factory, the factory must be called in __init__
442 # and we must assign that to self.fieldname. We can't
443 # fall back to the class dict's value, both because it's
444 # not set, and because it might be different per-class
445 # (which, after all, is why we have a factory function!).
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500446
447 globals[default_name] = f.default_factory
448 value = f'{default_name}()'
449 else:
450 # No default factory.
451 if f.init:
Eric V. Smith03220fd2017-12-29 13:59:58 -0500452 if f.default is MISSING:
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500453 # There's no default, just do an assignment.
454 value = f.name
Eric V. Smith03220fd2017-12-29 13:59:58 -0500455 elif f.default is not MISSING:
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500456 globals[default_name] = f.default
457 value = f.name
458 else:
Eric V. Smithf8e75492018-05-16 05:14:53 -0400459 # This field does not need initialization. Signify that
460 # to the caller by returning None.
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500461 return None
462
463 # Only test this now, so that we can create variables for the
Eric V. Smithf8e75492018-05-16 05:14:53 -0400464 # default. However, return None to signify that we're not going
465 # to actually do the assignment statement for InitVars.
Eric V. Smithe7adf2b2018-06-07 14:43:59 -0400466 if f._field_type is _FIELD_INITVAR:
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500467 return None
468
469 # Now, actually generate the field assignment.
470 return _field_assign(frozen, f.name, value, self_name)
471
472
473def _init_param(f):
Eric V. Smithf8e75492018-05-16 05:14:53 -0400474 # Return the __init__ parameter string for this field. For
475 # example, the equivalent of 'x:int=3' (except instead of 'int',
476 # reference a variable set to int, and instead of '3', reference a
477 # variable set to 3).
Eric V. Smith03220fd2017-12-29 13:59:58 -0500478 if f.default is MISSING and f.default_factory is MISSING:
Eric V. Smithf8e75492018-05-16 05:14:53 -0400479 # There's no default, and no default_factory, just output the
480 # variable name and type.
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500481 default = ''
Eric V. Smith03220fd2017-12-29 13:59:58 -0500482 elif f.default is not MISSING:
Eric V. Smithf8e75492018-05-16 05:14:53 -0400483 # There's a default, this will be the name that's used to look
484 # it up.
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500485 default = f'=_dflt_{f.name}'
Eric V. Smith03220fd2017-12-29 13:59:58 -0500486 elif f.default_factory is not MISSING:
Eric V. Smithf8e75492018-05-16 05:14:53 -0400487 # There's a factory function. Set a marker.
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500488 default = '=_HAS_DEFAULT_FACTORY'
489 return f'{f.name}:_type_{f.name}{default}'
490
491
Yury Selivanovd219cc42019-12-09 09:54:20 -0500492def _init_fn(fields, frozen, has_post_init, self_name, globals):
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500493 # fields contains both real fields and InitVar pseudo-fields.
494
495 # Make sure we don't have fields without defaults following fields
Eric V. Smithf8e75492018-05-16 05:14:53 -0400496 # with defaults. This actually would be caught when exec-ing the
497 # function source code, but catching it here gives a better error
498 # message, and future-proofs us in case we build up the function
499 # using ast.
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500500 seen_default = False
501 for f in fields:
502 # Only consider fields in the __init__ call.
503 if f.init:
Eric V. Smith03220fd2017-12-29 13:59:58 -0500504 if not (f.default is MISSING and f.default_factory is MISSING):
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500505 seen_default = True
506 elif seen_default:
507 raise TypeError(f'non-default argument {f.name!r} '
508 'follows default argument')
509
Yury Selivanovd219cc42019-12-09 09:54:20 -0500510 locals = {f'_type_{f.name}': f.type for f in fields}
511 locals.update({
512 'MISSING': MISSING,
513 '_HAS_DEFAULT_FACTORY': _HAS_DEFAULT_FACTORY,
514 })
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500515
516 body_lines = []
517 for f in fields:
Yury Selivanovd219cc42019-12-09 09:54:20 -0500518 line = _field_init(f, frozen, locals, self_name)
Eric V. Smithf96ddad2018-03-24 17:20:26 -0400519 # line is None means that this field doesn't require
Eric V. Smithf8e75492018-05-16 05:14:53 -0400520 # initialization (it's a pseudo-field). Just skip it.
Eric V. Smithf96ddad2018-03-24 17:20:26 -0400521 if line:
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500522 body_lines.append(line)
523
524 # Does this class have a post-init function?
525 if has_post_init:
526 params_str = ','.join(f.name for f in fields
527 if f._field_type is _FIELD_INITVAR)
Eric V. Smithf96ddad2018-03-24 17:20:26 -0400528 body_lines.append(f'{self_name}.{_POST_INIT_NAME}({params_str})')
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500529
530 # If no body lines, use 'pass'.
Eric V. Smithea8fc522018-01-27 19:07:40 -0500531 if not body_lines:
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500532 body_lines = ['pass']
533
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500534 return _create_fn('__init__',
Eric V. Smithf96ddad2018-03-24 17:20:26 -0400535 [self_name] + [_init_param(f) for f in fields if f.init],
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500536 body_lines,
537 locals=locals,
538 globals=globals,
539 return_type=None)
540
541
Yury Selivanovd219cc42019-12-09 09:54:20 -0500542def _repr_fn(fields, globals):
Srinivas Thatiparthy (శ్రీనివాస్ తాటిపర్తి)dd13c882018-10-19 22:24:50 +0530543 fn = _create_fn('__repr__',
544 ('self',),
545 ['return self.__class__.__qualname__ + f"(' +
546 ', '.join([f"{f.name}={{self.{f.name}!r}}"
547 for f in fields]) +
Yury Selivanovd219cc42019-12-09 09:54:20 -0500548 ')"'],
549 globals=globals)
Srinivas Thatiparthy (శ్రీనివాస్ తాటిపర్తి)dd13c882018-10-19 22:24:50 +0530550 return _recursive_repr(fn)
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500551
552
Yury Selivanovd219cc42019-12-09 09:54:20 -0500553def _frozen_get_del_attr(cls, fields, globals):
554 locals = {'cls': cls,
Eric V. Smithf199bc62018-03-18 20:40:34 -0400555 'FrozenInstanceError': FrozenInstanceError}
556 if fields:
557 fields_str = '(' + ','.join(repr(f.name) for f in fields) + ',)'
558 else:
559 # Special case for the zero-length tuple.
560 fields_str = '()'
561 return (_create_fn('__setattr__',
562 ('self', 'name', 'value'),
563 (f'if type(self) is cls or name in {fields_str}:',
564 ' raise FrozenInstanceError(f"cannot assign to field {name!r}")',
565 f'super(cls, self).__setattr__(name, value)'),
Yury Selivanovd219cc42019-12-09 09:54:20 -0500566 locals=locals,
Eric V. Smithf199bc62018-03-18 20:40:34 -0400567 globals=globals),
568 _create_fn('__delattr__',
569 ('self', 'name'),
570 (f'if type(self) is cls or name in {fields_str}:',
571 ' raise FrozenInstanceError(f"cannot delete field {name!r}")',
572 f'super(cls, self).__delattr__(name)'),
Yury Selivanovd219cc42019-12-09 09:54:20 -0500573 locals=locals,
Eric V. Smithf199bc62018-03-18 20:40:34 -0400574 globals=globals),
575 )
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500576
577
Yury Selivanovd219cc42019-12-09 09:54:20 -0500578def _cmp_fn(name, op, self_tuple, other_tuple, globals):
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500579 # Create a comparison function. If the fields in the object are
Eric V. Smithf8e75492018-05-16 05:14:53 -0400580 # named 'x' and 'y', then self_tuple is the string
581 # '(self.x,self.y)' and other_tuple is the string
582 # '(other.x,other.y)'.
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500583
584 return _create_fn(name,
Eric V. Smithf96ddad2018-03-24 17:20:26 -0400585 ('self', 'other'),
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500586 [ 'if other.__class__ is self.__class__:',
587 f' return {self_tuple}{op}{other_tuple}',
Yury Selivanovd219cc42019-12-09 09:54:20 -0500588 'return NotImplemented'],
589 globals=globals)
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500590
591
Yury Selivanovd219cc42019-12-09 09:54:20 -0500592def _hash_fn(fields, globals):
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500593 self_tuple = _tuple_str('self', fields)
594 return _create_fn('__hash__',
Eric V. Smithf96ddad2018-03-24 17:20:26 -0400595 ('self',),
Yury Selivanovd219cc42019-12-09 09:54:20 -0500596 [f'return hash({self_tuple})'],
597 globals=globals)
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500598
599
Eric V. Smith2a7bacb2018-05-15 22:44:27 -0400600def _is_classvar(a_type, typing):
Eric V. Smith92858352018-05-16 07:24:00 -0400601 # This test uses a typing internal class, but it's the best way to
602 # test if this is a ClassVar.
603 return (a_type is typing.ClassVar
604 or (type(a_type) is typing._GenericAlias
605 and a_type.__origin__ is typing.ClassVar))
Eric V. Smith2a7bacb2018-05-15 22:44:27 -0400606
607
608def _is_initvar(a_type, dataclasses):
609 # The module we're checking against is the module we're
610 # currently in (dataclasses.py).
Augusto Hack01ee12b2019-06-02 23:14:48 -0300611 return (a_type is dataclasses.InitVar
612 or type(a_type) is dataclasses.InitVar)
Eric V. Smith2a7bacb2018-05-15 22:44:27 -0400613
614
615def _is_type(annotation, cls, a_module, a_type, is_type_predicate):
616 # Given a type annotation string, does it refer to a_type in
617 # a_module? For example, when checking that annotation denotes a
618 # ClassVar, then a_module is typing, and a_type is
619 # typing.ClassVar.
620
621 # It's possible to look up a_module given a_type, but it involves
622 # looking in sys.modules (again!), and seems like a waste since
623 # the caller already knows a_module.
624
625 # - annotation is a string type annotation
626 # - cls is the class that this annotation was found in
627 # - a_module is the module we want to match
628 # - a_type is the type in that module we want to match
629 # - is_type_predicate is a function called with (obj, a_module)
630 # that determines if obj is of the desired type.
631
632 # Since this test does not do a local namespace lookup (and
633 # instead only a module (global) lookup), there are some things it
634 # gets wrong.
635
Eric V. Smithf8e75492018-05-16 05:14:53 -0400636 # With string annotations, cv0 will be detected as a ClassVar:
Eric V. Smith2a7bacb2018-05-15 22:44:27 -0400637 # CV = ClassVar
638 # @dataclass
639 # class C0:
640 # cv0: CV
641
Eric V. Smithf8e75492018-05-16 05:14:53 -0400642 # But in this example cv1 will not be detected as a ClassVar:
Eric V. Smith2a7bacb2018-05-15 22:44:27 -0400643 # @dataclass
644 # class C1:
645 # CV = ClassVar
646 # cv1: CV
647
Eric V. Smithf8e75492018-05-16 05:14:53 -0400648 # In C1, the code in this function (_is_type) will look up "CV" in
649 # the module and not find it, so it will not consider cv1 as a
650 # ClassVar. This is a fairly obscure corner case, and the best
651 # way to fix it would be to eval() the string "CV" with the
652 # correct global and local namespaces. However that would involve
653 # a eval() penalty for every single field of every dataclass
654 # that's defined. It was judged not worth it.
Eric V. Smith2a7bacb2018-05-15 22:44:27 -0400655
Batuhan Taskaya044a1042020-10-06 23:03:02 +0300656 # Strip away the extra quotes as a result of double-stringifying when the
657 # 'annotations' feature became default.
658 if annotation.startswith(("'", '"')) and annotation.endswith(("'", '"')):
659 annotation = annotation[1:-1]
660
Eric V. Smith2a7bacb2018-05-15 22:44:27 -0400661 match = _MODULE_IDENTIFIER_RE.match(annotation)
662 if match:
663 ns = None
664 module_name = match.group(1)
665 if not module_name:
666 # No module name, assume the class's module did
667 # "from dataclasses import InitVar".
668 ns = sys.modules.get(cls.__module__).__dict__
669 else:
670 # Look up module_name in the class's module.
671 module = sys.modules.get(cls.__module__)
672 if module and module.__dict__.get(module_name) is a_module:
673 ns = sys.modules.get(a_type.__module__).__dict__
674 if ns and is_type_predicate(ns.get(match.group(2)), a_module):
675 return True
676 return False
677
678
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500679def _get_field(cls, a_name, a_type):
Eric V. Smithf96ddad2018-03-24 17:20:26 -0400680 # Return a Field object for this field name and type. ClassVars
Eric V. Smithf8e75492018-05-16 05:14:53 -0400681 # and InitVars are also returned, but marked as such (see
682 # f._field_type).
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500683
Eric V. Smithf8e75492018-05-16 05:14:53 -0400684 # If the default value isn't derived from Field, then it's only a
685 # normal default value. Convert it to a Field().
Eric V. Smith03220fd2017-12-29 13:59:58 -0500686 default = getattr(cls, a_name, MISSING)
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500687 if isinstance(default, Field):
688 f = default
689 else:
Eric V. Smith7389fd92018-03-19 21:07:51 -0400690 if isinstance(default, types.MemberDescriptorType):
691 # This is a field in __slots__, so it has no default value.
692 default = MISSING
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500693 f = field(default=default)
694
Eric V. Smithf8e75492018-05-16 05:14:53 -0400695 # Only at this point do we know the name and the type. Set them.
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500696 f.name = a_name
697 f.type = a_type
698
Eric V. Smith2a7bacb2018-05-15 22:44:27 -0400699 # Assume it's a normal field until proven otherwise. We're next
Eric V. Smithf8e75492018-05-16 05:14:53 -0400700 # going to decide if it's a ClassVar or InitVar, everything else
701 # is just a normal field.
Eric V. Smith2a7bacb2018-05-15 22:44:27 -0400702 f._field_type = _FIELD
703
704 # In addition to checking for actual types here, also check for
Eric V. Smithf8e75492018-05-16 05:14:53 -0400705 # string annotations. get_type_hints() won't always work for us
706 # (see https://github.com/python/typing/issues/508 for example),
707 # plus it's expensive and would require an eval for every stirng
708 # annotation. So, make a best effort to see if this is a ClassVar
709 # or InitVar using regex's and checking that the thing referenced
710 # is actually of the correct type.
Eric V. Smith2a7bacb2018-05-15 22:44:27 -0400711
712 # For the complete discussion, see https://bugs.python.org/issue33453
713
714 # If typing has not been imported, then it's impossible for any
Eric V. Smithf8e75492018-05-16 05:14:53 -0400715 # annotation to be a ClassVar. So, only look for ClassVar if
716 # typing has been imported by any module (not necessarily cls's
717 # module).
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500718 typing = sys.modules.get('typing')
Eric V. Smith2a7bacb2018-05-15 22:44:27 -0400719 if typing:
Eric V. Smith2a7bacb2018-05-15 22:44:27 -0400720 if (_is_classvar(a_type, typing)
721 or (isinstance(f.type, str)
722 and _is_type(f.type, cls, typing, typing.ClassVar,
723 _is_classvar))):
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500724 f._field_type = _FIELD_CLASSVAR
725
Eric V. Smith2a7bacb2018-05-15 22:44:27 -0400726 # If the type is InitVar, or if it's a matching string annotation,
727 # then it's an InitVar.
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500728 if f._field_type is _FIELD:
Eric V. Smith2a7bacb2018-05-15 22:44:27 -0400729 # The module we're checking against is the module we're
730 # currently in (dataclasses.py).
731 dataclasses = sys.modules[__name__]
732 if (_is_initvar(a_type, dataclasses)
733 or (isinstance(f.type, str)
734 and _is_type(f.type, cls, dataclasses, dataclasses.InitVar,
735 _is_initvar))):
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500736 f._field_type = _FIELD_INITVAR
737
Eric V. Smith2a7bacb2018-05-15 22:44:27 -0400738 # Validations for individual fields. This is delayed until now,
739 # instead of in the Field() constructor, since only here do we
740 # know the field name, which allows for better error reporting.
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500741
742 # Special restrictions for ClassVar and InitVar.
743 if f._field_type in (_FIELD_CLASSVAR, _FIELD_INITVAR):
Eric V. Smith03220fd2017-12-29 13:59:58 -0500744 if f.default_factory is not MISSING:
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500745 raise TypeError(f'field {f.name} cannot have a '
746 'default factory')
747 # Should I check for other field settings? default_factory
Eric V. Smithf8e75492018-05-16 05:14:53 -0400748 # seems the most serious to check for. Maybe add others. For
749 # example, how about init=False (or really,
750 # init=<not-the-default-init-value>)? It makes no sense for
751 # ClassVar and InitVar to specify init=<anything>.
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500752
753 # For real fields, disallow mutable defaults for known types.
754 if f._field_type is _FIELD and isinstance(f.default, (list, dict, set)):
755 raise ValueError(f'mutable default {type(f.default)} for field '
756 f'{f.name} is not allowed: use default_factory')
757
758 return f
759
Batuhan Taskayac7437e22020-10-21 16:49:22 +0300760def _set_qualname(cls, value):
761 # Ensure that the functions returned from _create_fn uses the proper
762 # __qualname__ (the class they belong to).
763 if isinstance(value, FunctionType):
764 value.__qualname__ = f"{cls.__qualname__}.{value.__name__}"
765 return value
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500766
Eric V. Smithea8fc522018-01-27 19:07:40 -0500767def _set_new_attribute(cls, name, value):
768 # Never overwrites an existing attribute. Returns True if the
Eric V. Smithf8e75492018-05-16 05:14:53 -0400769 # attribute already exists.
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500770 if name in cls.__dict__:
Eric V. Smithea8fc522018-01-27 19:07:40 -0500771 return True
Batuhan Taskayac7437e22020-10-21 16:49:22 +0300772 _set_qualname(cls, value)
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500773 setattr(cls, name, value)
Eric V. Smithea8fc522018-01-27 19:07:40 -0500774 return False
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500775
776
Eric V. Smithdbf9cff2018-02-25 21:30:17 -0500777# Decide if/how we're going to create a hash function. Key is
Eric V. Smithf8e75492018-05-16 05:14:53 -0400778# (unsafe_hash, eq, frozen, does-hash-exist). Value is the action to
779# take. The common case is to do nothing, so instead of providing a
780# function that is a no-op, use None to signify that.
Eric V. Smith01d618c2018-03-24 22:10:14 -0400781
Yury Selivanovd219cc42019-12-09 09:54:20 -0500782def _hash_set_none(cls, fields, globals):
Eric V. Smith01d618c2018-03-24 22:10:14 -0400783 return None
784
Yury Selivanovd219cc42019-12-09 09:54:20 -0500785def _hash_add(cls, fields, globals):
Eric V. Smith01d618c2018-03-24 22:10:14 -0400786 flds = [f for f in fields if (f.compare if f.hash is None else f.hash)]
Batuhan Taskayac7437e22020-10-21 16:49:22 +0300787 return _set_qualname(cls, _hash_fn(flds, globals))
Eric V. Smith01d618c2018-03-24 22:10:14 -0400788
Yury Selivanovd219cc42019-12-09 09:54:20 -0500789def _hash_exception(cls, fields, globals):
Eric V. Smith01d618c2018-03-24 22:10:14 -0400790 # Raise an exception.
791 raise TypeError(f'Cannot overwrite attribute __hash__ '
792 f'in class {cls.__name__}')
793
Eric V. Smithdbf9cff2018-02-25 21:30:17 -0500794#
795# +-------------------------------------- unsafe_hash?
796# | +------------------------------- eq?
797# | | +------------------------ frozen?
798# | | | +---------------- has-explicit-hash?
799# | | | |
800# | | | | +------- action
801# | | | | |
802# v v v v v
Eric V. Smith01d618c2018-03-24 22:10:14 -0400803_hash_action = {(False, False, False, False): None,
804 (False, False, False, True ): None,
805 (False, False, True, False): None,
806 (False, False, True, True ): None,
807 (False, True, False, False): _hash_set_none,
808 (False, True, False, True ): None,
809 (False, True, True, False): _hash_add,
810 (False, True, True, True ): None,
811 (True, False, False, False): _hash_add,
812 (True, False, False, True ): _hash_exception,
813 (True, False, True, False): _hash_add,
814 (True, False, True, True ): _hash_exception,
815 (True, True, False, False): _hash_add,
816 (True, True, False, True ): _hash_exception,
817 (True, True, True, False): _hash_add,
818 (True, True, True, True ): _hash_exception,
Eric V. Smithdbf9cff2018-02-25 21:30:17 -0500819 }
820# See https://bugs.python.org/issue32929#msg312829 for an if-statement
Eric V. Smithf8e75492018-05-16 05:14:53 -0400821# version of this table.
Eric V. Smithdbf9cff2018-02-25 21:30:17 -0500822
823
Eric V. Smithf199bc62018-03-18 20:40:34 -0400824def _process_class(cls, init, repr, eq, order, unsafe_hash, frozen):
Eric V. Smithd1388922018-01-07 14:30:17 -0500825 # Now that dicts retain insertion order, there's no reason to use
Eric V. Smithf8e75492018-05-16 05:14:53 -0400826 # an ordered dict. I am leveraging that ordering here, because
827 # derived class fields overwrite base class fields, but the order
828 # is defined by the base class, which is found first.
Eric V. Smithd1388922018-01-07 14:30:17 -0500829 fields = {}
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500830
Yury Selivanovd219cc42019-12-09 09:54:20 -0500831 if cls.__module__ in sys.modules:
832 globals = sys.modules[cls.__module__].__dict__
833 else:
834 # Theoretically this can happen if someone writes
835 # a custom string to cls.__module__. In which case
836 # such dataclass won't be fully introspectable
837 # (w.r.t. typing.get_type_hints) but will still function
838 # correctly.
839 globals = {}
840
Eric V. Smithf199bc62018-03-18 20:40:34 -0400841 setattr(cls, _PARAMS, _DataclassParams(init, repr, eq, order,
842 unsafe_hash, frozen))
843
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500844 # Find our base classes in reverse MRO order, and exclude
Eric V. Smithf8e75492018-05-16 05:14:53 -0400845 # ourselves. In reversed order so that more derived classes
846 # override earlier field definitions in base classes. As long as
847 # we're iterating over them, see if any are frozen.
Eric V. Smithf199bc62018-03-18 20:40:34 -0400848 any_frozen_base = False
849 has_dataclass_bases = False
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500850 for b in cls.__mro__[-1:0:-1]:
851 # Only process classes that have been processed by our
Eric V. Smithf8e75492018-05-16 05:14:53 -0400852 # decorator. That is, they have a _FIELDS attribute.
Eric V. Smithf199bc62018-03-18 20:40:34 -0400853 base_fields = getattr(b, _FIELDS, None)
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500854 if base_fields:
Eric V. Smithf199bc62018-03-18 20:40:34 -0400855 has_dataclass_bases = True
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500856 for f in base_fields.values():
857 fields[f.name] = f
Eric V. Smithf199bc62018-03-18 20:40:34 -0400858 if getattr(b, _PARAMS).frozen:
859 any_frozen_base = True
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500860
Eric V. Smith56970b82018-03-22 16:28:48 -0400861 # Annotations that are defined in this class (not in base
Eric V. Smithf8e75492018-05-16 05:14:53 -0400862 # classes). If __annotations__ isn't present, then this class
863 # adds no new annotations. We use this to compute fields that are
864 # added by this class.
865 #
Eric V. Smith56970b82018-03-22 16:28:48 -0400866 # Fields are found from cls_annotations, which is guaranteed to be
Eric V. Smithf8e75492018-05-16 05:14:53 -0400867 # ordered. Default values are from class attributes, if a field
868 # has a default. If the default value is a Field(), then it
869 # contains additional info beyond (and possibly including) the
870 # actual default value. Pseudo-fields ClassVars and InitVars are
871 # included, despite the fact that they're not real fields. That's
872 # dealt with later.
Eric V. Smith56970b82018-03-22 16:28:48 -0400873 cls_annotations = cls.__dict__.get('__annotations__', {})
874
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500875 # Now find fields in our class. While doing so, validate some
Eric V. Smithf8e75492018-05-16 05:14:53 -0400876 # things, and set the default values (as class attributes) where
877 # we can.
Eric V. Smith56970b82018-03-22 16:28:48 -0400878 cls_fields = [_get_field(cls, name, type)
879 for name, type in cls_annotations.items()]
880 for f in cls_fields:
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500881 fields[f.name] = f
882
Eric V. Smithf8e75492018-05-16 05:14:53 -0400883 # If the class attribute (which is the default value for this
884 # field) exists and is of type 'Field', replace it with the
885 # real default. This is so that normal class introspection
886 # sees a real default value, not a Field.
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500887 if isinstance(getattr(cls, f.name, None), Field):
Eric V. Smith03220fd2017-12-29 13:59:58 -0500888 if f.default is MISSING:
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500889 # If there's no default, delete the class attribute.
Eric V. Smithf8e75492018-05-16 05:14:53 -0400890 # This happens if we specify field(repr=False), for
891 # example (that is, we specified a field object, but
892 # no default value). Also if we're using a default
893 # factory. The class attribute should not be set at
894 # all in the post-processed class.
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500895 delattr(cls, f.name)
896 else:
897 setattr(cls, f.name, f.default)
898
Eric V. Smith56970b82018-03-22 16:28:48 -0400899 # Do we have any Field members that don't also have annotations?
900 for name, value in cls.__dict__.items():
901 if isinstance(value, Field) and not name in cls_annotations:
902 raise TypeError(f'{name!r} is a field but has no type annotation')
903
Eric V. Smithf199bc62018-03-18 20:40:34 -0400904 # Check rules that apply if we are derived from any dataclasses.
905 if has_dataclass_bases:
906 # Raise an exception if any of our bases are frozen, but we're not.
907 if any_frozen_base and not frozen:
908 raise TypeError('cannot inherit non-frozen dataclass from a '
909 'frozen one')
Eric V. Smith2fa6b9e2018-02-26 20:38:33 -0500910
Eric V. Smithf199bc62018-03-18 20:40:34 -0400911 # Raise an exception if we're frozen, but none of our bases are.
912 if not any_frozen_base and frozen:
913 raise TypeError('cannot inherit frozen dataclass from a '
914 'non-frozen one')
Eric V. Smith2fa6b9e2018-02-26 20:38:33 -0500915
Eric V. Smithf8e75492018-05-16 05:14:53 -0400916 # Remember all of the fields on our class (including bases). This
917 # also marks this class as being a dataclass.
Eric V. Smithf199bc62018-03-18 20:40:34 -0400918 setattr(cls, _FIELDS, fields)
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500919
Eric V. Smithdbf9cff2018-02-25 21:30:17 -0500920 # Was this class defined with an explicit __hash__? Note that if
Eric V. Smithf8e75492018-05-16 05:14:53 -0400921 # __eq__ is defined in this class, then python will automatically
922 # set __hash__ to None. This is a heuristic, as it's possible
923 # that such a __hash__ == None was not auto-generated, but it
924 # close enough.
Eric V. Smithdbf9cff2018-02-25 21:30:17 -0500925 class_hash = cls.__dict__.get('__hash__', MISSING)
926 has_explicit_hash = not (class_hash is MISSING or
927 (class_hash is None and '__eq__' in cls.__dict__))
Eric V. Smithea8fc522018-01-27 19:07:40 -0500928
Eric V. Smithf8e75492018-05-16 05:14:53 -0400929 # If we're generating ordering methods, we must be generating the
930 # eq methods.
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500931 if order and not eq:
932 raise ValueError('eq must be true if order is true')
933
934 if init:
935 # Does this class have a post-init function?
936 has_post_init = hasattr(cls, _POST_INIT_NAME)
937
938 # Include InitVars and regular fields (so, not ClassVars).
Eric V. Smithea8fc522018-01-27 19:07:40 -0500939 flds = [f for f in fields.values()
940 if f._field_type in (_FIELD, _FIELD_INITVAR)]
941 _set_new_attribute(cls, '__init__',
942 _init_fn(flds,
Eric V. Smith2fa6b9e2018-02-26 20:38:33 -0500943 frozen,
Eric V. Smithea8fc522018-01-27 19:07:40 -0500944 has_post_init,
Eric V. Smithf8e75492018-05-16 05:14:53 -0400945 # The name to use for the "self"
946 # param in __init__. Use "self"
947 # if possible.
Eric V. Smithea8fc522018-01-27 19:07:40 -0500948 '__dataclass_self__' if 'self' in fields
949 else 'self',
Yury Selivanovd219cc42019-12-09 09:54:20 -0500950 globals,
Eric V. Smithea8fc522018-01-27 19:07:40 -0500951 ))
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500952
953 # Get the fields as a list, and include only real fields. This is
Eric V. Smithf8e75492018-05-16 05:14:53 -0400954 # used in all of the following methods.
Eric V. Smithea8fc522018-01-27 19:07:40 -0500955 field_list = [f for f in fields.values() if f._field_type is _FIELD]
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500956
957 if repr:
Eric V. Smithea8fc522018-01-27 19:07:40 -0500958 flds = [f for f in field_list if f.repr]
Yury Selivanovd219cc42019-12-09 09:54:20 -0500959 _set_new_attribute(cls, '__repr__', _repr_fn(flds, globals))
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500960
961 if eq:
Eric V. Smithea8fc522018-01-27 19:07:40 -0500962 # Create _eq__ method. There's no need for a __ne__ method,
Eric V. Smithf8e75492018-05-16 05:14:53 -0400963 # since python will call __eq__ and negate it.
Eric V. Smithea8fc522018-01-27 19:07:40 -0500964 flds = [f for f in field_list if f.compare]
965 self_tuple = _tuple_str('self', flds)
966 other_tuple = _tuple_str('other', flds)
967 _set_new_attribute(cls, '__eq__',
968 _cmp_fn('__eq__', '==',
Yury Selivanovd219cc42019-12-09 09:54:20 -0500969 self_tuple, other_tuple,
970 globals=globals))
Eric V. Smithf0db54a2017-12-04 16:58:55 -0500971
972 if order:
Eric V. Smithea8fc522018-01-27 19:07:40 -0500973 # Create and set the ordering methods.
974 flds = [f for f in field_list if f.compare]
975 self_tuple = _tuple_str('self', flds)
976 other_tuple = _tuple_str('other', flds)
977 for name, op in [('__lt__', '<'),
978 ('__le__', '<='),
979 ('__gt__', '>'),
980 ('__ge__', '>='),
981 ]:
982 if _set_new_attribute(cls, name,
Yury Selivanovd219cc42019-12-09 09:54:20 -0500983 _cmp_fn(name, op, self_tuple, other_tuple,
984 globals=globals)):
Eric V. Smithea8fc522018-01-27 19:07:40 -0500985 raise TypeError(f'Cannot overwrite attribute {name} '
Eric V. Smithdbf9cff2018-02-25 21:30:17 -0500986 f'in class {cls.__name__}. Consider using '
Eric V. Smithea8fc522018-01-27 19:07:40 -0500987 'functools.total_ordering')
988
Eric V. Smith2fa6b9e2018-02-26 20:38:33 -0500989 if frozen:
Yury Selivanovd219cc42019-12-09 09:54:20 -0500990 for fn in _frozen_get_del_attr(cls, field_list, globals):
Eric V. Smithf199bc62018-03-18 20:40:34 -0400991 if _set_new_attribute(cls, fn.__name__, fn):
992 raise TypeError(f'Cannot overwrite attribute {fn.__name__} '
Eric V. Smithdbf9cff2018-02-25 21:30:17 -0500993 f'in class {cls.__name__}')
Eric V. Smithea8fc522018-01-27 19:07:40 -0500994
995 # Decide if/how we're going to create a hash function.
Eric V. Smithdbf9cff2018-02-25 21:30:17 -0500996 hash_action = _hash_action[bool(unsafe_hash),
997 bool(eq),
998 bool(frozen),
999 has_explicit_hash]
Eric V. Smith01d618c2018-03-24 22:10:14 -04001000 if hash_action:
1001 # No need to call _set_new_attribute here, since by the time
Eric V. Smithf8e75492018-05-16 05:14:53 -04001002 # we're here the overwriting is unconditional.
Yury Selivanovd219cc42019-12-09 09:54:20 -05001003 cls.__hash__ = hash_action(cls, field_list, globals)
Eric V. Smithf0db54a2017-12-04 16:58:55 -05001004
1005 if not getattr(cls, '__doc__'):
1006 # Create a class doc-string.
1007 cls.__doc__ = (cls.__name__ +
Batuhan Taskaya044a1042020-10-06 23:03:02 +03001008 str(inspect.signature(cls)).replace(' -> NoneType', ''))
Eric V. Smithf0db54a2017-12-04 16:58:55 -05001009
Ben Avrahamibef7d292020-10-06 20:40:50 +03001010 abc.update_abstractmethods(cls)
1011
Eric V. Smithf0db54a2017-12-04 16:58:55 -05001012 return cls
1013
1014
Serhiy Storchaka2085bd02019-06-01 11:00:15 +03001015def dataclass(cls=None, /, *, init=True, repr=True, eq=True, order=False,
Eric V. Smith5da8cfb2018-03-01 08:01:41 -05001016 unsafe_hash=False, frozen=False):
Eric V. Smithf0db54a2017-12-04 16:58:55 -05001017 """Returns the same class as was passed in, with dunder methods
1018 added based on the fields defined in the class.
1019
1020 Examines PEP 526 __annotations__ to determine fields.
1021
1022 If init is true, an __init__() method is added to the class. If
1023 repr is true, a __repr__() method is added. If order is true, rich
Eric V. Smithdbf9cff2018-02-25 21:30:17 -05001024 comparison dunder methods are added. If unsafe_hash is true, a
1025 __hash__() method function is added. If frozen is true, fields may
1026 not be assigned to after instance creation.
Eric V. Smithf0db54a2017-12-04 16:58:55 -05001027 """
1028
1029 def wrap(cls):
Eric V. Smithf199bc62018-03-18 20:40:34 -04001030 return _process_class(cls, init, repr, eq, order, unsafe_hash, frozen)
Eric V. Smithf0db54a2017-12-04 16:58:55 -05001031
1032 # See if we're being called as @dataclass or @dataclass().
Serhiy Storchaka2085bd02019-06-01 11:00:15 +03001033 if cls is None:
Eric V. Smithf0db54a2017-12-04 16:58:55 -05001034 # We're called with parens.
1035 return wrap
1036
1037 # We're called as @dataclass without parens.
Serhiy Storchaka2085bd02019-06-01 11:00:15 +03001038 return wrap(cls)
Eric V. Smithf0db54a2017-12-04 16:58:55 -05001039
1040
1041def fields(class_or_instance):
1042 """Return a tuple describing the fields of this dataclass.
1043
1044 Accepts a dataclass or an instance of one. Tuple elements are of
1045 type Field.
1046 """
1047
1048 # Might it be worth caching this, per class?
1049 try:
Eric V. Smith2a7bacb2018-05-15 22:44:27 -04001050 fields = getattr(class_or_instance, _FIELDS)
Eric V. Smithf0db54a2017-12-04 16:58:55 -05001051 except AttributeError:
1052 raise TypeError('must be called with a dataclass type or instance')
1053
Eric V. Smithd1388922018-01-07 14:30:17 -05001054 # Exclude pseudo-fields. Note that fields is sorted by insertion
Eric V. Smithf8e75492018-05-16 05:14:53 -04001055 # order, so the order of the tuple is as the fields were defined.
Eric V. Smithf0db54a2017-12-04 16:58:55 -05001056 return tuple(f for f in fields.values() if f._field_type is _FIELD)
1057
1058
Eric V. Smithe7ba0132018-01-06 12:41:53 -05001059def _is_dataclass_instance(obj):
Eric V. Smithf0db54a2017-12-04 16:58:55 -05001060 """Returns True if obj is an instance of a dataclass."""
Eric V. Smithb0f4dab2019-08-20 01:40:28 -04001061 return hasattr(type(obj), _FIELDS)
Eric V. Smithf0db54a2017-12-04 16:58:55 -05001062
1063
Eric V. Smithe7ba0132018-01-06 12:41:53 -05001064def is_dataclass(obj):
1065 """Returns True if obj is a dataclass or an instance of a
1066 dataclass."""
Eric V. Smithb0f4dab2019-08-20 01:40:28 -04001067 cls = obj if isinstance(obj, type) else type(obj)
1068 return hasattr(cls, _FIELDS)
Eric V. Smithe7ba0132018-01-06 12:41:53 -05001069
1070
Eric V. Smithf0db54a2017-12-04 16:58:55 -05001071def asdict(obj, *, dict_factory=dict):
1072 """Return the fields of a dataclass instance as a new dictionary mapping
1073 field names to field values.
1074
1075 Example usage:
1076
1077 @dataclass
1078 class C:
1079 x: int
1080 y: int
1081
1082 c = C(1, 2)
1083 assert asdict(c) == {'x': 1, 'y': 2}
1084
1085 If given, 'dict_factory' will be used instead of built-in dict.
1086 The function applies recursively to field values that are
1087 dataclass instances. This will also look into built-in containers:
1088 tuples, lists, and dicts.
1089 """
Eric V. Smithe7ba0132018-01-06 12:41:53 -05001090 if not _is_dataclass_instance(obj):
Eric V. Smithf0db54a2017-12-04 16:58:55 -05001091 raise TypeError("asdict() should be called on dataclass instances")
1092 return _asdict_inner(obj, dict_factory)
1093
Eric V. Smithdbf9cff2018-02-25 21:30:17 -05001094
Eric V. Smithf0db54a2017-12-04 16:58:55 -05001095def _asdict_inner(obj, dict_factory):
Eric V. Smithe7ba0132018-01-06 12:41:53 -05001096 if _is_dataclass_instance(obj):
Eric V. Smithf0db54a2017-12-04 16:58:55 -05001097 result = []
1098 for f in fields(obj):
1099 value = _asdict_inner(getattr(obj, f.name), dict_factory)
1100 result.append((f.name, value))
1101 return dict_factory(result)
Eric V. Smith9b9d97d2018-09-14 11:32:16 -04001102 elif isinstance(obj, tuple) and hasattr(obj, '_fields'):
1103 # obj is a namedtuple. Recurse into it, but the returned
1104 # object is another namedtuple of the same type. This is
1105 # similar to how other list- or tuple-derived classes are
1106 # treated (see below), but we just need to create them
1107 # differently because a namedtuple's __init__ needs to be
1108 # called differently (see bpo-34363).
1109
1110 # I'm not using namedtuple's _asdict()
1111 # method, because:
1112 # - it does not recurse in to the namedtuple fields and
1113 # convert them to dicts (using dict_factory).
Jürgen Gmach80526f62020-06-24 12:46:52 +02001114 # - I don't actually want to return a dict here. The main
Eric V. Smith9b9d97d2018-09-14 11:32:16 -04001115 # use case here is json.dumps, and it handles converting
1116 # namedtuples to lists. Admittedly we're losing some
1117 # information here when we produce a json list instead of a
1118 # dict. Note that if we returned dicts here instead of
1119 # namedtuples, we could no longer call asdict() on a data
1120 # structure where a namedtuple was used as a dict key.
1121
1122 return type(obj)(*[_asdict_inner(v, dict_factory) for v in obj])
Eric V. Smithf0db54a2017-12-04 16:58:55 -05001123 elif isinstance(obj, (list, tuple)):
Eric V. Smith9b9d97d2018-09-14 11:32:16 -04001124 # Assume we can create an object of this type by passing in a
1125 # generator (which is not true for namedtuples, handled
1126 # above).
Eric V. Smithf0db54a2017-12-04 16:58:55 -05001127 return type(obj)(_asdict_inner(v, dict_factory) for v in obj)
1128 elif isinstance(obj, dict):
Eric V. Smith9b9d97d2018-09-14 11:32:16 -04001129 return type(obj)((_asdict_inner(k, dict_factory),
1130 _asdict_inner(v, dict_factory))
1131 for k, v in obj.items())
Eric V. Smithf0db54a2017-12-04 16:58:55 -05001132 else:
Eric V. Smithf96ddad2018-03-24 17:20:26 -04001133 return copy.deepcopy(obj)
Eric V. Smithf0db54a2017-12-04 16:58:55 -05001134
1135
1136def astuple(obj, *, tuple_factory=tuple):
1137 """Return the fields of a dataclass instance as a new tuple of field values.
1138
1139 Example usage::
1140
1141 @dataclass
1142 class C:
1143 x: int
1144 y: int
1145
1146 c = C(1, 2)
Raymond Hettingerd55209d2018-01-10 20:56:41 -08001147 assert astuple(c) == (1, 2)
Eric V. Smithf0db54a2017-12-04 16:58:55 -05001148
1149 If given, 'tuple_factory' will be used instead of built-in tuple.
1150 The function applies recursively to field values that are
1151 dataclass instances. This will also look into built-in containers:
1152 tuples, lists, and dicts.
1153 """
1154
Eric V. Smithe7ba0132018-01-06 12:41:53 -05001155 if not _is_dataclass_instance(obj):
Eric V. Smithf0db54a2017-12-04 16:58:55 -05001156 raise TypeError("astuple() should be called on dataclass instances")
1157 return _astuple_inner(obj, tuple_factory)
1158
Eric V. Smithdbf9cff2018-02-25 21:30:17 -05001159
Eric V. Smithf0db54a2017-12-04 16:58:55 -05001160def _astuple_inner(obj, tuple_factory):
Eric V. Smithe7ba0132018-01-06 12:41:53 -05001161 if _is_dataclass_instance(obj):
Eric V. Smithf0db54a2017-12-04 16:58:55 -05001162 result = []
1163 for f in fields(obj):
1164 value = _astuple_inner(getattr(obj, f.name), tuple_factory)
1165 result.append(value)
1166 return tuple_factory(result)
Eric V. Smith9b9d97d2018-09-14 11:32:16 -04001167 elif isinstance(obj, tuple) and hasattr(obj, '_fields'):
1168 # obj is a namedtuple. Recurse into it, but the returned
1169 # object is another namedtuple of the same type. This is
1170 # similar to how other list- or tuple-derived classes are
1171 # treated (see below), but we just need to create them
1172 # differently because a namedtuple's __init__ needs to be
1173 # called differently (see bpo-34363).
1174 return type(obj)(*[_astuple_inner(v, tuple_factory) for v in obj])
Eric V. Smithf0db54a2017-12-04 16:58:55 -05001175 elif isinstance(obj, (list, tuple)):
Eric V. Smith9b9d97d2018-09-14 11:32:16 -04001176 # Assume we can create an object of this type by passing in a
1177 # generator (which is not true for namedtuples, handled
1178 # above).
Eric V. Smithf0db54a2017-12-04 16:58:55 -05001179 return type(obj)(_astuple_inner(v, tuple_factory) for v in obj)
1180 elif isinstance(obj, dict):
1181 return type(obj)((_astuple_inner(k, tuple_factory), _astuple_inner(v, tuple_factory))
1182 for k, v in obj.items())
1183 else:
Eric V. Smithf96ddad2018-03-24 17:20:26 -04001184 return copy.deepcopy(obj)
Eric V. Smithf0db54a2017-12-04 16:58:55 -05001185
1186
Eric V. Smithd80b4432018-01-06 17:09:58 -05001187def make_dataclass(cls_name, fields, *, bases=(), namespace=None, init=True,
Eric V. Smith5da8cfb2018-03-01 08:01:41 -05001188 repr=True, eq=True, order=False, unsafe_hash=False,
Eric V. Smithdbf9cff2018-02-25 21:30:17 -05001189 frozen=False):
Eric V. Smithf0db54a2017-12-04 16:58:55 -05001190 """Return a new dynamically created dataclass.
1191
Eric V. Smithed7d4292018-01-06 16:14:03 -05001192 The dataclass name will be 'cls_name'. 'fields' is an iterable
1193 of either (name), (name, type) or (name, type, Field) objects. If type is
1194 omitted, use the string 'typing.Any'. Field objects are created by
Eric V. Smithd327ae62018-01-07 08:19:45 -05001195 the equivalent of calling 'field(name, type [, Field-info])'.
Eric V. Smithf0db54a2017-12-04 16:58:55 -05001196
Raymond Hettingerd55209d2018-01-10 20:56:41 -08001197 C = make_dataclass('C', ['x', ('y', int), ('z', int, field(init=False))], bases=(Base,))
Eric V. Smithf0db54a2017-12-04 16:58:55 -05001198
1199 is equivalent to:
1200
1201 @dataclass
1202 class C(Base):
Raymond Hettingerd55209d2018-01-10 20:56:41 -08001203 x: 'typing.Any'
1204 y: int
1205 z: int = field(init=False)
Eric V. Smithf0db54a2017-12-04 16:58:55 -05001206
Raymond Hettingerd55209d2018-01-10 20:56:41 -08001207 For the bases and namespace parameters, see the builtin type() function.
Eric V. Smithd80b4432018-01-06 17:09:58 -05001208
Eric V. Smithdbf9cff2018-02-25 21:30:17 -05001209 The parameters init, repr, eq, order, unsafe_hash, and frozen are passed to
Eric V. Smithd80b4432018-01-06 17:09:58 -05001210 dataclass().
Eric V. Smithf0db54a2017-12-04 16:58:55 -05001211 """
1212
1213 if namespace is None:
1214 namespace = {}
1215 else:
1216 # Copy namespace since we're going to mutate it.
1217 namespace = namespace.copy()
1218
Eric V. Smith4e812962018-05-16 11:31:29 -04001219 # While we're looking through the field names, validate that they
1220 # are identifiers, are not keywords, and not duplicates.
1221 seen = set()
Eric V. Smithd1388922018-01-07 14:30:17 -05001222 anns = {}
Eric V. Smithf0db54a2017-12-04 16:58:55 -05001223 for item in fields:
Eric V. Smithed7d4292018-01-06 16:14:03 -05001224 if isinstance(item, str):
1225 name = item
1226 tp = 'typing.Any'
1227 elif len(item) == 2:
1228 name, tp, = item
1229 elif len(item) == 3:
Eric V. Smithf0db54a2017-12-04 16:58:55 -05001230 name, tp, spec = item
1231 namespace[name] = spec
Eric V. Smith4e812962018-05-16 11:31:29 -04001232 else:
1233 raise TypeError(f'Invalid field: {item!r}')
1234
1235 if not isinstance(name, str) or not name.isidentifier():
Min ho Kim96e12d52019-07-22 06:12:33 +10001236 raise TypeError(f'Field names must be valid identifiers: {name!r}')
Eric V. Smith4e812962018-05-16 11:31:29 -04001237 if keyword.iskeyword(name):
1238 raise TypeError(f'Field names must not be keywords: {name!r}')
1239 if name in seen:
1240 raise TypeError(f'Field name duplicated: {name!r}')
1241
1242 seen.add(name)
Eric V. Smithed7d4292018-01-06 16:14:03 -05001243 anns[name] = tp
1244
1245 namespace['__annotations__'] = anns
Ivan Levkivskyi5a7092d2018-03-31 13:41:17 +01001246 # We use `types.new_class()` instead of simply `type()` to allow dynamic creation
1247 # of generic dataclassses.
1248 cls = types.new_class(cls_name, bases, {}, lambda ns: ns.update(namespace))
Eric V. Smithd80b4432018-01-06 17:09:58 -05001249 return dataclass(cls, init=init, repr=repr, eq=eq, order=order,
Eric V. Smithdbf9cff2018-02-25 21:30:17 -05001250 unsafe_hash=unsafe_hash, frozen=frozen)
1251
Eric V. Smithf0db54a2017-12-04 16:58:55 -05001252
Serhiy Storchaka2d88e632019-06-26 19:07:44 +03001253def replace(obj, /, **changes):
Eric V. Smithf0db54a2017-12-04 16:58:55 -05001254 """Return a new object replacing specified fields with new values.
1255
1256 This is especially useful for frozen classes. Example usage:
1257
1258 @dataclass(frozen=True)
1259 class C:
1260 x: int
1261 y: int
1262
1263 c = C(1, 2)
1264 c1 = replace(c, x=3)
1265 assert c1.x == 3 and c1.y == 2
1266 """
1267
Eric V. Smithf8e75492018-05-16 05:14:53 -04001268 # We're going to mutate 'changes', but that's okay because it's a
1269 # new dict, even if called with 'replace(obj, **my_changes)'.
Eric V. Smithf0db54a2017-12-04 16:58:55 -05001270
Eric V. Smithe7ba0132018-01-06 12:41:53 -05001271 if not _is_dataclass_instance(obj):
Eric V. Smithf0db54a2017-12-04 16:58:55 -05001272 raise TypeError("replace() should be called on dataclass instances")
1273
1274 # It's an error to have init=False fields in 'changes'.
1275 # If a field is not in 'changes', read its value from the provided obj.
1276
Eric V. Smithf199bc62018-03-18 20:40:34 -04001277 for f in getattr(obj, _FIELDS).values():
Eric V. Smithe7adf2b2018-06-07 14:43:59 -04001278 # Only consider normal fields or InitVars.
1279 if f._field_type is _FIELD_CLASSVAR:
1280 continue
1281
Eric V. Smithf0db54a2017-12-04 16:58:55 -05001282 if not f.init:
1283 # Error if this field is specified in changes.
1284 if f.name in changes:
1285 raise ValueError(f'field {f.name} is declared with '
1286 'init=False, it cannot be specified with '
1287 'replace()')
1288 continue
1289
1290 if f.name not in changes:
Dong-hee Na3d70f7a2018-06-23 23:46:32 +09001291 if f._field_type is _FIELD_INITVAR:
1292 raise ValueError(f"InitVar {f.name!r} "
1293 'must be specified with replace()')
Eric V. Smithf0db54a2017-12-04 16:58:55 -05001294 changes[f.name] = getattr(obj, f.name)
1295
Eric V. Smithf96ddad2018-03-24 17:20:26 -04001296 # Create the new object, which calls __init__() and
Eric V. Smithf8e75492018-05-16 05:14:53 -04001297 # __post_init__() (if defined), using all of the init fields we've
1298 # added and/or left in 'changes'. If there are values supplied in
1299 # changes that aren't fields, this will correctly raise a
1300 # TypeError.
Eric V. Smithf0db54a2017-12-04 16:58:55 -05001301 return obj.__class__(**changes)