Search in sources :

Example 1 with IPythonModuleResolver

use of org.python.pydev.ast.codecompletion.IPythonModuleResolver in project Pydev by fabioz.

the class PythonPathHelper method resolveModule.

/**
 * Resolves an absolute file system location of a module to its name, scoped to the paths in
 * the search locations and in context to a given project.
 *
 * @param absoluteModuleLocation the location of the module. Only for directories, or .py, .pyd,
 *      .dll, .so, .pyo files.
 * @param requireFileToExist if {@code true}, requires the path to exist on the filesystem.
 * @param baseLocations the locations relative to which to resolve the Python module.
 * @param project the project context in which the module resolution is being performed.
 *      Can be {@code null} if resolution should to be done without respect to a project.
 * @return a dot-separated qualified name of the Python module that the file or folder should
 *      represent. E.g.: {@code compiler.ast}.
 */
public String resolveModule(String absoluteModuleLocation, final boolean requireFileToExist, List<String> baseLocations, IProject project) {
    final File file = new File(absoluteModuleLocation);
    boolean fileExists = file.exists();
    if (requireFileToExist && !fileExists) {
        return null;
    }
    final IPath modulePath = Path.fromOSString(FileUtils.getFileAbsolutePath(file));
    // Try to consult each of the resolvers:
    IPythonModuleResolver[] pythonModuleResolvers = getPythonModuleResolvers();
    if (pythonModuleResolvers.length > 0) {
        List<IPath> convertedBasePaths = new ArrayList<>();
        for (String searchPath : baseLocations) {
            convertedBasePaths.add(Path.fromOSString(searchPath));
        }
        for (IPythonModuleResolver resolver : pythonModuleResolvers) {
            String resolved = resolver.resolveModule(project, modulePath, convertedBasePaths);
            if (resolved == null) {
                // The null string represents delegation to the next resolver.
                continue;
            }
            if (resolved.isEmpty()) {
                // The empty string represents resolution failure.
                return null;
            }
            return resolved;
        }
    }
    List<String> alternatives = new ArrayList<String>();
    // go through our pythonpath and check the beginning
    OUT: for (String pathEntry : baseLocations) {
        IPath element = Path.fromOSString(FileUtils.getFileAbsolutePath(pathEntry));
        if (FileUtils.isPrefixOf(element, modulePath)) {
            IPath relative = modulePath.removeFirstSegments(element.segmentCount());
            if (relative.segmentCount() == 0) {
                continue;
            }
            final String name = PythonPathHelper.getValidName(relative.lastSegment());
            if (!isValidModuleLastPart(name)) {
                continue;
            }
            if (relative.segmentCount() > 1) {
                IPath folderPath = relative.removeLastSegments(1);
                int segmentCount = folderPath.segmentCount();
                for (int i = 0; i < segmentCount; i++) {
                    if (!isValidModuleLastPart(folderPath.segment(i))) {
                        continue OUT;
                    }
                }
                String[] segments = relative.segments();
                segments[segments.length - 1] = name;
                alternatives.add(StringUtils.join(".", segments));
            } else {
                alternatives.add(name);
            }
        }
    }
    int size = alternatives.size();
    if (size == 1) {
        return alternatives.get(0);
    }
    if (size == 0) {
        return null;
    }
    // We have multiple alternatives. Get the one with the shortest len (if we have multiple pythonpath entries
    // where one is beneath the other a name may be resolved to multiple names and the correct one is the shortest
    // name).
    String ret = null;
    for (String string : alternatives) {
        if (ret == null) {
            ret = string;
        } else if (string.length() < ret.length()) {
            ret = string;
        }
    }
    return ret;
}
Also used : IPath(org.eclipse.core.runtime.IPath) ArrayList(java.util.ArrayList) IFile(org.eclipse.core.resources.IFile) ZipFile(java.util.zip.ZipFile) File(java.io.File) IPythonModuleResolver(org.python.pydev.ast.codecompletion.IPythonModuleResolver)

Example 2 with IPythonModuleResolver

use of org.python.pydev.ast.codecompletion.IPythonModuleResolver in project Pydev by fabioz.

the class PythonModuleResolverExtensionPointTest method testGetModulesFoundStructureWithResolver.

/**
 * Checks that participants can explicitly curtail the results collected by
 * {@link PythonPathHelper#getModulesFoundStructure(IProject, IProgressMonitor)}.
 */
