ffecb6ddb39c434ba6630222429710b8711eae5b
[idea/community.git] / python / src / com / jetbrains / python / console / PydevConsoleRunnerFactory.java
1 /*
2  * Copyright 2000-2014 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.console;
17
18 import com.google.common.collect.Maps;
19 import com.intellij.openapi.application.TransactionGuard;
20 import com.intellij.openapi.application.TransactionId;
21 import com.intellij.openapi.module.Module;
22 import com.intellij.openapi.module.ModuleManager;
23 import com.intellij.openapi.project.Project;
24 import com.intellij.openapi.projectRoots.Sdk;
25 import com.intellij.openapi.roots.ModuleRootManager;
26 import com.intellij.openapi.util.Pair;
27 import com.intellij.openapi.util.text.StringUtil;
28 import com.intellij.openapi.vfs.VirtualFile;
29 import com.intellij.util.PathMapper;
30 import com.jetbrains.python.buildout.BuildoutFacet;
31 import com.jetbrains.python.run.PythonCommandLineState;
32 import com.jetbrains.python.sdk.PythonEnvUtil;
33 import org.jetbrains.annotations.NotNull;
34 import org.jetbrains.annotations.Nullable;
35
36 import java.util.Collection;
37 import java.util.List;
38 import java.util.Map;
39
40 /**
41  * @author traff
42  */
43 public class PydevConsoleRunnerFactory extends PythonConsoleRunnerFactory {
44   @Override
45   public PydevConsoleRunnerImpl createConsoleRunner(@NotNull Project project,
46                                                     @Nullable Module contextModule) {
47     Pair<Sdk, Module> sdkAndModule = PydevConsoleRunner.findPythonSdkAndModule(project, contextModule);
48
49     Module module = sdkAndModule.second;
50     Sdk sdk = sdkAndModule.first;
51
52     assert sdk != null;
53
54     PyConsoleOptions.PyConsoleSettings settingsProvider = PyConsoleOptions.getInstance(project).getPythonConsoleSettings();
55
56     PathMapper pathMapper = PydevConsoleRunner.getPathMapper(project, sdk, settingsProvider);
57
58     String[] setupFragment;
59
60     Collection<String> pythonPath = PythonCommandLineState.collectPythonPath(module, settingsProvider.shouldAddContentRoots(),
61                                                                              settingsProvider.shouldAddSourceRoots());
62
63     if (pathMapper != null) {
64       pythonPath = pathMapper.convertToRemote(pythonPath);
65     }
66
67     String customStartScript = settingsProvider.getCustomStartScript();
68
69     if (customStartScript.trim().length() > 0) {
70       customStartScript = "\n" + customStartScript;
71     }
72
73     String selfPathAppend = PydevConsoleRunner.constructPythonPathCommand(pythonPath, customStartScript);
74
75     String workingDir = settingsProvider.getWorkingDirectory();
76     if (StringUtil.isEmpty(workingDir)) {
77       if (module != null && ModuleRootManager.getInstance(module).getContentRoots().length > 0) {
78         workingDir = ModuleRootManager.getInstance(module).getContentRoots()[0].getPath();
79       }
80       else {
81         if (ModuleManager.getInstance(project).getModules().length > 0) {
82           VirtualFile[] roots = ModuleRootManager.getInstance(ModuleManager.getInstance(project).getModules()[0]).getContentRoots();
83           if (roots.length > 0) {
84             workingDir = roots[0].getPath();
85           }
86         }
87       }
88     }
89
90     if (pathMapper != null && workingDir != null) {
91       workingDir = pathMapper.convertToRemote(workingDir);
92     }
93
94     BuildoutFacet facet = null;
95     if (module != null) {
96       facet = BuildoutFacet.getInstance(module);
97     }
98
99     if (facet != null) {
100       List<String> path = facet.getAdditionalPythonPath();
101       if (pathMapper != null) {
102         path = pathMapper.convertToRemote(path);
103       }
104       String prependStatement = facet.getPathPrependStatement(path);
105       setupFragment = new String[]{prependStatement, selfPathAppend};
106     }
107     else {
108       setupFragment = new String[]{selfPathAppend};
109     }
110
111     Map<String, String> envs = Maps.newHashMap(settingsProvider.getEnvs());
112     putIPythonEnvFlag(project, envs);
113
114     //The transaction is needed due the the FileDocumentManager.getInstance().saveAllDocuments() call in PydevConsoleRunnerImpl
115     Runnable rerunAction = () -> TransactionGuard.submitTransaction(project, () -> {
116       PydevConsoleRunnerImpl runner = createConsoleRunner(project, module);
117       runner.run();
118     });
119
120     return createConsoleRunner(project, sdk, workingDir, envs, PyConsoleType.PYTHON, settingsProvider, rerunAction, setupFragment);
121   }
122
123   public static void putIPythonEnvFlag(@NotNull Project project, Map<String, String> envs) {
124     String ipythonEnabled = PyConsoleOptions.getInstance(project).isIpythonEnabled() ? "True" : "False";
125     envs.put(PythonEnvUtil.IPYTHONENABLE, ipythonEnabled);
126   }
127
128   protected PydevConsoleRunnerImpl createConsoleRunner(Project project,
129                                                        Sdk sdk,
130                                                        String workingDir,
131                                                        Map<String, String> envs,
132                                                        PyConsoleType consoleType,
133                                                        PyConsoleOptions.PyConsoleSettings settingsProvider,
134                                                        Runnable rerunAction, String... setupFragment) {
135     return new PydevConsoleRunnerImpl(project, sdk, consoleType, workingDir, envs, settingsProvider, rerunAction, setupFragment);
136   }
137 }