def _load_module(evaluator, path=None, code=None, sys_path=None, import_names=None, safe_module_name=False): if import_names is None: dotted_name = None else: dotted_name = '.'.join(import_names) try: return evaluator.module_cache.get(dotted_name) except KeyError: pass try: return evaluator.module_cache.get_from_path(path) except KeyError: pass if isinstance(path, ImplicitNSInfo): from jedi.evaluate.context.namespace import ImplicitNamespaceContext module = ImplicitNamespaceContext( evaluator, fullname=path.name, paths=path.paths, ) else: if sys_path is None: sys_path = evaluator.get_sys_path() if path is not None and path.endswith(('.py', '.zip', '.egg')): module_node = evaluator.parse(code=code, path=path, cache=True, diff_cache=settings.fast_parser, cache_path=settings.cache_directory) from jedi.evaluate.context import ModuleContext module = ModuleContext( evaluator, module_node, path=path, code_lines=get_cached_code_lines(evaluator.grammar, path), ) else: assert dotted_name is not None module = compiled.load_module(evaluator, dotted_name=dotted_name, sys_path=sys_path) if module is not None and dotted_name is not None: add_module_to_cache(evaluator, dotted_name, module, safe=safe_module_name) return module
def _load_module(evaluator, path=None, code=None, sys_path=None, module_name=None, safe_module_name=False): try: return evaluator.module_cache.get(module_name) except KeyError: pass try: return evaluator.module_cache.get_from_path(path) except KeyError: pass if isinstance(path, ImplicitNSInfo): from jedi.evaluate.context.namespace import ImplicitNamespaceContext module = ImplicitNamespaceContext( evaluator, fullname=path.name, paths=path.paths, ) else: if sys_path is None: sys_path = evaluator.get_sys_path() dotted_path = path and dotted_from_fs_path(path, sys_path) if path is not None and path.endswith(('.py', '.zip', '.egg')) \ and dotted_path not in settings.auto_import_modules: module_node = evaluator.parse(code=code, path=path, cache=True, diff_cache=True, cache_path=settings.cache_directory) from jedi.evaluate.context import ModuleContext module = ModuleContext(evaluator, module_node, path=path) else: module = compiled.load_module(evaluator, path=path, sys_path=sys_path) add_module(evaluator, module_name, module, safe=safe_module_name) return module
def _do_import(self, import_path, sys_path): """ This method is very similar to importlib's `_gcd_import`. """ import_parts = [ i.value if isinstance(i, tree.Name) else i for i in import_path ] # Handle "magic" Flask extension imports: # ``flask.ext.foo`` is really ``flask_foo`` or ``flaskext.foo``. if len(import_path) > 2 and import_parts[:2] == ['flask', 'ext']: # New style. ipath = ('flask_' + str(import_parts[2]), ) + import_path[3:] modules = self._do_import(ipath, sys_path) if modules: return modules else: # Old style return self._do_import(('flaskext', ) + import_path[2:], sys_path) module_name = '.'.join(import_parts) try: return ContextSet(self._evaluator.modules[module_name]) except KeyError: pass if len(import_path) > 1: # This is a recursive way of importing that works great with # the module cache. bases = self._do_import(import_path[:-1], sys_path) if not bases: return NO_CONTEXTS # We can take the first element, because only the os special # case yields multiple modules, which is not important for # further imports. parent_module = list(bases)[0] # This is a huge exception, we follow a nested import # ``os.path``, because it's a very important one in Python # that is being achieved by messing with ``sys.modules`` in # ``os``. if import_parts == ['os', 'path']: return parent_module.py__getattribute__('path') try: method = parent_module.py__path__ except AttributeError: # The module is not a package. _add_error(self.module_context, import_path[-1]) return NO_CONTEXTS else: paths = method() debug.dbg('search_module %s in paths %s', module_name, paths) for path in paths: # At the moment we are only using one path. So this is # not important to be correct. try: if not isinstance(path, list): path = [path] module_file, module_path, is_pkg = \ find_module(import_parts[-1], path, fullname=module_name) break except ImportError: module_path = None if module_path is None: _add_error(self.module_context, import_path[-1]) return NO_CONTEXTS else: parent_module = None try: debug.dbg('search_module %s in %s', import_parts[-1], self.file_path) # Override the sys.path. It works only good that way. # Injecting the path directly into `find_module` did not work. sys.path, temp = sys_path, sys.path try: module_file, module_path, is_pkg = \ find_module(import_parts[-1], fullname=module_name) finally: sys.path = temp except ImportError: # The module is not a package. _add_error(self.module_context, import_path[-1]) return NO_CONTEXTS code = None if is_pkg: # In this case, we don't have a file yet. Search for the # __init__ file. if module_path.endswith(('.zip', '.egg')): code = module_file.loader.get_source(module_name) else: module_path = get_init_path(module_path) elif module_file: if module_path.endswith(('.zip', '.egg')): # Unfortunately we are reading unicode here already, not byes. # It seems however hard to get bytes, because the zip importer # logic just unpacks the zip file and returns a file descriptor # that we cannot as easily access. Therefore we just read it as # a string. code = module_file.read() else: # Read the code with a binary file, because the binary file # might not be proper unicode. This is handled by the parser # wrapper. with open(module_path, 'rb') as f: code = f.read() module_file.close() if isinstance(module_path, ImplicitNSInfo): from jedi.evaluate.context.namespace import ImplicitNamespaceContext fullname, paths = module_path.name, module_path.paths module = ImplicitNamespaceContext(self._evaluator, fullname=fullname) module.paths = paths elif module_file is None and not module_path.endswith( ('.py', '.zip', '.egg')): module = compiled.load_module(self._evaluator, module_path) else: module = _load_module(self._evaluator, module_path, code, sys_path, parent_module) if module is None: # The file might raise an ImportError e.g. and therefore not be # importable. return NO_CONTEXTS self._evaluator.modules[module_name] = module return ContextSet(module)
def _do_import(self, import_path, sys_path): """ This method is very similar to importlib's `_gcd_import`. """ import_parts = [ force_unicode(i.value if isinstance(i, tree.Name) else i) for i in import_path ] # Handle "magic" Flask extension imports: # ``flask.ext.foo`` is really ``flask_foo`` or ``flaskext.foo``. if len(import_path) > 2 and import_parts[:2] == ['flask', 'ext']: # New style. ipath = ('flask_' + str(import_parts[2]), ) + import_path[3:] modules = self._do_import(ipath, sys_path) if modules: return modules else: # Old style return self._do_import(('flaskext', ) + import_path[2:], sys_path) module_name = '.'.join(import_parts) try: return ContextSet(self._evaluator.modules[module_name]) except KeyError: pass if len(import_path) > 1: # This is a recursive way of importing that works great with # the module cache. bases = self._do_import(import_path[:-1], sys_path) if not bases: return NO_CONTEXTS # We can take the first element, because only the os special # case yields multiple modules, which is not important for # further imports. parent_module = list(bases)[0] # This is a huge exception, we follow a nested import # ``os.path``, because it's a very important one in Python # that is being achieved by messing with ``sys.modules`` in # ``os``. if import_parts == ['os', 'path']: return parent_module.py__getattribute__('path') try: method = parent_module.py__path__ except AttributeError: # The module is not a package. _add_error(self.module_context, import_path[-1]) return NO_CONTEXTS else: paths = method() debug.dbg('search_module %s in paths %s', module_name, paths) for path in paths: # At the moment we are only using one path. So this is # not important to be correct. if not isinstance(path, list): path = [path] code, module_path, is_pkg = self._evaluator.compiled_subprocess.get_module_info( string=import_parts[-1], path=path, full_name=module_name) if module_path is not None: break else: _add_error(self.module_context, import_path[-1]) return NO_CONTEXTS else: parent_module = None debug.dbg('search_module %s in %s', import_parts[-1], self.file_path) # Override the sys.path. It works only good that way. # Injecting the path directly into `find_module` did not work. code, module_path, is_pkg = self._evaluator.compiled_subprocess.get_module_info( string=import_parts[-1], full_name=module_name, sys_path=sys_path, ) if module_path is None: # The module is not a package. _add_error(self.module_context, import_path[-1]) return NO_CONTEXTS if isinstance(module_path, ImplicitNSInfo): from jedi.evaluate.context.namespace import ImplicitNamespaceContext module = ImplicitNamespaceContext( self._evaluator, fullname=module_path.name, paths=module_path.paths, ) elif code is not None or module_path.endswith(('.py', '.zip', '.egg')): module = _load_module(self._evaluator, module_path, code, sys_path, parent_module) else: module = compiled.load_module(self._evaluator, path=module_path, sys_path=sys_path) if module is None: # The file might raise an ImportError e.g. and therefore not be # importable. return NO_CONTEXTS self._evaluator.modules[module_name] = module return ContextSet(module)
def import_module(evaluator, import_names, parent_module_context, sys_path): """ This method is very similar to importlib's `_gcd_import`. """ if import_names[0] in settings.auto_import_modules: module = _load_builtin_module(evaluator, import_names, sys_path) if module is None: return NO_CONTEXTS return ContextSet([module]) module_name = '.'.join(import_names) if parent_module_context is None: # Override the sys.path. It works only good that way. # Injecting the path directly into `find_module` did not work. file_io_or_ns, is_pkg = evaluator.compiled_subprocess.get_module_info( string=import_names[-1], full_name=module_name, sys_path=sys_path, is_global_search=True, ) if is_pkg is None: return NO_CONTEXTS else: try: method = parent_module_context.py__path__ except AttributeError: # The module is not a package. return NO_CONTEXTS else: paths = method() for path in paths: # At the moment we are only using one path. So this is # not important to be correct. if not isinstance(path, list): path = [path] file_io_or_ns, is_pkg = evaluator.compiled_subprocess.get_module_info( string=import_names[-1], path=path, full_name=module_name, is_global_search=False, ) if is_pkg is not None: break else: return NO_CONTEXTS if isinstance(file_io_or_ns, ImplicitNSInfo): from jedi.evaluate.context.namespace import ImplicitNamespaceContext module = ImplicitNamespaceContext( evaluator, fullname=file_io_or_ns.name, paths=file_io_or_ns.paths, ) elif file_io_or_ns is None: module = _load_builtin_module(evaluator, import_names, sys_path) if module is None: return NO_CONTEXTS else: module = _load_python_module( evaluator, file_io_or_ns, sys_path, import_names=import_names, is_package=is_pkg, ) if parent_module_context is None: debug.dbg('global search_module %s: %s', import_names[-1], module) else: debug.dbg('search_module %s in paths %s: %s', module_name, paths, module) return ContextSet([module])