diff --git a/python/ide/impl/src/com/intellij/pycharm/community/ide/impl/miscProject/PyMiscService.kt b/python/ide/impl/src/com/intellij/pycharm/community/ide/impl/miscProject/PyMiscService.kt index 3816b7b2bd83..b760b7bdbf50 100644 --- a/python/ide/impl/src/com/intellij/pycharm/community/ide/impl/miscProject/PyMiscService.kt +++ b/python/ide/impl/src/com/intellij/pycharm/community/ide/impl/miscProject/PyMiscService.kt @@ -10,7 +10,7 @@ import com.intellij.pycharm.community.ide.impl.PyCharmCommunityCustomizationBund import com.intellij.pycharm.community.ide.impl.miscProject.impl.MiscProjectUsageCollector import com.jetbrains.python.Result import com.jetbrains.python.errorProcessing.emit -import com.jetbrains.python.util.ShowingMessageErrorSync +import com.jetbrains.python.errorProcessing.ErrorSink import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch @@ -42,7 +42,7 @@ class PyMiscService(private val scope: CoroutineScope) { } is Result.Failure -> { withContext(Dispatchers.EDT) { - ShowingMessageErrorSync.emit(projectCreationResult.error, project) + ErrorSink().emit(projectCreationResult.error, project) } } } diff --git a/python/junit5Tests-framework/src/com/intellij/python/junit5Tests/framework/fixtures.kt b/python/junit5Tests-framework/src/com/intellij/python/junit5Tests/framework/fixtures.kt index 2d3db4120925..48f35aaa161d 100644 --- a/python/junit5Tests-framework/src/com/intellij/python/junit5Tests/framework/fixtures.kt +++ b/python/junit5Tests-framework/src/com/intellij/python/junit5Tests/framework/fixtures.kt @@ -16,7 +16,6 @@ import kotlinx.coroutines.CoroutineExceptionHandler import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.cancel import kotlinx.coroutines.cancelAndJoin -import kotlinx.coroutines.flow.FlowCollector import kotlinx.coroutines.job import org.jetbrains.annotations.TestOnly import java.nio.file.Path @@ -52,16 +51,16 @@ fun applicationScope(name: String = UUID.randomUUID().toString()): TestFixture { - private val _errors = mutableListOf() - val errors: List get() = _errors +class CollectingErrorSink internal constructor() : ErrorSink { + val errors: List + field = mutableListOf() override suspend fun emit(value: PyErrorDetail) { - _errors.add(value) + errors.add(value) } fun clear() { - _errors.clear() + errors.clear() } } diff --git a/python/openapi/src/com/jetbrains/python/errorProcessing/ErrorSink.kt b/python/openapi/src/com/jetbrains/python/errorProcessing/ErrorSink.kt index 11bb24c169cb..c80e43d8ba77 100644 --- a/python/openapi/src/com/jetbrains/python/errorProcessing/ErrorSink.kt +++ b/python/openapi/src/com/jetbrains/python/errorProcessing/ErrorSink.kt @@ -1,6 +1,8 @@ // Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.jetbrains.python.errorProcessing +import com.intellij.openapi.application.ApplicationManager +import com.intellij.openapi.components.service import com.intellij.openapi.project.Project import kotlinx.coroutines.flow.FlowCollector @@ -11,11 +13,17 @@ import kotlinx.coroutines.flow.FlowCollector * For the most business-logic and backend functions please return [PyResult] or [PyError]. * * There will be a unified sink soon to show and log errors. - * Currently, only [com.jetbrains.python.util.ShowingMessageErrorSync] is a well-known implementation. + * Use function of the same name to get an instance, or accept it as an argument as it can be mocked in tests. * * See [PyError] */ -typealias ErrorSink = FlowCollector +fun interface ErrorSink : FlowCollector + +/** + * Default implementation of [ErrorSink] that shows message to user, but try to accept [ErrorSink] as an argument, use + * this function as a default value as a last resort only. + */ +fun ErrorSink(): ErrorSink = ApplicationManager.getApplication().service() data class PyErrorDetail( val error: PyError, @@ -24,4 +32,8 @@ data class PyErrorDetail( suspend fun ErrorSink.emit(error: PyError, project: Project? = null) { emit(PyErrorDetail(error, project)) +} + +fun ErrorSink.withProject(project: Project): ErrorSink = ErrorSink { + emit(PyErrorDetail(it.error, project)) } \ No newline at end of file diff --git a/python/pluginResources/intellij.python.community.impl.xml b/python/pluginResources/intellij.python.community.impl.xml index d57e7747b45f..615ad848d5d9 100644 --- a/python/pluginResources/intellij.python.community.impl.xml +++ b/python/pluginResources/intellij.python.community.impl.xml @@ -47,6 +47,7 @@ messages.PyBundle + diff --git a/python/python-features-trainer/src/com/intellij/python/featuresTrainer/ift/PythonLangSupport.kt b/python/python-features-trainer/src/com/intellij/python/featuresTrainer/ift/PythonLangSupport.kt index 5b568e209fdd..674b9c816d1c 100644 --- a/python/python-features-trainer/src/com/intellij/python/featuresTrainer/ift/PythonLangSupport.kt +++ b/python/python-features-trainer/src/com/intellij/python/featuresTrainer/ift/PythonLangSupport.kt @@ -10,7 +10,6 @@ import com.intellij.openapi.vfs.VirtualFile import com.intellij.util.concurrency.annotations.RequiresEdt import com.intellij.util.concurrency.annotations.RequiresReadLock import com.jetbrains.python.Result -import com.jetbrains.python.errorProcessing.ErrorSink import com.jetbrains.python.errorProcessing.emit import com.jetbrains.python.inspections.interpreter.InterpreterSettingsQuickFix import com.jetbrains.python.projectCreation.createVenvAndSdk @@ -18,7 +17,7 @@ import com.jetbrains.python.sdk.ModuleOrProject import com.jetbrains.python.sdk.pythonSdk import com.jetbrains.python.sdk.runWithSdkConfigurationLock import com.jetbrains.python.statistics.modules -import com.jetbrains.python.util.ShowingMessageErrorSync +import com.jetbrains.python.errorProcessing.ErrorSink import training.dsl.LessonContext import training.lang.AbstractLangSupport import training.learn.CourseManager @@ -33,7 +32,7 @@ import training.util.getFeedbackLink import training.util.isLearningProject import java.nio.file.Path -internal class PythonLangSupport(private val errorSink: ErrorSink = ShowingMessageErrorSync) : AbstractLangSupport() { +internal class PythonLangSupport(private val errorSink: ErrorSink = ErrorSink()) : AbstractLangSupport() { override val contentRootDirectoryName = "PyCharmLearningProject" diff --git a/python/src/com/jetbrains/python/util/ShowingMessageErrorSync.kt b/python/src/com/jetbrains/python/impl/ShowingMessageErrorSink.kt similarity index 78% rename from python/src/com/jetbrains/python/util/ShowingMessageErrorSync.kt rename to python/src/com/jetbrains/python/impl/ShowingMessageErrorSink.kt index 60fd6380eb76..c9bd05b996d5 100644 --- a/python/src/com/jetbrains/python/util/ShowingMessageErrorSync.kt +++ b/python/src/com/jetbrains/python/impl/ShowingMessageErrorSink.kt @@ -1,8 +1,7 @@ -// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. -package com.jetbrains.python.util +// Copyright 2000-2026 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +package com.jetbrains.python.impl import com.intellij.openapi.application.ApplicationManager -import com.intellij.openapi.project.Project import com.intellij.openapi.application.EDT import com.intellij.openapi.application.ModalityState import com.intellij.openapi.application.asContextElement @@ -18,13 +17,11 @@ import com.jetbrains.python.packaging.PyExecutionException import com.jetbrains.python.showProcessExecutionErrorDialog import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext -import org.jetbrains.annotations.ApiStatus /** * Displays the error with a message box and writes it to a log. */ -@ApiStatus.Internal -object ShowingMessageErrorSync : ErrorSink { +internal class ShowingMessageErrorSink : ErrorSink { override suspend fun emit(value: PyErrorDetail) { val (error, project) = value @@ -37,9 +34,9 @@ object ShowingMessageErrorSync : ErrorSink { thisLogger().warn(error.message) // Platform doesn't allow dialogs without a lock for now, fix later writeIntentReadAction { - when (val e = error) { + when (error) { is ExecError -> { - showProcessExecutionErrorDialog(project, e) + showProcessExecutionErrorDialog(project, error) } is MessageError -> { Messages.showErrorDialog(error.message, PyBundle.message("python.error")) @@ -48,8 +45,4 @@ object ShowingMessageErrorSync : ErrorSink { } } } - - fun withProject(project: Project): ErrorSink = ErrorSink { - emit(PyErrorDetail(it.error, project)) - } } diff --git a/python/src/com/jetbrains/python/impl/package-info.java b/python/src/com/jetbrains/python/impl/package-info.java new file mode 100644 index 000000000000..45eebcbc8938 --- /dev/null +++ b/python/src/com/jetbrains/python/impl/package-info.java @@ -0,0 +1,5 @@ +// Copyright 2000-2026 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +@Internal +package com.jetbrains.python.impl; + +import org.jetbrains.annotations.ApiStatus.Internal; diff --git a/python/src/com/jetbrains/python/newProject/NewProjectWizardPythonData.kt b/python/src/com/jetbrains/python/newProject/NewProjectWizardPythonData.kt index 73d245b2f9f4..23c2bf24eac8 100644 --- a/python/src/com/jetbrains/python/newProject/NewProjectWizardPythonData.kt +++ b/python/src/com/jetbrains/python/newProject/NewProjectWizardPythonData.kt @@ -15,7 +15,6 @@ import com.intellij.ui.dsl.builder.Panel import com.jetbrains.python.PyBundle import com.jetbrains.python.sdk.runWithSdkConfigurationLock import com.jetbrains.python.PythonModuleTypeBase -import com.jetbrains.python.errorProcessing.ErrorSink import com.jetbrains.python.errorProcessing.emit import com.jetbrains.python.newProjectWizard.projectPath.ProjectPathFlows import com.jetbrains.python.onFailure @@ -24,7 +23,7 @@ import com.jetbrains.python.sdk.add.v2.PySdkCreator import com.jetbrains.python.sdk.add.v2.PythonSdkPanelBuilderAndSdkCreator import com.jetbrains.python.sdk.configurePythonSdk import com.jetbrains.python.sdk.moduleIfExists -import com.jetbrains.python.util.ShowingMessageErrorSync +import com.jetbrains.python.errorProcessing.ErrorSink import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.combine @@ -85,7 +84,7 @@ class NewPythonProjectStep(parent: NewProjectWizardStep, val createPythonModuleS private var intellijModule: Module? = null private lateinit var pySdkCreator: PySdkCreator - private val errorSink: ErrorSink = ShowingMessageErrorSync + private val errorSink: ErrorSink = ErrorSink() private val projectPathFlows = ProjectPathFlows.create( pathProperty.toFlow().combine(nameProperty.toFlow()) { dirPath, projectName -> diff --git a/python/src/com/jetbrains/python/newProjectWizard/impl/PyV3UIServicesProd.kt b/python/src/com/jetbrains/python/newProjectWizard/impl/PyV3UIServicesProd.kt index fd61a609033c..a4ce4d040832 100644 --- a/python/src/com/jetbrains/python/newProjectWizard/impl/PyV3UIServicesProd.kt +++ b/python/src/com/jetbrains/python/newProjectWizard/impl/PyV3UIServicesProd.kt @@ -8,7 +8,6 @@ import com.intellij.ui.tree.ui.DefaultTreeUI.AUTO_EXPAND_ALLOWED import com.intellij.util.ui.showingScope import com.jetbrains.python.errorProcessing.ErrorSink import com.jetbrains.python.newProjectWizard.PyV3UIServices -import com.jetbrains.python.util.ShowingMessageErrorSync import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext @@ -21,7 +20,7 @@ internal object PyV3UIServicesProd : PyV3UIServices { } } - override val errorSink: ErrorSink = ShowingMessageErrorSync + override val errorSink: ErrorSink get() = ErrorSink() override suspend fun expandProjectTreeView(project: Project): Unit = withContext(Dispatchers.EDT) { // Null means no project pane opened diff --git a/python/src/com/jetbrains/python/packaging/management/PythonPackageManagerAction.kt b/python/src/com/jetbrains/python/packaging/management/PythonPackageManagerAction.kt index d24a4c47b181..d265d896b687 100644 --- a/python/src/com/jetbrains/python/packaging/management/PythonPackageManagerAction.kt +++ b/python/src/com/jetbrains/python/packaging/management/PythonPackageManagerAction.kt @@ -20,7 +20,6 @@ import com.jetbrains.python.packaging.management.ui.PythonPackageManagerUI import com.jetbrains.python.packaging.utils.PyPackageCoroutine import com.jetbrains.python.sdk.associatedModuleDir import com.jetbrains.python.sdk.pythonSdk -import com.jetbrains.python.util.ShowingMessageErrorSync import kotlinx.coroutines.Dispatchers import org.jetbrains.annotations.ApiStatus import kotlin.text.Regex.Companion.escape @@ -34,7 +33,7 @@ import kotlin.text.Regex.Companion.escape */ @ApiStatus.Internal abstract class PythonPackageManagerAction : DumbAwareAction() { - protected val errorSink: ErrorSink = ShowingMessageErrorSync + protected val errorSink: ErrorSink = ErrorSink() /** * The regex pattern that matches the file names that this action is applicable to. diff --git a/python/src/com/jetbrains/python/packaging/management/ui/PythonPackageManagerUI.kt b/python/src/com/jetbrains/python/packaging/management/ui/PythonPackageManagerUI.kt index 766494aa68be..162b161637ec 100644 --- a/python/src/com/jetbrains/python/packaging/management/ui/PythonPackageManagerUI.kt +++ b/python/src/com/jetbrains/python/packaging/management/ui/PythonPackageManagerUI.kt @@ -10,7 +10,6 @@ import com.intellij.platform.ide.progress.runWithModalProgressBlocking import com.intellij.util.concurrency.annotations.RequiresBlockingContext import com.intellij.util.concurrency.annotations.RequiresEdt import com.jetbrains.python.PyBundle -import com.jetbrains.python.errorProcessing.ErrorSink import com.jetbrains.python.errorProcessing.PyResult import com.jetbrains.python.errorProcessing.emit import com.jetbrains.python.getOrNull @@ -24,7 +23,7 @@ import com.jetbrains.python.packaging.management.PythonPackageManager import com.jetbrains.python.packaging.management.findPackageSpecification import com.jetbrains.python.packaging.pyRequirement import com.jetbrains.python.statistics.PyPackagesUsageCollector -import com.jetbrains.python.util.ShowingMessageErrorSync +import com.jetbrains.python.errorProcessing.ErrorSink import org.jetbrains.annotations.ApiStatus import org.jetbrains.annotations.Nls @@ -46,7 +45,7 @@ import org.jetbrains.annotations.Nls @ApiStatus.Experimental class PythonPackageManagerUI private constructor( @get:ApiStatus.Internal val manager: PythonPackageManager, - @get:ApiStatus.Internal val sink: ErrorSink = ShowingMessageErrorSync, + @get:ApiStatus.Internal val sink: ErrorSink = ErrorSink(), ) { @ApiStatus.Internal val project: Project = manager.project @@ -198,7 +197,7 @@ class PythonPackageManagerUI private constructor( @JvmStatic @JvmOverloads @ApiStatus.Internal - fun forSdk(project: Project, sdk: Sdk, sink: ErrorSink = ShowingMessageErrorSync): PythonPackageManagerUI { + fun forSdk(project: Project, sdk: Sdk, sink: ErrorSink = ErrorSink()): PythonPackageManagerUI { val packageManager = PythonPackageManager.forSdk(project, sdk) return PythonPackageManagerUI(packageManager, sink) } @@ -206,6 +205,6 @@ class PythonPackageManagerUI private constructor( @ApiStatus.Experimental fun forPackageManager( packageManager: PythonPackageManager, - ): PythonPackageManagerUI = PythonPackageManagerUI(packageManager, ShowingMessageErrorSync) + ): PythonPackageManagerUI = PythonPackageManagerUI(packageManager, ErrorSink()) } } diff --git a/python/src/com/jetbrains/python/poetry/sdk/configuration/PyPoetrySdkConfiguration.kt b/python/src/com/jetbrains/python/poetry/sdk/configuration/PyPoetrySdkConfiguration.kt index bc79ec3df923..e097a1451da4 100644 --- a/python/src/com/jetbrains/python/poetry/sdk/configuration/PyPoetrySdkConfiguration.kt +++ b/python/src/com/jetbrains/python/poetry/sdk/configuration/PyPoetrySdkConfiguration.kt @@ -40,7 +40,8 @@ import com.jetbrains.python.sdk.poetry.getPoetryExecutable import com.jetbrains.python.sdk.poetry.runPoetry import com.jetbrains.python.sdk.poetry.setupPoetry import com.jetbrains.python.sdk.poetry.suggestedSdkName -import com.jetbrains.python.util.ShowingMessageErrorSync +import com.jetbrains.python.errorProcessing.ErrorSink +import com.jetbrains.python.errorProcessing.withProject import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext import java.nio.file.Path @@ -138,7 +139,7 @@ internal class PyPoetrySdkConfiguration : PyProjectTomlConfigurationExtension { basePythonBinaryPath = baseSystemPython.pythonBinary, installPackages = true, init = tomlFile == null, - errorSink = ShowingMessageErrorSync.withProject(module.project) + errorSink = ErrorSink().withProject(module.project) ).getOr { return@withBackgroundProgress it } val path = poetry.resolvePythonBinary() diff --git a/python/src/com/jetbrains/python/sdk/AddInterpreterActions.kt b/python/src/com/jetbrains/python/sdk/AddInterpreterActions.kt index b3c7f3d7c0a5..bc6323db948a 100644 --- a/python/src/com/jetbrains/python/sdk/AddInterpreterActions.kt +++ b/python/src/com/jetbrains/python/sdk/AddInterpreterActions.kt @@ -43,7 +43,7 @@ import com.jetbrains.python.sdk.add.v2.PythonAddLocalInterpreterDialog import com.jetbrains.python.sdk.add.v2.PythonAddLocalInterpreterPresenter import com.jetbrains.python.sdk.configuration.CreateSdkInfoWithTool import com.jetbrains.python.target.PythonLanguageRuntimeType -import com.jetbrains.python.util.ShowingMessageErrorSync +import com.jetbrains.python.errorProcessing.ErrorSink import kotlinx.coroutines.CompletableDeferred import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Deferred @@ -121,7 +121,7 @@ internal class AddLocalInterpreterAction( ), DumbAware { override fun createDialog(): PythonAddLocalInterpreterDialog { val dialogPresenter = PythonAddLocalInterpreterPresenter( - moduleOrProject, errorSink = ShowingMessageErrorSync, bestGuessCreateSdkInfo = bestGuessCreateSdkInfo + moduleOrProject, errorSink = ErrorSink(), bestGuessCreateSdkInfo = bestGuessCreateSdkInfo ).apply { // Model provides flow, but we need to call Consumer sdkCreatedFlow.oneShotConsumer(onSdkCreated) 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 9e17dbabe622..8b45d1c74907 100644 --- a/python/src/com/jetbrains/python/sdk/add/v2/PythonAddLocalInterpreterDialog.kt +++ b/python/src/com/jetbrains/python/sdk/add/v2/PythonAddLocalInterpreterDialog.kt @@ -16,7 +16,8 @@ import com.jetbrains.python.TraceContext import com.jetbrains.python.newProjectWizard.projectPath.ProjectPathFlows import com.jetbrains.python.packaging.utils.PyPackageCoroutine import com.jetbrains.python.sdk.moduleIfExists -import com.jetbrains.python.util.ShowingMessageErrorSync +import com.jetbrains.python.errorProcessing.ErrorSink +import com.jetbrains.python.errorProcessing.withProject import kotlinx.coroutines.supervisorScope import org.jetbrains.annotations.NonNls import javax.swing.JComponent @@ -54,7 +55,7 @@ internal class PythonAddLocalInterpreterDialog(private val dialogPresenter: Pyth } override fun createCenterPanel(): JComponent { - val errorSink = ShowingMessageErrorSync.withProject(dialogPresenter.moduleOrProject.project) + val errorSink = ErrorSink().withProject(dialogPresenter.moduleOrProject.project) val rootPanel = panel { model = PythonLocalAddInterpreterModel(ProjectPathFlows.create(basePath), EelFileSystem(eelApi = localEel)) 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 be725ff7d819..6deadd37c6ea 100644 --- a/python/src/com/jetbrains/python/sdk/add/v2/PythonSdkPanelBuilderAndSdkCreator.kt +++ b/python/src/com/jetbrains/python/sdk/add/v2/PythonSdkPanelBuilderAndSdkCreator.kt @@ -33,7 +33,8 @@ import com.jetbrains.python.sdk.add.v2.venv.setupVirtualenv import com.jetbrains.python.statistics.InterpreterCreationMode import com.jetbrains.python.statistics.InterpreterTarget import com.jetbrains.python.statistics.InterpreterType -import com.jetbrains.python.util.ShowingMessageErrorSync +import com.jetbrains.python.errorProcessing.ErrorSink +import com.jetbrains.python.errorProcessing.withProject import com.jetbrains.python.venvReader.VirtualEnvReader import kotlinx.coroutines.CompletableDeferred import kotlinx.coroutines.CoroutineScope @@ -108,7 +109,7 @@ internal class PythonSdkPanelBuilderAndSdkCreator( custom = PythonAddCustomInterpreter( model = model, module = module, - errorSink = module?.project?.let { ShowingMessageErrorSync.withProject(it) } ?: ShowingMessageErrorSync, + errorSink = module?.project?.let { ErrorSink().withProject(it) } ?: ErrorSink(), limitExistingEnvironments = limitExistingEnvironments, bestGuessCreateSdkInfo = CompletableDeferred(value = null) ) diff --git a/python/src/com/jetbrains/python/sdk/add/v2/uiUtils.kt b/python/src/com/jetbrains/python/sdk/add/v2/uiUtils.kt index d8c31eaf275a..143e414c5c47 100644 --- a/python/src/com/jetbrains/python/sdk/add/v2/uiUtils.kt +++ b/python/src/com/jetbrains/python/sdk/add/v2/uiUtils.kt @@ -35,7 +35,6 @@ import com.intellij.util.SystemProperties import com.intellij.util.ui.JBUI import com.jetbrains.python.PyBundle import com.jetbrains.python.PyBundle.message -import com.jetbrains.python.errorProcessing.ErrorSink import com.jetbrains.python.errorProcessing.PyResult import com.jetbrains.python.errorProcessing.emit import com.jetbrains.python.onFailure @@ -47,7 +46,7 @@ import com.jetbrains.python.sdk.add.v2.PythonSupportedEnvironmentManagers.VIRTUA import com.jetbrains.python.sdk.flavors.PythonSdkFlavor import com.jetbrains.python.sdk.flavors.conda.PyCondaEnv import com.jetbrains.python.sdk.flavors.conda.PyCondaEnvIdentity -import com.jetbrains.python.util.ShowingMessageErrorSync +import com.jetbrains.python.errorProcessing.ErrorSink import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineStart import kotlinx.coroutines.Dispatchers @@ -316,7 +315,7 @@ internal fun

Panel.pythonInterpreterComboBox( onPathSelected: suspend (P) -> PyResult>, customizer: RowsRange.() -> Unit = {}, ): PythonInterpreterComboBox

{ - val comboBox = PythonInterpreterComboBox(onPathSelected, fileSystem, ShowingMessageErrorSync) + val comboBox = PythonInterpreterComboBox(onPathSelected, fileSystem, ErrorSink()) .apply { setBusy(true) } diff --git a/python/src/com/jetbrains/python/sdk/add/v2/uv/EnvironmentCreatorUv.kt b/python/src/com/jetbrains/python/sdk/add/v2/uv/EnvironmentCreatorUv.kt index 345d99c41734..d648b64a03ee 100644 --- a/python/src/com/jetbrains/python/sdk/add/v2/uv/EnvironmentCreatorUv.kt +++ b/python/src/com/jetbrains/python/sdk/add/v2/uv/EnvironmentCreatorUv.kt @@ -18,7 +18,6 @@ import com.intellij.ui.dsl.gridLayout.UnscaledGaps import com.intellij.ui.dsl.listCellRenderer.textListCellRenderer import com.intellij.util.ui.AsyncProcessIcon import com.jetbrains.python.PyBundle.message -import com.jetbrains.python.errorProcessing.ErrorSink import com.jetbrains.python.errorProcessing.PyResult import com.jetbrains.python.newProjectWizard.collector.PythonNewProjectWizardCollector import com.jetbrains.python.sdk.add.v2.CustomNewEnvironmentCreator @@ -39,7 +38,8 @@ import com.jetbrains.python.sdk.uv.impl.createUvLowLevel import com.jetbrains.python.sdk.uv.impl.setUvExecutableLocal import com.jetbrains.python.sdk.uv.setupNewUvSdkAndEnv import com.jetbrains.python.statistics.InterpreterType -import com.jetbrains.python.util.ShowingMessageErrorSync +import com.jetbrains.python.errorProcessing.ErrorSink +import com.jetbrains.python.errorProcessing.withProject import com.jetbrains.python.venvReader.VirtualEnvReader import io.github.z4kn4fein.semver.Version import kotlinx.coroutines.CoroutineScope @@ -62,7 +62,7 @@ import kotlin.io.path.readText * UV-specific selector if a .venv directory already exists. */ internal fun PythonMutableTargetAddInterpreterModel.uvCreator(module: Module?): EnvironmentCreatorUv { - val errorSink = module?.project?.let { ShowingMessageErrorSync.withProject(it) } ?: ShowingMessageErrorSync + val errorSink = module?.project?.let { ErrorSink().withProject(it) } ?: ErrorSink() return EnvironmentCreatorUv(this, module, errorSink) } diff --git a/python/src/com/jetbrains/python/sdk/configuration/PyProjectSdkConfiguration.kt b/python/src/com/jetbrains/python/sdk/configuration/PyProjectSdkConfiguration.kt index 28514a7bb292..7f28d3e069be 100644 --- a/python/src/com/jetbrains/python/sdk/configuration/PyProjectSdkConfiguration.kt +++ b/python/src/com/jetbrains/python/sdk/configuration/PyProjectSdkConfiguration.kt @@ -17,7 +17,7 @@ import com.jetbrains.python.sdk.configuration.suppressors.PyPackageRequirementsI import com.jetbrains.python.sdk.configuration.suppressors.TipOfTheDaySuppressor import com.jetbrains.python.sdk.configurePythonSdk import com.jetbrains.python.sdk.installExecutableViaPythonScript -import com.jetbrains.python.util.ShowingMessageErrorSync +import com.jetbrains.python.errorProcessing.ErrorSink import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext import java.nio.file.Path @@ -25,7 +25,7 @@ import java.nio.file.Path object PyProjectSdkConfiguration { internal suspend fun installToolAndShowErrorIfNeeded(module: Module, pathPersister: (Path) -> Unit, toolToInstall: String) { performToolInstallation(pathPersister, toolToInstall).errorOrNull?.also { - ShowingMessageErrorSync.emit(it, module.project) + ErrorSink().emit(it, module.project) } } @@ -41,7 +41,7 @@ object PyProjectSdkConfiguration { thisLogger().debug("Configuring sdk using ${createSdkInfoWithTool.toolId}") val sdk = createSdkInfoWithTool.createSdkInfo.getSdkCreator(module).createSdk().getOr { - ShowingMessageErrorSync.emit(it.error, module.project) + ErrorSink().emit(it.error, module.project) return@withContext true } diff --git a/python/src/com/jetbrains/python/sdk/pipenv/PipEnvPipFileWatcher.kt b/python/src/com/jetbrains/python/sdk/pipenv/PipEnvPipFileWatcher.kt index 2ec02d4e7e1f..e51b9248bb47 100644 --- a/python/src/com/jetbrains/python/sdk/pipenv/PipEnvPipFileWatcher.kt +++ b/python/src/com/jetbrains/python/sdk/pipenv/PipEnvPipFileWatcher.kt @@ -30,7 +30,7 @@ import com.jetbrains.python.sdk.findAmongRoots import com.jetbrains.python.sdk.pythonSdk import com.jetbrains.python.sdk.skeleton.PySkeletonUtil import com.jetbrains.python.statistics.PipfileWatcherIdsHolder.Companion.RUN_PIPENV_LOCK_SUGGESTION -import com.jetbrains.python.util.ShowingMessageErrorSync +import com.jetbrains.python.errorProcessing.ErrorSink import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext import java.nio.file.Path @@ -115,7 +115,7 @@ internal class PipEnvPipFileWatcher : EditorFactoryListener { withBackgroundProgress(module.project, description) { val sdk = module.pythonSdk ?: return@withBackgroundProgress runPipEnv(sdk.associatedModulePath?.let { Path.of(it) }, *args.toTypedArray()).onFailure { - ShowingMessageErrorSync.emit(it, module.project) + ErrorSink().emit(it, module.project) } withContext(Dispatchers.IO) { diff --git a/python/src/com/jetbrains/python/target/PythonLanguageRuntimeUI.kt b/python/src/com/jetbrains/python/target/PythonLanguageRuntimeUI.kt index 5f644328545c..98a8352b9dac 100644 --- a/python/src/com/jetbrains/python/target/PythonLanguageRuntimeUI.kt +++ b/python/src/com/jetbrains/python/target/PythonLanguageRuntimeUI.kt @@ -19,7 +19,6 @@ import com.intellij.util.concurrency.annotations.RequiresEdt import com.intellij.util.ui.launchOnShow import com.jetbrains.python.PyBundle.message import com.jetbrains.python.TraceContext -import com.jetbrains.python.errorProcessing.ErrorSink import com.jetbrains.python.errorProcessing.emit import com.jetbrains.python.newProjectWizard.projectPath.ProjectPathFlows import com.jetbrains.python.onFailure @@ -32,7 +31,8 @@ import com.jetbrains.python.sdk.add.v2.PythonLocalAddInterpreterModel import com.jetbrains.python.sdk.add.v2.TargetFileSystem import com.jetbrains.python.sdk.configurePythonSdk import com.jetbrains.python.sdk.runWithSdkConfigurationLock -import com.jetbrains.python.util.ShowingMessageErrorSync +import com.jetbrains.python.errorProcessing.ErrorSink +import com.jetbrains.python.errorProcessing.withProject import kotlinx.coroutines.CompletableDeferred import kotlinx.coroutines.supervisorScope import kotlinx.coroutines.withContext @@ -51,7 +51,7 @@ internal class PythonLanguageRuntimeUI( private lateinit var mainPanel: PythonAddCustomInterpreter private var validationErrors: Collection = emptyList() - private val errorSink: ErrorSink = ShowingMessageErrorSync + private val errorSink: ErrorSink = ErrorSink() override fun createPanel(): DialogPanel { val targetEnvironmentConfiguration = targetSupplier.get() @@ -67,7 +67,7 @@ internal class PythonLanguageRuntimeUI( mainPanel = PythonAddCustomInterpreter( model = model, module = module, - errorSink = ShowingMessageErrorSync.withProject(project), + errorSink = ErrorSink().withProject(project), limitExistingEnvironments = false, bestGuessCreateSdkInfo = CompletableDeferred(value = null) ) diff --git a/python/src/com/jetbrains/python/util/package-info.java b/python/src/com/jetbrains/python/util/package-info.java new file mode 100644 index 000000000000..7df0bb45d3c2 --- /dev/null +++ b/python/src/com/jetbrains/python/util/package-info.java @@ -0,0 +1,5 @@ +// Copyright 2000-2026 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +@Internal +package com.jetbrains.python.util; + +import org.jetbrains.annotations.ApiStatus.Internal; diff --git a/python/src/com/jetbrains/python/uv/sdk/configuration/uvVenv.kt b/python/src/com/jetbrains/python/uv/sdk/configuration/uvVenv.kt index 8fbc97856819..097812dfd980 100644 --- a/python/src/com/jetbrains/python/uv/sdk/configuration/uvVenv.kt +++ b/python/src/com/jetbrains/python/uv/sdk/configuration/uvVenv.kt @@ -20,7 +20,8 @@ import com.jetbrains.python.sdk.setAssociationToModule import com.jetbrains.python.sdk.uv.impl.getUvExecutableLocal import com.jetbrains.python.sdk.uv.setupExistingEnvAndSdk import com.jetbrains.python.sdk.uv.setupNewUvSdkAndEnv -import com.jetbrains.python.util.ShowingMessageErrorSync +import com.jetbrains.python.errorProcessing.ErrorSink +import com.jetbrains.python.errorProcessing.withProject import com.jetbrains.python.venvReader.tryResolvePath import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext @@ -46,7 +47,7 @@ internal suspend fun createUvSdk(module: Module, toolId: ToolId, venvsInModule: throw IllegalStateException("Can't determine working dir for the module") } - val errorSink = ShowingMessageErrorSync.withProject(sdkAssociatedModule.project) + val errorSink = ErrorSink().withProject(sdkAssociatedModule.project) val sdkSetupResult = if (envExists) { getUvEnv(venvsInModule)?.let { setupExistingEnvAndSdk(it, uv, workingDir, false)