diff --git a/python/python-community.iml b/python/python-community.iml
index b5f980a97e1a..a1d6fc61d2b9 100644
--- a/python/python-community.iml
+++ b/python/python-community.iml
@@ -26,6 +26,15 @@
+
+
+
+
+
+
+
+
+
+
-
-
+
\ No newline at end of file
diff --git a/python/src/com/jetbrains/python/actions/PySciViewAction.java b/python/src/com/jetbrains/python/actions/PySciViewAction.java
index eb900f63169c..33364d0ee0b0 100644
--- a/python/src/com/jetbrains/python/actions/PySciViewAction.java
+++ b/python/src/com/jetbrains/python/actions/PySciViewAction.java
@@ -26,6 +26,8 @@ import com.intellij.openapi.actionSystem.Presentation;
import com.intellij.openapi.actionSystem.ToggleAction;
import com.intellij.openapi.editor.colors.EditorColorsManager;
import com.intellij.openapi.editor.colors.EditorColorsScheme;
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.module.ModuleUtilCore;
import com.intellij.openapi.options.FontSize;
import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.project.Project;
@@ -35,6 +37,7 @@ import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiManager;
import com.intellij.util.ui.UIUtil;
import com.jetbrains.python.console.PythonConsoleToolWindow;
+import com.jetbrains.python.documentation.PyDocumentationSettings;
import com.jetbrains.python.run.PythonConfigurationType;
import com.jetbrains.python.run.PythonRunConfiguration;
import org.jetbrains.annotations.NotNull;
@@ -78,12 +81,21 @@ public class PySciViewAction extends ToggleAction implements DumbAware {
showDocumentationToolwindow(project, element);
showDataViewAsToolwindow(project);
showCommandLineInRunConfiguration(project, true);
+ renderExternalDocumentation(element, true);
}
else {
hideConsoleToolwindow(project);
restoreDocumentationPopup(project);
hideDataViewer(project);
showCommandLineInRunConfiguration(project, false);
+ renderExternalDocumentation(element, false);
+ }
+ }
+
+ private static void renderExternalDocumentation(PsiElement element, boolean render) {
+ final Module module = ModuleUtilCore.findModuleForPsiElement(element);
+ if (module != null) {
+ PyDocumentationSettings.getInstance(module).setRenderExternalDocumentation(render);
}
}
diff --git a/python/src/com/jetbrains/python/codeInsight/stdlib/PyStdlibDocumentationLinkProvider.java b/python/src/com/jetbrains/python/codeInsight/stdlib/PyStdlibDocumentationLinkProvider.java
index e982087327e5..9325337c3ecc 100644
--- a/python/src/com/jetbrains/python/codeInsight/stdlib/PyStdlibDocumentationLinkProvider.java
+++ b/python/src/com/jetbrains/python/codeInsight/stdlib/PyStdlibDocumentationLinkProvider.java
@@ -22,6 +22,7 @@ import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFileSystemItem;
import com.intellij.psi.PsiNamedElement;
+import com.intellij.psi.util.QualifiedName;
import com.jetbrains.python.PyNames;
import com.jetbrains.python.documentation.PythonDocumentationLinkProvider;
import com.jetbrains.python.documentation.PythonDocumentationProvider;
@@ -29,7 +30,6 @@ import com.jetbrains.python.psi.PyClass;
import com.jetbrains.python.psi.PyFile;
import com.jetbrains.python.psi.PyFunction;
import com.jetbrains.python.psi.impl.PyBuiltinCache;
-import com.intellij.psi.util.QualifiedName;
import com.jetbrains.python.psi.resolve.QualifiedNameFinder;
import com.jetbrains.python.sdk.PythonSdkType;
@@ -544,6 +544,7 @@ public class PyStdlibDocumentationLinkProvider implements PythonDocumentationLin
@Override
public String getExternalDocumentationUrl(PsiElement element, PsiElement originalElement) {
+ if (PyBuiltinCache.getInstance(element).isBuiltin(element)) return null;
PsiFileSystemItem file = element instanceof PsiFileSystemItem ? (PsiFileSystemItem) element : element.getContainingFile();
if (PyNames.INIT_DOT_PY.equals(file.getName())) {
file = file.getParent();
diff --git a/python/src/com/jetbrains/python/configuration/PyIntegratedToolsConfigurable.form b/python/src/com/jetbrains/python/configuration/PyIntegratedToolsConfigurable.form
index 5aacd414fb03..50e117174f63 100644
--- a/python/src/com/jetbrains/python/configuration/PyIntegratedToolsConfigurable.form
+++ b/python/src/com/jetbrains/python/configuration/PyIntegratedToolsConfigurable.form
@@ -49,7 +49,7 @@
-
+
@@ -82,6 +82,14 @@
+
+
+
+
+
+
+
+
diff --git a/python/src/com/jetbrains/python/configuration/PyIntegratedToolsConfigurable.java b/python/src/com/jetbrains/python/configuration/PyIntegratedToolsConfigurable.java
index dc3d88ca5cd3..c519eda530ce 100644
--- a/python/src/com/jetbrains/python/configuration/PyIntegratedToolsConfigurable.java
+++ b/python/src/com/jetbrains/python/configuration/PyIntegratedToolsConfigurable.java
@@ -39,7 +39,6 @@ import com.intellij.ui.ListCellRendererWrapper;
import com.intellij.util.FileContentUtil;
import com.intellij.util.FileContentUtilCore;
import com.jetbrains.python.PyBundle;
-import com.jetbrains.python.PyNames;
import com.jetbrains.python.PythonFileType;
import com.jetbrains.python.ReSTService;
import com.jetbrains.python.documentation.PyDocumentationSettings;
@@ -78,6 +77,7 @@ public class PyIntegratedToolsConfigurable implements SearchableConfigurable {
private JCheckBox analyzeDoctest;
private JPanel myDocStringsPanel;
private JPanel myRestPanel;
+ private JCheckBox renderExternal;
public PyIntegratedToolsConfigurable(@NotNull Module module) {
myModule = module;
@@ -99,6 +99,7 @@ public class PyIntegratedToolsConfigurable implements SearchableConfigurable {
myWorkDir.setText(service.getWorkdir());
txtIsRst.setSelected(service.txtIsRst());
analyzeDoctest.setSelected(myDocumentationSettings.isAnalyzeDoctest());
+ renderExternal.setSelected(myDocumentationSettings.isRenderExternalDocumentation());
myRequirementsPathField.addBrowseFolderListener("Choose path to the package requirements file:", null, myProject,
FileChooserDescriptorFactory.createSingleLocalFileDescriptor());
myRequirementsPathField.setText(getRequirementsPath());
@@ -207,6 +208,9 @@ public class PyIntegratedToolsConfigurable implements SearchableConfigurable {
if (analyzeDoctest.isSelected() != myDocumentationSettings.isAnalyzeDoctest()) {
return true;
}
+ if (renderExternal.isSelected() != myDocumentationSettings.isRenderExternalDocumentation()) {
+ return true;
+ }
if (!ReSTService.getInstance(myModule).getWorkdir().equals(myWorkDir.getText())) {
return true;
}
@@ -235,6 +239,7 @@ public class PyIntegratedToolsConfigurable implements SearchableConfigurable {
FileContentUtil.reparseFiles(myProject, Lists.newArrayList(files), false);
}
myModel.apply();
+ myDocumentationSettings.setRenderExternalDocumentation(renderExternal.isSelected());
myDocumentationSettings.setFormat((DocStringFormat)myDocstringFormatComboBox.getSelectedItem());
final ReSTService reSTService = ReSTService.getInstance(myModule);
reSTService.setWorkdir(myWorkDir.getText());
@@ -271,6 +276,7 @@ public class PyIntegratedToolsConfigurable implements SearchableConfigurable {
myWorkDir.setText(ReSTService.getInstance(myModule).getWorkdir());
txtIsRst.setSelected(ReSTService.getInstance(myModule).txtIsRst());
analyzeDoctest.setSelected(myDocumentationSettings.isAnalyzeDoctest());
+ renderExternal.setSelected(myDocumentationSettings.isRenderExternalDocumentation());
myRequirementsPathField.setText(getRequirementsPath());
}
diff --git a/python/src/com/jetbrains/python/documentation/PyDocumentationSettings.java b/python/src/com/jetbrains/python/documentation/PyDocumentationSettings.java
index fd43b67011b1..9e21a47b6c43 100644
--- a/python/src/com/jetbrains/python/documentation/PyDocumentationSettings.java
+++ b/python/src/com/jetbrains/python/documentation/PyDocumentationSettings.java
@@ -47,6 +47,7 @@ public class PyDocumentationSettings implements PersistentStateComponent docUrls) {
- return null;
+ final Module module = ModuleUtilCore.findModuleForPsiElement(element);
+ if (module != null && !PyDocumentationSettings.getInstance(module).isRenderExternalDocumentation()) return null;
+ return ApplicationManager.getApplication().runReadAction((Computable)() -> {
+ PsiFileSystemItem file = element instanceof PsiFileSystemItem ? (PsiFileSystemItem)element : element.getContainingFile();
+ if (file == null) return null;
+ if (PyNames.INIT_DOT_PY.equals(file.getName())) {
+ file = file.getParent();
+ assert file != null;
+ }
+ final Sdk sdk = PyBuiltinCache.findSdkForFile(file);
+ if (sdk == null) {
+ return null;
+ }
+
+ final QualifiedName moduleQName = QualifiedNameFinder.findCanonicalImportPath(element, element);
+ if (moduleQName == null) {
+ return null;
+ }
+ PsiNamedElement namedElement = (element instanceof PsiNamedElement && !(element instanceof PsiFileSystemItem))
+ ? (PsiNamedElement)element
+ : null;
+ if (namedElement instanceof PyFunction && PyNames.INIT.equals(namedElement.getName())) {
+ final PyClass containingClass = ((PyFunction)namedElement).getContainingClass();
+ if (containingClass != null) {
+ namedElement = containingClass;
+ }
+ }
+ final PyStdlibDocumentationLinkProvider stdlibDocumentationLinkProvider =
+ Extensions.findExtension(PythonDocumentationLinkProvider.EP_NAME, PyStdlibDocumentationLinkProvider.class);
+ final String url = stdlibDocumentationLinkProvider.getExternalDocumentationUrl(element, element);
+ if (url == null) {
+ return null;
+ }
+
+ try {
+ final Document document = Jsoup.parse(new URL(url), 1000);
+ final String elementId = namedElement != null ? moduleQName + "." + namedElement.getName() : "module-" + moduleQName;
+ document.select("a.headerlink").remove();
+ final Elements parents = document.getElementsByAttributeValue("id", elementId).parents();
+ if (parents.isEmpty()) {
+ return document.toString();
+ }
+ return parents.get(0).toString();
+ }
+ catch (MalformedURLException ignored) {
+ }
+ catch (IOException ignored) {
+ }
+ return null;
+ });
}
@Override