1
1
import sys
2
+ import copy
2
3
import types
3
- from copy import deepcopy
4
4
import inspect
5
5
6
6
__all__ = ['dataclass' ,
137
137
# For boxes that are blank, __hash__ is untouched and therefore
138
138
# inherited from the base class. If the base is object, then
139
139
# id-based hashing is used.
140
- # Note that a class may have already __hash__=None if it specified an
140
+ # Note that a class may already have __hash__=None if it specified an
141
141
# __eq__ method in the class body (not one that was created by
142
142
# @dataclass).
143
143
# See _hash_action (below) for a coded version of this table.
147
147
class FrozenInstanceError (AttributeError ): pass
148
148
149
149
# A sentinel object for default values to signal that a
150
- # default- factory will be used.
150
+ # default factory will be used.
151
151
# This is given a nice repr() which will appear in the function
152
152
# signature of dataclasses' constructors.
153
153
class _HAS_DEFAULT_FACTORY_CLASS :
@@ -249,6 +249,7 @@ class _DataclassParams:
249
249
'unsafe_hash' ,
250
250
'frozen' ,
251
251
)
252
+
252
253
def __init__ (self , init , repr , eq , order , unsafe_hash , frozen ):
253
254
self .init = init
254
255
self .repr = repr
@@ -267,6 +268,7 @@ def __repr__(self):
267
268
f'frozen={ self .frozen } '
268
269
')' )
269
270
271
+
270
272
# This function is used instead of exposing Field creation directly,
271
273
# so that a type checker can be told (via overloads) that this is a
272
274
# function whose type depends on its parameters.
@@ -307,6 +309,8 @@ def _tuple_str(obj_name, fields):
307
309
def _create_fn (name , args , body , * , globals = None , locals = None ,
308
310
return_type = MISSING ):
309
311
# Note that we mutate locals when exec() is called. Caller beware!
312
+ # The only callers are internal to this module, so no worries
313
+ # about external callers.
310
314
if locals is None :
311
315
locals = {}
312
316
return_annotation = ''
@@ -429,26 +433,25 @@ def _init_fn(fields, frozen, has_post_init, self_name):
429
433
430
434
body_lines = []
431
435
for f in fields :
432
- # Do not initialize the pseudo-fields, only the real ones.
433
436
line = _field_init (f , frozen , globals , self_name )
434
- if line is not None :
435
- # line is None means that this field doesn't require
436
- # initialization. Just skip it.
437
+ # line is None means that this field doesn't require
438
+ # initialization (it's a pseudo-field). Just skip it.
439
+ if line :
437
440
body_lines .append (line )
438
441
439
442
# Does this class have a post-init function?
440
443
if has_post_init :
441
444
params_str = ',' .join (f .name for f in fields
442
445
if f ._field_type is _FIELD_INITVAR )
443
- body_lines += [ f'{ self_name } .{ _POST_INIT_NAME } ({ params_str } )' ]
446
+ body_lines . append ( f'{ self_name } .{ _POST_INIT_NAME } ({ params_str } )' )
444
447
445
448
# If no body lines, use 'pass'.
446
449
if not body_lines :
447
450
body_lines = ['pass' ]
448
451
449
452
locals = {f'_type_{ f .name } ' : f .type for f in fields }
450
453
return _create_fn ('__init__' ,
451
- [self_name ] + [_init_param (f ) for f in fields if f .init ],
454
+ [self_name ] + [_init_param (f ) for f in fields if f .init ],
452
455
body_lines ,
453
456
locals = locals ,
454
457
globals = globals ,
@@ -457,7 +460,7 @@ def _init_fn(fields, frozen, has_post_init, self_name):
457
460
458
461
def _repr_fn (fields ):
459
462
return _create_fn ('__repr__' ,
460
- [ 'self' ] ,
463
+ ( 'self' ,) ,
461
464
['return self.__class__.__qualname__ + f"(' +
462
465
', ' .join ([f"{ f .name } ={{self.{ f .name } !r}}"
463
466
for f in fields ]) +
@@ -496,7 +499,7 @@ def _cmp_fn(name, op, self_tuple, other_tuple):
496
499
# '(other.x,other.y)'.
497
500
498
501
return _create_fn (name ,
499
- [ 'self' , 'other' ] ,
502
+ ( 'self' , 'other' ) ,
500
503
[ 'if other.__class__ is self.__class__:' ,
501
504
f' return { self_tuple } { op } { other_tuple } ' ,
502
505
'return NotImplemented' ])
@@ -505,12 +508,12 @@ def _cmp_fn(name, op, self_tuple, other_tuple):
505
508
def _hash_fn (fields ):
506
509
self_tuple = _tuple_str ('self' , fields )
507
510
return _create_fn ('__hash__' ,
508
- [ 'self' ] ,
511
+ ( 'self' ,) ,
509
512
[f'return hash({ self_tuple } )' ])
510
513
511
514
512
515
def _get_field (cls , a_name , a_type ):
513
- # Return a Field object, for this field name and type. ClassVars
516
+ # Return a Field object for this field name and type. ClassVars
514
517
# and InitVars are also returned, but marked as such (see
515
518
# f._field_type).
516
519
@@ -560,9 +563,9 @@ def _get_field(cls, a_name, a_type):
560
563
raise TypeError (f'field { f .name } cannot have a '
561
564
'default factory' )
562
565
# Should I check for other field settings? default_factory
563
- # seems the most serious to check for. Maybe add others. For
564
- # example, how about init=False (or really,
565
- # init=<not-the-default-init-value>)? It makes no sense for
566
+ # seems the most serious to check for. Maybe add others.
567
+ # For example, how about init=False (or really,
568
+ # init=<not-the-default-init-value>)? It makes no sense for
566
569
# ClassVar and InitVar to specify init=<anything>.
567
570
568
571
# For real fields, disallow mutable defaults for known types.
@@ -903,7 +906,7 @@ def _asdict_inner(obj, dict_factory):
903
906
return type (obj )((_asdict_inner (k , dict_factory ), _asdict_inner (v , dict_factory ))
904
907
for k , v in obj .items ())
905
908
else :
906
- return deepcopy (obj )
909
+ return copy . deepcopy (obj )
907
910
908
911
909
912
def astuple (obj , * , tuple_factory = tuple ):
@@ -943,7 +946,7 @@ def _astuple_inner(obj, tuple_factory):
943
946
return type (obj )((_astuple_inner (k , tuple_factory ), _astuple_inner (v , tuple_factory ))
944
947
for k , v in obj .items ())
945
948
else :
946
- return deepcopy (obj )
949
+ return copy . deepcopy (obj )
947
950
948
951
949
952
def make_dataclass (cls_name , fields , * , bases = (), namespace = None , init = True ,
@@ -1032,9 +1035,9 @@ class C:
1032
1035
if f .name not in changes :
1033
1036
changes [f .name ] = getattr (obj , f .name )
1034
1037
1035
- # Create the new object, which calls __init__() and __post_init__
1036
- # ( if defined), using all of the init fields we've added and/or
1037
- # left in 'changes'.
1038
- # If there are values supplied in changes that aren't fields, this
1039
- # will correctly raise a TypeError.
1038
+ # Create the new object, which calls __init__() and
1039
+ # __post_init__() ( if defined), using all of the init fields
1040
+ # we've added and/or left in 'changes'. If there are values
1041
+ # supplied in changes that aren't fields, this will correctly
1042
+ # raise a TypeError.
1040
1043
return obj .__class__ (** changes )
0 commit comments