6
6
import imp
7
7
import os
8
8
import re
9
+ import pkgutil
10
+ import warnings
9
11
try :
10
12
import importlib
11
13
except ImportError :
12
14
pass
13
15
16
+ # Cannot use sys.version.major and minor names, because in Python 2.6 it's not
17
+ # a namedtuple.
14
18
is_py3 = sys .version_info [0 ] >= 3
15
- is_py33 = is_py3 and sys .version_info .minor >= 3
19
+ is_py33 = is_py3 and sys .version_info [1 ] >= 3
20
+ is_py34 = is_py3 and sys .version_info [1 ] >= 4
21
+ is_py35 = is_py3 and sys .version_info [1 ] >= 5
16
22
is_py26 = not is_py3 and sys .version_info [1 ] < 7
23
+ py_version = int (str (sys .version_info [0 ]) + str (sys .version_info [1 ]))
17
24
18
25
19
- def find_module_py33 (string , path = None ):
20
- loader = importlib .machinery .PathFinder .find_module (string , path )
26
+ class DummyFile (object ):
27
+ def __init__ (self , loader , string ):
28
+ self .loader = loader
29
+ self .string = string
30
+
31
+ def read (self ):
32
+ return self .loader .get_source (self .string )
33
+
34
+ def close (self ):
35
+ del self .loader
36
+
37
+
38
+ def find_module_py34 (string , path = None , fullname = None ):
39
+ implicit_namespace_pkg = False
40
+ spec = None
41
+ loader = None
42
+
43
+ spec = importlib .machinery .PathFinder .find_spec (string , path )
44
+ if hasattr (spec , 'origin' ):
45
+ origin = spec .origin
46
+ implicit_namespace_pkg = origin == 'namespace'
47
+
48
+ # We try to disambiguate implicit namespace pkgs with non implicit namespace pkgs
49
+ if implicit_namespace_pkg :
50
+ fullname = string if not path else fullname
51
+ implicit_ns_info = ImplicitNSInfo (fullname , spec .submodule_search_locations ._path )
52
+ return None , implicit_ns_info , False
53
+
54
+ # we have found the tail end of the dotted path
55
+ if hasattr (spec , 'loader' ):
56
+ loader = spec .loader
57
+ return find_module_py33 (string , path , loader )
58
+
59
+ def find_module_py33 (string , path = None , loader = None , fullname = None ):
60
+ loader = loader or importlib .machinery .PathFinder .find_module (string , path )
21
61
22
62
if loader is None and path is None : # Fallback to find builtins
23
63
try :
24
- loader = importlib .find_loader (string )
64
+ with warnings .catch_warnings (record = True ):
65
+ # Mute "DeprecationWarning: Use importlib.util.find_spec()
66
+ # instead." While we should replace that in the future, it's
67
+ # probably good to wait until we deprecate Python 3.3, since
68
+ # it was added in Python 3.4 and find_loader hasn't been
69
+ # removed in 3.6.
70
+ loader = importlib .find_loader (string )
25
71
except ValueError as e :
26
72
# See #491. Importlib might raise a ValueError, to avoid this, we
27
73
# just raise an ImportError to fix the issue.
28
- raise ImportError ("Originally ValueError: " + e . message )
74
+ raise ImportError ("Originally " + repr ( e ) )
29
75
30
76
if loader is None :
31
77
raise ImportError ("Couldn't find a loader for {0}" .format (string ))
32
78
33
79
try :
34
80
is_package = loader .is_package (string )
35
81
if is_package :
36
- module_path = os .path .dirname (loader .path )
37
- module_file = None
82
+ if hasattr (loader , 'path' ):
83
+ module_path = os .path .dirname (loader .path )
84
+ else :
85
+ # At least zipimporter does not have path attribute
86
+ module_path = os .path .dirname (loader .get_filename (string ))
87
+ if hasattr (loader , 'archive' ):
88
+ module_file = DummyFile (loader , string )
89
+ else :
90
+ module_file = None
38
91
else :
39
92
module_path = loader .get_filename (string )
40
- module_file = open ( module_path , 'rb' )
93
+ module_file = DummyFile ( loader , string )
41
94
except AttributeError :
42
95
# ExtensionLoader has not attribute get_filename, instead it has a
43
96
# path attribute that we can use to retrieve the module path
44
97
try :
45
98
module_path = loader .path
46
- module_file = open (loader . path , 'rb' )
99
+ module_file = DummyFile (loader , string )
47
100
except AttributeError :
48
101
module_path = string
49
102
module_file = None
50
103
finally :
51
104
is_package = False
52
105
106
+ if hasattr (loader , 'archive' ):
107
+ module_path = loader .archive
108
+
53
109
return module_file , module_path , is_package
54
110
55
111
56
- def find_module_pre_py33 (string , path = None ):
57
- module_file , module_path , description = imp .find_module (string , path )
58
- module_type = description [2 ]
59
- return module_file , module_path , module_type is imp .PKG_DIRECTORY
112
+ def find_module_pre_py33 (string , path = None , fullname = None ):
113
+ try :
114
+ module_file , module_path , description = imp .find_module (string , path )
115
+ module_type = description [2 ]
116
+ return module_file , module_path , module_type is imp .PKG_DIRECTORY
117
+ except ImportError :
118
+ pass
119
+
120
+ if path is None :
121
+ path = sys .path
122
+ for item in path :
123
+ loader = pkgutil .get_importer (item )
124
+ if loader :
125
+ try :
126
+ loader = loader .find_module (string )
127
+ if loader :
128
+ is_package = loader .is_package (string )
129
+ is_archive = hasattr (loader , 'archive' )
130
+ try :
131
+ module_path = loader .get_filename (string )
132
+ except AttributeError :
133
+ # fallback for py26
134
+ try :
135
+ module_path = loader ._get_filename (string )
136
+ except AttributeError :
137
+ continue
138
+ if is_package :
139
+ module_path = os .path .dirname (module_path )
140
+ if is_archive :
141
+ module_path = loader .archive
142
+ file = None
143
+ if not is_package or is_archive :
144
+ file = DummyFile (loader , string )
145
+ return (file , module_path , is_package )
146
+ except ImportError :
147
+ pass
148
+ raise ImportError ("No module named {0}" .format (string ))
60
149
61
150
62
151
find_module = find_module_py33 if is_py33 else find_module_pre_py33
152
+ find_module = find_module_py34 if is_py34 else find_module
63
153
find_module .__doc__ = """
64
154
Provides information about a module.
65
155
@@ -71,28 +161,18 @@ def find_module_pre_py33(string, path=None):
71
161
"""
72
162
73
163
164
+ class ImplicitNSInfo (object ):
165
+ """Stores information returned from an implicit namespace spec"""
166
+ def __init__ (self , name , paths ):
167
+ self .name = name
168
+ self .paths = paths
169
+
74
170
# unicode function
75
171
try :
76
172
unicode = unicode
77
173
except NameError :
78
174
unicode = str
79
175
80
- if is_py3 :
81
- u = lambda s : s
82
- else :
83
- u = lambda s : s .decode ('utf-8' )
84
-
85
- u .__doc__ = """
86
- Decode a raw string into unicode object. Do nothing in Python 3.
87
- """
88
-
89
- # exec function
90
- if is_py3 :
91
- def exec_function (source , global_map ):
92
- exec (source , global_map )
93
- else :
94
- eval (compile ("""def exec_function(source, global_map):
95
- exec source in global_map """ , 'blub' , 'exec' ))
96
176
97
177
# re-raise function
98
178
if is_py3 :
@@ -147,7 +227,8 @@ def u(string):
147
227
"""
148
228
if is_py3 :
149
229
return str (string )
150
- elif not isinstance (string , unicode ):
230
+
231
+ if not isinstance (string , unicode ):
151
232
return unicode (str (string ), 'UTF-8' )
152
233
return string
153
234
@@ -174,6 +255,11 @@ def literal_eval(string):
174
255
except ImportError :
175
256
from itertools import izip_longest as zip_longest # Python 2
176
257
258
+ try :
259
+ FileNotFoundError = FileNotFoundError
260
+ except NameError :
261
+ FileNotFoundError = IOError
262
+
177
263
178
264
def no_unicode_pprint (dct ):
179
265
"""
0 commit comments