Skip to content

Commit 7a580fd

Browse files
link/PY-85711/skip-non-python-modules-for-non-pycharm-ides
[python]: PY-85709: Support Python facet for non-PyCharm IDEs. The following code doesn't work for anything but PyCharm. ```kotlin ModuleRootManager.getInstance(module).sdk ``` We now call `com.jetbrains.python.module.PyModuleService.findPythonSdk` which supports both Python SDK and Facet. [python]: PY-85711 : Do not touch non-python modules in `removeFakeModuleEntity` and do not set `inherited` for newly created modules. 1. We should never delete any module which isn't python. 2. No need to look for sdk in workspace as we already do that for all modules by reverting their SDK settings. Moreover, `InheritedSdkDependency` was wrong: it set project-level Java JDK as Python SDK [python]: PY-85711 : Make `PyActiveSdkModuleConfigurable` filter non-python modules. See `com.jetbrains.python.configuration.PyActiveSdkModuleConfigurable.isSuitableForModule` comment [python]: PY-85711 : Move `isPythonModule` to `PyModuleService`. We are going to reuse it all over the code [python]: PY-85711 : Refactor `PyModuleService`. Drop unneeded class Merge-request: IJ-MR-183088 Merged-by: Ilya Kazakevich <[email protected]> GitOrigin-RevId: 19f65ba65ea7ea8d8ff8698a64e6a3cbe6803cb0
1 parent 2119408 commit 7a580fd

15 files changed

Lines changed: 77 additions & 66 deletions

File tree

python/interpreters/src/impl/InterpreterServiceImpl.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ internal object InterpreterServiceImpl : InterpreterService {
4141
}
4242

4343
override suspend fun getForModule(module: Module): Interpreter? {
44-
val pythonSdk = ModuleRootManager.getInstance(module).sdk?.takeIf { isPythonSdk(it) } ?: return null
44+
val pythonSdk = PythonSdkUtil.findPythonSdk(module)?.takeIf { isPythonSdk(it) } ?: return null
4545
val data = pythonSdk.getOrCreateAdditionalData()
4646

4747
return findInterpreter(data, pythonSdk)

python/openapi/src/com/jetbrains/python/module/PyModuleService.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,18 @@
44
import com.intellij.openapi.application.ApplicationManager;
55
import com.intellij.openapi.module.Module;
66
import com.intellij.openapi.projectRoots.Sdk;
7+
import com.intellij.openapi.roots.ModuleRootManager;
78
import com.intellij.openapi.vfs.VirtualFile;
89
import com.intellij.util.Consumer;
10+
import org.jetbrains.annotations.ApiStatus;
911
import org.jetbrains.annotations.NotNull;
1012
import org.jetbrains.annotations.Nullable;
1113

1214

1315
public abstract class PyModuleService {
14-
public abstract @Nullable Sdk findPythonSdk(@NotNull Module module);
16+
public @Nullable Sdk findPythonSdk(@NotNull Module module) {
17+
return ModuleRootManager.getInstance(module).getSdk();
18+
}
1519

1620
public void forAllFacets(@NotNull Module module, @NotNull Consumer<Object> facetConsumer) {
1721
}
@@ -24,4 +28,6 @@ public static PyModuleService getInstance() {
2428
public boolean isFileIgnored(@NotNull VirtualFile file) {
2529
return false;
2630
}
31+
@ApiStatus.Internal
32+
public abstract boolean isPythonModule(@NotNull Module module);
2733
}

python/pluginCore/impl/src/com/intellij/python/community/plugin/impl/run/PyPluginSdkFragment.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ class PyPluginSdkFragment<T : AbstractPythonRunConfiguration<*>> : SettingsEdito
155155
private fun getSelectedSdk(): Sdk? {
156156
if (currentMode == SDK_OF_MODULE) {
157157
((modulesCombo?.selectedItem) as? Module)?.let {
158-
return ModuleRootManager.getInstance(it).sdk
158+
return PythonSdkUtil.findPythonSdk(it)
159159
}
160160
}
161161
else if (currentMode == SDK_FROM_LIST) {

python/pluginMinor/src/com/intellij/python/community/plugin/minor/facet/PyPluginSdkModuleConfigurable.kt

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import com.intellij.openapi.projectRoots.Sdk
1010
import com.intellij.python.community.plugin.impl.facet.PythonFacetUtil
1111
import com.jetbrains.python.configuration.PyActiveSdkConfigurable
1212
import com.jetbrains.python.configuration.PyActiveSdkModuleConfigurable
13+
import com.jetbrains.python.module.PyModuleService
1314
import com.jetbrains.python.sdk.removeTransferredRoots
1415
import com.jetbrains.python.sdk.transferRoots
1516
import org.jetbrains.annotations.ApiStatus
@@ -22,7 +23,7 @@ internal class PyPluginSdkModuleConfigurable(project: Project?) : PyActiveSdkMod
2223
}
2324

2425
override fun getSdk(): Sdk? {
25-
return getSdkFromFacet(module)
26+
return PyModuleService.getInstance().findPythonSdk(module)
2627
}
2728
}
2829
}
@@ -42,13 +43,6 @@ fun setSdkToFacet(item: Sdk?, module: Module) {
4243
}
4344
}
4445

