From e255e8d0d06dad2834aab5741b09b634a99f9ce8 Mon Sep 17 00:00:00 2001 From: Vitaly Legchilkin Date: Wed, 25 Jun 2025 10:27:32 +0200 Subject: [PATCH] [python] i18n strings (remove hardcoded literals) GitOrigin-RevId: 14ad16249d0b030f4d3b88fc6b86dc7146dc3c72 --- .../PyPipfileSdkConfiguration.kt | 11 ++++---- .../configuration/PyPoetrySdkConfiguration.kt | 6 ++--- .../messages/PyBundle.properties | 26 +++++++------------ .../resources/messages/PyPsiBundle.properties | 2 ++ .../python/packaging/PyRequirements.kt | 7 +++-- .../conda/CondaPackageManagerEngine.kt | 3 ++- .../src/com/jetbrains/python/sdk/PySdkExt.kt | 13 +++++----- .../sdk/add/v2/uv/EnvironmentCreatorUv.kt | 3 ++- .../v2/uv/UvExistingEnvironmentSelector.kt | 9 +++++-- .../sdk/pipenv/PipenvCommandExecutor.kt | 13 ++++++---- .../python/sdk/poetry/PoetryPackageManager.kt | 3 ++- .../com/jetbrains/python/sdk/poetry/poetry.kt | 9 ++++--- .../sdk/poetry/ui/PoetryPanelCreator.kt | 11 ++++++-- .../python/sdk/uv/impl/UvLowLevel.kt | 7 ++--- 14 files changed, 70 insertions(+), 53 deletions(-) diff --git a/python/ide/impl/src/com/intellij/pycharm/community/ide/impl/configuration/PyPipfileSdkConfiguration.kt b/python/ide/impl/src/com/intellij/pycharm/community/ide/impl/configuration/PyPipfileSdkConfiguration.kt index 89fb33e59fe6..b2a031824eeb 100644 --- a/python/ide/impl/src/com/intellij/pycharm/community/ide/impl/configuration/PyPipfileSdkConfiguration.kt +++ b/python/ide/impl/src/com/intellij/pycharm/community/ide/impl/configuration/PyPipfileSdkConfiguration.kt @@ -40,9 +40,9 @@ import javax.swing.JPanel import kotlin.io.path.isExecutable import kotlin.io.path.pathString -internal class PyPipfileSdkConfiguration : PyProjectSdkConfigurationExtension { +private val LOGGER = Logger.getInstance(PyPipfileSdkConfiguration::class.java) - private val LOGGER = Logger.getInstance(PyPipfileSdkConfiguration::class.java) +internal class PyPipfileSdkConfiguration : PyProjectSdkConfigurationExtension { override suspend fun createAndAddSdkForConfigurator(module: Module): Sdk? = createAndAddSDk(module, Source.CONFIGURATOR) @@ -87,7 +87,8 @@ internal class PyPipfileSdkConfiguration : PyProjectSdkConfigurationExtension { private suspend fun createPipEnv(module: Module): PyResult { LOGGER.debug("Creating pipenv environment") return withBackgroundProgress(module.project, PyBundle.message("python.sdk.setting.up.pipenv.sentence")) { - val basePath = module.basePath ?: return@withBackgroundProgress PyResult.localizedError("Can't find module base path") + val basePath = module.basePath + ?: return@withBackgroundProgress PyResult.localizedError(PyBundle.message("python.sdk.provided.path.is.invalid",module.basePath)) val pipEnv = setupPipEnv(Path.of(basePath), null, true).getOr { PySdkConfigurationCollector.logPipEnv(module.project, PipEnvResult.CREATION_FAILURE) return@withBackgroundProgress it @@ -95,12 +96,12 @@ internal class PyPipfileSdkConfiguration : PyProjectSdkConfigurationExtension { val path = withContext(Dispatchers.IO) { VirtualEnvReader.Instance.findPythonInPythonRoot(Path.of(pipEnv)) } if (path == null) { - return@withBackgroundProgress PyResult.localizedError("Python executable is not found: $pipEnv") + return@withBackgroundProgress PyResult.localizedError(PyBundle.message("cannot.find.executable","python", pipEnv)) } val file = LocalFileSystem.getInstance().refreshAndFindFileByPath(path.toString()) if (file == null) { - return@withBackgroundProgress PyResult.localizedError("Python executable file is not found: $path") + return@withBackgroundProgress PyResult.localizedError(PyBundle.message("cannot.find.executable","python", path)) } PySdkConfigurationCollector.logPipEnv(module.project, PipEnvResult.CREATED) diff --git a/python/ide/impl/src/com/intellij/pycharm/community/ide/impl/configuration/PyPoetrySdkConfiguration.kt b/python/ide/impl/src/com/intellij/pycharm/community/ide/impl/configuration/PyPoetrySdkConfiguration.kt index 29d4a8540624..d9330d179030 100644 --- a/python/ide/impl/src/com/intellij/pycharm/community/ide/impl/configuration/PyPoetrySdkConfiguration.kt +++ b/python/ide/impl/src/com/intellij/pycharm/community/ide/impl/configuration/PyPoetrySdkConfiguration.kt @@ -105,19 +105,19 @@ internal class PyPoetrySdkConfiguration : PyProjectSdkConfigurationExtension { val basePath = module.basePath?.let { Path.of(it) } if (basePath == null) { - return@withBackgroundProgress PyResult.localizedError("Can't find module base path") + return@withBackgroundProgress PyResult.localizedError(PyBundle.message("python.sdk.provided.path.is.invalid",module.basePath)) } val poetry = setupPoetry(basePath, null, true, findAmongRoots(module, PY_PROJECT_TOML) == null).getOr { return@withBackgroundProgress it } val path = withContext(Dispatchers.IO) { VirtualEnvReader.Instance.findPythonInPythonRoot(Path.of(poetry)) } if (path == null) { - return@withBackgroundProgress PyResult.localizedError("Can't find python executable in $poetry") + return@withBackgroundProgress PyResult.localizedError(PyBundle.message("cannot.find.executable","python", poetry)) } val file = LocalFileSystem.getInstance().refreshAndFindFileByPath(path.pathString) if (file == null) { - return@withBackgroundProgress PyResult.localizedError("Can't find python executable in $poetry") + return@withBackgroundProgress PyResult.localizedError(PyBundle.message("cannot.find.executable","python", path)) } LOGGER.debug("Setting up associated poetry environment: $path, $basePath") diff --git a/python/pluginResources/messages/PyBundle.properties b/python/pluginResources/messages/PyBundle.properties index 201ddf5306ad..5d53116b4f6f 100644 --- a/python/pluginResources/messages/PyBundle.properties +++ b/python/pluginResources/messages/PyBundle.properties @@ -357,7 +357,7 @@ python.sdk.next=Next python.sdk.previous=Previous python.sdk.finish=Finish python.sdk.setting.up.pipenv.sentence=Setting up pipenv environment -python.sdk.setting.up.pipenv.title=Setting up pipenv environment +python.sdk.setting.up.pipenv.title=Setting up Pipenv Environment python.sdk.install.requirements.from.pipenv.lock=Install requirements from Pipfile.lock python.sdk.pipenv.executable.not.found=Pipenv executable is not found python.sdk.pipenv.executable=Pipenv executable: @@ -385,41 +385,30 @@ python.sdk.dialog.title.setting.up.poetry.environment=Setting up poetry environm python.sdk.inspection.message.poetry.interpreter.associated.with.another.project=Poetry interpreter is associated with another {0}: {1} python.sdk.inspection.message.poetry.interpreter.not.associated.with.any.project=Poetry interpreter is not associated with any {0} python.sdk.inspection.message.version.outdated.latest=''{0}'' version {1} is outdated (latest: {2}) -python.sdk.intention.family.name.install.requirements.from.poetry.lock=Install requirements from poetry.lock python.sdk.poetry.associated.module=Associated module: python.sdk.poetry.associated.project=Associated project: python.sdk.poetry.dialog.add.new.environment.in.project.checkbox=Create an in-project environment python.sdk.poetry.environment.panel.title=Poetry Environment python.sdk.poetry.executable.not.found=Poetry executable is not found python.sdk.poetry.executable=Poetry executable: -python.sdk.poetry.detecting.environments=Detecting poetry environments python.sdk.poetry.execution.exception.no.poetry.message=Cannot find Poetry python.sdk.poetry.install.packages.from.toml.checkbox.text=Install packages from pyproject.toml -python.sdk.poetry.pip.file.lock.not.found=poetry.lock is not found -python.sdk.poetry.pip.file.lock.out.of.date=poetry.lock is out of date -python.sdk.poetry.pip.file.notification.content.without.updating=Run poetry lock, poetry lock --no-update or poetry update -python.sdk.poetry.pip.file.notification.content=Run poetry lock or poetry update -python.sdk.poetry.pip.file.notification.locking.without.updating=Locking poetry.lock without updating -python.sdk.poetry.pip.file.notification.locking=Locking poetry.lock -python.sdk.poetry.pip.file.notification.updating=Updating Poetry environment python.sdk.poetry.pip.file.watcher=pyproject.toml Watcher python.sdk.poetry.quickfix.use.pipenv.name=Use Poetry interpreter python.sdk.poetry.select.executable.title=Select Path to Poetry Executable python.sdk.progress.setting.up.environment=Setting up Environment +python.sdk.poetry.supports.installing.only.packages.from.repositories=Poetry supports installing only packages from repositories +python.sdk.provided.path.is.invalid=The provided path is invalid: {0} # UV -python.sdk.uv.setting.up.uv.environment=Setting up uv environment -python.sdk.dialog.title.setting.up.uv.environment=Setting up uv environment python.sdk.inspection.message.uv.interpreter.associated.with.another.project=uv interpreter is associated with another {0}: {1} python.sdk.inspection.message.uv.interpreter.not.associated.with.any.project=uv interpreter is not associated with any {0} -python.sdk.intention.family.name.install.requirements.from.uv.lock=Install requirements from uv.lock python.sdk.quickfix.use.uv.name=Use uv interpreter -python.sdk.uv.associated.module=Associated module: -python.sdk.uv.associated.project=Associated project: -python.sdk.uv.environment.panel.title=uv environment python.sdk.uv.executable.not.found=uv executable is not found python.sdk.uv.executable=uv executable: -python.sdk.uv.install.packages.from.toml.checkbox.text=Install packages from pyproject.toml +python.sdk.uv.failed.to.initialize.uv.environment=Failed to initialize uv environment +python.sdk.uv.failed.to.detect.uv.python.directory=Failed to detect uv python directory +python.sdk.uv.working.dir.is.not.specified=working dir is not specified for uv environment setup python.sdk.local=Local python.sdk.creating.python.module.structure=Creating Python Module Structure @@ -972,6 +961,7 @@ python.packaging.create.setup.license=License python.packaging.create.setup.author=Author python.packaging.create.setup.author.email=Author Email python.packaging.create.setup.description=Description +python.packaging.conda.does.not.support.location.uri=Conda manager does not support installing from location uri # Example of produced message: # You are attempting to uninstall MarkupSafe package which is required for Jinja2 package @@ -1193,6 +1183,7 @@ python.add.sdk.panel.name.new.project.interpreter=New project interpreter python.add.sdk.panel.name.pipenv.environment=Pipenv Environment python.add.sdk.panel.name.system.interpreter=System interpreter python.add.sdk.panel.name.virtualenv.environment=Virtualenv environment +python.add.sdk.panel.name.poetry.environment=Poetry Environment python.add.sdk.conda.executable.path.is.empty=Conda executable path is empty python.add.sdk.conda.executable.path.is.not.found=Conda executable is not found @@ -1689,5 +1680,6 @@ command.name.add.package.to.conda.environments.yml=Add a package to conda enviro command.name.add.package.to.requirements.txt=Add a package to requirements.txt command.name.add.package.to.setup.py=Add a package to setup.py python.sdk.conda.requirements.file.not.found=Conda Environment.yml file is not found +cannot.find.executable=Cannot find executable "{0}" in {1} diff --git a/python/python-psi-impl/resources/messages/PyPsiBundle.properties b/python/python-psi-impl/resources/messages/PyPsiBundle.properties index a0b48b1033f2..92cb864874d9 100644 --- a/python/python-psi-impl/resources/messages/PyPsiBundle.properties +++ b/python/python-psi-impl/resources/messages/PyPsiBundle.properties @@ -1313,3 +1313,5 @@ INSP.NAME.new.type.variable.name.does.not.match.new.type.name=Variable name ''{0 INSP.NAME.new.type.expected.class=Expected class INSP.NAME.new.type.new.type.cannot.be.used.with=NewType cannot be used with ''{0}'' INSP.NAME.new.type.new.type.cannot.be.generic=NewType cannot be generic + +packaging.could.not.parse.relation=Could not parse relation from: {0} diff --git a/python/python-psi-impl/src/com/jetbrains/python/packaging/PyRequirements.kt b/python/python-psi-impl/src/com/jetbrains/python/packaging/PyRequirements.kt index a7e203e805eb..72dc7ba11b8a 100644 --- a/python/python-psi-impl/src/com/jetbrains/python/packaging/PyRequirements.kt +++ b/python/python-psi-impl/src/com/jetbrains/python/packaging/PyRequirements.kt @@ -2,7 +2,7 @@ package com.jetbrains.python.packaging import com.intellij.openapi.util.NlsSafe -import com.intellij.openapi.util.text.StringUtil +import com.jetbrains.python.PyPsiBundle import com.jetbrains.python.errorProcessing.PyResult import com.jetbrains.python.packaging.requirement.PyRequirementRelation import com.jetbrains.python.packaging.requirement.PyRequirementVersionSpec @@ -49,7 +49,7 @@ fun pyRequirement(name: String, relation: PyRequirementRelation, version: String fun pyRequirementVersionSpec(relationWithVersion: @NlsSafe String): PyResult { val value = relationWithVersion.trim() val relation = PyRequirementRelation.entries.lastOrNull { value.startsWith(it.presentableText) } - ?: return PyResult.localizedError("Could not parse relation from: $value") + ?: return PyResult.localizedError(PyPsiBundle.message("packaging.could.not.parse.relation", value)) val version = value.removePrefix(relation.presentableText) return PyResult.success(pyRequirementVersionSpec(relation, version)) @@ -121,12 +121,11 @@ private data class PyRequirementVersionSpecImpl( toEqPartOfCompatibleRelation(parsedVersion)).matches(version) } PyRequirementRelation.STR_EQ -> version == this.version - else -> false } } private fun splitIntoPublicAndLocalVersions(version: PyPackageVersion): Pair { - return version.copy(local = null).presentableText to StringUtil.notNullize(version.local) + return version.copy(local = null).presentableText to (version.local ?: "") } private fun splitIntoPublicAndLocalVersions(version: String): Pair { diff --git a/python/src/com/jetbrains/python/packaging/conda/CondaPackageManagerEngine.kt b/python/src/com/jetbrains/python/packaging/conda/CondaPackageManagerEngine.kt index 81586d69960b..1847b913ed92 100644 --- a/python/src/com/jetbrains/python/packaging/conda/CondaPackageManagerEngine.kt +++ b/python/src/com/jetbrains/python/packaging/conda/CondaPackageManagerEngine.kt @@ -3,6 +3,7 @@ package com.jetbrains.python.packaging.conda import com.intellij.openapi.projectRoots.Sdk import com.intellij.openapi.vfs.VirtualFile +import com.jetbrains.python.PyBundle import com.jetbrains.python.errorProcessing.PyResult import com.jetbrains.python.packaging.common.PythonOutdatedPackage import com.jetbrains.python.packaging.common.PythonPackage @@ -59,7 +60,7 @@ internal class CondaPackageManagerEngine(private val sdk: Sdk) : PythonPackageMa private fun getEnvData(): PyCondaEnv = (sdk.getOrCreateAdditionalData().flavorAndData.data as PyCondaFlavorData).env private fun PythonPackageInstallRequest.buildInstallationArguments(): PyResult> = when (this) { - is PythonPackageInstallRequest.ByLocation -> PyResult.localizedError("CondaManager does not support installing from location uri") + is PythonPackageInstallRequest.ByLocation -> PyResult.localizedError(PyBundle.message("python.packaging.conda.does.not.support.location.uri")) is PythonPackageInstallRequest.ByRepositoryPythonPackageSpecifications -> { val condaSpecs = specifications.filter { it.repository is CondaPackageRepository } val specs = condaSpecs.map { it.nameWithVersionSpec } diff --git a/python/src/com/jetbrains/python/sdk/PySdkExt.kt b/python/src/com/jetbrains/python/sdk/PySdkExt.kt index 43324f92dd2b..9c20d3f73835 100644 --- a/python/src/com/jetbrains/python/sdk/PySdkExt.kt +++ b/python/src/com/jetbrains/python/sdk/PySdkExt.kt @@ -96,7 +96,7 @@ fun configurePythonSdk(project: Project, module: Module, sdk: Sdk) { } // TODO: PythonInterpreterService: get system pythons /** - * @param context used to get [BASE_DIR] in [com.jetbrains.python.sdk.flavors.VirtualEnvSdkFlavor.suggestLocalHomePaths] + * @param context used to get [BASE_DIR] in [VirtualEnvSdkFlavor.suggestLocalHomePaths] */ @JvmOverloads fun detectSystemWideSdks( @@ -296,18 +296,18 @@ internal fun PyDetectedSdk.setupAssociatedLogged(existingSdks: List, associ fun PyDetectedSdk.setupAssociated(existingSdks: List, associatedModulePath: String?, doAssociate: Boolean): PyResult { if (!sdkSeemsValid) { - return PyResult.localizedError("sdk is not valid") + return PyResult.localizedError(PyBundle.message("python.sdk.error.invalid.interpreter.selected", homePath)) } val homePath = this.homePath if (homePath == null) { // e.g. directory is not there anymore - return PyResult.localizedError("homePath is null") + return PyResult.localizedError(PyBundle.message("python.sdk.provided.path.is.invalid", null)) } val homeDir = this.homeDirectory if (homeDir == null) { - return PyResult.localizedError("homeDir is null") + return PyResult.localizedError(PyBundle.message("python.sdk.provided.path.is.invalid", null)) } val suggestedName = if (doAssociate) { @@ -508,12 +508,13 @@ fun Sdk?.isTargetBased(): Boolean = this != null && targetEnvConfiguration != nu /** * Additional data if sdk is target-based */ -val Sdk.targetAdditionalData get():PyTargetAwareAdditionalData? = sdkAdditionalData as? PyTargetAwareAdditionalData +val Sdk.targetAdditionalData: PyTargetAwareAdditionalData? + get():PyTargetAwareAdditionalData? = sdkAdditionalData as? PyTargetAwareAdditionalData /** * Returns target environment if configuration is target api based */ -val Sdk.targetEnvConfiguration +val Sdk.targetEnvConfiguration: TargetEnvironmentConfiguration? get():TargetEnvironmentConfiguration? = (sdkAdditionalData as? TargetBasedSdkAdditionalData)?.targetEnvironmentConfiguration /** 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 d831674844af..c57f465a05ac 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 @@ -6,6 +6,7 @@ import com.intellij.openapi.observable.properties.ObservableMutableProperty import com.intellij.openapi.project.Project import com.intellij.openapi.projectRoots.Sdk import com.intellij.util.text.nullize +import com.jetbrains.python.PyBundle import com.jetbrains.python.errorProcessing.ErrorSink import com.jetbrains.python.errorProcessing.PyResult import com.jetbrains.python.newProjectWizard.collector.PythonNewProjectWizardCollector @@ -70,7 +71,7 @@ internal class EnvironmentCreatorUv( override suspend fun setupEnvSdk(project: Project, module: Module?, baseSdks: List, projectPath: String, homePath: String?, installPackages: Boolean): PyResult { val workingDir = module?.basePath?.let { tryResolvePath(it) } ?: project.basePath?.let { tryResolvePath(it) } if (workingDir == null) { - return PyResult.localizedError("working dir is not specified for uv environment setup") + return PyResult.localizedError(PyBundle.message("python.sdk.uv.working.dir.is.not.specified")) } val python = homePath?.let { Path.of(it) } diff --git a/python/src/com/jetbrains/python/sdk/add/v2/uv/UvExistingEnvironmentSelector.kt b/python/src/com/jetbrains/python/sdk/add/v2/uv/UvExistingEnvironmentSelector.kt index 3bf9b638954a..8d77c1bce47a 100644 --- a/python/src/com/jetbrains/python/sdk/add/v2/uv/UvExistingEnvironmentSelector.kt +++ b/python/src/com/jetbrains/python/sdk/add/v2/uv/UvExistingEnvironmentSelector.kt @@ -5,6 +5,7 @@ import com.intellij.openapi.module.Module import com.intellij.openapi.observable.properties.ObservableMutableProperty import com.intellij.openapi.projectRoots.ProjectJdkTable import com.intellij.openapi.projectRoots.Sdk +import com.jetbrains.python.PyBundle import com.jetbrains.python.Result import com.jetbrains.python.errorProcessing.PyResult import com.jetbrains.python.sdk.ModuleOrProject @@ -28,11 +29,15 @@ internal class UvExistingEnvironmentSelector(model: PythonMutableTargetAddInterp override val interpreterType: InterpreterType = InterpreterType.UV override suspend fun getOrCreateSdk(moduleOrProject: ModuleOrProject): PyResult { - val selectedInterpreterPath = tryResolvePath(selectedEnv.get()?.homePath) ?: return PyResult.localizedError("No selected interpreter") + val sdkHomePathString = selectedEnv.get()?.homePath + val selectedInterpreterPath = tryResolvePath(sdkHomePathString) + ?: return PyResult.localizedError(PyBundle.message("python.sdk.provided.path.is.invalid", sdkHomePathString)) val allSdk = ProjectJdkTable.getInstance().allJdks val existingSdk = allSdk.find { it.homePath == selectedInterpreterPath.pathString } val associatedModule = extractModule(moduleOrProject) - val projectDir = tryResolvePath(associatedModule?.basePath ?: moduleOrProject.project.basePath) ?: return PyResult.localizedError("No base path") + val basePathString = associatedModule?.basePath ?: moduleOrProject.project.basePath + val projectDir = tryResolvePath(basePathString) + ?: return PyResult.localizedError(PyBundle.message("python.sdk.provided.path.is.invalid", basePathString)) // uv sdk in current module if (existingSdk != null && existingSdk.isUv && existingSdk.isAssociatedWithModule(associatedModule)) { diff --git a/python/src/com/jetbrains/python/sdk/pipenv/PipenvCommandExecutor.kt b/python/src/com/jetbrains/python/sdk/pipenv/PipenvCommandExecutor.kt index b815d5f4bce0..914e98313f6f 100644 --- a/python/src/com/jetbrains/python/sdk/pipenv/PipenvCommandExecutor.kt +++ b/python/src/com/jetbrains/python/sdk/pipenv/PipenvCommandExecutor.kt @@ -1,13 +1,16 @@ // 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.sdk.pipenv -import com.intellij.execution.configurations.PathEnvironmentVariableUtil import com.intellij.ide.util.PropertiesComponent import com.intellij.openapi.module.Module import com.intellij.openapi.progress.runBlockingCancellable import com.intellij.openapi.project.Project import com.intellij.openapi.projectRoots.Sdk import com.intellij.openapi.util.SystemInfo +import com.intellij.platform.eel.provider.asNioPath +import com.intellij.platform.eel.provider.localEel +import com.intellij.platform.eel.where +import com.jetbrains.python.PyBundle import com.jetbrains.python.errorProcessing.PyResult import com.jetbrains.python.getOrNull import com.jetbrains.python.sdk.basePath @@ -45,9 +48,9 @@ suspend fun detectPipEnvExecutable(): PyResult { SystemInfo.isWindows -> "pipenv.exe" else -> "pipenv" } - val executablePath = withContext(Dispatchers.IO) { PathEnvironmentVariableUtil.findInPath(name) }?.toPath() + val executablePath = localEel.exec.where(name)?.asNioPath() if (executablePath == null) { - return PyResult.localizedError("Cannot find $name in PATH") + return PyResult.localizedError(PyBundle.message("cannot.find.executable", name, localEel.descriptor.userReadableDescription)) } return PyResult.success(executablePath) @@ -86,7 +89,7 @@ suspend fun setupPipEnvSdkWithProgressReport( installPackages: Boolean, ): PyResult { val projectPath = newProjectPath ?: module?.basePath ?: project?.basePath - ?: return PyResult.localizedError("Can't find path to project or module") + ?: return PyResult.localizedError(PyBundle.message("python.sdk.provided.path.is.invalid", null)) val actualProject = project ?: module?.project val pythonExecutablePath = if (actualProject != null) { setUpPipEnv(projectPath, python, installPackages) @@ -123,6 +126,6 @@ private suspend fun setUpPipEnv(projectPathString: String, python: String?, inst val pipEnv = setupPipEnv(Path.of(projectPathString), python, installPackages).getOr { return it } val pipEnvExecutablePathString = withContext(Dispatchers.IO) { VirtualEnvReader.Instance.findPythonInPythonRoot(Path.of(pipEnv))?.toString() - } ?: return PyResult.localizedError("Can't find pipenv in PATH") + } ?: return PyResult.localizedError(PyBundle.message("python.sdk.provided.path.is.invalid", pipEnv)) return PyResult.success(Path.of(pipEnvExecutablePathString)) } \ No newline at end of file diff --git a/python/src/com/jetbrains/python/sdk/poetry/PoetryPackageManager.kt b/python/src/com/jetbrains/python/sdk/poetry/PoetryPackageManager.kt index f6f9e58cb3ac..4393f4c40b8f 100644 --- a/python/src/com/jetbrains/python/sdk/poetry/PoetryPackageManager.kt +++ b/python/src/com/jetbrains/python/sdk/poetry/PoetryPackageManager.kt @@ -3,6 +3,7 @@ package com.jetbrains.python.sdk.poetry import com.intellij.openapi.project.Project import com.intellij.openapi.projectRoots.Sdk +import com.jetbrains.python.PyBundle import com.jetbrains.python.errorProcessing.PyResult import com.jetbrains.python.packaging.common.NormalizedPythonPackageName import com.jetbrains.python.packaging.common.PythonOutdatedPackage @@ -33,7 +34,7 @@ class PoetryPackageManager(project: Project, sdk: Sdk) : PythonPackageManager(pr override suspend fun installPackageCommand(installRequest: PythonPackageInstallRequest, options: List): PyResult { if (installRequest !is PythonPackageInstallRequest.ByRepositoryPythonPackageSpecifications) { - return PyResult.localizedError("Poetry supports installing only packages from repositories") + return PyResult.localizedError(PyBundle.message("python.sdk.poetry.supports.installing.only.packages.from.repositories")) } val packageSpecifications = installRequest.specifications diff --git a/python/src/com/jetbrains/python/sdk/poetry/poetry.kt b/python/src/com/jetbrains/python/sdk/poetry/poetry.kt index 7f5a382d0629..213178727ef9 100644 --- a/python/src/com/jetbrains/python/sdk/poetry/poetry.kt +++ b/python/src/com/jetbrains/python/sdk/poetry/poetry.kt @@ -8,6 +8,7 @@ import com.intellij.openapi.projectRoots.Sdk import com.intellij.openapi.util.NlsSafe import com.intellij.openapi.vfs.StandardFileSystems import com.intellij.util.PathUtil +import com.jetbrains.python.PyBundle import com.jetbrains.python.PythonModuleTypeBase import com.jetbrains.python.errorProcessing.PyResult import com.jetbrains.python.icons.PythonIcons @@ -20,10 +21,11 @@ import kotlinx.coroutines.withContext import org.jetbrains.annotations.ApiStatus.Internal import java.nio.file.Path import java.util.regex.Pattern +import javax.swing.Icon import kotlin.io.path.pathString // TODO: Provide a special icon for poetry -val POETRY_ICON = PythonIcons.Python.Origami +val POETRY_ICON: Icon = PythonIcons.Python.Origami @Internal fun suggestedSdkName(basePath: Path): @NlsSafe String = "Poetry (${PathUtil.getFileName(basePath.pathString)})" @@ -49,8 +51,9 @@ suspend fun setupPoetrySdk( installPackages: Boolean, poetryPath: String? = null, ): PyResult { - val projectPath = (newProjectPath ?: module?.basePath ?: project?.basePath)?.let { Path.of(it) } - ?: return PyResult.localizedError("Can't find path to project or module") + val pathString = newProjectPath ?: module?.basePath ?: project?.basePath + val projectPath = pathString?.let { Path.of(it) } + ?: return PyResult.localizedError(PyBundle.message("python.sdk.provided.path.is.invalid", pathString)) val actualProject = project ?: module?.project val pythonExecutablePath = if (actualProject != null) { diff --git a/python/src/com/jetbrains/python/sdk/poetry/ui/PoetryPanelCreator.kt b/python/src/com/jetbrains/python/sdk/poetry/ui/PoetryPanelCreator.kt index f08d54cc678e..71e124e66294 100644 --- a/python/src/com/jetbrains/python/sdk/poetry/ui/PoetryPanelCreator.kt +++ b/python/src/com/jetbrains/python/sdk/poetry/ui/PoetryPanelCreator.kt @@ -6,6 +6,7 @@ import com.intellij.openapi.project.Project import com.intellij.openapi.projectRoots.Sdk import com.intellij.openapi.util.UserDataHolder import com.intellij.util.PlatformUtils +import com.jetbrains.python.PyBundle import com.jetbrains.python.sdk.add.PyAddSdkGroupPanel import com.jetbrains.python.sdk.add.PyAddSdkPanel import com.jetbrains.python.sdk.isAssociatedWithModule @@ -31,12 +32,18 @@ fun createPoetryPanel( val existingSdkPaths = sdkHomes(existingSdks) val defaultPanel = when { pyModalBlocking { - detectPoetryEnvs(module, existingSdkPaths, project?.basePath ?: newProjectPath) + detectPoetryEnvs(module, existingSdkPaths, project.basePath ?: newProjectPath) }.any { it.isAssociatedWithModule(module) } -> existingPoetryPanel newPoetryPanel != null -> newPoetryPanel else -> existingPoetryPanel } - return PyAddSdkGroupPanel(Supplier { "Poetry environment" }, POETRY_ICON, panels, defaultPanel) + + return PyAddSdkGroupPanel( + nameGetter = Supplier { PyBundle.message("python.add.sdk.panel.name.poetry.environment") }, + panelIcon = POETRY_ICON, + panels = panels, + defaultPanel = defaultPanel + ) } private fun allowCreatingNewEnvironments(project: Project?) = diff --git a/python/src/com/jetbrains/python/sdk/uv/impl/UvLowLevel.kt b/python/src/com/jetbrains/python/sdk/uv/impl/UvLowLevel.kt index 123afc9263c4..3cadca4e1110 100644 --- a/python/src/com/jetbrains/python/sdk/uv/impl/UvLowLevel.kt +++ b/python/src/com/jetbrains/python/sdk/uv/impl/UvLowLevel.kt @@ -5,6 +5,7 @@ import com.fasterxml.jackson.databind.DeserializationFeature import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper import com.fasterxml.jackson.module.kotlin.readValue import com.intellij.util.io.delete +import com.jetbrains.python.PyBundle import com.jetbrains.python.errorProcessing.* import com.jetbrains.python.errorProcessing.PyExecResult import com.jetbrains.python.errorProcessing.PyResult @@ -69,7 +70,7 @@ private class UvLowLevelImpl(val cwd: Path, private val uvCli: UvCli) : UvLowLev val path = VirtualEnvReader.Instance.findPythonInPythonRoot(cwd.resolve(VirtualEnvReader.DEFAULT_VIRTUALENV_DIRNAME)) if (path == null) { - return PyResult.localizedError("failed to initialize uv environment") + return PyResult.localizedError(PyBundle.message("python.sdk.uv.failed.to.initialize.uv.environment")) } return PyResult.success(path) @@ -81,7 +82,7 @@ private class UvLowLevelImpl(val cwd: Path, private val uvCli: UvCli) : UvLowLev val uvDir = tryResolvePath(out) if (uvDir == null) { - return PyResult.localizedError("failed to detect uv python directory") + return PyResult.localizedError(PyBundle.message("python.sdk.uv.failed.to.detect.uv.python.directory")) } // TODO: ask for json output format @@ -233,7 +234,7 @@ private class UvLowLevelImpl(val cwd: Path, private val uvCli: UvCli) : UvLowLev fun parseUvPythonList(uvDir: Path, out: String): Set { val lines = out.lines() val pythons = lines.mapNotNull { line -> - var arrow = line.lastIndexOf("->").takeIf { it > 0 } ?: line.length + val arrow = line.lastIndexOf("->").takeIf { it > 0 } ?: line.length val pythonAndPath = line .substring(0, arrow)