<lang.documentationProvider language="Python" implementationClass="com.jetbrains.python.documentation.PythonDocumentationProvider"/>
<lang.documentationProvider language="Python" implementationClass="com.jetbrains.python.console.PydevDocumentationProvider"/>
<lang.emacs language="Python" implementationClass="com.jetbrains.python.editor.PyEmacsHandler"/>
+ <highlightRangeExtension implementation="com.jetbrains.python.validation.DumbAwareHighlightingAnnotator"/>
<annotator language="Python" implementationClass="com.jetbrains.python.validation.PyAnnotatingVisitor"/>
<annotator language="Python" implementationClass="com.jetbrains.python.validation.PyDumbAwareAnnotator"/>
<quoteHandler fileType="Python" className="com.jetbrains.python.editor.PythonQuoteHandler"/>
<applicationService serviceInterface="com.jetbrains.python.packaging.PyPackageService"
serviceImplementation="com.jetbrains.python.packaging.PyPackageService"/>
+ <applicationService serviceInterface="com.jetbrains.python.packaging.PyCondaPackageService"
+ serviceImplementation="com.jetbrains.python.packaging.PyCondaPackageService"/>
<applicationService serviceInterface="com.jetbrains.python.module.PyModuleService"
serviceImplementation="com.jetbrains.python.module.PyModuleServiceImpl"/>
<search.optionContributor implementation="com.jetbrains.python.configuration.PySearchableOptionContributor"/>
<moduleService serviceInterface="com.jetbrains.python.documentation.PyDocumentationSettings"
serviceImplementation="com.jetbrains.python.documentation.PyDocumentationSettings"/>
- <psi.referenceContributor implementation="com.jetbrains.python.documentation.DocStringReferenceContributor"/>
- <completion.contributor language="Python" implementationClass="com.jetbrains.python.documentation.DocStringTagCompletionContributor"/>
+ <psi.referenceContributor implementation="com.jetbrains.python.documentation.docstrings.DocStringReferenceContributor"/>
+ <completion.contributor language="Python" implementationClass="com.jetbrains.python.documentation.docstrings.DocStringTagCompletionContributor"/>
+ <completion.contributor language="Python" implementationClass="com.jetbrains.python.documentation.docstrings.DocStringSectionHeaderCompletionContributor"/>
<projectService serviceInterface="com.intellij.psi.search.ProjectScopeBuilder"
serviceImplementation="com.jetbrains.python.psi.search.PyProjectScopeBuilder"
<additionalTextAttributes scheme="Darcula" file="colorSchemes/PythonDarcula.xml"/>
<postStartupActivity implementation="com.jetbrains.python.sdk.PythonSdkUpdater"/>
- <postStartupActivity implementation="com.jetbrains.python.packaging.PyPIPackagesUpdater"/>
- <postStartupActivity implementation="com.jetbrains.python.testing.PyTestRunnerUpdater"/>
+ <postStartupActivity implementation="com.jetbrains.python.packaging.PyPackagesUpdater"/>
+ <directoryProjectConfigurator implementation="com.jetbrains.python.testing.PyIntegratedToolsProjectConfigurator" id="integratedTools" order="after sdk"/>
+
<macro implementation="com.jetbrains.python.sdk.InterpreterDirectoryMacro"/>
<!-- typing -->
<multiHostInjector implementation="com.jetbrains.python.codeInsight.PyTypingAnnotationInjector"/>
+ <lang.parserDefinition language="PythonStub" implementationClass="com.jetbrains.python.pyi.PyiParserDefinition"/>
+ <fileTypeFactory implementation="com.jetbrains.python.pyi.PyiFileTypeFactory"/>
+ <codeInsight.lineMarkerProvider language="Python" implementationClass="com.jetbrains.python.pyi.PyiRelatedItemLineMarkerProvider"/>
<lang.inspectionSuppressor language="Python" implementationClass="com.jetbrains.python.inspections.PyInspectionsSuppressor"/>
<refactoring.invertBoolean implementation="com.jetbrains.python.refactoring.invertBoolean.PyInvertBooleanDelegate"/>
<extensionPoint qualifiedName="Pythonid.runConfigurationExtension" interface="com.jetbrains.python.run.PythonRunConfigurationExtension"/>
<extensionPoint qualifiedName="Pythonid.visitorFilter" beanClass="com.intellij.lang.LanguageExtensionPoint"/>
<extensionPoint qualifiedName="Pythonid.remoteInterpreterManager" interface="com.jetbrains.python.remote.PythonRemoteInterpreterManager"/>
+ <extensionPoint qualifiedName="Pythonid.remoteProcessStarterManager" interface="com.jetbrains.python.run.PyRemoteProcessStarterManager"/>
<extensionPoint qualifiedName="Pythonid.keywordArgumentProvider" interface="com.jetbrains.python.psi.impl.PyKeywordArgumentProvider"/>
<extensionPoint qualifiedName="Pythonid.canonicalPathProvider" interface="com.jetbrains.python.psi.resolve.PyCanonicalPathProvider"/>
<extensionPoint qualifiedName="Pythonid.templateContextProvider" interface="com.jetbrains.python.templateLanguages.TemplateContextProvider"/>
<dumbAnnotator implementation="com.jetbrains.python.validation.GeneratorInArgumentListAnnotator"/>
<dumbAnnotator implementation="com.jetbrains.python.validation.StarAnnotator"/>
<dumbAnnotator implementation="com.jetbrains.python.validation.StringLiteralQuotesAnnotator"/>
+ <dumbAnnotator implementation="com.jetbrains.python.validation.DumbAwareHighlightingAnnotator"/>
<customTargetExpressionStubType implementation="com.jetbrains.python.psi.impl.stubs.PropertyStubType"/>
<dialectsTokenSetContributor implementation="com.jetbrains.python.PythonTokenSetContributor"/>
<!-- typing -->
<typeProvider implementation="com.jetbrains.python.codeInsight.PyTypingTypeProvider"/>
+ <typeProvider implementation="com.jetbrains.python.pyi.PyiTypeProvider"/>
+ <pyModuleMembersProvider implementation="com.jetbrains.python.pyi.PyiModuleMembersProvider"/>
+ <pyClassMembersProvider implementation="com.jetbrains.python.pyi.PyiClassMembersProvider"/>
+ <visitorFilter language="PythonStub" implementationClass="com.jetbrains.python.pyi.PyiVisitorFilter"/>
<typeProvider implementation="com.jetbrains.python.debugger.PyCallSignatureTypeProvider"/>
<pyReferenceResolveProvider implementation="com.jetbrains.python.psi.resolve.PythonBuiltinReferenceResolveProvider"/>
package com.jetbrains.python.sdk;
import com.google.common.collect.ImmutableMap;
+ import com.google.common.collect.Lists;
import com.intellij.execution.ExecutionException;
import com.intellij.execution.configurations.GeneralCommandLine;
import com.intellij.execution.process.ProcessOutput;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationManager;
+ import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.fileChooser.FileChooserDescriptor;
import com.intellij.openapi.roots.ModuleRootManager;
import com.intellij.openapi.roots.OrderRootType;
import com.intellij.openapi.ui.Messages;
- import com.intellij.openapi.util.Comparing;
- import com.intellij.openapi.util.Key;
- import com.intellij.openapi.util.Ref;
- import com.intellij.openapi.util.SystemInfo;
+ import com.intellij.openapi.util.*;
import com.intellij.openapi.util.io.FileSystemUtil;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.CharFilter;
import com.intellij.util.ArrayUtil;
import com.intellij.util.Consumer;
import com.intellij.util.NullableConsumer;
+ import com.intellij.util.ui.UIUtil;
import com.jetbrains.python.PyBundle;
import com.jetbrains.python.PyNames;
import com.jetbrains.python.PythonFileType;
- import com.jetbrains.python.PythonHelpersLocator;
+ import com.jetbrains.python.PythonHelper;
import com.jetbrains.python.codeInsight.userSkeletons.PyUserSkeletonsUtil;
import com.jetbrains.python.facet.PythonFacetSettings;
+ import com.jetbrains.python.packaging.PyCondaPackageManagerImpl;
import com.jetbrains.python.psi.LanguageLevel;
import com.jetbrains.python.psi.impl.PyBuiltinCache;
import com.jetbrains.python.psi.search.PyProjectScopeBuilder;
public static boolean isVagrant(@Nullable Sdk sdk) {
if (sdk != null && sdk.getSdkAdditionalData() instanceof PyRemoteSdkAdditionalDataBase) {
- PyRemoteSdkAdditionalDataBase data = (PyRemoteSdkAdditionalDataBase) sdk.getSdkAdditionalData();
+ PyRemoteSdkAdditionalDataBase data = (PyRemoteSdkAdditionalDataBase)sdk.getSdkAdditionalData();
return data.getRemoteConnectionType() == CredentialsType.VAGRANT;
}
return path != null && getVirtualEnvRoot(path) != null;
}
+ public static boolean isCondaVirtualEnv(Sdk sdk) {
+ final String path = sdk.getHomePath();
+ return path != null && PyCondaPackageManagerImpl.isCondaVEnv(sdk);
+ }
+
@Nullable
public Sdk getVirtualEnvBaseSdk(Sdk sdk) {
if (isVirtualEnv(sdk)) {
return PythonSdkAdditionalData.load(currentSdk, additional);
}
- @Nullable
- public static String findSkeletonsPath(Sdk sdk) {
- final String[] urls = sdk.getRootProvider().getUrls(BUILTIN_ROOT_TYPE);
- for (String url : urls) {
- if (isSkeletonsPath(url)) {
- return VfsUtilCore.urlToPath(url);
- }
- }
- return null;
- }
-
public static boolean isSkeletonsPath(String path) {
return path.contains(SKELETON_DIR_NAME);
}
return true; // run setupSdkPaths only once (from PythonSdkDetailsStep). Skip this from showCustomCreateUI
}
- public static void setupSdkPaths(Sdk sdk, @Nullable Project project, @Nullable Component ownerComponent) {
- final SdkModificator sdkModificator = sdk.getSdkModificator();
- final boolean success = setupSdkPaths(project, ownerComponent, sdk, sdkModificator);
- if (success) {
- sdkModificator.commitChanges();
- }
- else {
- Messages.showErrorDialog(
- project,
- PyBundle.message("MSG.cant.setup.sdk.$0", FileUtil.toSystemDependentName(sdk.getSdkModificator().getHomePath())),
- PyBundle.message("MSG.title.bad.sdk")
- );
- }
+ public static void setupSdkPaths(@NotNull final Sdk sdk,
+ @Nullable final Project project,
+ @Nullable final Component ownerComponent,
+ @NotNull final SdkModificator sdkModificator) {
+ doSetupSdkPaths(project, ownerComponent, PySdkUpdater.fromSdkModificator(sdk, sdkModificator));
}
- public static boolean setupSdkPaths(@Nullable final Project project,
- @Nullable final Component ownerComponent,
- @NotNull final Sdk sdk,
- @NotNull final SdkModificator sdkModificator) {
- if (isRemote(sdk) && project == null && ownerComponent == null) {
+
+ public static void setupSdkPaths(final Sdk sdk, @Nullable final Project project, @Nullable final Component ownerComponent) {
+ ApplicationManager.getApplication().invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ final boolean success = doSetupSdkPaths(project, ownerComponent, PySdkUpdater.fromSdkPath(sdk.getHomePath()));
+
+ if (!success) {
+ Messages.showErrorDialog(
+ project,
+ PyBundle.message("MSG.cant.setup.sdk.$0", FileUtil.toSystemDependentName(sdk.getSdkModificator().getHomePath())),
+ PyBundle.message("MSG.title.bad.sdk")
+ );
+ }
+ }
+ catch (PySdkUpdater.PySdkNotFoundException e) {
+ // sdk was removed from sdk table so no need to setup paths
+ }
+ }
+ }, ModalityState.NON_MODAL);
+ }
+
+ private static boolean doSetupSdkPaths(@Nullable final Project project,
+ @Nullable final Component ownerComponent,
+ @NotNull final PySdkUpdater sdkUpdater) {
+ if (isRemote(sdkUpdater.getSdk()) && project == null && ownerComponent == null) {
LOG.error("For refreshing skeletons of remote SDK, either project or owner component must be specified");
}
final ProgressManager progressManager = ProgressManager.getInstance();
- final Ref<Boolean> sdkPathsUpdatedRef = new Ref<Boolean>(false);
- final Task.Modal setupTask = new Task.Modal(project, "Setting up library files for " + sdk.getName(), false) {
- public void run(@NotNull final ProgressIndicator indicator) {
- sdkModificator.removeAllRoots();
- try {
- updateSdkRootsFromSysPath(sdk, sdkModificator, indicator);
- updateUserAddedPaths(sdk, sdkModificator, indicator);
- PythonSdkUpdater.getInstance().markAlreadyUpdated(sdk.getHomePath());
- sdkPathsUpdatedRef.set(true);
- }
- catch (InvalidSdkException ignored) {
+ boolean sdkPathsUpdated = UIUtil.<Boolean>invokeAndWaitIfNeeded(
+ new Computable<Boolean>() {
+ @Override
+ public Boolean compute() {
+ return updateSdkPaths(sdkUpdater);
}
}
- };
- progressManager.run(setupTask);
- final Boolean sdkPathsUpdated = sdkPathsUpdatedRef.get();
+ );
+
final Application application = ApplicationManager.getApplication();
if (sdkPathsUpdated && !application.isUnitTestMode()) {
application.invokeLater(new Runnable() {
@Override
public void run(@NotNull ProgressIndicator indicator) {
try {
- final String skeletonsPath = getSkeletonsPath(PathManager.getSystemPath(), sdk.getHomePath());
- PythonSdkUpdater.updateSdk(project, ownerComponent, sdk, skeletonsPath);
+ PythonSdkUpdater.updateSdk(project, ownerComponent, sdkUpdater);
}
catch (InvalidSdkException e) {
// If the SDK is invalid, the user should worry about the SDK itself, not about skeletons generation errors
- if (isVagrant(sdk)) {
+ if (isVagrant(sdkUpdater.getSdk())) {
notifyRemoteSdkSkeletonsFail(e, new Runnable() {
@Override
public void run() {
- setupSdkPaths(project, ownerComponent, sdk, sdkModificator);
+ setupSdkPaths(sdkUpdater.getSdk(), project, ownerComponent);
}
});
}
- else if (!isInvalid(sdk)) {
+ else if (!isInvalid(sdkUpdater.getSdk())) {
LOG.error(e);
}
}
return sdkPathsUpdated;
}
+ @NotNull
+ public static Boolean updateSdkPaths(@NotNull PySdkUpdater sdkUpdater) {
+ sdkUpdater.modifySdk(new PySdkUpdater.SdkModificationProcessor() {
+ @Override
+ public void process(@NotNull Sdk sdk,
+ @NotNull SdkModificator sdkModificator) {
+ sdkModificator.removeAllRoots();
+ }
+ });
+ try {
+ updateSdkRootsFromSysPath(sdkUpdater);
+ updateUserAddedPaths(sdkUpdater);
+ PythonSdkUpdater.getInstance()
+ .markAlreadyUpdated(sdkUpdater.getHomePath());
+ return true;
+ }
+ catch (InvalidSdkException ignored) {
+ }
+ return false;
+ }
+
public static void notifyRemoteSdkSkeletonsFail(final InvalidSdkException e, @Nullable final Runnable restartAction) {
NotificationListener notificationListener;
Notifications.Bus.notify(
new Notification(
- SKELETONS_TOPIC, "Couldn't refresh skeletons for remote interpreter", e.getMessage() + "\n<a href=\"#\">Launch vagrant and refresh skeletons</a>",
+ SKELETONS_TOPIC, "Couldn't refresh skeletons for remote interpreter",
+ e.getMessage() + "\n<a href=\"#\">Launch vagrant and refresh skeletons</a>",
NotificationType.WARNING,
notificationListener
)
private final static Pattern PYTHON_NN_RE = Pattern.compile("python\\d\\.\\d.*");
- public static void updateSdkRootsFromSysPath(Sdk sdk, SdkModificator sdkModificator, ProgressIndicator indicator)
+ public static void updateSdkRootsFromSysPath(PySdkUpdater sdkUpdater)
throws InvalidSdkException {
Application application = ApplicationManager.getApplication();
boolean not_in_unit_test_mode = (application != null && !application.isUnitTestMode());
- String sdkHome = sdkModificator.getHomePath();
+ String sdkHome = sdkUpdater.getHomePath();
assert sdkHome != null;
final String sep = File.separator;
- // we have a number of lib dirs, those listed in python's sys.path
- if (indicator != null) {
- indicator.setText("Adding library roots");
- }
// Add folders from sys.path
- if (!PySdkUtil.isRemote(sdk)) { //no sense to add roots of remote sdk
+ if (!PySdkUtil.isRemote(sdkUpdater.getSdk())) { //no sense to add roots of remote sdk
final List<String> paths = getSysPath(sdkHome);
if (paths.size() > 0) {
// add every path as root.
for (String path : paths) {
if (!path.contains(sep)) continue; // TODO: interpret possible 'special' paths reasonably
- if (indicator != null) {
- indicator.setText2(path);
- }
- addSdkRoot(sdkModificator, path);
+ addSdkRoot(sdkUpdater, path);
}
}
}
- PyUserSkeletonsUtil.addUserSkeletonsRoot(sdkModificator);
- addSkeletonsRoot(sdkModificator, sdkHome);
+ PyUserSkeletonsUtil.addUserSkeletonsRoot(sdkUpdater);
+ addSkeletonsRoot(sdkUpdater, sdkHome);
if (not_in_unit_test_mode) {
File venv_root = getVirtualEnvRoot(sdkHome);
}
}
}
- addHardcodedPaths(sdkModificator);
+ addHardcodedPaths(sdkUpdater);
}
}
- public static void updateUserAddedPaths(Sdk sdk, SdkModificator sdkModificator, ProgressIndicator indicator)
+ public static void updateUserAddedPaths(PySdkUpdater sdkUpdater)
throws InvalidSdkException {
- if (indicator != null) {
- indicator.setText("Adding user-added roots");
- }
- SdkAdditionalData data = sdk.getSdkAdditionalData();
+ SdkAdditionalData data = sdkUpdater.getSdk().getSdkAdditionalData();
if (data instanceof PythonSdkAdditionalData) {
for (VirtualFile file : ((PythonSdkAdditionalData)data).getAddedPathFiles()) {
- addSdkRoot(sdkModificator, file);
+ addSdkRoot(sdkUpdater, file);
}
}
}
- private static void addSkeletonsRoot(@NotNull SdkModificator sdkModificator, String sdkHome) {
+ private static void addSkeletonsRoot(@NotNull PySdkUpdater sdkUpdater, String sdkHome) {
@NonNls final String skeletonsPath = getSkeletonsPath(PathManager.getSystemPath(), sdkHome);
new File(skeletonsPath).mkdirs();
final VirtualFile builtins_root = LocalFileSystem.getInstance().refreshAndFindFileByPath(skeletonsPath);
assert builtins_root != null : "Cannot find skeletons path " + skeletonsPath + " in VFS";
- sdkModificator.addRoot(builtins_root, BUILTIN_ROOT_TYPE);
+ sdkUpdater.addRoot(builtins_root, BUILTIN_ROOT_TYPE);
}
- protected static void addHardcodedPaths(SdkModificator sdkModificator) {
+ protected static void addHardcodedPaths(PySdkUpdater sdkUpdater) {
// Add python-django installed as package in Linux
// NOTE: fragile and arbitrary
if (SystemInfo.isLinux) {
final VirtualFile file = LocalFileSystem.getInstance().findFileByPath("/usr/lib/python-django");
if (file != null) {
- sdkModificator.addRoot(file, OrderRootType.CLASSES);
+ sdkUpdater.addRoot(file, OrderRootType.CLASSES);
}
}
}
- public static void addSdkRoot(SdkModificator sdkModificator, String path) {
+ public static void addSdkRoot(PySdkUpdater sdkUpdater, String path) {
final VirtualFile file = LocalFileSystem.getInstance().refreshAndFindFileByPath(path);
if (file != null) {
- addSdkRoot(sdkModificator, file);
+ addSdkRoot(sdkUpdater, file);
}
else {
LOG.info("Bogus sys.path entry " + path);
}
}
- private static void addSdkRoot(@NotNull SdkModificator sdkModificator, @NotNull VirtualFile child) {
+ private static void addSdkRoot(@NotNull PySdkUpdater sdkUpdater, final @NotNull VirtualFile child) {
// NOTE: Files marked as library sources are not considered part of project source. Since the directory of the project the
// user is working on is included in PYTHONPATH with many configurations (e.g. virtualenv), we must not mark SDK paths as
// library sources, only as classes.
- sdkModificator.addRoot(getSdkRootVirtualFile(child), OrderRootType.CLASSES);
+ sdkUpdater.addRoot(getSdkRootVirtualFile(child), OrderRootType.CLASSES);
}
@NotNull
return path;
}
+ /**
+ * Returns skeletons location on the local machine. Independent of SDK credentials type (e.g. ssh, Vagrant, Docker or else).
+ */
public static String getSkeletonsPath(String basePath, String sdkHome) {
String sep = File.separator;
return getSkeletonsRootPath(basePath) + sep + FileUtil.toSystemIndependentName(sdkHome).hashCode() + sep;
@NotNull
public static List<String> getSysPathsFromScript(@NotNull String binaryPath) throws InvalidSdkException {
- String scriptFile = PythonHelpersLocator.getHelperPath("syspath.py");
// to handle the situation when PYTHONPATH contains ., we need to run the syspath script in the
// directory of the script itself - otherwise the dir in which we run the script (e.g. /usr/bin) will be added to SDK path
- final ProcessOutput run_result = PySdkUtil.getProcessOutput(new File(scriptFile).getParent(), new String[]{binaryPath, scriptFile},
+ GeneralCommandLine cmd = PythonHelper.SYSPATH.newCommandLine(binaryPath, Lists.<String>newArrayList());
+ final ProcessOutput runResult = PySdkUtil.getProcessOutput(cmd, new File(binaryPath).getParent(),
getVirtualEnvExtraEnv(binaryPath), MINUTE);
- if (!run_result.checkSuccess(LOG)) {
+ if (!runResult.checkSuccess(LOG)) {
throw new InvalidSdkException(String.format("Failed to determine Python's sys.path value:\nSTDOUT: %s\nSTDERR: %s",
- run_result.getStdout(),
- run_result.getStderr()));
+ runResult.getStdout(),
+ runResult.getStderr()));
}
- return run_result.getStdoutLines();
+ return runResult.getStdoutLines();
}
/**
return null;
}
+ @Nullable
+ @Override
+ public String getVersionString(@NotNull Sdk sdk) {
+ if (isRemote(sdk)) {
+ final PyRemoteSdkAdditionalDataBase data = (PyRemoteSdkAdditionalDataBase)sdk.getSdkAdditionalData();
+ assert data != null;
+ String versionString = data.getVersionString();
+ if (StringUtil.isEmpty(versionString)) {
+ final PythonRemoteInterpreterManager remoteInterpreterManager = PythonRemoteInterpreterManager.getInstance();
+ if (remoteInterpreterManager != null) {
+ try {
+ versionString =
+ remoteInterpreterManager.getInterpreterVersion(null, data);
+ }
+ catch (Exception e) {
+ LOG.warn("Couldn't get interpreter version:" + e.getMessage(), e);
+ versionString = "undefined";
+ }
+ }
+ data.setVersionString(versionString);
+ }
+ return versionString;
+ }
+ else {
+ return getVersionString(sdk.getHomePath());
+ }
+ }
+
@Nullable
public String getVersionString(final String sdkHome) {
final PythonSdkFlavor flavor = PythonSdkFlavor.getFlavor(sdkHome);
@Override
public void deployment(@NotNull WebDeploymentCredentialsHolder cred) {
}
+
+ @Override
+ public void docker(@NotNull DockerCredentialsHolder credentials) {
+ }
});
return result.get();
}