45-
@ApiStatus.Internal
46-
fun getSdkFromFacet(module: Module): Sdk? {
47-
val facetManager = FacetManager.getInstance(module)
48-
val facet = facetManager.getFacetByType(MinorPythonFacet.ID)
49-
return facet?.configuration?.sdk
50-
}
51-
5246
private fun setFacetSdk(facet: MinorPythonFacet,
5347
item: Sdk?,
5448
module: Module) {

python/python-core-impl/src/com/jetbrains/python/extensions/ModuleExt.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ package com.jetbrains.python.extensions
1717

1818
import com.intellij.openapi.module.Module
1919
import com.intellij.openapi.projectRoots.Sdk
20-
import com.intellij.openapi.roots.ModuleRootManager
20+
import com.jetbrains.python.sdk.legacy.PythonSdkUtil
2121

2222

23-
fun Module.getSdk(): Sdk? = ModuleRootManager.getInstance(this).sdk
23+
fun Module.getSdk(): Sdk? = PythonSdkUtil.findPythonSdk(this)

python/python-pyproject/src/com/intellij/python/pyproject/model/internal/workspaceTools.kt

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import com.intellij.openapi.externalSystem.autoimport.ExternalSystemRefreshStatu
66
import com.intellij.openapi.project.Project
77
import com.intellij.openapi.project.modules
88
import com.intellij.openapi.projectRoots.ProjectJdkTable
9-
import com.intellij.openapi.roots.ModuleRootManager
109
import com.intellij.openapi.roots.ModuleRootModificationUtil
1110
import com.intellij.openapi.util.Key
1211
import com.intellij.openapi.util.NlsSafe
@@ -27,6 +26,10 @@ import com.intellij.python.pyproject.model.spi.PyProjectTomlProject
2726
import com.intellij.python.pyproject.model.spi.Tool
2827
import com.intellij.python.pyproject.model.spi.WorkspaceName
2928
import com.intellij.util.messages.Topic
29+
import com.intellij.workspaceModel.ide.impl.legacyBridge.module.findModule
30+
import com.jetbrains.python.PyNames
31+
import com.jetbrains.python.module.PyModuleService
32+
import com.jetbrains.python.sdk.legacy.PythonSdkUtil
3033
import com.jetbrains.python.venvReader.Directory
3134
import kotlinx.coroutines.Dispatchers
3235
import kotlinx.coroutines.sync.Mutex
@@ -70,7 +73,7 @@ internal suspend fun linkProject(project: Project, projectModelRoot: Path) {
7073
val entries = generatePyProjectTomlEntries(files, excludeDirs)
7174

7275
if (entries.isNotEmpty()) {
73-
val sdks = project.modules.associate { Pair(it.name, ModuleRootManager.getInstance(it).sdk?.name) }
76+
val sdks = project.modules.associate { Pair(it.name, PythonSdkUtil.findPythonSdk(it)?.name) }
7477
project.workspaceModel.currentSnapshot.entities(ModuleEntity::class.java)
7578
unlinkProjectImpl(project, externalProjectPath)
7679

@@ -90,7 +93,7 @@ internal suspend fun linkProject(project: Project, projectModelRoot: Path) {
9093

9194
// Restore SDK assoc
9295
for (module in project.modules) {
93-
if (ModuleRootManager.getInstance(module).sdk == null) {
96+
if (PythonSdkUtil.findPythonSdk(module) == null) {
9497
val sdkName = sdks[module.name] ?: continue
9598
ProjectJdkTable.getInstance().findJdk(sdkName)?.let { sdk ->
9699
ModuleRootModificationUtil.setModuleSdk(module, sdk)
@@ -177,17 +180,8 @@ private suspend fun createEntityStorage(
177180
val fileUrlManager = project.workspaceModel.getVirtualFileUrlManager()
178181
val storage = MutableEntityStorage.create()
179182
for (pyProject in graph) {
180-
val existingModuleEntity = project.workspaceModel.currentSnapshot
181-
.entitiesBySource { it is PyProjectTomlEntitySource }
182-
.filterIsInstance<ModuleEntity>()
183-
.find { it.name == pyProject.name.name }
184-
val existingSdkEntity = existingModuleEntity
185-
?.dependencies
186-
?.find { it is SdkDependency } as? SdkDependency
187-
val sdkDependency = existingSdkEntity ?: InheritedSdkDependency
188183
val entitySource = PyProjectTomlEntitySource(pyProject.tomlFile.toVirtualFileUrl(virtualFileUrlManager))
189184
val moduleEntity = storage addEntity ModuleEntity(pyProject.name.name, emptyList(), entitySource) {
190-
dependencies += sdkDependency
191185
dependencies += ModuleSourceDependency
192186
for (moduleName in pyProject.dependencies) {
193187
dependencies += ModuleDependency(ModuleId(moduleName.name), true, DependencyScope.COMPILE, false)
@@ -210,6 +204,7 @@ private suspend fun createEntityStorage(
210204
}
211205
}
212206

207+
type = PYTHON_MODULE_ID_DATA_CLASS
213208
pyProjectTomlEntity = PyProjectTomlWorkspaceEntity(participatedTools = participatedTools, pyProject.tomlFile.parent.toVirtualFileUrl(fileUrlManager), entitySource)
214209
exModuleOptions = ExternalSystemModuleOptionsEntity(entitySource) {
215210
externalSystem = PYTHON_SOURCE_ROOT_TYPE.name
@@ -220,6 +215,7 @@ private suspend fun createEntityStorage(
220215
return@withContext storage
221216
}
222217

218+
223219
private class PyProjectTomlEntitySource(tomlFile: VirtualFileUrl) : EntitySource {
224220
override val virtualFileUrl: VirtualFileUrl = tomlFile
225221
}
@@ -247,9 +243,14 @@ private data class PyProjectTomlBasedEntryImpl(
247243
* @see com.intellij.openapi.project.impl.getOrInitializeModule
248244
*/
249245
private fun removeFakeModuleEntity(storage: MutableEntityStorage, modulesToRemove: Set<String>) {
246+
val moduleService = PyModuleService.getInstance()
250247
val contentRoots = storage
251248
.entitiesBySource { it !is PyProjectTomlEntitySource }
252249
.filterIsInstance<ContentRootEntity>()
250+
.filter {
251+
val module = it.module.findModule(storage) ?: return@filter false
252+
moduleService.isPythonModule(module)
253+
}
253254
.toList()
254255
for (entity in contentRoots) {
255256
if (entity.module.name in modulesToRemove) {
@@ -285,4 +286,6 @@ private suspend fun findSrc(root: Directory): Set<Directory> =
285286
withContext(Dispatchers.IO) {
286287
val src = root.resolve("src")
287288
if (src.exists()) setOf(src) else emptySet()
288-
}
289+
}
290+
291+
private val PYTHON_MODULE_ID_DATA_CLASS: ModuleTypeId = ModuleTypeId(PyNames.PYTHON_MODULE_ID)

python/python-sdk-configurator/backend/src/impl/ModulesSdkConfigurator.kt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import com.jetbrains.python.sdk.configuration.CreateSdkInfo
2525
import com.jetbrains.python.sdk.configuration.CreateSdkInfoWithTool
2626
import com.jetbrains.python.sdk.configuration.PyProjectSdkConfigurationExtension
2727
import com.jetbrains.python.sdk.getOrCreateAdditionalData
28+
import com.jetbrains.python.sdk.legacy.PythonSdkUtil
2829
import com.jetbrains.python.sdk.setAssociationToPath
2930
import com.jetbrains.python.venvReader.Directory
3031
import kotlinx.collections.immutable.toPersistentList
@@ -108,7 +109,7 @@ internal class ModulesSdkConfigurator private constructor(
108109
val tools = PyProjectSdkConfigurationExtension.createMap()
109110
val limit = Semaphore(permits = Registry.intValue("intellij.python.sdkConfigurator.backend.sdk.parallel"))
110111
val now = System.currentTimeMillis()
111-
val resultDef = project.modules.filter { ModuleRootManager.getInstance(it).sdk == null }.map { module ->
112+
val resultDef = project.modules.filter { PythonSdkUtil.findPythonSdk(it) == null }.map { module ->
112113
limit.withPermit {
113114
async {
114115
val moduleInfo = getModuleInfo(module, tools) ?: return@async null
@@ -190,7 +191,7 @@ internal class ModulesSdkConfigurator private constructor(
190191
} // Link workspace members with their workspace
191192
val reportedBrokenModules = mutableSetOf<Module>()
192193
for ((module, parentModule) in modulesWithSameSdk) {
193-
val parentSdk = ModuleRootManager.getInstance(parentModule).sdk
194+
val parentSdk = PythonSdkUtil.findPythonSdk(module)
194195
if (parentSdk != null) {
195196
ModuleRootModificationUtil.setModuleSdk(module, parentSdk) // This SDK is shared, no need to associate it
196197
// TODO: Support association with multiple modules

python/python-sdk/src/com/jetbrains/python/sdk/legacy/PythonSdkUtil.java

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -97,13 +97,7 @@ public static boolean isFreeTier() {
9797
if (module == null || module.isDisposed()) {
9898
return null;
9999
}
100-
101-
Sdk sdk = ModuleRootManager.getInstance(module).getSdk();
102-
if (sdk != null && isPythonSdk(sdk)) {
103-
return sdk;
104-
}
105-
106-
sdk = PyModuleService.getInstance().findPythonSdk(module);
100+
var sdk = PyModuleService.getInstance().findPythonSdk(module);
107101
if (sdk != null && isPythonSdk(sdk)) {
108102
return sdk;
109103
}

python/src/com/jetbrains/python/configuration/PyActiveSdkConfigurable.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -282,7 +282,7 @@ public boolean isModified() {
282282
sdk = ProjectRootManager.getInstance(myProject).getProjectSdk();
283283
}
284284
else {
285-
sdk = ModuleRootManager.getInstance(myModule).getSdk();
285+
sdk = com.jetbrains.python.sdk.PythonSdkUtil.findPythonSdk(myModule);
286286
}
287287

288288
if (sdk != null && PythonSdkUtil.isPythonSdk(sdk)) {

python/src/com/jetbrains/python/configuration/PyActiveSdkModuleConfigurable.java

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,29 @@
66
import com.intellij.openapi.options.UnnamedConfigurable;
77
import com.intellij.openapi.project.Project;
88
import com.jetbrains.python.PyBundle;
9+
import com.jetbrains.python.module.PyModuleService;
910
import org.jetbrains.annotations.ApiStatus;
1011
import org.jetbrains.annotations.NotNull;
1112

1213

1314
// Inherit in the module you are going to use it
1415
@ApiStatus.Internal
15-
public abstract class PyActiveSdkModuleConfigurable extends ModuleAwareProjectConfigurable {
16+
public abstract class PyActiveSdkModuleConfigurable extends ModuleAwareProjectConfigurable<UnnamedConfigurable> {
1617
private final Project myProject;
1718

1819
protected PyActiveSdkModuleConfigurable(Project project) {
19-
super(project, PyBundle.message("configurable.PyActiveSdkModuleConfigurable.python.interpreter.display.name"), "reference.settings.project.interpreter");
20+
super(project, PyBundle.message("configurable.PyActiveSdkModuleConfigurable.python.interpreter.display.name"),
21+
"reference.settings.project.interpreter");
2022
myProject = project;
2123
}
2224

25+
@Override
26+
protected final boolean isSuitableForModule(@NotNull Module module) {
27+
// One can't configure Python SDK for a random module as random module doesn't have a `baseDir`
28+
// which is a requirement for various SDK types.
29+
return PyModuleService.getInstance().isPythonModule(module);
30+
}
31+
2332
@Override
2433
protected @NotNull UnnamedConfigurable createModuleConfigurable(Module module) {
2534
return new PyActiveSdkConfigurable(module);

0 commit comments

Comments
 (0)