PY-20797 Fixed: Type checking can be improved: now not showing warning when trying...
[idea/community.git] / python / src / com / jetbrains / python / run / PyVirtualEnvReader.kt
1 /*
2  * Copyright 2000-2016 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.run
17
18 import com.intellij.openapi.diagnostic.Logger
19 import com.intellij.openapi.util.SystemInfo
20 import com.intellij.openapi.util.io.FileUtil
21 import com.intellij.util.EnvironmentUtil
22 import com.intellij.util.LineSeparator
23 import java.io.File
24
25 /**
26  * @author traff
27  */
28
29
30 class PyVirtualEnvReader(val virtualEnvSdkPath: String) : EnvironmentUtil.ShellEnvReader() {
31   private val LOG = Logger.getInstance("#com.jetbrains.python.run.PyVirtualEnvReader")
32
33   val activate = findActivateScript(virtualEnvSdkPath, shell)
34
35   override fun getShell(): String? {
36     if (File("/bin/bash").exists()) {
37       return "/bin/bash";
38     }
39     else
40       if (File("/bin/sh").exists()) {
41         return "/bin/sh";
42       }
43       else {
44         return super.getShell();
45       }
46   }
47
48   override fun readShellEnv(): MutableMap<String, String> {
49     if (SystemInfo.isUnix) {
50       return super.readShellEnv()
51     }
52     else {
53       if (activate != null) {
54         return readVirtualEnvOnWindows(activate);
55       }
56       else {
57         LOG.error("Can't find activate script for $virtualEnvSdkPath")
58         return mutableMapOf();
59       }
60     }
61   }
62
63   private fun readVirtualEnvOnWindows(activate: String): MutableMap<String, String> {
64     val activateFile = FileUtil.createTempFile("pycharm-virualenv-activate.", ".bat", false)
65     val envFile = FileUtil.createTempFile("pycharm-virualenv-envs.", ".tmp", false)
66     try {
67       FileUtil.copy(File(activate), activateFile);
68       FileUtil.appendToFile(activateFile, "\n\nset")
69       val command = listOf<String>(activateFile.path, ">", envFile.absolutePath)
70
71       return runProcessAndReadEnvs(command, envFile, LineSeparator.CRLF.separatorString)
72     }
73     finally {
74       FileUtil.delete(activateFile)
75       FileUtil.delete(envFile)
76     }
77
78   }
79
80   override fun getShellProcessCommand(): MutableList<String>? {
81     val shellPath = shell
82
83     if (shellPath == null || !File(shellPath).canExecute()) {
84       throw Exception("shell:" + shellPath)
85     }
86
87     return if (activate != null)
88       if (File(shellPath).name == "bash") {
89         mutableListOf(shellPath, "--rcfile", activate, "-i")
90       }
91       else {
92         mutableListOf(shellPath, "-i", "-c", "source '$activate'")
93       }
94     else super.getShellProcessCommand()
95   }
96
97 }
98
99 fun findActivateScript(path: String?, shellPath: String?): String? {
100   val shellName = if (shellPath != null) File(shellPath).name else null
101   val activate = if (SystemInfo.isWindows) File(File(path).parentFile, "activate.bat")
102   else if (shellName == "fish" || shellName == "csh") File(File(path).parentFile, "activate." + shellName)
103   else File(File(path).parentFile, "activate")
104
105   return if (activate.exists()) activate.absolutePath else null
106 }