7616af9d9072cd940f8e724d5b52660ffc9d2294
[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", ""), COVERAGE("coverage_runner", "run_coverage"),
40   DEBUGGER("pydev", "pydevd"),
41   ATTACH_DEBUGGER("pydev", "pydevd_attach_to_process.attach_pydevd"),
42
43   CONSOLE("pydev", "pydevconsole"),
44   RUN_IN_CONSOLE("pydev", "pydev_run_in_console"),
45   PROFILER("profiler", "run_profiler"),
46
47   LOAD_ENTRY_POINT("pycharm", "pycharm_load_entry_point"),
48
49   // Test runners
50   UT("pycharm", "utrunner"),
51   SETUPPY("pycharm", "pycharm_setup_runner"),
52   NOSE("pycharm", "noserunner"),
53   PYTEST("pycharm", "pytestrunner"),
54   ATTEST("pycharm", "attestrunner"),
55   DOCSTRING("pycharm", "docrunner"),
56
57   BEHAVE("pycharm", "behave_runner"),
58   LETTUCE("pycharm", "lettuce_runner"),
59
60   DJANGO_TEST_MANAGE("pycharm", "django_test_manage"),
61   DJANGO_MANAGE("pycharm", "django_manage"),
62   MANAGE_TASKS_PROVIDER("pycharm", "_jb_manage_tasks_provider"),
63
64   APPCFG_CONSOLE("pycharm", "appcfg_fetcher"),
65
66   BUILDOUT_ENGULFER("pycharm", "buildout_engulfer"),
67
68   EPYDOC_FORMATTER("epydoc_formatter.py"),
69   REST_FORMATTER("rest_formatter.py"),
70   GOOGLE_FORMATTER("google_formatter.py"),
71   NUMPY_FORMATTER("numpy_formatter.py"),
72
73   EXTRA_SYSPATH("extra_syspath.py"),
74   SYSPATH("syspath.py"),
75
76   PEP8("pep8.py"),
77
78   REST_RUNNER("rest_runners/rst2smth.py"),
79
80   SPHINX_RUNNER("rest_runners/sphinx_runner.py");
81
82   public static final String PY3_HELPER_DEPENDENCIES_DIR = "py3only";
83   public static final String PY2_HELPER_DEPENDENCIES_DIR = "py2only";
84
85   @NotNull
86   private static PathHelperPackage findModule(String moduleEntryPoint, String path, boolean asModule) {
87     if (getHelperFile(path + ".zip").isFile()) {
88       return new ModuleHelperPackage(moduleEntryPoint, path + ".zip");
89     }
90
91     if (!asModule && new File(getHelperFile(path), moduleEntryPoint + ".py").isFile()) {
92       return new ScriptPythonHelper(moduleEntryPoint + ".py", getHelperFile(path));
93     }
94
95     return new ModuleHelperPackage(moduleEntryPoint, path);
96   }
97
98   private final PathHelperPackage myModule;
99
100   PythonHelper(String pythonPath, String moduleName) {
101     this(pythonPath, moduleName, false);
102   }
103
104   PythonHelper(String pythonPath, String moduleName, boolean asModule) {
105     myModule = findModule(moduleName, pythonPath, asModule);
106   }
107
108   PythonHelper(String helperScript) {
109     myModule = new ScriptPythonHelper(helperScript, getHelpersRoot());
110   }
111
112   public abstract static class PathHelperPackage implements HelperPackage {
113     protected final File myPath;
114
115     PathHelperPackage(String path) {
116       myPath = new File(path);
117     }
118
119     @Override
120     public void addToPythonPath(@NotNull Map<String, String> environment) {
121       PythonEnvUtil.addToPythonPath(environment, getPythonPathEntry());
122     }
123
124     @Override
125     public void addToGroup(@NotNull ParamsGroup group, @NotNull GeneralCommandLine cmd) {
126       addToPythonPath(cmd.getEnvironment());
127       group.addParameter(asParamString());
128     }
129
130     @NotNull
131     @Override
132     public String asParamString() {
133       return FileUtil.toSystemDependentName(myPath.getAbsolutePath());
134     }
135
136     @NotNull
137     @Override
138     public GeneralCommandLine newCommandLine(@NotNull String sdkPath, @NotNull List<String> parameters) {
139       final List<String> args = Lists.newArrayList();
140       args.add(sdkPath);
141       args.add(asParamString());
142       args.addAll(parameters);
143       final GeneralCommandLine cmd = new GeneralCommandLine(args);
144       addToPythonPath(cmd.getEnvironment());
145       return cmd;
146     }
147
148     @NotNull
149     @Override
150     public GeneralCommandLine newCommandLine(@NotNull Sdk pythonSdk, @NotNull List<String> parameters) {
151       final String sdkHomePath = pythonSdk.getHomePath();
152       assert sdkHomePath != null;
153       final GeneralCommandLine cmd = newCommandLine(sdkHomePath, parameters);
154       final LanguageLevel version = PythonSdkType.getLanguageLevelForSdk(pythonSdk);
155       final String perVersionDependenciesDir = version.isPy3K() ? PY3_HELPER_DEPENDENCIES_DIR : PY2_HELPER_DEPENDENCIES_DIR;
156       PythonEnvUtil.addToPythonPath(cmd.getEnvironment(), FileUtil.join(getPythonPathEntry(), perVersionDependenciesDir));
157       return cmd;
158     }
159   }
160
161   /**
162    * Module Python helper can be executed from zip-archive
163    */
164   public static class ModuleHelperPackage extends PathHelperPackage {
165     private final String myModuleName;
166
167     public ModuleHelperPackage(String moduleName, String relativePath) {
168       super(getHelperFile(relativePath).getAbsolutePath());
169       this.myModuleName = moduleName;
170     }
171
172     @NotNull
173     @Override
174     public String asParamString() {
175       return "-m" + myModuleName;
176     }
177
178     @NotNull
179     @Override
180     public String getPythonPathEntry() {
181       return FileUtil.toSystemDependentName(myPath.getAbsolutePath());
182     }
183   }
184
185   /**
186    * Script Python helper can be executed as a Python script, therefore
187    * PYTHONDONTWRITEBYTECODE option is set not to spoil installation
188    * with .pyc files
189    */
190   public static class ScriptPythonHelper extends PathHelperPackage {
191     private final String myPythonPath;
192
193     public ScriptPythonHelper(String script, File pythonPath) {
194       super(new File(pythonPath, script).getAbsolutePath());
195       myPythonPath = pythonPath.getAbsolutePath();
196     }
197
198     @Override
199     public void addToPythonPath(@NotNull Map<String, String> environment) {
200       PythonEnvUtil.setPythonDontWriteBytecode(environment);
201       super.addToPythonPath(environment);
202     }
203
204     @NotNull
205     @Override
206     public String getPythonPathEntry() {
207       return myPythonPath;
208     }
209   }
210
211   
212   @NotNull
213   @Override
214   public String getPythonPathEntry() {
215     return myModule.getPythonPathEntry();
216   }
217
218   @Override
219   public void addToPythonPath(@NotNull Map<String, String> environment) {
220     myModule.addToPythonPath(environment);
221   }
222
223   @Override
224   public void addToGroup(@NotNull ParamsGroup group, @NotNull GeneralCommandLine cmd) {
225     myModule.addToGroup(group, cmd);
226   }
227
228   @NotNull
229   @Override
230   public String asParamString() {
231     return myModule.asParamString();
232   }
233
234   @NotNull
235   @Override
236   public GeneralCommandLine newCommandLine(@NotNull String sdkPath, @NotNull List<String> parameters) {
237     return myModule.newCommandLine(sdkPath, parameters);
238   }
239
240   @NotNull
241   @Override
242   public GeneralCommandLine newCommandLine(@NotNull Sdk pythonSdk, @NotNull List<String> parameters) {
243     return myModule.newCommandLine(pythonSdk, parameters);
244   }
245
246 }