public void testGetModulesFoundStructureWithResolver() {
    PythonPathHelper helper = new PythonPathHelper();
    boolean isPython3Test = false;
    String path = TestDependent.getCompletePythonLib(true, isPython3Test) + "|" + TestDependent.TEST_PYSRC_TESTING_LOC;
    helper.setPythonPath(path);
    setTestingModuleResolver(new IPythonModuleResolver() {

        @Override
        public String resolveModule(IProject project, IPath moduleLocation, List<IPath> baseLocations) {
            if (moduleLocation.equals(Path.fromOSString("/root/x/y.py"))) {
                return "x.y";
            }
            return null;
        }

        @Override
        public Collection<IPath> findAllModules(IProject project, IProgressMonitor monitor) {
            List<IPath> modules = new ArrayList<>();
            modules.add(Path.fromOSString("/root/x/y.py"));
            return modules;
        }
    });
    ModulesFoundStructure modulesFoundStructure = helper.getModulesFoundStructure(null, null);
    Map<File, String> regularModules = modulesFoundStructure.regularModules;
    assertEquals(1, regularModules.keySet().size());
    assertEquals(new File("/root/x/y.py"), regularModules.keySet().iterator().next());
    assertEquals("x.y", regularModules.values().iterator().next());
}
Also used : ModulesFoundStructure(org.python.pydev.ast.codecompletion.revisited.ModulesFoundStructure) IPath(org.eclipse.core.runtime.IPath) IProject(org.eclipse.core.resources.IProject) PythonPathHelper(org.python.pydev.ast.codecompletion.revisited.PythonPathHelper) IProgressMonitor(org.eclipse.core.runtime.IProgressMonitor) Collection(java.util.Collection) ArrayList(java.util.ArrayList) List(java.util.List) IPythonModuleResolver(org.python.pydev.ast.codecompletion.IPythonModuleResolver) File(java.io.File)

Example 3 with IPythonModuleResolver

use of org.python.pydev.ast.codecompletion.IPythonModuleResolver in project Pydev by fabioz.

the class PythonPathHelper method getModulesFoundStructure.

/**
 * Collects the Python modules.
 * <p>
 * Plugins that extend the {@code org.python.pydev.pydev_python_module_resolver} extension point
 * can extend the behavior of this method.  If no such extension exists, the default behavior
 * is to recursively traverse the directories in the PYTHONPATH.
 *
 * @param project the project scope, can be {@code null} to represent a system-wide collection.
 * @param monitor a project monitor, can be {@code null}.
 * @return a {@link ModulesFoundStructure} containing the encountered modules.
 */
public ModulesFoundStructure getModulesFoundStructure(IProject project, IProgressMonitor monitor) {
    if (monitor == null) {
        monitor = new NullProgressMonitor();
    }
    IPythonModuleResolver[] pythonModuleResolvers = getPythonModuleResolvers();
    if (pythonModuleResolvers.length > 0) {
        List<IPath> searchPaths = this.searchPaths;
        for (IPythonModuleResolver finder : pythonModuleResolvers) {
            Collection<IPath> modulesAndZips = finder.findAllModules(project, monitor);
            if (modulesAndZips == null) {
                continue;
            }
            ModulesFoundStructure modulesFoundStructure = new ModulesFoundStructure();
            for (IPath moduleOrZip : modulesAndZips) {
                File moduleOrZipFile = moduleOrZip.toFile();
                if (FileTypesPreferences.isValidZipFile(moduleOrZip.toOSString())) {
                    ModulesFoundStructure.ZipContents zipContents = getFromZip(moduleOrZipFile, monitor);
                    if (zipContents != null) {
                        modulesFoundStructure.zipContents.add(zipContents);
                    }
                } else {
                    String qualifiedName = finder.resolveModule(project, moduleOrZip, searchPaths);
                    if (qualifiedName != null && !qualifiedName.isEmpty()) {
                        modulesFoundStructure.regularModules.put(moduleOrZipFile, qualifiedName);
                    }
                }
            }
            return modulesFoundStructure;
        }
    }
    // The default behavior is to recursively traverse the directories in the PYTHONPATH to
    // collect all encountered Python modules.
    ModulesFoundStructure ret = new ModulesFoundStructure();
    List<String> pythonpathList = getPythonpath();
    FastStringBuffer tempBuf = new FastStringBuffer();
    for (Iterator<String> iter = pythonpathList.iterator(); iter.hasNext(); ) {
        String element = iter.next();
        if (monitor.isCanceled()) {
            break;
        }
        // the slow part is getting the files... not much we can do (I think).
        File root = new File(element);
        PyFileListing below = getModulesBelow(root, monitor, pythonpathList);
        if (below != null) {
            Iterator<PyFileInfo> e1 = below.getFoundPyFileInfos().iterator();
            while (e1.hasNext()) {
                PyFileInfo pyFileInfo = e1.next();
                File file = pyFileInfo.getFile();
                String modName = pyFileInfo.getModuleName(tempBuf);
                if (isValidModuleLastPart(FullRepIterable.getLastPart(modName))) {
                    // Only override if the new name is < than the previous name
                    // (a file may be found multiple times depending on the pythonpath).
                    String existing = ret.regularModules.get(file);
                    if (existing != null) {
                        if (existing.length() < modName.length()) {
                            ret.regularModules.put(file, modName);
                        }
                    } else {
                        ret.regularModules.put(file, modName);
                    }
                }
            }
        } else {
            // ok, it was null, so, maybe this is not a folder, but zip file with java classes...
            ModulesFoundStructure.ZipContents zipContents = getFromZip(root, monitor);
            if (zipContents != null) {
                ret.zipContents.add(zipContents);
            }
        }
    }
    return ret;
}
Also used : NullProgressMonitor(org.eclipse.core.runtime.NullProgressMonitor) IPath(org.eclipse.core.runtime.IPath) FastStringBuffer(org.python.pydev.shared_core.string.FastStringBuffer) PyFileListing(org.python.pydev.ast.listing_utils.PyFileListing) ZipContents(org.python.pydev.ast.codecompletion.revisited.ModulesFoundStructure.ZipContents) PyFileInfo(org.python.pydev.ast.listing_utils.PyFileListing.PyFileInfo) IPythonModuleResolver(org.python.pydev.ast.codecompletion.IPythonModuleResolver) IFile(org.eclipse.core.resources.IFile) ZipFile(java.util.zip.ZipFile) File(java.io.File)

