From 12f18602e624d8274f74ac416bbda794e0856a0d Mon Sep 17 00:00:00 2001 From: Vitaly Legchilkin Date: Mon, 16 Feb 2026 11:39:16 +0100 Subject: [PATCH] PY-87683 Refactor and extend trace contexts in Python plugin Rename bundle keys from tracecontext.* to trace.context.*, consolidate tool-specific detection contexts into a parameterized key, and add new trace contexts for ToolDetectionService and PyCondaEnvProvider. GitOrigin-RevId: 8c3933c324366db13934a818b3463a28f4494ae6 --- .../messages/PyBundle.properties | 29 ++++++++----------- .../PyV3BaseProjectSettings.kt | 2 +- .../toolwindow/PyPackagingToolWindowPanel.kt | 2 +- .../PyPackagingToolWindowService.kt | 6 ++-- .../modules/PyPackagesSdkController.kt | 2 +- .../python/sdk/AddInterpreterActions.kt | 6 +++- .../add/v2/PythonAddLocalInterpreterDialog.kt | 2 +- .../v2/PythonSdkPanelBuilderAndSdkCreator.kt | 2 +- .../python/sdk/add/v2/ToolValidator.kt | 2 +- .../com/jetbrains/python/sdk/add/v2/models.kt | 2 +- .../sdk/flavors/conda/PyCondaEnvProvider.kt | 7 ++++- .../python/target/PythonLanguageRuntimeUI.kt | 2 +- 12 files changed, 34 insertions(+), 30 deletions(-) diff --git a/python/pluginResources/messages/PyBundle.properties b/python/pluginResources/messages/PyBundle.properties index 4a71e729d315..d258187c45bf 100644 --- a/python/pluginResources/messages/PyBundle.properties +++ b/python/pluginResources/messages/PyBundle.properties @@ -1744,23 +1744,18 @@ python.source.root.detection.confirm.notification.action.revert=Revert python.source.root.detection.confirm.notification.action.mute=Don't show again read.only.python.sdk.system.wide.read.only.message=System Python packages are read-only. Select a different interpreter to modify packages. -tracecontext.detecting.poetry.executable=Detecting Poetry Executable -tracecontext.detecting.pip.executable=Detecting Pip Executable -tracecontext.detecting.uv.executable=Detecting uv Executable -tracecontext.detecting.hatch.executable=Detecting Hatch Executable -tracecontext.detecting.hatch.environments=Detecting Hatch Environments -tracecontext.detecting.executable=Detecting {0} Executable -tracecontext.detecting.venv=Detecting venv folder -tracecontext.generating.git=Generating git -tracecontext.packaging.tool.window=Packaging Tool Window -tracecontext.packages.sdk.controller=Packages SDK Controller -tracecontext.add.local.python.sdk.dialog=Add Local Python SDK Dialog -tracecontext.add.remote.python.sdk.dialog=Add {0} Python SDK Dialog -tracecontext.new.project.wizard=New Project Wizard -tracecontext.loading.interpreter.list=Loading Interpreter List -tracecontext.detecting.conda.executable.and.environments=Detecting Conda Executable and environments -tracecontext.packaging.tool.window.delete=Deleting Python Package -tracecontext.packaging.tool.window.install=Installing Python Package +trace.context.detecting.executable=Detecting {0} Executable +trace.context.generating.git=Generating git +trace.context.packaging.tool.window=Packaging Tool Window +trace.context.packages.sdk.controller=Packages SDK Controller +trace.context.add.local.python.sdk.dialog=Add Local Python SDK Dialog +trace.context.add.remote.python.sdk.dialog=Add {0} Python SDK Dialog +trace.context.new.project.wizard=New Project Wizard +trace.context.loading.interpreter.list=Loading Interpreter List +trace.context.packaging.tool.window.delete=Deleting Python Package +trace.context.packaging.tool.window.install=Installing Python Package +trace.context.python.tool.detection.service.detect.tools.for.module=Detect Tools for {0} +trace.context.py.conda.env.provider.cache.update=Conda Environments Cache Update evolution.uv.executable.is.not.found=uv executable is not found evolution.pyproject.toml.file.is.required.for.poetry=pyproject.toml file is required for Poetry diff --git a/python/src/com/jetbrains/python/newProjectWizard/PyV3BaseProjectSettings.kt b/python/src/com/jetbrains/python/newProjectWizard/PyV3BaseProjectSettings.kt index fa675c8c152e..be4c55b91e11 100644 --- a/python/src/com/jetbrains/python/newProjectWizard/PyV3BaseProjectSettings.kt +++ b/python/src/com/jetbrains/python/newProjectWizard/PyV3BaseProjectSettings.kt @@ -27,7 +27,7 @@ class PyV3BaseProjectSettings(var createGitRepository: Boolean = false) { suspend fun generateAndGetSdk(module: Module, baseDir: VirtualFile, supportsNotEmptyModuleStructure: Boolean = false): PyResult> = coroutineScope { val project = module.project if (createGitRepository) { - launch(TraceContext(PyBundle.message("tracecontext.generating.git")) + Dispatchers.IO) { + launch(TraceContext(PyBundle.message("trace.context.generating.git")) + Dispatchers.IO) { withBackgroundProgress(project, PyBundle.message("new.project.git")) { GitRepositoryInitializer.getInstance()?.initRepository(project, baseDir, true) ?: error("No git service available") } diff --git a/python/src/com/jetbrains/python/packaging/toolwindow/PyPackagingToolWindowPanel.kt b/python/src/com/jetbrains/python/packaging/toolwindow/PyPackagingToolWindowPanel.kt index 58f1ddb8df0d..d3d0f1560b7e 100644 --- a/python/src/com/jetbrains/python/packaging/toolwindow/PyPackagingToolWindowPanel.kt +++ b/python/src/com/jetbrains/python/packaging/toolwindow/PyPackagingToolWindowPanel.kt @@ -64,7 +64,7 @@ class PyPackagingToolWindowPanel(private val project: Project) : SimpleToolWindo private val moduleController = PyPackagesSdkController(project) private val descriptionController = PyPackageInfoPanel(project) private val packagingScope = PyPackageCoroutine.getScope(project) - .childScope("Packaging tool window", TraceContext(message("tracecontext.packaging.tool.window"), null)).also { + .childScope("Packaging tool window", TraceContext(message("trace.context.packaging.tool.window"), null)).also { Disposer.register(this, it.asDisposable()) } diff --git a/python/src/com/jetbrains/python/packaging/toolwindow/PyPackagingToolWindowService.kt b/python/src/com/jetbrains/python/packaging/toolwindow/PyPackagingToolWindowService.kt index 146ae9e45793..226018a9d56c 100644 --- a/python/src/com/jetbrains/python/packaging/toolwindow/PyPackagingToolWindowService.kt +++ b/python/src/com/jetbrains/python/packaging/toolwindow/PyPackagingToolWindowService.kt @@ -234,7 +234,7 @@ class PyPackagingToolWindowService(val project: Project, val serviceScope: Corou val context = sdkContext ?: return val managerUI = context.managerUI - withContext(TraceContext(message("tracecontext.packaging.tool.window.install"))) { + withContext(TraceContext(message("trace.context.packaging.tool.window.install"))) { PythonPackagesToolwindowStatisticsCollector.installPackageEvent.log(project) managerUI.installPackagesRequestBackground(installRequest, options)?.let { handleActionCompleted( @@ -248,7 +248,7 @@ class PyPackagingToolWindowService(val project: Project, val serviceScope: Corou suspend fun installPackage(pkg: PythonPackage, options: List = emptyList()) { val context = sdkContext ?: return - withContext(TraceContext(message("tracecontext.packaging.tool.window.install"))) { + withContext(TraceContext(message("trace.context.packaging.tool.window.install"))) { val installRequest = context.manager.findPackageSpecification(pkg.name, pkg.version)?.toInstallRequest() ?: return@withContext PythonPackagesToolwindowStatisticsCollector.installPackageEvent.log(project) context.managerUI.installPackagesRequestBackground(installRequest, options)?.let { @@ -265,7 +265,7 @@ class PyPackagingToolWindowService(val project: Project, val serviceScope: Corou val context = sdkContext ?: return val managerUI = context.managerUI - withContext(TraceContext(message("tracecontext.packaging.tool.window.delete"))) { + withContext(TraceContext(message("trace.context.packaging.tool.window.delete"))) { PythonPackagesToolwindowStatisticsCollector.uninstallPackageEvent.log(project) managerUI.uninstallPackagesBackground(selectedPackages.map { it.instance.name }) ?: return@withContext handleActionCompleted( diff --git a/python/src/com/jetbrains/python/packaging/toolwindow/modules/PyPackagesSdkController.kt b/python/src/com/jetbrains/python/packaging/toolwindow/modules/PyPackagesSdkController.kt index 940c2dc1c39f..8ed3c7abeb9b 100644 --- a/python/src/com/jetbrains/python/packaging/toolwindow/modules/PyPackagesSdkController.kt +++ b/python/src/com/jetbrains/python/packaging/toolwindow/modules/PyPackagesSdkController.kt @@ -38,7 +38,7 @@ import javax.swing.event.ListSelectionListener internal class PyPackagesSdkController(private val project: Project) : Disposable.Default { private val packagingScope: CoroutineScope = PyPackageCoroutine.getScope(project) - .childScope("Packages SDK Controller", TraceContext(PyBundle.message("tracecontext.packages.sdk.controller"), null)).also { + .childScope("Packages SDK Controller", TraceContext(PyBundle.message("trace.context.packages.sdk.controller"), null)).also { Disposer.register(this, it.asDisposable()) } diff --git a/python/src/com/jetbrains/python/sdk/AddInterpreterActions.kt b/python/src/com/jetbrains/python/sdk/AddInterpreterActions.kt index 3333847950c3..a7628b28a75e 100644 --- a/python/src/com/jetbrains/python/sdk/AddInterpreterActions.kt +++ b/python/src/com/jetbrains/python/sdk/AddInterpreterActions.kt @@ -32,6 +32,7 @@ import com.intellij.psi.util.ParameterizedCachedValue import com.intellij.python.pyproject.model.api.ModuleCreateInfo import com.intellij.python.pyproject.model.api.getModuleInfo import com.jetbrains.python.PyBundle +import com.jetbrains.python.TraceContext import com.jetbrains.python.run.PythonInterpreterTargetEnvironmentFactory import com.jetbrains.python.run.allowCreationTargetOfThisType import com.jetbrains.python.sdk.ModuleOrProject.ModuleAndProject @@ -48,6 +49,7 @@ import kotlinx.coroutines.Deferred import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.async import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext import org.jetbrains.annotations.ApiStatus import org.jetbrains.annotations.Nls import java.util.function.Consumer @@ -201,7 +203,9 @@ private class ToolDetectionService(project: Project, val coroutineScope: Corouti private fun detectBestToolAsync(module: Module): CachedValueProvider.Result> { val result = coroutineScope.async { - detectBestToolForModule(module) + withContext(TraceContext(PyBundle.message("trace.context.python.tool.detection.service.detect.tools.for.module", module.name))) { + detectBestToolForModule(module) + } } result.invokeOnCompletion { getOrCreateModificationTracker(module).incModificationCount() } return CachedValueProvider.Result.create(result, getOrCreateModificationTracker(module)) diff --git a/python/src/com/jetbrains/python/sdk/add/v2/PythonAddLocalInterpreterDialog.kt b/python/src/com/jetbrains/python/sdk/add/v2/PythonAddLocalInterpreterDialog.kt index f288e52cee66..a8db22483170 100644 --- a/python/src/com/jetbrains/python/sdk/add/v2/PythonAddLocalInterpreterDialog.kt +++ b/python/src/com/jetbrains/python/sdk/add/v2/PythonAddLocalInterpreterDialog.kt @@ -67,7 +67,7 @@ internal class PythonAddLocalInterpreterDialog(private val dialogPresenter: Pyth mainPanel.setupUI(this, WHEN_PROPERTY_CHANGED(AtomicProperty(basePath))) } - rootPanel.launchOnShow("PythonAddLocalInterpreterDialog launchOnShow", TraceContext(PyBundle.message("tracecontext.add.local.python.sdk.dialog"), null)) { + rootPanel.launchOnShow("PythonAddLocalInterpreterDialog launchOnShow", TraceContext(PyBundle.message("trace.context.add.local.python.sdk.dialog"), null)) { supervisorScope { model.initialize(this@supervisorScope) mainPanel.onShown(this@supervisorScope) diff --git a/python/src/com/jetbrains/python/sdk/add/v2/PythonSdkPanelBuilderAndSdkCreator.kt b/python/src/com/jetbrains/python/sdk/add/v2/PythonSdkPanelBuilderAndSdkCreator.kt index 0618b86534c4..fb6edee67b11 100644 --- a/python/src/com/jetbrains/python/sdk/add/v2/PythonSdkPanelBuilderAndSdkCreator.kt +++ b/python/src/com/jetbrains/python/sdk/add/v2/PythonSdkPanelBuilderAndSdkCreator.kt @@ -158,7 +158,7 @@ internal class PythonSdkPanelBuilderAndSdkCreator( } override fun onShownInitialization(scopingComponent: Component) { - scopingComponent.launchOnShow("${this::class.java} onShown initialization", TraceContext(message("tracecontext.new.project.wizard"), null)) { + scopingComponent.launchOnShow("${this::class.java} onShown initialization", TraceContext(message("trace.context.new.project.wizard"), null)) { initMutex.withLock { supervisorScope { initialize(this@supervisorScope) diff --git a/python/src/com/jetbrains/python/sdk/add/v2/ToolValidator.kt b/python/src/com/jetbrains/python/sdk/add/v2/ToolValidator.kt index b39f8ec7a9cc..627fcea78a7e 100644 --- a/python/src/com/jetbrains/python/sdk/add/v2/ToolValidator.kt +++ b/python/src/com/jetbrains/python/sdk/add/v2/ToolValidator.kt @@ -74,7 +74,7 @@ class ToolValidator

