@@ -354,13 +354,17 @@ def _create_fn(name, args, body, *, globals=None, locals=None,
354354 locals ['_return_type' ] = return_type
355355 return_annotation = '->_return_type'
356356 args = ',' .join (args )
357- body = '\n ' .join (f' { b } ' for b in body )
357+ body = '\n ' .join (f' { b } ' for b in body )
358358
359359 # 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 } "
361364
362365 exec (txt , globals , locals )
363- return locals [name ]
366+ create_fn = locals .pop ('__create_fn__' )
367+ return create_fn (** locals )
364368
365369
366370def _field_assign (frozen , name , value , self_name ):
@@ -448,7 +452,7 @@ def _init_param(f):
448452 return f'{ f .name } :_type_{ f .name } { default } '
449453
450454
451- def _init_fn (fields , frozen , has_post_init , self_name ):
455+ def _init_fn (fields , frozen , has_post_init , self_name , modname ):
452456 # fields contains both real fields and InitVar pseudo-fields.
453457
454458 # 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):
466470 raise TypeError (f'non-default argument { f .name !r} '
467471 'follows default argument' )
468472
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+ })
471481
472482 body_lines = []
473483 for f in fields :
474- line = _field_init (f , frozen , globals , self_name )
484+ line = _field_init (f , frozen , locals , self_name )
475485 # line is None means that this field doesn't require
476486 # initialization (it's a pseudo-field). Just skip it.
477487 if line :
@@ -487,7 +497,6 @@ def _init_fn(fields, frozen, has_post_init, self_name):
487497 if not body_lines :
488498 body_lines = ['pass' ]
489499
490- locals = {f'_type_{ f .name } ' : f .type for f in fields }
491500 return _create_fn ('__init__' ,
492501 [self_name ] + [_init_param (f ) for f in fields if f .init ],
493502 body_lines ,
@@ -877,6 +886,7 @@ def _process_class(cls, init, repr, eq, order, unsafe_hash, frozen):
877886 # if possible.
878887 '__dataclass_self__' if 'self' in fields
879888 else 'self' ,
889+ cls .__module__
880890 ))
881891
882892 # Get the fields as a list, and include only real fields. This is
0 commit comments