Example 4 with IPythonModuleResolver

use of org.python.pydev.ast.codecompletion.IPythonModuleResolver in project Pydev by fabioz.

the class PythonModuleResolverExtensionPointTest method testResolvePathWithResolver.

/**
 * Checks to see that module resolver extensions can be used in resolveModule().
 */
public void testResolvePathWithResolver() {
    PythonPathHelper helper = new PythonPathHelper();
    boolean isPython3Test = false;
    String path = TestDependent.getCompletePythonLib(true, isPython3Test) + "|" + TestDependent.TEST_PYSRC_TESTING_LOC;
    helper.setPythonPath(path);
    final IPath stubbedModulePath1 = Path.fromOSString(FileUtils.getFileAbsolutePath("/this/is/a/path/to/a/file1.py"));
    final IPath stubbedModulePath2 = Path.fromOSString(FileUtils.getFileAbsolutePath("/this/is/a/path/to/a/file2.py"));
    final IPath stubbedNegativeCase = Path.fromOSString(FileUtils.getFileAbsolutePath("/this/is/a/path/to/another/file.py"));
    setTestingModuleResolver(new IPythonModuleResolver() {

        @Override
        public String resolveModule(IProject project, IPath moduleLocation, List<IPath> baseLocations) {
            if (moduleLocation.equals(stubbedModulePath1)) {
                return "stubbed.library";
            }
            if (moduleLocation.equals(stubbedModulePath2)) {
                return "stubbed.second_library";
            }
            if (moduleLocation.equals(stubbedNegativeCase)) {
                return "";
            }
            // Otherwise, delegate.
            return null;
        }

        @Override
        public Collection<IPath> findAllModules(IProject project, IProgressMonitor monitor) {
            throw new UnsupportedOperationException();
        }
    });
    IProject project = null;
    // Check normal resolution:
    assertEquals("stubbed.library", helper.resolveModule(stubbedModulePath1.toOSString(), project));
    assertEquals("stubbed.second_library", helper.resolveModule(stubbedModulePath2.toOSString(), project));
    // Check to see that delegation also works:
    assertEquals("unittest", helper.resolveModule(TestDependent.PYTHON2_LIB + "unittest.py", project));
    // Check the negative case:
    assertNull(helper.resolveModule(stubbedNegativeCase.toOSString(), project));
}
Also used : IProgressMonitor(org.eclipse.core.runtime.IProgressMonitor) IPath(org.eclipse.core.runtime.IPath) Collection(java.util.Collection) IPythonModuleResolver(org.python.pydev.ast.codecompletion.IPythonModuleResolver) IProject(org.eclipse.core.resources.IProject) PythonPathHelper(org.python.pydev.ast.codecompletion.revisited.PythonPathHelper)

Aggregations

IPath (org.eclipse.core.runtime.IPath)4 IPythonModuleResolver (org.python.pydev.ast.codecompletion.IPythonModuleResolver)4 File (java.io.File)3 ArrayList (java.util.ArrayList)2 Collection (java.util.Collection)2 ZipFile (java.util.zip.ZipFile)2 IFile (org.eclipse.core.resources.IFile)2 IProject (org.eclipse.core.resources.IProject)2 IProgressMonitor (org.eclipse.core.runtime.IProgressMonitor)2 PythonPathHelper (org.python.pydev.ast.codecompletion.revisited.PythonPathHelper)2 List (java.util.List)1 NullProgressMonitor (org.eclipse.core.runtime.NullProgressMonitor)1 ModulesFoundStructure (org.python.pydev.ast.codecompletion.revisited.ModulesFoundStructure)1 ZipContents (org.python.pydev.ast.codecompletion.revisited.ModulesFoundStructure.ZipContents)1 PyFileListing (org.python.pydev.ast.listing_utils.PyFileListing)1 PyFileInfo (org.python.pydev.ast.listing_utils.PyFileListing.PyFileInfo)1 FastStringBuffer (org.python.pydev.shared_core.string.FastStringBuffer)1