Skip to content

Commit ef1531d

Browse files
authored
Support run configuration for PyCharm Community & Professional (#19)
Closes: #10
1 parent 523b52d commit ef1531d

File tree

9 files changed

+194
-12
lines changed

9 files changed

+194
-12
lines changed

.idea/gradle.xml

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

build.gradle.kts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ dependencies {
3838
pluginModule(implementation(project(":mise-products-gradle")))
3939
pluginModule(implementation(project(":mise-products-idea")))
4040
pluginModule(implementation(project(":mise-products-nodejs")))
41+
pluginModule(implementation(project(":mise-products-pycharm")))
4142
pluginModule(implementation(project(":mise-products-rider")))
4243

4344
plugins(listOf())
@@ -161,6 +162,7 @@ allprojects {
161162
detekt(project(":mise-products-gradle"))
162163
detekt(project(":mise-products-idea"))
163164
detekt(project(":mise-products-nodejs"))
165+
detekt(project(":mise-products-pycharm"))
164166
detekt(project(":mise-products-rider"))
165167
}
166168

@@ -215,7 +217,7 @@ val runIdePlatformTypes =
215217
runIdePlatformTypes.forEach { platformType ->
216218
intellijPlatformTesting.runIde.register("run${platformType.name}") {
217219
type = platformType
218-
version = "2024.1"
220+
version = "2024.3"
219221

220222
plugins {
221223
// plugin("pluginId", "1.0.0")

modules/core/src/main/kotlin/com/github/l34130/mise/core/MiseHelper.kt

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,11 @@ import com.github.l34130.mise.core.run.MiseRunConfigurationSettingsEditor
77
import com.github.l34130.mise.core.setting.MiseSettings
88
import com.intellij.execution.configurations.RunConfigurationBase
99
import com.intellij.openapi.components.service
10+
import com.intellij.platform.ide.progress.TaskCancellation
11+
import com.intellij.platform.ide.progress.withBackgroundProgress
1012
import com.intellij.util.application
13+
import kotlinx.coroutines.Dispatchers
14+
import kotlinx.coroutines.runBlocking
1115
import java.util.function.Supplier
1216

1317
object MiseHelper {
@@ -30,16 +34,20 @@ object MiseHelper {
3034
else -> return emptyMap()
3135
}
3236

33-
return MiseCommandLineHelper
34-
.getEnvVars(workDir, configEnvironment)
35-
.fold(
36-
onSuccess = { envVars -> envVars },
37-
onFailure = {
38-
if (it !is MiseCommandLineNotFoundException) {
39-
MiseNotificationServiceUtils.notifyException("Failed to load environment variables", it)
40-
}
41-
emptyMap()
42-
},
43-
)
37+
return runBlocking(Dispatchers.IO) {
38+
withBackgroundProgress(configuration.project, "Getting Mise envvars", TaskCancellation.nonCancellable()) {
39+
MiseCommandLineHelper
40+
.getEnvVars(workDir, configEnvironment)
41+
.fold(
42+
onSuccess = { envVars -> envVars },
43+
onFailure = {
44+
if (it !is MiseCommandLineNotFoundException) {
45+
MiseNotificationServiceUtils.notifyException("Failed to load environment variables", it)
46+
}
47+
mapOf()
48+
},
49+
)
50+
}
51+
}
4452
}
4553
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import org.jetbrains.intellij.platform.gradle.IntelliJPlatformType
2+
import org.jetbrains.intellij.platform.gradle.TestFrameworkType
3+
4+
fun properties(key: String) = project.findProperty(key).toString()
5+
6+
plugins {
7+
id("org.jetbrains.intellij.platform.module")
8+
alias(libs.plugins.kotlin) // Kotlin support
9+
}
10+
11+
dependencies {
12+
implementation(project(":mise-core"))
13+
testImplementation(libs.junit)
14+
15+
// Configure Gradle IntelliJ Plugin - read more: https://github.com/JetBrains/gradle-intellij-plugin
16+
intellijPlatform {
17+
create(IntelliJPlatformType.PyCharmCommunity, properties("platformVersion"))
18+
19+
bundledPlugins("PythonCore")
20+
21+
jetbrainsRuntime()
22+
testFramework(TestFrameworkType.Platform)
23+
}
24+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
package com.github.l34130.mise.pycharm.run
2+
3+
import com.github.l34130.mise.core.MiseHelper
4+
import com.intellij.execution.ExecutionListener
5+
import com.intellij.execution.process.ProcessHandler
6+
import com.intellij.execution.runners.ExecutionEnvironment
7+
import com.jetbrains.python.run.PythonRunConfiguration
8+
9+
class MisePythonExecutionListener : ExecutionListener {
10+
override fun processStarting(
11+
executorId: String,
12+
env: ExecutionEnvironment,
13+
) {
14+
val pythonRunConfiguration = env.runProfile as? PythonRunConfiguration ?: return
15+
16+
val envVars =
17+
MiseHelper.getMiseEnvVarsOrNotify(
18+
configuration = pythonRunConfiguration,
19+
workingDirectory = { pythonRunConfiguration.workingDirectory },
20+
)
21+
22+
if (envVars.isEmpty()) {
23+
return super.processStarting(executorId, env)
24+
}
25+
26+
executions[env.executionId] = pythonRunConfiguration.envs
27+
pythonRunConfiguration.envs.putAll(envVars)
28+
29+
super.processStarting(executorId, env)
30+
}
31+
32+
override fun processStarted(
33+
executorId: String,
34+
env: ExecutionEnvironment,
35+
handler: ProcessHandler,
36+
) {
37+
restoreEnvVars(env)
38+
super.processStarted(executorId, env, handler)
39+
}
40+
41+
override fun processNotStarted(
42+
executorId: String,
43+
env: ExecutionEnvironment,
44+
) {
45+
restoreEnvVars(env)
46+
super.processNotStarted(executorId, env)
47+
}
48+
49+
override fun processTerminating(
50+
executorId: String,
51+
env: ExecutionEnvironment,
52+
handler: ProcessHandler,
53+
) {
54+
restoreEnvVars(env)
55+
super.processTerminating(executorId, env, handler)
56+
}
57+
58+
private fun restoreEnvVars(env: ExecutionEnvironment) {
59+
val originalEnvVars = executions[env.executionId] ?: return
60+
executions.remove(env.executionId)
61+
62+
val pythonRunConfiguration = env.runProfile as? PythonRunConfiguration ?: return
63+
pythonRunConfiguration.envs = originalEnvVars.toMutableMap()
64+
}
65+
66+
companion object {
67+
// Contains original environment variables
68+
private val executions: MutableMap<Long, Map<String, String>> = mutableMapOf()
69+
}
70+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
package com.github.l34130.mise.pycharm.run
2+
3+
import com.github.l34130.mise.core.MiseHelper
4+
import com.github.l34130.mise.core.run.MiseRunConfigurationSettingsEditor
5+
import com.intellij.execution.Location
6+
import com.intellij.execution.configurations.GeneralCommandLine
7+
import com.intellij.execution.configurations.RunnerSettings
8+
import com.intellij.openapi.options.SettingsEditor
9+
import com.jetbrains.python.run.AbstractPythonRunConfiguration
10+
import com.jetbrains.python.run.PythonRunConfigurationExtension
11+
import org.jdom.Element
12+
13+
class MisePythonRunConfigurationExtension : PythonRunConfigurationExtension() {
14+
override fun isApplicableFor(runConfiguration: AbstractPythonRunConfiguration<*>): Boolean = true
15+
16+
override fun isEnabledFor(
17+
runConfiguration: AbstractPythonRunConfiguration<*>,
18+
runnerSettings: RunnerSettings?,
19+
): Boolean = true
20+
21+
override fun <P : AbstractPythonRunConfiguration<*>> createEditor(configuration: P): SettingsEditor<P> =
22+
MiseRunConfigurationSettingsEditor(configuration.project)
23+
24+
override fun getSerializationId(): String = MiseRunConfigurationSettingsEditor.SERIALIZATION_ID
25+
26+
override fun writeExternal(
27+
runConfiguration: AbstractPythonRunConfiguration<*>,
28+
element: Element,
29+
) {
30+
MiseRunConfigurationSettingsEditor.writeExternal(runConfiguration, element)
31+
}
32+
33+
override fun readExternal(
34+
runConfiguration: AbstractPythonRunConfiguration<*>,
35+
element: Element,
36+
) {
37+
MiseRunConfigurationSettingsEditor.readExternal(runConfiguration, element)
38+
}
39+
40+
override fun getEditorTitle(): String = MiseRunConfigurationSettingsEditor.EDITOR_TITLE
41+
42+
override fun patchCommandLine(
43+
runConfiguration: AbstractPythonRunConfiguration<*>,
44+
runnerSettings: RunnerSettings?,
45+
cmdLine: GeneralCommandLine,
46+
runnerId: String,
47+
) {
48+
val envVars =
49+
MiseHelper.getMiseEnvVarsOrNotify(
50+
configuration = runConfiguration,
51+
workingDirectory = { runConfiguration.workingDirectory },
52+
)
53+
54+
cmdLine.withEnvironment(envVars)
55+
}
56+
57+
override fun extendCreatedConfiguration(
58+
configuration: AbstractPythonRunConfiguration<*>,
59+
location: Location<*>,
60+
) {
61+
super.extendCreatedConfiguration(configuration, location)
62+
}
63+
}

settings.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ include(
2222
"modules/products/gradle",
2323
"modules/products/idea",
2424
"modules/products/nodejs",
25+
"modules/products/pycharm",
2526
"modules/products/rider",
2627
)
2728

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<idea-plugin require-restart="false">
2+
<extensions defaultExtensionNs="Pythonid">
3+
<runConfigurationExtension implementation="com.github.l34130.mise.pycharm.run.MisePythonRunConfigurationExtension"/>
4+
<!-- <pythonCommandLineTargetEnvironmentProvider implementation="com.github.l34130.mise.python.run.PythonCommandLineTargetEnvironmentProvider"/>-->
5+
</extensions>
6+
7+
<projectListeners>
8+
<listener class="com.github.l34130.mise.pycharm.run.MisePythonExecutionListener" topic="com.intellij.execution.ExecutionListener"/>
9+
</projectListeners>
10+
11+
</idea-plugin>

src/main/resources/META-INF/plugin.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,5 +68,6 @@
6868
<depends optional="true" config-file="mise-gradle.xml">com.intellij.gradle</depends>
6969
<depends optional="true" config-file="mise-idea.xml">com.intellij.java</depends>
7070
<depends optional="true" config-file="mise-javascript.xml">JavaScript</depends>
71+
<depends optional="true" config-file="mise-pycharm.xml">com.intellij.modules.python</depends>
7172
<depends optional="true" config-file="mise-rider.xml">com.intellij.modules.rider</depends>
7273
</idea-plugin>

0 commit comments

Comments
 (0)