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
« 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
10from jedi.inference.compiled import access
11from jedi import debug
12from jedi import parser_utils
13from jedi.file_io import KnownContentFileIO, ZipFileIO
16def get_sys_path():
17 return sys.path
20def load_module(inference_state, **kwargs):
21 return access.load_module(inference_state, **kwargs)
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)
29def create_simple_object(inference_state, obj):
30 return access.create_access_path(inference_state, obj)
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
48def get_builtin_module_names(inference_state):
49 return sys.builtin_module_names
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
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()
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
83def safe_literal_eval(inference_state, value):
84 return parser_utils.safe_literal_eval(value)
87def iter_module_names(*args, **kwargs):
88 return list(_iter_module_names(*args, **kwargs))
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)
121 if modname and '.' not in modname:
122 if modname != '__init__':
123 yield modname
126def _find_module(string, path=None, full_name=None, is_global_search=True):
127 """
128 Provides information about a module.
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
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
151 spec = find_spec(string, p)
152 if spec is not None:
153 if spec.origin == "frozen":
154 continue
156 loader = spec.loader
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
165 return _find_module_py33(string, path, loader)
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
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))
184 if loader is None:
185 raise ImportError("Couldn't find a loader for {}".format(string))
187 return _from_loader(loader, string)
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)
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")
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)
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
226 return KnownContentFileIO(module_path, code), is_package
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)
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("/")
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