@@ -63,37 +63,63 @@ def initpkg(pkgname, exportdefs, attr=None, eager=False):
63
63
attr = attr or {}
64
64
mod = sys .modules .get (pkgname )
65
65
66
- # In Python 2 we can't update __class__ for an instance of types.Module, and
67
- # imports are protected by the global import lock anyway, so it is safe for a
68
- # module to replace itself during import. Python 3.3+ uses finer grained locking
69
- # for imports, and checks sys.modules before acquiring the lock to avoid the
70
- # overhead of the fine-grained locking. This introduces a race condition when a
71
- # module is imported by multiple threads concurrently - some threads will see the
72
- # initial module and some the replacement ApiModule. We avoid this by updating the
73
- # existing module in-place.
74
66
if _PY2 :
75
- d = {}
76
- f = getattr (mod , "__file__" , None )
77
- if f :
78
- f = _py_abspath (f )
79
- d ["__file__" ] = f
80
- if hasattr (mod , "__version__" ):
81
- d ["__version__" ] = mod .__version__
82
- if hasattr (mod , "__loader__" ):
83
- d ["__loader__" ] = mod .__loader__
84
- if hasattr (mod , "__path__" ):
85
- d ["__path__" ] = [_py_abspath (p ) for p in mod .__path__ ]
86
- if hasattr (mod , "__package__" ):
87
- d ["__package__" ] = mod .__package__
88
- if "__doc__" not in exportdefs and getattr (mod , "__doc__" , None ):
89
- d ["__doc__" ] = mod .__doc__
90
- d ["__spec__" ] = getattr (mod , "__spec__" , None )
91
- d .update (attr )
92
- if hasattr (mod , "__dict__" ):
93
- mod .__dict__ .update (d )
94
- mod = ApiModule (pkgname , exportdefs , implprefix = pkgname , attr = d )
95
- sys .modules [pkgname ] = mod
96
- elif mod is None :
67
+ mod = _initpkg_py2 (mod , pkgname , exportdefs , attr = attr )
68
+ else :
69
+ mod = _initpkg_py3 (mod , pkgname , exportdefs , attr = attr )
70
+
71
+ # eagerload in bypthon to avoid their monkeypatching breaking packages
72
+ if "bpython" in sys .modules or eager :
73
+ for module in list (sys .modules .values ()):
74
+ if isinstance (module , ApiModule ):
75
+ module .__dict__
76
+
77
+ return mod
78
+
79
+
80
+ def _initpkg_py2 (mod , pkgname , exportdefs , attr = None ):
81
+ """Python 2 helper for initpkg.
82
+
83
+ In Python 2 we can't update __class__ for an instance of types.Module, and
84
+ imports are protected by the global import lock anyway, so it is safe for a
85
+ module to replace itself during import.
86
+
87
+ """
88
+ d = {}
89
+ f = getattr (mod , "__file__" , None )
90
+ if f :
91
+ f = _py_abspath (f )
92
+ d ["__file__" ] = f
93
+ if hasattr (mod , "__version__" ):
94
+ d ["__version__" ] = mod .__version__
95
+ if hasattr (mod , "__loader__" ):
96
+ d ["__loader__" ] = mod .__loader__
97
+ if hasattr (mod , "__path__" ):
98
+ d ["__path__" ] = [_py_abspath (p ) for p in mod .__path__ ]
99
+ if hasattr (mod , "__package__" ):
100
+ d ["__package__" ] = mod .__package__
101
+ if "__doc__" not in exportdefs and getattr (mod , "__doc__" , None ):
102
+ d ["__doc__" ] = mod .__doc__
103
+ d ["__spec__" ] = getattr (mod , "__spec__" , None )
104
+ d .update (attr )
105
+ if hasattr (mod , "__dict__" ):
106
+ mod .__dict__ .update (d )
107
+ mod = ApiModule (pkgname , exportdefs , implprefix = pkgname , attr = d )
108
+ sys .modules [pkgname ] = mod
109
+ return mod
110
+
111
+
112
+ def _initpkg_py3 (mod , pkgname , exportdefs , attr = None ):
113
+ """Python 3 helper for initpkg.
114
+
115
+ Python 3.3+ uses finer grained locking for imports, and checks sys.modules before
116
+ acquiring the lock to avoid the overhead of the fine-grained locking. This
117
+ introduces a race condition when a module is imported by multiple threads
118
+ concurrently - some threads will see the initial module and some the replacement
119
+ ApiModule. We avoid this by updating the existing module in-place.
120
+
121
+ """
122
+ if mod is None :
97
123
d = {"__file__" : None , "__spec__" : None }
98
124
d .update (attr )
99
125
mod = ApiModule (pkgname , exportdefs , implprefix = pkgname , attr = d )
@@ -114,13 +140,6 @@ def initpkg(pkgname, exportdefs, attr=None, eager=False):
114
140
# Updating class of existing module as per importlib.util.LazyLoader
115
141
mod .__class__ = ApiModule
116
142
mod .__init__ (pkgname , exportdefs , implprefix = pkgname , attr = attr )
117
-
118
- # eagerload in bypthon to avoid their monkeypatching breaking packages
119
- if "bpython" in sys .modules or eager :
120
- for module in list (sys .modules .values ()):
121
- if isinstance (module , ApiModule ):
122
- module .__dict__
123
-
124
143
return mod
125
144
126
145
0 commit comments