diff --git a/python/helpers/generator3.py b/python/helpers/generator3.py index 34870b7a8f0b..0eb5ad7835b4 100644 --- a/python/helpers/generator3.py +++ b/python/helpers/generator3.py @@ -1692,6 +1692,23 @@ class ModuleRedeclarator(object): out(0, "# from file " + self.module.__file__) self.outDocAttr(out, self.module, 0) + + def redoImports(self): + module_type = type(sys) + for item_name in self.module.__dict__.keys(): + try: + item = self.module.__dict__[item_name] + except: + continue + if isinstance(item, module_type): + self.imported_modules[item_name] = item + self.addImportHeaderIfNeeded() + ref_notice = getattr(item, "__file__", str(item)) + if hasattr(item, "__name__"): + self.imports_buf.out(0, "import ", item.__name__, " as ", item_name, " # ", ref_notice) + else: + self.imports_buf.out(0, item_name, " = None # ??? name unknown; ", ref_notice) + def addImportHeaderIfNeeded(self): if self.imports_buf.isEmpty(): self.imports_buf.out(0, "") @@ -1703,9 +1720,15 @@ class ModuleRedeclarator(object): Intended for built-in modules and thus does not handle import statements. @param p_name name of module """ - action("redong module %r", p_name) + action("redoing module %r %r", p_name, str(self.module)) self.redoSimpleHeader(p_name) + # find whatever other self.imported_modules the module knows; effectively these are imports + try: + self.redoImports() + except: + pass + module_type = type(sys) for item_name, item in self.module.__dict__.items(): if type(item) is module_type: # not isinstance, py2.7 + PyQt4.QtCore on windows have a bug here @@ -2084,7 +2107,10 @@ if __name__ == "__main__": try: __import__(name) # sys.modules will fill up with what we want except ImportError: - report("Name %r failed to import", name) + exctype, value = sys.exc_info()[:2] + report("Name %r failed to import: %r", name, str(value)) + if debug_mode: + sys.exit(1) continue if my_finder: diff --git a/python/src/com/jetbrains/python/psi/impl/PyBuiltinCache.java b/python/src/com/jetbrains/python/psi/impl/PyBuiltinCache.java index 3b39bfd5cd0a..8d487ffea4ea 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyBuiltinCache.java +++ b/python/src/com/jetbrains/python/psi/impl/PyBuiltinCache.java @@ -75,7 +75,7 @@ public class PyBuiltinCache { sdk = PythonSdkType.findPythonSdk(module); } else { - final VirtualFile vfile = psifile.getVirtualFile(); + final VirtualFile vfile = psifile instanceof PsiFile ? ((PsiFile) psifile).getOriginalFile().getVirtualFile() : psifile.getVirtualFile(); if (vfile != null) { // reality final ProjectRootManager projectRootManager = ProjectRootManager.getInstance(project); sdk = projectRootManager.getProjectSdk(); diff --git a/python/src/com/jetbrains/python/psi/resolve/ResolveImportUtil.java b/python/src/com/jetbrains/python/psi/resolve/ResolveImportUtil.java index 0113fd88def7..d6faa25e90aa 100644 --- a/python/src/com/jetbrains/python/psi/resolve/ResolveImportUtil.java +++ b/python/src/com/jetbrains/python/psi/resolve/ResolveImportUtil.java @@ -2,7 +2,6 @@ package com.jetbrains.python.psi.resolve; import com.google.common.collect.Sets; import com.intellij.facet.FacetManager; -import com.intellij.facet.ProjectFacetManager; import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModuleUtil; @@ -229,17 +228,7 @@ public class ResolveImportUtil { } List found_in_roots = resolveModulesInRoots(qualifiedName, source_file); if (found_in_roots.size() > 0) return found_in_roots; - // resolve the name considering every source root as a package dir, as if it's a deployed package. django console does so. - boolean has_djando_facet = false; - final Module source_module = ModuleUtil.findModuleForPsiElement(source_file); - if (source_module != null) { - has_djando_facet = FacetManager.getInstance(source_module).getFacetByType(DjangoFacetType.ID) != null; - } - if (has_djando_facet) { - ResolveInRootVisitor visitor = new ResolveInRootAsTopPackageVisitor(qualifiedName, source_file.getManager(), source_file, true); - visitRoots(source_file, visitor); - return visitor.results; - } + return Collections.emptyList(); } } @@ -274,7 +263,7 @@ public class ResolveImportUtil { } @Nullable - public static PsiElement resolveModuleInRoots(@NotNull PyQualifiedName moduleQualifiedName, PsiElement foothold) { + public static PsiElement resolveModuleInRoots(@NotNull PyQualifiedName moduleQualifiedName, @Nullable PsiElement foothold) { final List candidates = resolveModulesInRoots(moduleQualifiedName, foothold); return candidates.isEmpty() ? null : candidates.get(0); } @@ -287,7 +276,7 @@ public class ResolveImportUtil { * @return the list of matching directories or files, or an empty list if nothing was found */ @NotNull - public static List resolveModulesInRoots(@NotNull PyQualifiedName moduleQualifiedName, PsiElement foothold) { + public static List resolveModulesInRoots(@NotNull PyQualifiedName moduleQualifiedName, @Nullable PsiElement foothold) { if (foothold == null || !foothold.isValid()) return Collections.emptyList(); PsiFile footholdFile = foothold.getContainingFile(); if (footholdFile == null || !footholdFile.isValid()) return Collections.emptyList(); @@ -299,11 +288,31 @@ public class ResolveImportUtil { return cachedResults; } } - ResolveInRootVisitor visitor = new ResolveInRootVisitor(moduleQualifiedName, foothold.getManager(), footholdFile, true); - visitRoots(foothold, visitor); + + List results = visitRoots(moduleQualifiedName, foothold); + if (cache != null) { - cache.put(moduleQualifiedName, visitor.results); + cache.put(moduleQualifiedName, results); } + return results; + } + + private static List visitRoots(@NotNull PyQualifiedName moduleQualifiedName, @NotNull PsiElement foothold) { + PsiFile footholdFile = foothold.getContainingFile(); + // resolve the name considering every source root as a package dir, as if it's a deployed package. django console does so. + boolean has_djando_facet = false; + final Module source_module = ModuleUtil.findModuleForPsiElement(foothold); + if (source_module != null) { + has_djando_facet = FacetManager.getInstance(source_module).getFacetByType(DjangoFacetType.ID) != null; + } + ResolveInRootVisitor visitor; + if (has_djando_facet) { + visitor = new ResolveInRootAsTopPackageVisitor(moduleQualifiedName, foothold.getManager(), footholdFile, true); + } + else { + visitor = new ResolveInRootVisitor(moduleQualifiedName, foothold.getManager(), footholdFile, true); + } + visitRoots(foothold, visitor); return visitor.results; } @@ -437,7 +446,7 @@ public class ResolveImportUtil { // no module, another way to look in SDK roots final PsiFile elt_psifile = elt.getContainingFile(); if (elt_psifile != null) { // formality - final VirtualFile elt_vfile = elt_psifile.getVirtualFile(); + final VirtualFile elt_vfile = elt_psifile.getOriginalFile().getVirtualFile(); if (elt_vfile != null) { // reality final ProjectFileIndex fileIndex = ProjectRootManager.getInstance(elt.getProject()).getFileIndex(); final List orderEntries = fileIndex.getOrderEntriesForFile(elt_vfile); @@ -513,7 +522,7 @@ public class ResolveImportUtil { /** * Looks for a name among element's module's roots; if there's no module, then among project's roots. * - * @param context PSI element that defines the module and/or the project. + * @param context PSI element that defines the module and/or the project. * @param refName module name to be found among roots. * @return a PsiFile, a child of a root. */ @@ -559,7 +568,7 @@ public class ResolveImportUtil { static class ResolveInRootVisitor implements RootVisitor { final PsiFile myFootholdFile; - private final boolean myCheckForPackage; + final boolean myCheckForPackage; final @NotNull PyQualifiedName myQualifiedName; final @NotNull PsiManager myPsiManager; final List results = new ArrayList(); @@ -582,17 +591,17 @@ public class ResolveImportUtil { if (module != null) { results.add(module); } + return true; } @Nullable - private PsiElement resolveInRoot(VirtualFile root, - PyQualifiedName qualifiedName, - PsiManager psiManager, - @Nullable PsiFile foothold_file, - boolean checkForPackage) { + protected PsiElement resolveInRoot(VirtualFile root, + PyQualifiedName qualifiedName, + PsiManager psiManager, + @Nullable PsiFile foothold_file, + boolean checkForPackage) { PsiElement module = root.isDirectory() ? psiManager.findDirectory(root) : psiManager.findFile(root); - module = patchModule(module, qualifiedName); if (module == null) return null; for (String component : qualifiedName.getComponents()) { if (component == null) { @@ -603,18 +612,6 @@ public class ResolveImportUtil { } return module; } - - /** - * @param root_module file or dir representing a module's root. - * @param name what we try to resolve - * @return altered parent module; this implementation returns root_module unmodified. - */ - @Nullable - @SuppressWarnings({"MethodMayBeStatic"}) - protected PsiElement patchModule(PsiElement root_module, PyQualifiedName name) { - return root_module; - } - } /** @@ -629,13 +626,24 @@ public class ResolveImportUtil { super(qName, psiManager, foothold_file, checkForPackage); } - @Nullable @Override - protected PsiElement patchModule(PsiElement root_module, PyQualifiedName name) { - if (name.matchesPrefix(PyQualifiedName.fromDottedString(((PsiNamedElement)root_module).getName()))) { - return root_module.getParent(); + public boolean visitRoot(VirtualFile root) { + if (!root.isValid()) { + return true; } - return null; + PsiElement module = resolveInRoot(root, myQualifiedName, myPsiManager, myFootholdFile, myCheckForPackage); + if (module != null) { + results.add(module); + } + + if (myQualifiedName.matchesPrefix(PyQualifiedName.fromDottedString(root.getName()))) { + module = resolveInRoot(root.getParent(), myQualifiedName, myPsiManager, myFootholdFile, myCheckForPackage); + if (module != null) { + results.add(module); + } + } + + return true; } } diff --git a/python/testData/completion/importItself.after.py b/python/testData/completion/importItself.after.py index 17090ac3c5fd..5fc2231a302c 100644 --- a/python/testData/completion/importItself.after.py +++ b/python/testData/completion/importItself.after.py @@ -1 +1 @@ -from package1.submodule2 \ No newline at end of file +from package1.submodule2 import \ No newline at end of file