3816e5ba9f04f6f2cfa138a0300ced7f7b55380d
[idea/community.git] / python / src / com / jetbrains / python / PythonHelper.java
1 /*
2  * Copyright 2000-2015 JetBrains s.r.o.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.jetbrains.python;
17
18 import com.google.common.collect.Lists;
19 import com.intellij.execution.configurations.GeneralCommandLine;
20 import com.intellij.execution.configurations.ParamsGroup;
21 import com.intellij.openapi.projectRoots.Sdk;
22 import com.intellij.openapi.util.io.FileUtil;
23 import com.jetbrains.python.psi.LanguageLevel;
24 import com.jetbrains.python.sdk.PythonEnvUtil;
25 import com.jetbrains.python.sdk.PythonSdkType;
26 import org.jetbrains.annotations.NotNull;
27
28 import java.io.File;
29 import java.util.List;
30 import java.util.Map;
31
32 import static com.jetbrains.python.PythonHelpersLocator.getHelperFile;
33 import static com.jetbrains.python.PythonHelpersLocator.getHelpersRoot;
34
35 /**
36  * @author traff
37  */
38 public enum PythonHelper implements HelperPackage {
39   COVERAGEPY("coveragepy", ""),
40   COVERAGE("coverage_runner", "run_coverage"),
41   DEBUGGER("pydev", "pydevd"),
42   
43   ATTACH_DEBUGGER("pydev/pydevd_attach_to_process/attach_pydevd.py"),
44
45   CONSOLE("pydev", "pydevconsole"),
46   RUN_IN_CONSOLE("pydev", "pydev_run_in_console"),
47   PROFILER("profiler", "run_profiler"),
48
49   LOAD_ENTRY_POINT("pycharm", "pycharm_load_entry_point"),
50
51   // Test runners
52   UT("pycharm", "utrunner"),
53   SETUPPY("pycharm", "pycharm_setup_runner"),
54   NOSE("pycharm", "noserunner"),
55   PYTEST("pycharm", "pytestrunner"),
56   ATTEST("pycharm", "attestrunner"),
57   DOCSTRING("pycharm", "docrunner"),
58
59   BEHAVE("pycharm", "behave_runner"),
60   LETTUCE("pycharm", "lettuce_runner"),
61
62   DJANGO_TEST_MANAGE("pycharm", "django_test_manage"),
63   DJANGO_MANAGE("pycharm", "django_manage"),
64   MANAGE_TASKS_PROVIDER("pycharm", "_jb_manage_tasks_provider"),
65
66   APPCFG_CONSOLE("pycharm", "appcfg_fetcher"),
67
68   BUILDOUT_ENGULFER("pycharm", "buildout_engulfer"),
69
70   EPYDOC_FORMATTER("epydoc_formatter.py"),
71   REST_FORMATTER("rest_formatter.py"),
72   GOOGLE_FORMATTER("google_formatter.py"),
73   NUMPY_FORMATTER("numpy_formatter.py"),
74
75   EXTRA_SYSPATH("extra_syspath.py"),
76   SYSPATH("syspath.py"),
77
78   PEP8("pep8.py"),
79
80   REST_RUNNER("rest_runners/rst2smth.py"),
81
82   SPHINX_RUNNER("rest_runners/sphinx_runner.py");
83
84   public static final String PY3_HELPER_DEPENDENCIES_DIR = "py3only";
85   public static final String PY2_HELPER_DEPENDENCIES_DIR = "py2only";
86
87   @NotNull
88   private static PathHelperPackage findModule(String moduleEntryPoint, String path, boolean asModule) {
89     if (getHelperFile(path + ".zip").isFile()) {
90       return new ModuleHelperPackage(moduleEntryPoint, path + ".zip");
91     }
92
93     if (!asModule && new File(getHelperFile(path), moduleEntryPoint + ".py").isFile()) {
94       return new ScriptPythonHelper(moduleEntryPoint + ".py", getHelperFile(path));
95     }
96
97     return new ModuleHelperPackage(moduleEntryPoint, path);
98   }
99
100   private final PathHelperPackage myModule;
101
102   PythonHelper(String pythonPath, String moduleName) {
103     this(pythonPath, moduleName, false);
104   }
105
106   PythonHelper(String pythonPath, String moduleName, boolean asModule) {
107     myModule = findModule(moduleName, pythonPath, asModule);
108   }
109
110   PythonHelper(String helperScript) {
111     myModule = new ScriptPythonHelper(helperScript, getHelpersRoot());
112   }
113
114   public abstract static class PathHelperPackage implements HelperPackage {
115     protected final File myPath;
116
117     PathHelperPackage(String path) {
118       myPath = new File(path);
119     }
120
121     @Override
122     public void addToPythonPath(@NotNull Map<String, String> environment) {
123       PythonEnvUtil.addToPythonPath(environment, getPythonPathEntry());
124     }
125
126     @Override
127     public void addToGroup(@NotNull ParamsGroup group, @NotNull GeneralCommandLine cmd) {
128       addToPythonPath(cmd.getEnvironment());
129       group.addParameter(asParamString());
130     }
131
132     @NotNull
133     @Override
134     public String asParamString() {
135       return FileUtil.toSystemDependentName(myPath.getAbsolutePath());
136     }
137
138     @NotNull
139     @Override
140     public GeneralCommandLine newCommandLine(@NotNull String sdkPath, @NotNull List<String> parameters) {
141       final List<String> args = Lists.newArrayList();
142       args.add(sdkPath);
143       args.add(asParamString());
144       args.addAll(parameters);
145       final GeneralCommandLine cmd = new GeneralCommandLine(args);
146       addToPythonPath(cmd.getEnvironment());
147       return cmd;
148     }
149
150     @NotNull
151     @Override
152     public GeneralCommandLine newCommandLine(@NotNull Sdk pythonSdk, @NotNull List<String> parameters) {
153       final String sdkHomePath = pythonSdk.getHomePath();
154       assert sdkHomePath != null;
155       final GeneralCommandLine cmd = newCommandLine(sdkHomePath, parameters);
156       final LanguageLevel version = PythonSdkType.getLanguageLevelForSdk(pythonSdk);
157       final String perVersionDependenciesDir = version.isPy3K() ? PY3_HELPER_DEPENDENCIES_DIR : PY2_HELPER_DEPENDENCIES_DIR;
158       PythonEnvUtil.addToPythonPath(cmd.getEnvironment(), FileUtil.join(getPythonPathEntry(), perVersionDependenciesDir));
159       return cmd;
160     }
161   }
162
163   /**
164    * Module Python helper can be executed from zip-archive
165    */
166   public static class ModuleHelperPackage extends PathHelperPackage {
167     private final String myModuleName;
168
169     public ModuleHelperPackage(String moduleName, String relativePath) {
170       super(getHelperFile(relativePath).getAbsolutePath());
171       this.myModuleName = moduleName;
172     }
173
174     @NotNull
175     @Override
176     public String asParamString() {
177       return "-m" + myModuleName;
178     }
179
180     @NotNull
181     @Override
182     public String getPythonPathEntry() {
183       return FileUtil.toSystemDependentName(myPath.getAbsolutePath());
184     }
185   }
186
187   /**
188    * Script Python helper can be executed as a Python script, therefore
189    * PYTHONDONTWRITEBYTECODE option is set not to spoil installation
190    * with .pyc files
191    */
192   public static class ScriptPythonHelper extends PathHelperPackage {
193     private final String myPythonPath;
194
195     public ScriptPythonHelper(String script, File pythonPath) {
196       super(new File(pythonPath, script).getAbsolutePath());
197       myPythonPath = pythonPath.getAbsolutePath();
198     }
199
200     @Override
201     public void addToPythonPath(@NotNull Map<String, String> environment) {
202       PythonEnvUtil.setPythonDontWriteBytecode(environment);
203       super.addToPythonPath(environment);
204     }
205
206     @NotNull
207     @Override
208     public String getPythonPathEntry() {
209       return myPythonPath;
210     }
211   }
212
213   
214   @NotNull
215   @Override
216   public String getPythonPathEntry() {
217     return myModule.getPythonPathEntry();
218   }
219
220   @Override
221   public void addToPythonPath(@NotNull Map<String, String> environment) {
222     myModule.addToPythonPath(environment);
223   }
224
225   @Override
226   public void addToGroup(@NotNull ParamsGroup group, @NotNull GeneralCommandLine cmd) {
227     myModule.addToGroup(group, cmd);
228   }
229
230   @NotNull
231   @Override
232   public String asParamString() {
233     return myModule.asParamString();
234   }
235
236   @NotNull
237   @Override
238   public GeneralCommandLine newCommandLine(@NotNull String sdkPath, @NotNull List<String> parameters) {
239     return myModule.newCommandLine(sdkPath, parameters);
240   }
241
242   @NotNull
243   @Override
244   public GeneralCommandLine newCommandLine(@NotNull Sdk pythonSdk, @NotNull List<String> parameters) {
245     return myModule.newCommandLine(pythonSdk, parameters);
246   }
247
248 }