2 * Copyright 2000-2013 JetBrains s.r.o.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
16 package com.jetbrains.python.console;
18 import com.google.common.base.Function;
19 import com.google.common.base.Joiner;
20 import com.google.common.collect.Collections2;
21 import com.google.common.collect.Maps;
22 import com.intellij.openapi.actionSystem.AnAction;
23 import com.intellij.openapi.actionSystem.AnActionEvent;
24 import com.intellij.openapi.actionSystem.CommonDataKeys;
25 import com.intellij.openapi.actionSystem.LangDataKeys;
26 import com.intellij.openapi.fileEditor.FileDocumentManager;
27 import com.intellij.openapi.module.Module;
28 import com.intellij.openapi.module.ModuleManager;
29 import com.intellij.openapi.project.DumbAware;
30 import com.intellij.openapi.project.Project;
31 import com.intellij.openapi.projectRoots.Sdk;
32 import com.intellij.openapi.roots.ModuleRootManager;
33 import com.intellij.openapi.util.Pair;
34 import com.intellij.openapi.util.text.StringUtil;
35 import com.intellij.openapi.vfs.VirtualFile;
36 import com.intellij.util.PathMappingSettings;
37 import com.jetbrains.python.buildout.BuildoutFacet;
38 import com.jetbrains.python.remote.PyRemoteSdkCredentials;
39 import com.jetbrains.python.remote.PythonRemoteInterpreterManager;
40 import com.jetbrains.python.run.PythonCommandLineState;
41 import com.jetbrains.python.sdk.PySdkUtil;
42 import com.jetbrains.python.sdk.PythonSdkType;
43 import icons.PythonIcons;
44 import org.jetbrains.annotations.NotNull;
46 import java.util.Collection;
47 import java.util.List;
52 public class RunPythonConsoleAction extends AnAction implements DumbAware {
54 public RunPythonConsoleAction() {
56 getTemplatePresentation().setIcon(PythonIcons.Python.Python);
60 public void update(final AnActionEvent e) {
61 e.getPresentation().setVisible(true);
62 e.getPresentation().setEnabled(false);
63 final Project project = e.getData(CommonDataKeys.PROJECT);
64 if (project != null) {
65 Pair<Sdk, Module> sdkAndModule = findPythonSdkAndModule(project, e.getData(LangDataKeys.MODULE));
66 if (sdkAndModule.first != null) {
67 e.getPresentation().setEnabled(true);
72 public void actionPerformed(final AnActionEvent e) {
73 final Project project = e.getData(CommonDataKeys.PROJECT);
74 runPythonConsole(project, e.getData(LangDataKeys.MODULE));
78 public static PydevConsoleRunner runPythonConsole(Project project, Module contextModule) {
79 assert project != null : "Project is null";
81 FileDocumentManager.getInstance().saveAllDocuments();
83 Pair<Sdk, Module> sdkAndModule = findPythonSdkAndModule(project, contextModule);
85 Module module = sdkAndModule.second;
86 Sdk sdk = sdkAndModule.first;
90 PathMappingSettings mappingSettings = getMappings(project, sdk);
92 String[] setupFragment;
94 PyConsoleOptions.PyConsoleSettings settingsProvider = PyConsoleOptions.getInstance(project).getPythonConsoleSettings();
95 Collection<String> pythonPath = PythonCommandLineState.collectPythonPath(module, settingsProvider.addContentRoots(),
96 settingsProvider.addSourceRoots());
98 if (mappingSettings != null) {
99 pythonPath = mappingSettings.convertToRemote(pythonPath);
102 String selfPathAppend = constructPythonPathCommand(pythonPath);
104 String customStartScript = settingsProvider.getCustomStartScript();
106 if (customStartScript.trim().length() > 0) {
107 selfPathAppend += "\n" + customStartScript.trim();
110 String workingDir = settingsProvider.getWorkingDirectory();
111 if (StringUtil.isEmpty(workingDir)) {
112 if (module != null && ModuleRootManager.getInstance(module).getContentRoots().length > 0) {
113 workingDir = ModuleRootManager.getInstance(module).getContentRoots()[0].getPath();
116 if (ModuleManager.getInstance(project).getModules().length > 0) {
117 VirtualFile[] roots = ModuleRootManager.getInstance(ModuleManager.getInstance(project).getModules()[0]).getContentRoots();
118 if (roots.length > 0) {
119 workingDir = roots[0].getPath();
125 if (mappingSettings != null) {
126 workingDir = mappingSettings.convertToRemote(workingDir);
129 BuildoutFacet facet = null;
130 if (module != null) {
131 facet = BuildoutFacet.getInstance(module);
135 List<String> path = facet.getAdditionalPythonPath();
136 if (mappingSettings != null) {
137 path = mappingSettings.convertToRemote(path);
139 String prependStatement = facet.getPathPrependStatement(path);
140 setupFragment = new String[]{prependStatement, selfPathAppend};
143 setupFragment = new String[]{selfPathAppend};
146 return PydevConsoleRunner
147 .createAndRun(project, sdk, PyConsoleType.PYTHON, workingDir, Maps.newHashMap(settingsProvider.getEnvs()), setupFragment);
150 public static PathMappingSettings getMappings(Project project, Sdk sdk) {
151 PathMappingSettings mappingSettings = null;
152 if (PySdkUtil.isRemote(sdk)) {
153 PythonRemoteInterpreterManager instance = PythonRemoteInterpreterManager.getInstance();
154 if (instance != null) {
156 instance.setupMappings(project, (PyRemoteSdkCredentials)sdk.getSdkAdditionalData(), null);
159 return mappingSettings;
163 private static Pair<Sdk, Module> findPythonSdkAndModule(Project project, Module contextModule) {
165 Module module = null;
166 PyConsoleOptions.PyConsoleSettings settings = PyConsoleOptions.getInstance(project).getPythonConsoleSettings();
167 String sdkHome = settings.getSdkHome();
168 if (sdkHome != null) {
169 sdk = PythonSdkType.findSdkByPath(sdkHome);
170 if (settings.getModuleName() != null) {
171 module = ModuleManager.getInstance(project).findModuleByName(settings.getModuleName());
174 module = contextModule;
175 if (module == null && ModuleManager.getInstance(project).getModules().length > 0) {
176 module = ModuleManager.getInstance(project).getModules()[0];
180 if (sdk == null && settings.isUseModuleSdk()) {
181 if (contextModule != null) {
182 module = contextModule;
184 else if (settings.getModuleName() != null) {
185 module = ModuleManager.getInstance(project).findModuleByName(settings.getModuleName());
187 if (module != null) {
188 if (PythonSdkType.findPythonSdk(module) != null) {
189 sdk = PythonSdkType.findPythonSdk(module);
193 else if (contextModule != null) {
194 if (module == null) {
195 module = contextModule;
198 sdk = PythonSdkType.findPythonSdk(module);
203 for (Module m : ModuleManager.getInstance(project).getModules()) {
204 if (PythonSdkType.findPythonSdk(m) != null) {
205 sdk = PythonSdkType.findPythonSdk(m);
212 if (PythonSdkType.getAllSdks().size() > 0) {
213 //noinspection UnusedAssignment
214 sdk = PythonSdkType.getAllSdks().get(0); //take any python sdk
217 return Pair.create(sdk, module);
220 public static String constructPythonPathCommand(Collection<String> pythonPath) {
221 final String path = Joiner.on(", ").join(Collections2.transform(pythonPath, new Function<String, String>() {
223 public String apply(String input) {
224 return "'" + input.replace("\\", "\\\\") + "'";
228 return "sys.path.extend([" + path + "])";