Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/jedi/inference/compiled/subprocess/functions.py: 21%

151 statements  

« prev     ^ index     » next       coverage.py v7.4.4, created at 2024-04-20 06:09 +0000

1import sys 

2import os 

3import inspect 

4import importlib 

5from pathlib import Path 

6from zipfile import ZipFile 

7from zipimport import zipimporter, ZipImportError 

8from importlib.machinery import all_suffixes 

9 

10from jedi.inference.compiled import access 

11from jedi import debug 

12from jedi import parser_utils 

13from jedi.file_io import KnownContentFileIO, ZipFileIO 

14 

15 

16def get_sys_path(): 

17 return sys.path 

18 

19 

20def load_module(inference_state, **kwargs): 

21 return access.load_module(inference_state, **kwargs) 

22 

23 

24def get_compiled_method_return(inference_state, id, attribute, *args, **kwargs): 

25 handle = inference_state.compiled_subprocess.get_access_handle(id) 

26 return getattr(handle.access, attribute)(*args, **kwargs) 

27 

28 

29def create_simple_object(inference_state, obj): 

30 return access.create_access_path(inference_state, obj) 

31 

32 

33def get_module_info(inference_state, sys_path=None, full_name=None, **kwargs): 

34 """ 

35 Returns Tuple[Union[NamespaceInfo, FileIO, None], Optional[bool]] 

36 """ 

37 if sys_path is not None: 

38 sys.path, temp = sys_path, sys.path 

39 try: 

40 return _find_module(full_name=full_name, **kwargs) 

41 except ImportError: 

42 return None, None 

43 finally: 

44 if sys_path is not None: 

45 sys.path = temp 

46 

47 

48def get_builtin_module_names(inference_state): 

49 return sys.builtin_module_names 

50 

51 

52def _test_raise_error(inference_state, exception_type): 

53 """ 

54 Raise an error to simulate certain problems for unit tests. 

55 """ 

56 raise exception_type 

57 

58 

59def _test_print(inference_state, stderr=None, stdout=None): 

60 """ 

61 Force some prints in the subprocesses. This exists for unit tests. 

62 """ 

63 if stderr is not None: 

64 print(stderr, file=sys.stderr) 

65 sys.stderr.flush() 

66 if stdout is not None: 

67 print(stdout) 

68 sys.stdout.flush() 

69 

70 

71def _get_init_path(directory_path): 

72 """ 

73 The __init__ file can be searched in a directory. If found return it, else 

74 None. 

75 """ 

76 for suffix in all_suffixes(): 

77 path = os.path.join(directory_path, '__init__' + suffix) 

78 if os.path.exists(path): 

79 return path 

80 return None 

81 

82 

83def safe_literal_eval(inference_state, value): 

84 return parser_utils.safe_literal_eval(value) 

85 

86 

87def iter_module_names(*args, **kwargs): 

88 return list(_iter_module_names(*args, **kwargs)) 

89 

90 

91def _iter_module_names(inference_state, paths): 

92 # Python modules/packages 

93 for path in paths: 

94 try: 

95 dir_entries = ((entry.name, entry.is_dir()) for entry in os.scandir(path)) 

96 except OSError: 

97 try: 

98 zip_import_info = zipimporter(path) 

99 # Unfortunately, there is no public way to access zipimporter's 

100 # private _files member. We therefore have to use a 

101 # custom function to iterate over the files. 

102 dir_entries = _zip_list_subdirectory( 

103 zip_import_info.archive, zip_import_info.prefix) 

104 except ZipImportError: 

105 # The file might not exist or reading it might lead to an error. 

106 debug.warning("Not possible to list directory: %s", path) 

107 continue 

108 for name, is_dir in dir_entries: 

109 # First Namespaces then modules/stubs 

110 if is_dir: 

111 # pycache is obviously not an interesting namespace. Also the 

112 # name must be a valid identifier. 

113 if name != '__pycache__' and name.isidentifier(): 

114 yield name 

115 else: 

116 if name.endswith('.pyi'): # Stub files 

117 modname = name[:-4] 

118 else: 

119 modname = inspect.getmodulename(name) 

120 

121 if modname and '.' not in modname: 

122 if modname != '__init__': 

123 yield modname 

124 

125 

126def _find_module(string, path=None, full_name=None, is_global_search=True): 

