mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
don't access remote packages synchronously from inspections
This commit is contained in:
@@ -11,6 +11,12 @@ public abstract class PyPackageManager {
|
||||
return PyPackageManagers.getInstance().forSdk(sdk);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if pip is installed for the specific interpreter; returns false if pip is not
|
||||
* installed or if it is not currently known whether it's installed (e.g. for a remote interpreter).
|
||||
*
|
||||
* @return true if pip is known to be installed, false otherwise.
|
||||
*/
|
||||
public abstract boolean hasPip();
|
||||
public abstract void install(String requirementString) throws PyExternalProcessException;
|
||||
public abstract void showInstallationError(Project project, String title, String description);
|
||||
|
||||
@@ -169,6 +169,7 @@ public class PyPackageRequirementsInspection extends PyInspection {
|
||||
if (sdk != null) {
|
||||
requirements = getTransitiveRequirements(sdk, requirements, new HashSet<PyPackage>());
|
||||
}
|
||||
if (requirements == null) return;
|
||||
for (PyRequirement req : requirements) {
|
||||
if (packageName.equalsIgnoreCase(req.getName())) {
|
||||
return;
|
||||
@@ -202,22 +203,21 @@ public class PyPackageRequirementsInspection extends PyInspection {
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Nullable
|
||||
private static Set<PyRequirement> getTransitiveRequirements(@NotNull Sdk sdk, @NotNull Collection<PyRequirement> requirements,
|
||||
@NotNull Set<PyPackage> visited) {
|
||||
final Set<PyRequirement> results = new HashSet<PyRequirement>(requirements);
|
||||
try {
|
||||
final List<PyPackage> packages = ((PyPackageManagerImpl) PyPackageManager.getInstance(sdk)).getPackages();
|
||||
for (PyRequirement req : requirements) {
|
||||
final PyPackage pkg = req.match(packages);
|
||||
if (pkg != null && !visited.contains(pkg)) {
|
||||
visited.add(pkg);
|
||||
results.addAll(getTransitiveRequirements(sdk, pkg.getRequirements(), visited));
|
||||
}
|
||||
final List<PyPackage> packages = ((PyPackageManagerImpl) PyPackageManager.getInstance(sdk)).getPackagesFast();
|
||||
if (packages == null) return null;
|
||||
for (PyRequirement req : requirements) {
|
||||
final PyPackage pkg = req.match(packages);
|
||||
if (pkg != null && !visited.contains(pkg)) {
|
||||
visited.add(pkg);
|
||||
final Set<PyRequirement> transitive = getTransitiveRequirements(sdk, pkg.getRequirements(), visited);
|
||||
if (transitive == null) return null;
|
||||
results.addAll(transitive);
|
||||
}
|
||||
}
|
||||
catch (PyExternalProcessException ignored) {
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
@@ -237,13 +237,8 @@ public class PyPackageRequirementsInspection extends PyInspection {
|
||||
final PyPackageManagerImpl manager = (PyPackageManagerImpl)PyPackageManager.getInstance(sdk);
|
||||
List<PyRequirement> requirements = PyPackageManagerImpl.getRequirements(module);
|
||||
if (requirements != null) {
|
||||
final List<PyPackage> packages;
|
||||
try {
|
||||
packages = manager.getPackages();
|
||||
}
|
||||
catch (PyExternalProcessException ignored) {
|
||||
return null;
|
||||
}
|
||||
final List<PyPackage> packages = manager.getPackagesFast();
|
||||
if (packages == null) return null;
|
||||
final List<PyRequirement> unsatisfied = new ArrayList<PyRequirement>();
|
||||
for (PyRequirement req : requirements) {
|
||||
if (!ignoredPackages.contains(req.getName()) && req.match(packages) == null) {
|
||||
|
||||
@@ -421,6 +421,28 @@ public class PyPackageManagerImpl extends PyPackageManager {
|
||||
return myPackagesCache != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of packages for the SDK without initiating a remote connection. Returns null
|
||||
* for a remote interpreter if the list of packages was not loaded.
|
||||
*
|
||||
* @return the list of packages or null
|
||||
*/
|
||||
@Nullable
|
||||
public synchronized List<PyPackage> getPackagesFast() {
|
||||
if (myPackagesCache != null) {
|
||||
return myPackagesCache;
|
||||
}
|
||||
if (PySdkUtil.isRemote(mySdk)) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return getPackages();
|
||||
}
|
||||
catch (PyExternalProcessException e) {
|
||||
throw new UnsupportedOperationException("can't have PyExternalProcessException when running tool for local SDK");
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public synchronized List<PyPackage> getPackages() throws PyExternalProcessException {
|
||||
if (myPackagesCache == null) {
|
||||
@@ -428,28 +450,42 @@ public class PyPackageManagerImpl extends PyPackageManager {
|
||||
throw myExceptionCache;
|
||||
}
|
||||
|
||||
try {
|
||||
final String output = runPythonHelper(PACKAGING_TOOL, list("list"));
|
||||
myPackagesCache = parsePackagingToolOutput(output);
|
||||
Collections.sort(myPackagesCache, new Comparator<PyPackage>() {
|
||||
@Override
|
||||
public int compare(PyPackage aPackage, PyPackage aPackage1) {
|
||||
return aPackage.getName().compareTo(aPackage1.getName());
|
||||
}
|
||||
});
|
||||
}
|
||||
catch (PyExternalProcessException e) {
|
||||
myExceptionCache = e;
|
||||
LOG.info("Error loading packages list: " + e.getMessage(), e);
|
||||
throw e;
|
||||
}
|
||||
loadPackages();
|
||||
}
|
||||
return myPackagesCache;
|
||||
}
|
||||
|
||||
public synchronized void loadPackages() throws PyExternalProcessException {
|
||||
try {
|
||||
final String output = runPythonHelper(PACKAGING_TOOL, list("list"));
|
||||
myPackagesCache = parsePackagingToolOutput(output);
|
||||
Collections.sort(myPackagesCache, new Comparator<PyPackage>() {
|
||||
@Override
|
||||
public int compare(PyPackage aPackage, PyPackage aPackage1) {
|
||||
return aPackage.getName().compareTo(aPackage1.getName());
|
||||
}
|
||||
});
|
||||
}
|
||||
catch (PyExternalProcessException e) {
|
||||
myExceptionCache = e;
|
||||
LOG.info("Error loading packages list: " + e.getMessage(), e);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public PyPackage findPackage(String name) throws PyExternalProcessException {
|
||||
for (PyPackage pkg : getPackages()) {
|
||||
return findPackageByName(name, getPackages());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public PyPackage findPackageFast(String name) {
|
||||
final List<PyPackage> packages = getPackagesFast();
|
||||
return packages != null ? findPackageByName(name, packages) : null;
|
||||
}
|
||||
|
||||
private static PyPackage findPackageByName(String name, List<PyPackage> packages) {
|
||||
for (PyPackage pkg : packages) {
|
||||
if (name.equals(pkg.getName())) {
|
||||
return pkg;
|
||||
}
|
||||
@@ -458,12 +494,7 @@ public class PyPackageManagerImpl extends PyPackageManager {
|
||||
}
|
||||
|
||||
public boolean hasPip() {
|
||||
try {
|
||||
return findPackage(PACKAGE_PIP) != null;
|
||||
}
|
||||
catch (PyExternalProcessException e) {
|
||||
return false;
|
||||
}
|
||||
return findPackageFast(PACKAGE_PIP) != null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -24,6 +24,9 @@ import com.intellij.util.SmartList;
|
||||
import com.intellij.util.io.ZipUtil;
|
||||
import com.jetbrains.python.PyBundle;
|
||||
import com.jetbrains.python.PyNames;
|
||||
import com.jetbrains.python.packaging.PyExternalProcessException;
|
||||
import com.jetbrains.python.packaging.PyPackageManager;
|
||||
import com.jetbrains.python.packaging.PyPackageManagerImpl;
|
||||
import com.jetbrains.python.psi.resolve.PythonSdkPathCache;
|
||||
import com.jetbrains.python.remote.PythonRemoteInterpreterManager;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
@@ -283,8 +286,16 @@ public class PySkeletonRefresher {
|
||||
indicate(PyBundle.message("sdk.gen.cleaning.$0", readablePath));
|
||||
cleanUpSkeletons(skeletonsDir);
|
||||
}
|
||||
if (PySdkUtil.isRemote(mySdk)) {
|
||||
try {
|
||||
((PyPackageManagerImpl) PyPackageManager.getInstance(mySdk)).loadPackages();
|
||||
}
|
||||
catch (PyExternalProcessException e) {
|
||||
// ignore - already logged
|
||||
}
|
||||
}
|
||||
|
||||
if (mustUpdateBuiltins && myProject != null) {
|
||||
if ((mustUpdateBuiltins || PySdkUtil.isRemote(mySdk)) && myProject != null) {
|
||||
ApplicationManager.getApplication().invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
@@ -19,6 +19,7 @@ import com.jetbrains.python.PyNames;
|
||||
import com.jetbrains.python.packaging.PyExternalProcessException;
|
||||
import com.jetbrains.python.packaging.PyPackageManager;
|
||||
import com.jetbrains.python.packaging.PyPackageManagerImpl;
|
||||
import com.jetbrains.python.sdk.PySdkUtil;
|
||||
import com.jetbrains.python.sdk.PythonSdkType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@@ -54,6 +55,9 @@ public class VFSTestFrameworkListener implements ApplicationComponent, Persisten
|
||||
if (!containsAt && !containsNose && !containsPy) continue;
|
||||
SDKLOOP:
|
||||
for (Sdk sdk : PythonSdkType.getAllSdks()) {
|
||||
if (PySdkUtil.isRemote(sdk)) {
|
||||
continue;
|
||||
}
|
||||
for (String root : sdk.getRootProvider().getUrls(OrderRootType.CLASSES)) {
|
||||
if (path.contains(root)) {
|
||||
if (containsNose) {
|
||||
@@ -63,7 +67,8 @@ public class VFSTestFrameworkListener implements ApplicationComponent, Persisten
|
||||
else if (containsPy) {
|
||||
updateTestFrameworks(sdk, PyNames.PY_TEST);
|
||||
break SDKLOOP;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
updateTestFrameworks(sdk, PyNames.AT_TEST);
|
||||
break SDKLOOP;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user