@@ -354,13 +354,17 @@ def _create_fn(name, args, body, *, globals=None, locals=None,
354
354
locals ['_return_type' ] = return_type
355
355
return_annotation = '->_return_type'
356
356
args = ',' .join (args )
357
- body = '\n ' .join (f' { b } ' for b in body )
357
+ body = '\n ' .join (f' { b } ' for b in body )
358
358
359
359
# Compute the text of the entire function.
360
- txt = f'def { name } ({ args } ){ return_annotation } :\n { body } '
360
+ txt = f' def { name } ({ args } ){ return_annotation } :\n { body } '
361
+
362
+ local_vars = ', ' .join (locals .keys ())
363
+ txt = f"def __create_fn__({ local_vars } ):\n { txt } \n return { name } "
361
364
362
365
exec (txt , globals , locals )
363
- return locals [name ]
366
+ create_fn = locals .pop ('__create_fn__' )
367
+ return create_fn (** locals )
364
368
365
369
366
370
def _field_assign (frozen , name , value , self_name ):
@@ -448,7 +452,7 @@ def _init_param(f):
448
452
return f'{ f .name } :_type_{ f .name } { default } '
449
453
450
454
451
- def _init_fn (fields , frozen , has_post_init , self_name ):
455
+ def _init_fn (fields , frozen , has_post_init , self_name , modname ):
452
456
# fields contains both real fields and InitVar pseudo-fields.
453
457
454
458
# Make sure we don't have fields without defaults following fields
@@ -466,12 +470,18 @@ def _init_fn(fields, frozen, has_post_init, self_name):
466
470
raise TypeError (f'non-default argument { f .name !r} '
467
471
'follows default argument' )
468
472
469
- globals = {'MISSING' : MISSING ,
470
- '_HAS_DEFAULT_FACTORY' : _HAS_DEFAULT_FACTORY }
473
+ globals = sys .modules [modname ].__dict__
474
+
475
+ locals = {f'_type_{ f .name } ' : f .type for f in fields }
476
+ locals .update ({
477
+ 'MISSING' : MISSING ,
478
+ '_HAS_DEFAULT_FACTORY' : _HAS_DEFAULT_FACTORY ,
479
+ '__builtins__' : builtins ,
480
+ })
471
481
472
482
body_lines = []
473
483
for f in fields :
474
- line = _field_init (f , frozen , globals , self_name )
484
+ line = _field_init (f , frozen , locals , self_name )
475
485
# line is None means that this field doesn't require
476
486
# initialization (it's a pseudo-field). Just skip it.
477
487
if line :
@@ -487,7 +497,6 @@ def _init_fn(fields, frozen, has_post_init, self_name):
487
497
if not body_lines :
488
498
body_lines = ['pass' ]
489
499
490
- locals = {f'_type_{ f .name } ' : f .type for f in fields }
491
500
return _create_fn ('__init__' ,
492
501
[self_name ] + [_init_param (f ) for f in fields if f .init ],
493
502
body_lines ,
@@ -877,6 +886,7 @@ def _process_class(cls, init, repr, eq, order, unsafe_hash, frozen):
877
886
# if possible.
878
887
'__dataclass_self__' if 'self' in fields
879
888
else 'self' ,
889
+ cls .__module__
880
890
))
881
891
882
892
# Get the fields as a list, and include only real fields. This is
0 commit comments