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;
}
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());
}
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;
}
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));
}
Aggregations