From ca4c9823e798bbd4a02db01895887ec4f7d7eb1d Mon Sep 17 00:00:00 2001 From: Ekaterina Tuzova Date: Wed, 6 Sep 2017 11:01:23 +0300 Subject: [PATCH] extract conda interpreter flavor from virtual env gives us ability to add custom icons and rules --- python/gen/icons/PythonIcons.java | 1 + .../PyConfigurableInterpreterList.java | 4 +- .../icons/com/jetbrains/python/condaenv.png | Bin 0 -> 285 bytes .../com/jetbrains/python/condaenv@2x.png | Bin 0 -> 423 bytes .../com/jetbrains/python/condaenv_dark.png | Bin 0 -> 286 bytes .../com/jetbrains/python/condaenv_dark@2x.png | Bin 0 -> 294 bytes .../packaging/PyCondaPackageService.java | 4 +- .../python/sdk/CreateCondaEnvDialog.java | 4 +- .../python/sdk/flavors/CondaEnvSdkFlavor.java | 115 ++++++++++++++++++ .../python/sdk/flavors/PythonSdkFlavor.java | 1 + .../sdk/flavors/VirtualEnvSdkFlavor.java | 42 ------- 11 files changed, 124 insertions(+), 47 deletions(-) create mode 100644 python/resources/icons/com/jetbrains/python/condaenv.png create mode 100644 python/resources/icons/com/jetbrains/python/condaenv@2x.png create mode 100644 python/resources/icons/com/jetbrains/python/condaenv_dark.png create mode 100644 python/resources/icons/com/jetbrains/python/condaenv_dark@2x.png create mode 100644 python/src/com/jetbrains/python/sdk/flavors/CondaEnvSdkFlavor.java diff --git a/python/gen/icons/PythonIcons.java b/python/gen/icons/PythonIcons.java index 96603fa94042..a5948cb713df 100644 --- a/python/gen/icons/PythonIcons.java +++ b/python/gen/icons/PythonIcons.java @@ -42,6 +42,7 @@ public class PythonIcons { public static final Icon Buildout = load("/icons/com/jetbrains/python/buildout/buildout.png"); // 16x16 } + public static final Icon Condaenv = load("/icons/com/jetbrains/python/condaenv.png"); // 16x16 public static final Icon DataView = load("/icons/com/jetbrains/python/DataView.png"); // 13x13 public static class Debug { diff --git a/python/python-community-configure/src/com/jetbrains/python/configuration/PyConfigurableInterpreterList.java b/python/python-community-configure/src/com/jetbrains/python/configuration/PyConfigurableInterpreterList.java index a3a221f96020..b57a729c9198 100644 --- a/python/python-community-configure/src/com/jetbrains/python/configuration/PyConfigurableInterpreterList.java +++ b/python/python-community-configure/src/com/jetbrains/python/configuration/PyConfigurableInterpreterList.java @@ -26,6 +26,7 @@ import com.jetbrains.python.sdk.PyDetectedSdk; import com.jetbrains.python.sdk.PySdkUtil; import com.jetbrains.python.sdk.PythonSdkAdditionalData; import com.jetbrains.python.sdk.PythonSdkType; +import com.jetbrains.python.sdk.flavors.CondaEnvSdkFlavor; import com.jetbrains.python.sdk.flavors.PythonSdkFlavor; import com.jetbrains.python.sdk.flavors.VirtualEnvSdkFlavor; import org.jetbrains.annotations.NotNull; @@ -79,8 +80,9 @@ public class PyConfigurableInterpreterList { private void addDetectedSdks(@NotNull final List result) { final List sdkHomes = new ArrayList<>(); sdkHomes.addAll(VirtualEnvSdkFlavor.INSTANCE.suggestHomePaths()); + sdkHomes.addAll(CondaEnvSdkFlavor.INSTANCE.suggestHomePaths()); for (PythonSdkFlavor flavor : PythonSdkFlavor.getApplicableFlavors()) { - if (flavor instanceof VirtualEnvSdkFlavor) continue; + if (flavor instanceof VirtualEnvSdkFlavor || flavor instanceof CondaEnvSdkFlavor) continue; sdkHomes.addAll(flavor.suggestHomePaths()); } Collections.sort(sdkHomes); diff --git a/python/resources/icons/com/jetbrains/python/condaenv.png b/python/resources/icons/com/jetbrains/python/condaenv.png new file mode 100644 index 0000000000000000000000000000000000000000..8681282f0d52858c27e9dfc5e05531dee7a3b6bd GIT binary patch literal 285 zcmV+&0pk9NP))_^lOa2h^mr@?Fo;+aSoZa~_KWexvN zGNeJVF|q;s@z@H-4ePpQ0yUn2;{C`5oFN8xZm3^|WWX7c42WK~ar4Jx{F@0H;J5g| z<|l{cP!!_ASPj^=Ghi7WP5Xh^7ZiXv19AUu*O|C9FPY&U7E{=8ABg`$@p_m6#;|C- zc~G+fP2)@`_62G<55)>V>;T057-<3;$Jkt847Jq(Z%V{w08EZp1Js~_h3bcJ*Km00000NkvXXu0mjfj5c+6 literal 0 HcmV?d00001 diff --git a/python/resources/icons/com/jetbrains/python/condaenv@2x.png b/python/resources/icons/com/jetbrains/python/condaenv@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..d3d7529470124c6d3059b426cd15e08bf88f63b5 GIT binary patch literal 423 zcmV;Y0a*TtP)I7{~7m95_2UbrTAi+_H#Mp=+r_ry{s08C)~h!PQRJL2h(8oE$O>2lr9@2=#d& zkr40YNiOLv9{jkWCI4Suo~LP+{XfKq9~uGFM8uTghHXp%Gw2M+0Ywl{DFkv&MOlRu z0*V@*O2CVl0<4F40)eN!ljB#$fZ9O>Q}Gdy)LEqx;3LDNE=Oju@)2Nx z!R6cQ&DHIrEP!v|Xwd*0YAX&AD4*p0q9xcx*#dackTC@G%uP7HAAmE=fj7rs{n-oY zS8^bbIh^ZdH?y3#jrnH_MhLiYYxYHy3yDWKmg~%#{pOScmAPo75TJBH)glmW3${Lu z$2o+&;}HH<230~(C7yTdOQ#H_RfbEe44Y*CC2{`=ji|^{J`ixx(~6h)ogb%~-OpTM R%{Tx6002ovPDHLkV1lq|x6l9p literal 0 HcmV?d00001 diff --git a/python/resources/icons/com/jetbrains/python/condaenv_dark.png b/python/resources/icons/com/jetbrains/python/condaenv_dark.png new file mode 100644 index 0000000000000000000000000000000000000000..7e983a1f419e08a113915356f34c5373b5cf3bc8 GIT binary patch literal 286 zcmV+(0pb3MP))_^lOa2h^mr@?Fo;+aSoZa~_KWexvN zGNeJVF|q;s@z@H-4ePpQ0yUn2;{C`5oFN8xZm3^|WWX7c42WK~ar4Jx{F@0H;J5g| z<|l{cP!!_ASPj^=Ghi7WP5Xh^7ZiXv19AUu*O|C9Upt%^wr&5h`#}63ir2#oFos3r z&4Zc^Xc}iiu`f`=c_>x@Vh14Z$4C>0OMz+@Md!GWB>pF07*qoM6N<$g1=RC00000 literal 0 HcmV?d00001 diff --git a/python/resources/icons/com/jetbrains/python/condaenv_dark@2x.png b/python/resources/icons/com/jetbrains/python/condaenv_dark@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..5ed486884ef0ed2e73bc95ba5d984f6a086d66d8 GIT binary patch literal 294 zcmV+>0oneEP)moQBWYX-KxuM8a?b(pD^M_gOLF}QO>{W2s2&X8n4^stF3ndC=B(Mc`_OwJ{tw0TVFnn(qVeWI z%?31$VB78-j_84EY5-yZAWi_{evC8$jbjYkkMHl^4AgL*U`oVcKm*ifq6|<2B@%Q) s9v<;t2K7Qek{8yKlvAOuKn}!y0GvUp8p2DNCjbBd07*qoM6N<$f{z?`E&u=k literal 0 HcmV?d00001 diff --git a/python/src/com/jetbrains/python/packaging/PyCondaPackageService.java b/python/src/com/jetbrains/python/packaging/PyCondaPackageService.java index 29f3e5a70cdd..a6f8be202e3d 100644 --- a/python/src/com/jetbrains/python/packaging/PyCondaPackageService.java +++ b/python/src/com/jetbrains/python/packaging/PyCondaPackageService.java @@ -30,7 +30,7 @@ import com.intellij.util.xmlb.XmlSerializerUtil; import com.jetbrains.python.PythonHelpersLocator; import com.jetbrains.python.sdk.PySdkUtil; import com.jetbrains.python.sdk.PythonSdkType; -import com.jetbrains.python.sdk.flavors.VirtualEnvSdkFlavor; +import com.jetbrains.python.sdk.flavors.CondaEnvSdkFlavor; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -132,7 +132,7 @@ public class PyCondaPackageService implements PersistentStateComponent locations = VirtualEnvSdkFlavor.getCondaDefaultLocations(); + final List locations = CondaEnvSdkFlavor.getCondaDefaultLocations(); if (!locations.isEmpty()) { myInitialPath = locations.get(0).getPath(); return; diff --git a/python/src/com/jetbrains/python/sdk/flavors/CondaEnvSdkFlavor.java b/python/src/com/jetbrains/python/sdk/flavors/CondaEnvSdkFlavor.java new file mode 100644 index 000000000000..1f9baad43ac0 --- /dev/null +++ b/python/src/com/jetbrains/python/sdk/flavors/CondaEnvSdkFlavor.java @@ -0,0 +1,115 @@ +/* + * Copyright 2000-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.jetbrains.python.sdk.flavors; + +import com.intellij.openapi.util.SystemInfo; +import com.intellij.openapi.vfs.LocalFileSystem; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.util.SystemProperties; +import com.jetbrains.python.sdk.PythonSdkType; +import icons.PythonIcons; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import javax.swing.*; +import java.io.File; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import static com.jetbrains.python.sdk.flavors.VirtualEnvSdkFlavor.findInDirectory; + +public class CondaEnvSdkFlavor extends CPythonSdkFlavor { + private CondaEnvSdkFlavor() { + } + + public final static String[] CONDA_DEFAULT_ROOTS = new String[]{"anaconda", "anaconda2", "anaconda3", "miniconda", "miniconda2", + "miniconda3", "Anaconda", "Anaconda2", "Anaconda3", "Miniconda", "Miniconda2", "Miniconda3"}; + + public static CondaEnvSdkFlavor INSTANCE = new CondaEnvSdkFlavor(); + + @Override + public Collection suggestHomePaths() { + List candidates = new ArrayList<>(); + + for (VirtualFile file : getCondaDefaultLocations()) { + candidates.addAll(findInDirectory(file)); + } + + return candidates; + } + + public static List getCondaDefaultLocations() { + List roots = new ArrayList<>(); + final VirtualFile userHome = LocalFileSystem.getInstance().findFileByPath(SystemProperties.getUserHome().replace('\\','/')); + if (userHome != null) { + final VirtualFile condaHidden = userHome.findChild(".conda"); + if (condaHidden != null) { + addEnvsFolder(roots, condaHidden); + } + for (String root : CONDA_DEFAULT_ROOTS) { + VirtualFile condaFolder = userHome.findChild(root); + addEnvsFolder(roots, condaFolder); + if (SystemInfo.isWindows) { + final VirtualFile appData = userHome.findFileByRelativePath("AppData\\Local\\Continuum\\" + root); + addEnvsFolder(roots, appData); + condaFolder = LocalFileSystem.getInstance().findFileByPath("C:\\" + root); + addEnvsFolder(roots, condaFolder); + } + else { + final String systemWidePath = "/opt/anaconda"; + condaFolder = LocalFileSystem.getInstance().findFileByPath(systemWidePath); + addEnvsFolder(roots, condaFolder); + } + } + } + return roots; + } + + private static void addEnvsFolder(@NotNull final List roots, @Nullable final VirtualFile condaFolder) { + if (condaFolder != null) { + final VirtualFile envs = condaFolder.findChild("envs"); + if (envs != null) { + roots.add(envs); + } + } + } + + @Override + public boolean isValidSdkPath(@NotNull File file) { + if (!super.isValidSdkPath(file)) return false; + final File bin = file.getParentFile(); + String condaName = "conda"; + if (SystemInfo.isWindows) { + condaName = new File(bin, "envs").exists() ? "conda.exe" : "conda.bat"; + } + if (bin != null) { + final File conda = new File(bin, condaName); + if (conda.exists()) { + return true; + } + final File condaFolder = bin.getParentFile(); + final File condaExecutable = PythonSdkType.findExecutableFile(condaFolder, condaName); + if (condaExecutable != null) return true; + } + return false; + } + + @Override + public Icon getIcon() { + return PythonIcons.Python.Condaenv; + } +} diff --git a/python/src/com/jetbrains/python/sdk/flavors/PythonSdkFlavor.java b/python/src/com/jetbrains/python/sdk/flavors/PythonSdkFlavor.java index 5181beb33af4..414d3646c0bb 100644 --- a/python/src/com/jetbrains/python/sdk/flavors/PythonSdkFlavor.java +++ b/python/src/com/jetbrains/python/sdk/flavors/PythonSdkFlavor.java @@ -117,6 +117,7 @@ public abstract class PythonSdkFlavor { result.add(IronPythonSdkFlavor.INSTANCE); result.add(PyPySdkFlavor.INSTANCE); result.add(VirtualEnvSdkFlavor.INSTANCE); + result.add(CondaEnvSdkFlavor.INSTANCE); result.add(PyRemoteSdkFlavor.INSTANCE); return result; diff --git a/python/src/com/jetbrains/python/sdk/flavors/VirtualEnvSdkFlavor.java b/python/src/com/jetbrains/python/sdk/flavors/VirtualEnvSdkFlavor.java index c931f54c9648..3034a11072b1 100644 --- a/python/src/com/jetbrains/python/sdk/flavors/VirtualEnvSdkFlavor.java +++ b/python/src/com/jetbrains/python/sdk/flavors/VirtualEnvSdkFlavor.java @@ -42,8 +42,6 @@ public class VirtualEnvSdkFlavor extends CPythonSdkFlavor { private VirtualEnvSdkFlavor() { } private final static String[] NAMES = new String[]{"jython", "pypy", "python.exe", "jython.bat", "pypy.exe"}; - public final static String[] CONDA_DEFAULT_ROOTS = new String[]{"anaconda", "anaconda2", "anaconda3", "miniconda", "miniconda2", - "miniconda3", "Anaconda", "Anaconda2", "Anaconda3", "Miniconda", "Miniconda2", "Miniconda3"}; public static VirtualEnvSdkFlavor INSTANCE = new VirtualEnvSdkFlavor(); @@ -61,10 +59,6 @@ public class VirtualEnvSdkFlavor extends CPythonSdkFlavor { if (path != null) candidates.addAll(findInDirectory(path)); - for (VirtualFile file : getCondaDefaultLocations()) { - candidates.addAll(findInDirectory(file)); - } - final VirtualFile pyEnvLocation = getPyEnvDefaultLocations(); if (pyEnvLocation != null) { candidates.addAll(findInDirectory(pyEnvLocation)); @@ -88,42 +82,6 @@ public class VirtualEnvSdkFlavor extends CPythonSdkFlavor { return null; } - public static List getCondaDefaultLocations() { - List roots = new ArrayList<>(); - final VirtualFile userHome = LocalFileSystem.getInstance().findFileByPath(SystemProperties.getUserHome().replace('\\','/')); - if (userHome != null) { - final VirtualFile condaHidden = userHome.findChild(".conda"); - if (condaHidden != null) { - addEnvsFolder(roots, condaHidden); - } - for (String root : CONDA_DEFAULT_ROOTS) { - VirtualFile condaFolder = userHome.findChild(root); - addEnvsFolder(roots, condaFolder); - if (SystemInfo.isWindows) { - final VirtualFile appData = userHome.findFileByRelativePath("AppData\\Local\\Continuum\\" + root); - addEnvsFolder(roots, appData); - condaFolder = LocalFileSystem.getInstance().findFileByPath("C:\\" + root); - addEnvsFolder(roots, condaFolder); - } - else { - final String systemWidePath = "/opt/anaconda"; - condaFolder = LocalFileSystem.getInstance().findFileByPath(systemWidePath); - addEnvsFolder(roots, condaFolder); - } - } - } - return roots; - } - - private static void addEnvsFolder(@NotNull final List roots, @Nullable final VirtualFile condaFolder) { - if (condaFolder != null) { - final VirtualFile envs = condaFolder.findChild("envs"); - if (envs != null) { - roots.add(envs); - } - } - } - public static VirtualFile getDefaultLocation() { final String path = System.getenv().get("WORKON_HOME"); if (!StringUtil.isEmpty(path)) {