1313
1414import apipkg
1515
16+
17+ PY2 = sys .version_info [0 ] == 2
18+ PY3 = sys .version_info [0 ] == 3
19+
20+
1621#
1722# test support for importing modules
1823#
@@ -270,12 +275,12 @@ def parsenamespace(spec):
270275 return ns
271276
272277
273- def test_initpkg_replaces_sysmodules (monkeypatch ):
278+ def test_initpkg_updates_sysmodules (monkeypatch ):
274279 mod = ModuleType ("hello" )
275280 monkeypatch .setitem (sys .modules , "hello" , mod )
276281 apipkg .initpkg ("hello" , {"x" : "os.path:abspath" })
277282 newmod = sys .modules ["hello" ]
278- assert newmod != mod
283+ assert ( PY2 and newmod != mod ) or ( PY3 and newmod is mod )
279284 assert newmod .x == os .path .abspath
280285
281286
@@ -286,15 +291,17 @@ def test_initpkg_transfers_attrs(monkeypatch):
286291 mod .__loader__ = "loader"
287292 mod .__package__ = "package"
288293 mod .__doc__ = "this is the documentation"
294+ mod .goodbye = "goodbye"
289295 monkeypatch .setitem (sys .modules , "hello" , mod )
290296 apipkg .initpkg ("hello" , {})
291297 newmod = sys .modules ["hello" ]
292- assert newmod != mod
298+ assert ( PY2 and newmod != mod ) or ( PY3 and newmod is mod )
293299 assert newmod .__file__ == os .path .abspath (mod .__file__ )
294300 assert newmod .__version__ == mod .__version__
295301 assert newmod .__loader__ == mod .__loader__
296302 assert newmod .__package__ == mod .__package__
297303 assert newmod .__doc__ == mod .__doc__
304+ assert not hasattr (newmod , "goodbye" )
298305
299306
300307def test_initpkg_nodoc (monkeypatch ):
@@ -312,7 +319,7 @@ def test_initpkg_overwrite_doc(monkeypatch):
312319 monkeypatch .setitem (sys .modules , "hello" , hello )
313320 apipkg .initpkg ("hello" , {"__doc__" : "sys:__doc__" })
314321 newhello = sys .modules ["hello" ]
315- assert newhello != hello
322+ assert ( PY2 and newhello != hello ) or ( PY3 and newhello is hello )
316323 assert newhello .__doc__ == sys .__doc__
317324
318325
@@ -324,7 +331,7 @@ def test_initpkg_not_transfers_not_existing_attrs(monkeypatch):
324331 monkeypatch .setitem (sys .modules , "hello" , mod )
325332 apipkg .initpkg ("hello" , {})
326333 newmod = sys .modules ["hello" ]
327- assert newmod != mod
334+ assert ( PY2 and newmod != mod ) or ( PY3 and newmod is mod )
328335 assert newmod .__file__ == os .path .abspath (mod .__file__ )
329336 assert not hasattr (newmod , "__path__" )
330337 assert not hasattr (newmod , "__package__" ) or mod .__package__ is None
@@ -337,7 +344,7 @@ def test_initpkg_not_changing_jython_paths(monkeypatch):
337344 monkeypatch .setitem (sys .modules , "hello" , mod )
338345 apipkg .initpkg ("hello" , {})
339346 newmod = sys .modules ["hello" ]
340- assert newmod != mod
347+ assert ( PY2 and newmod != mod ) or ( PY3 and newmod is mod )
341348 assert newmod .__file__ .startswith ("__pyclasspath__" )
342349 unchanged , changed = newmod .__path__
343350 assert changed != "ichange"
@@ -565,6 +572,58 @@ def run(self):
565572 assert thread .attr == 42
566573
567574
575+ @pytest .mark .skipif ("threading" not in sys .modules , reason = "requires thread support" )
576+ def test_import_race (tmpdir , monkeypatch ):
577+ pkgdir = tmpdir .mkdir ("importrace" )
578+ pkgdir .join ("__init__.py" ).write (
579+ textwrap .dedent (
580+ """
581+ import time
582+ time.sleep(0.1)
583+ import apipkg
584+ apipkg.initpkg(__name__, exportdefs={
585+ 'attr': '.submod:attr',
586+ },
587+ )
588+ """
589+ )
590+ )
591+ pkgdir .join ("submod.py" ).write (
592+ textwrap .dedent (
593+ """
594+ attr = 43
595+ """
596+ )
597+ )
598+ monkeypatch .syspath_prepend (tmpdir )
599+
600+ class TestThread (threading .Thread ):
601+ def __init__ (self ):
602+ super (TestThread , self ).__init__ ()
603+ self .importrace = None
604+
605+ def run (self ):
606+ import importrace
607+
608+ self .importrace = importrace
609+
610+ threads = [TestThread () for _ in range (8 )]
611+ for thread in threads :
612+ thread .start ()
613+ for thread in threads :
614+ thread .join ()
615+ for thread in threads :
616+ assert isinstance (thread .importrace , apipkg .ApiModule )
617+ assert thread .importrace .attr == 43
618+
619+ import importrace
620+ assert isinstance (importrace , apipkg .ApiModule )
621+ assert importrace .attr == 43
622+
623+ for thread in threads :
624+ assert thread .importrace is importrace
625+
626+
568627def test_bpython_getattr_override (tmpdir , monkeypatch ):
569628 def patchgetattr (self , name ):
570629 raise AttributeError (name )
0 commit comments