11import importlib
22import pickle
3+ import sys
34import threading
5+ import types
46from textwrap import dedent
57import unittest
68
@@ -382,28 +384,25 @@ def test_put_get_full_fallback(self):
382384 self .assertIsNot (obj , obj2 )
383385
384386 def _check_unpickle_attributeerror_arg (self , arg ):
385- # Cross an object through a queue where get() must re-import its
386- # class via a module __getattr__ that raises AttributeError(arg).
387- source = dedent ("""
388- _attrerr_arg = None
389-
390- class Thing:
391- pass
392-
393- def break_module(mod, arg):
394- del mod.Thing
395- mod._attrerr_arg = arg
396- def __getattr__(name):
397- raise AttributeError(mod._attrerr_arg)
398- mod.__getattr__ = __getattr__
399- """ )
400- with import_helper .ready_to_import ('_xi_attrerr' , source ) as (name , _ ):
401- mod = importlib .import_module (name )
402- queue = queues .create ()
403- queue .put (mod .Thing ())
404- mod .break_module (mod , arg )
405- with self .assertRaises (interpreters .NotShareableError ):
406- queue .get ()
387+ # Put an object through a queue where get() must re-import its class
388+ # via a module __getattr__ that raises AttributeError(arg).
389+ modname = '_test_xi_attrerr'
390+ mod = types .ModuleType (modname )
391+ class Thing :
392+ pass
393+ Thing .__module__ = modname
394+ Thing .__qualname__ = 'Thing'
395+ mod .Thing = Thing
396+ sys .modules [modname ] = mod
397+ self .addCleanup (sys .modules .pop , modname , None )
398+ queue = queues .create ()
399+ queue .put (Thing ())
400+ del mod .Thing
401+ def raise_attributeerror (name ):
402+ raise AttributeError (arg )
403+ mod .__getattr__ = raise_attributeerror
404+ with self .assertRaises (interpreters .NotShareableError ):
405+ queue .get ()
407406
408407 def test_get_unpickle_fails_with_bad_attributeerror_arg (self ):
409408 # gh-151862: an AttributeError arg that can't be UTF-8 encoded used
@@ -413,11 +412,10 @@ def test_get_unpickle_fails_with_bad_attributeerror_arg(self):
413412 self ._check_unpickle_attributeerror_arg (arg )
414413
415414 def test_get_unpickle_fails_with_str_attributeerror_arg (self ):
416- # Positive control: a normal str arg (incl. the real missing-__main__
417- # message) must not crash, locking in the non-NULL strncmp() path.
418- for arg in ['boom' , "module '__main__' has no attribute 'Thing'" ]:
419- with self .subTest (arg = arg ):
420- self ._check_unpickle_attributeerror_arg (arg )
415+ # Positive control: a normal str arg must not crash, locking in the
416+ # non-NULL strncmp() path.
417+ with self .subTest (arg = 'boom' ):
418+ self ._check_unpickle_attributeerror_arg ('boom' )
421419
422420 def test_put_get_same_interpreter (self ):
423421 interp = interpreters .create ()
0 commit comments