( } private fun autodetectExecutableJob(): Deferred { - return scope.async(TraceContext(PyBundle.message("tracecontext.detecting.executable", toolVersionPrefix), scope)) { + return scope.async(TraceContext(PyBundle.message("trace.context.detecting.executable", toolVersionPrefix), scope)) { withContext(Dispatchers.EDT) { isDirtyValue.set(true) } val validatedPath = fileSystem.autodetectWithVersionProbe(toolVersionPrefix, defaultPathSupplier) withContext(Dispatchers.EDT) { backProperty.set(validatedPath) } diff --git a/python/src/com/jetbrains/python/sdk/add/v2/models.kt b/python/src/com/jetbrains/python/sdk/add/v2/models.kt index 7020383ee114..3ba828b284ac 100644 --- a/python/src/com/jetbrains/python/sdk/add/v2/models.kt +++ b/python/src/com/jetbrains/python/sdk/add/v2/models.kt @@ -104,7 +104,7 @@ abstract class PythonAddInterpreterModel

( modificationCounter.updateAndGet { it + 1 } }.launchIn(scope + Dispatchers.EDT) - scope.launch(TraceContext(message("tracecontext.loading.interpreter.list"), scope) + Dispatchers.EDT) { + scope.launch(TraceContext(message("trace.context.loading.interpreter.list"), scope) + Dispatchers.EDT) { installable = fileSystem.getInstallableInterpreters() val projectPathPrefix = projectPathFlows.projectPathWithDefault.first() val existingSelectableInterpreters = fileSystem.getExistingSelectableInterpreters(projectPathPrefix) diff --git a/python/src/com/jetbrains/python/sdk/flavors/conda/PyCondaEnvProvider.kt b/python/src/com/jetbrains/python/sdk/flavors/conda/PyCondaEnvProvider.kt index 8f4ee04473d9..cd15254d107e 100644 --- a/python/src/com/jetbrains/python/sdk/flavors/conda/PyCondaEnvProvider.kt +++ b/python/src/com/jetbrains/python/sdk/flavors/conda/PyCondaEnvProvider.kt @@ -9,6 +9,8 @@ import com.intellij.python.community.execService.BinOnEel import com.intellij.python.community.execService.BinOnTarget import com.intellij.python.community.execService.BinaryToExec import com.intellij.python.community.execService.ExecService +import com.jetbrains.python.PyBundle +import com.jetbrains.python.TraceContext import com.jetbrains.python.errorProcessing.PyResult import com.jetbrains.python.isFailure import com.jetbrains.python.isSuccess @@ -16,6 +18,7 @@ import com.jetbrains.python.sdk.conda.execution.CondaExecutor import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.asExecutor import kotlinx.coroutines.future.asDeferred +import kotlinx.coroutines.withContext import org.jetbrains.annotations.ApiStatus import java.nio.file.Path import java.util.Locale @@ -38,7 +41,9 @@ class PyCondaEnvProvider( .expireAfterWrite(ttlAfterWrite.toJavaDuration()) .buildAsync { binaryToExec -> runBlockingMaybeCancellable { - getEnvsInternal(binaryToExec) + withContext(TraceContext(PyBundle.message("trace.context.py.conda.env.provider.cache.update"))) { + getEnvsInternal(binaryToExec) + } } } diff --git a/python/src/com/jetbrains/python/target/PythonLanguageRuntimeUI.kt b/python/src/com/jetbrains/python/target/PythonLanguageRuntimeUI.kt index 221a253e5fd0..6bbeea78c7f4 100644 --- a/python/src/com/jetbrains/python/target/PythonLanguageRuntimeUI.kt +++ b/python/src/com/jetbrains/python/target/PythonLanguageRuntimeUI.kt @@ -81,7 +81,7 @@ class PythonLanguageRuntimeUI( dialogPanel.launchOnShow( debugName = "PythonLanguageRuntimeUI launchOnShow", context = TraceContext( - title = message("tracecontext.add.remote.python.sdk.dialog", targetEnvironmentConfiguration.getTargetType().displayName), + title = message("trace.context.add.remote.python.sdk.dialog", targetEnvironmentConfiguration.getTargetType().displayName), parentTraceContext = null ) ) {