Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/jedi/inference/compiled/subprocess/functions.py: 22%
148 statements
« prev ^ index » next coverage.py v7.2.2, created at 2023-03-26 06:07 +0000
« prev ^ index » next coverage.py v7.2.2, created at 2023-03-26 06:07 +0000
1import sys
2import os
3import inspect
4import importlib
5import warnings
6from pathlib import Path
7from zipfile import ZipFile
8from zipimport import zipimporter, ZipImportError
9from importlib.machinery import all_suffixes
11from jedi.inference.compiled import access
12from jedi import debug
13from jedi import parser_utils
14from jedi.file_io import KnownContentFileIO, ZipFileIO
17def get_sys_path():
18 return sys.path
21def load_module(inference_state, **kwargs):
22 return access.load_module(inference_state, **kwargs)
25def get_compiled_method_return(inference_state, id, attribute, *args, **kwargs):
26 handle = inference_state.compiled_subprocess.get_access_handle(id)
27 return getattr(handle.access, attribute)(*args, **kwargs)
30def create_simple_object(inference_state, obj):
31 return access.create_access_path(inference_state, obj)
34def get_module_info(inference_state, sys_path=None, full_name=None, **kwargs):
35 """
36 Returns Tuple[Union[NamespaceInfo, FileIO, None], Optional[bool]]
37 """
38 if sys_path is not None:
39 sys.path, temp = sys_path, sys.path
40 try:
41 return _find_module(full_name=full_name, **kwargs)
42 except ImportError:
43 return None, None
44 finally:
45 if sys_path is not None:
46 sys.path = temp
49def get_builtin_module_names(inference_state):
50 return sys.builtin_module_names
53def _test_raise_error(inference_state, exception_type):
54 """
55 Raise an error to simulate certain problems for unit tests.
56 """
57 raise exception_type
60def _test_print(inference_state, stderr=None, stdout=None):
61 """
62 Force some prints in the subprocesses. This exists for unit tests.
63 """
64 if stderr is not None:
65 print(stderr, file=sys.stderr)
66 sys.stderr.flush()
67 if stdout is not None:
68 print(stdout)
69 sys.stdout.flush()
72def _get_init_path(directory_path):
73 """
74 The __init__ file can be searched in a directory. If found return it, else
75 None.
76 """
77 for suffix in all_suffixes():
78 path = os.path.join(directory_path, '__init__' + suffix)
79 if os.path.exists(path):
80 return path
81 return None
84def safe_literal_eval(inference_state, value):
85 return parser_utils.safe_literal_eval(value)
88def iter_module_names(*args, **kwargs):
89 return list(_iter_module_names(*args, **kwargs))
92def _iter_module_names(inference_state, paths):
93 # Python modules/packages
94 for path in paths:
95 try:
96 dir_entries = ((entry.name, entry.is_dir()) for entry in os.scandir(path))
97 except OSError:
98 try:
99 zip_import_info = zipimporter(path)
100 # Unfortunately, there is no public way to access zipimporter's
101 # private _files member. We therefore have to use a
102 # custom function to iterate over the files.
103 dir_entries = _zip_list_subdirectory(
104 zip_import_info.archive, zip_import_info.prefix)
105 except ZipImportError:
106 # The file might not exist or reading it might lead to an error.
107 debug.warning("Not possible to list directory: %s", path)
108 continue
109 for name, is_dir in dir_entries:
110 # First Namespaces then modules/stubs
111 if is_dir:
112 # pycache is obviously not an interesting namespace. Also the
113 # name must be a valid identifier.
114 if name != '__pycache__' and name.isidentifier():
115 yield name
116 else:
117 if name.endswith('.pyi'): # Stub files
118 modname = name[:-4]
119 else:
120 modname = inspect.getmodulename(name)
122 if modname and '.' not in modname:
123 if modname != '__init__':
124 yield modname
127def _find_module(string, path=None, full_name=None, is_global_search=True):
128 """
129 Provides information about a module.
131 This function isolates the differences in importing libraries introduced with
132 python 3.3 on; it gets a module name and optionally a path. It will return a
133 tuple containin an open file for the module (if not builtin), the filename
134 or the name of the module if it is a builtin one and a boolean indicating
135 if the module is contained in a package.
136 """
137 spec = None
138 loader = None
140 for finder in sys.meta_path:
141 if is_global_search and finder != importlib.machinery.PathFinder:
142 p = None
143 else:
144 p = path
145 try:
146 find_spec = finder.find_spec
147 except AttributeError:
148 # These are old-school clases that still have a different API, just
149 # ignore those.
150 continue
152 spec = find_spec(string, p)
153 if spec is not None:
154 if spec.origin == "frozen":
155 continue
157 loader = spec.loader
159 if loader is None and not spec.has_location:
160 # This is a namespace package.
161 full_name = string if not path else full_name
162 implicit_ns_info = ImplicitNSInfo(full_name, spec.submodule_search_locations._path)
163 return implicit_ns_info, True
164 break
166 return _find_module_py33(string, path, loader)
169def _find_module_py33(string, path=None, loader=None, full_name=None, is_global_search=True):
170 loader = loader or importlib.machinery.PathFinder.find_module(string, path)
172 if loader is None and path is None: # Fallback to find builtins
173 try:
174 with warnings.catch_warnings(record=True):
175 # Mute "DeprecationWarning: Use importlib.util.find_spec()
176 # instead." While we should replace that in the future, it's
177 # probably good to wait until we deprecate Python 3.3, since
178 # it was added in Python 3.4 and find_loader hasn't been
179 # removed in 3.6.
180 loader = importlib.find_loader(string)
181 except ValueError as e:
182 # See #491. Importlib might raise a ValueError, to avoid this, we
183 # just raise an ImportError to fix the issue.
184 raise ImportError("Originally " + repr(e))
186 if loader is None:
187 raise ImportError("Couldn't find a loader for {}".format(string))
189 return _from_loader(loader, string)
192def _from_loader(loader, string):
193 try:
194 is_package_method = loader.is_package
195 except AttributeError:
196 is_package = False
197 else:
198 is_package = is_package_method(string)
199 try:
200 get_filename = loader.get_filename
201 except AttributeError:
202 return None, is_package
203 else:
204 module_path = get_filename(string)
206 # To avoid unicode and read bytes, "overwrite" loader.get_source if
207 # possible.
208 try:
209 f = type(loader).get_source
210 except AttributeError:
211 raise ImportError("get_source was not defined on loader")
213 if f is not importlib.machinery.SourceFileLoader.get_source:
214 # Unfortunately we are reading unicode here, not bytes.
215 # It seems hard to get bytes, because the zip importer
216 # logic just unpacks the zip file and returns a file descriptor
217 # that we cannot as easily access. Therefore we just read it as
218 # a string in the cases where get_source was overwritten.
219 code = loader.get_source(string)
220 else:
221 code = _get_source(loader, string)
223 if code is None:
224 return None, is_package
225 if isinstance(loader, zipimporter):
226 return ZipFileIO(module_path, code, Path(loader.archive)), is_package
228 return KnownContentFileIO(module_path, code), is_package
231def _get_source(loader, fullname):
232 """
233 This method is here as a replacement for SourceLoader.get_source. That
234 method returns unicode, but we prefer bytes.
235 """
236 path = loader.get_filename(fullname)
237 try:
238 return loader.get_data(path)
239 except OSError:
240 raise ImportError('source not available through get_data()',
241 name=fullname)
244def _zip_list_subdirectory(zip_path, zip_subdir_path):
245 zip_file = ZipFile(zip_path)
246 zip_subdir_path = Path(zip_subdir_path)
247 zip_content_file_paths = zip_file.namelist()
248 for raw_file_name in zip_content_file_paths:
249 file_path = Path(raw_file_name)
250 if file_path.parent == zip_subdir_path:
251 file_path = file_path.relative_to(zip_subdir_path)
252 yield file_path.name, raw_file_name.endswith("/")
255class ImplicitNSInfo:
256 """Stores information returned from an implicit namespace spec"""
257 def __init__(self, name, paths):
258 self.name = name
259 self.paths = paths