127 """ 

128 Provides information about a module. 

129 

130 This function isolates the differences in importing libraries introduced with 

131 python 3.3 on; it gets a module name and optionally a path. It will return a 

132 tuple containin an open file for the module (if not builtin), the filename 

133 or the name of the module if it is a builtin one and a boolean indicating 

134 if the module is contained in a package. 

135 """ 

136 spec = None 

137 loader = None 

138 

139 for finder in sys.meta_path: 

140 if is_global_search and finder != importlib.machinery.PathFinder: 

141 p = None 

142 else: 

143 p = path 

144 try: 

145 find_spec = finder.find_spec 

146 except AttributeError: 

147 # These are old-school clases that still have a different API, just 

148 # ignore those. 

149 continue 

150 

151 spec = find_spec(string, p) 

152 if spec is not None: 

153 if spec.origin == "frozen": 

154 continue 

155 

156 loader = spec.loader 

157 

158 if loader is None and not spec.has_location: 

159 # This is a namespace package. 

160 full_name = string if not path else full_name 

161 implicit_ns_info = ImplicitNSInfo(full_name, spec.submodule_search_locations._path) 

162 return implicit_ns_info, True 

163 break 

164 

165 return _find_module_py33(string, path, loader) 

166 

167 

168def _find_module_py33(string, path=None, loader=None, full_name=None, is_global_search=True): 

169 if not loader: 

170 spec = importlib.machinery.PathFinder.find_spec(string, path) 

171 if spec is not None: 

172 loader = spec.loader 

173 

174 if loader is None and path is None: # Fallback to find builtins 

175 try: 

176 spec = importlib.util.find_spec(string) 

177 if spec is not None: 

178 loader = spec.loader 

179 except ValueError as e: 

180 # See #491. Importlib might raise a ValueError, to avoid this, we 

181 # just raise an ImportError to fix the issue. 

182 raise ImportError("Originally " + repr(e)) 

183 

184 if loader is None: 

185 raise ImportError("Couldn't find a loader for {}".format(string)) 

186 

187 return _from_loader(loader, string) 

188 

189 

190def _from_loader(loader, string): 

191 try: 

192 is_package_method = loader.is_package 

193 except AttributeError: 

194 is_package = False 

195 else: 

196 is_package = is_package_method(string) 

197 try: 

198 get_filename = loader.get_filename 

199 except AttributeError: 

200 return None, is_package 

201 else: 

202 module_path = get_filename(string) 

203 

204 # To avoid unicode and read bytes, "overwrite" loader.get_source if 

205 # possible. 

206 try: 

207 f = type(loader).get_source 

208 except AttributeError: 

209 raise ImportError("get_source was not defined on loader") 

210 

211 if f is not importlib.machinery.SourceFileLoader.get_source: 

212 # Unfortunately we are reading unicode here, not bytes. 

213 # It seems hard to get bytes, because the zip importer 

214 # logic just unpacks the zip file and returns a file descriptor 

215 # that we cannot as easily access. Therefore we just read it as 

216 # a string in the cases where get_source was overwritten. 

217 code = loader.get_source(string) 

218 else: 

219 code = _get_source(loader, string) 

220 

221 if code is None: 

222 return None, is_package 

223 if isinstance(loader, zipimporter): 

224 return ZipFileIO(module_path, code, Path(loader.archive)), is_package 

225 

226 return KnownContentFileIO(module_path, code), is_package 

227 

228 

229def _get_source(loader, fullname): 

230 """ 

231 This method is here as a replacement for SourceLoader.get_source. That 

232 method returns unicode, but we prefer bytes. 

233 """ 

234 path = loader.get_filename(fullname) 

235 try: 

236 return loader.get_data(path) 

237 except OSError: 

238 raise ImportError('source not available through get_data()', 

239 name=fullname) 

240 

241 

242def _zip_list_subdirectory(zip_path, zip_subdir_path): 

243 zip_file = ZipFile(zip_path) 

244 zip_subdir_path = Path(zip_subdir_path) 

245 zip_content_file_paths = zip_file.namelist() 

246 for raw_file_name in zip_content_file_paths: 

247 file_path = Path(raw_file_name) 

248 if file_path.parent == zip_subdir_path: 

249 file_path = file_path.relative_to(zip_subdir_path) 

250 yield file_path.name, raw_file_name.endswith("/") 

251 

252 

253class ImplicitNSInfo: 

254 """Stores information returned from an implicit namespace spec""" 

255 def __init__(self, name, paths): 

256 self.name = name 

257 self.paths = paths