mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
PY-87404 add PyDependenciesFile entity for SDK dependency declarations
Add the PyDependenciesFile interface in intellij.python.requirements
together with its implementations:
- RequirementsTxtFile, SetupPyFile (intellij.python.requirements)
- PyProjectTomlFile (intellij.python.pyproject)
- CondaEnvironmentYmlFile (intellij.python.community.impl.conda;
renamed from CondaEnvironmentYmlSdkUtils.kt)
- PipFileLockFile (intellij.python.community.impl;
replaces PipEnvFileHelper)
Each implementation owns its display icon (requirements/toml/yaml
SVGs are colocated with the new owners, with generated icon classes
PythonRequirementsIcons/PythonPyprojectIcons.Toml/
PythonCommunityImplCondaIcons.Yaml).
Wire the entity into the packaging API: PythonPackageManager exposes
an open getDependencyFile() hook, and the pip, conda, poetry, uv,
hatch, and pipenv managers each return the appropriate concrete
PyDependenciesFile (or null when none applies). Update SDK-extension
helpers (associatedModuleDir moves from PySdkExt to SdkExt so the
shared module can resolve dependency paths) and rename
PyProjectToml.findFile -> findPyProjectTomlFile to return the new
typed entity. Refresh callers across configuration, conda, poetry,
and v2 SDK-add flows accordingly, plus the in-memory
TestPackageManager.
GitOrigin-RevId: 64abfc53fe94aa3a221be293200e11cb9abbc432
This commit is contained in:
committed by
intellij-monorepo-bot
parent
334ace79a0
commit
0460aa53f0
+1
@@ -16,4 +16,5 @@ public final class PythonCommunityImplCondaIcons {
|
||||
return IconManager.getInstance().loadRasterizedIcon(path, PythonCommunityImplCondaIcons.class.getClassLoader(), cacheKey, flags);
|
||||
}
|
||||
/** 16x16 */ public static final @NotNull Icon Anaconda = load("icons/com/intellij/python/community/impl/conda/expui/anaconda.svg", 1479605221, 2);
|
||||
/** 16x16 */ public static final @NotNull Icon Yaml = load("icons/com/intellij/python/community/impl/conda/expui/yaml.svg", -1755535915, 2);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
<!-- Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. -->
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M11 2C11.5523 2 12 2.44772 12 3V9H11C10.4477 9 10 9.44772 10 10V14H5C4.44772 14 4 13.5523 4 13V6H6C7.10457 6 8 5.10457 8 4V2H11Z" fill="#FFF7F7"/>
|
||||
<path d="M7 4C7 4.06893 6.99277 4.13617 6.97949 4.20117C6.88625 4.65686 6.48325 5 6 5H4.41406L7 2.41406V4Z" fill="#FFF7F7"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M11 1C12.1046 1 13 1.89543 13 3V9H12V3C12 2.44772 11.5523 2 11 2H8V4C8 5.10457 7.10457 6 6 6H4V13C4 13.5523 4.44772 14 5 14H10V15H5C3.89543 15 3 14.1046 3 13V5.41406C3.00004 5.1489 3.10547 4.89453 3.29297 4.70703L6.70703 1.29297C6.89453 1.10547 7.1489 1.00004 7.41406 1H11ZM4.41406 5H6C6.55228 5 7 4.55228 7 4V2.41406L4.41406 5Z" fill="#DB3B4B"/>
|
||||
<path d="M12.4018 16V13.827L10.647 10.014H11.7212L12.656 12.0886C12.727 12.2526 12.7872 12.4139 12.8364 12.5724C12.8856 12.7309 12.9184 12.8539 12.9348 12.9414C12.9566 12.8539 12.9894 12.7309 13.0332 12.5724C13.0824 12.4139 13.1425 12.2526 13.2136 12.0886L14.1238 10.014H15.1898L13.435 13.827V16H12.4018Z" fill="#6C707E"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
+7
@@ -0,0 +1,7 @@
|
||||
<!-- Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. -->
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M11 2C11.5523 2 12 2.44772 12 3V9H11C10.4477 9 10 9.44772 10 10V14H5C4.44772 14 4 13.5523 4 13V6H6C7.10457 6 8 5.10457 8 4V2H11Z" fill="#402929"/>
|
||||
<path d="M7 4C7 4.06893 6.99277 4.13617 6.97949 4.20117C6.88625 4.65686 6.48325 5 6 5H4.41406L7 2.41406V4Z" fill="#402929"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M11 1C12.1046 1 13 1.89543 13 3V9H12V3C12 2.44772 11.5523 2 11 2H8V4C8 5.10457 7.10457 6 6 6H4V13C4 13.5523 4.44772 14 5 14H10V15H5C3.89543 15 3 14.1046 3 13V5.41406C3.00004 5.1489 3.10547 4.89453 3.29297 4.70703L6.70703 1.29297C6.89453 1.10547 7.1489 1.00004 7.41406 1H11ZM4.41406 5H6C6.55228 5 7 4.55228 7 4V2.41406L4.41406 5Z" fill="#DB5C5C"/>
|
||||
<path d="M12.4018 16V13.827L10.647 10.014H11.7212L12.656 12.0886C12.727 12.2526 12.7872 12.4139 12.8364 12.5724C12.8856 12.7309 12.9184 12.8539 12.9348 12.9414C12.9566 12.8539 12.9894 12.7309 13.0332 12.5724C13.0824 12.4139 13.1425 12.2526 13.2136 12.0886L14.1238 10.014H15.1898L13.435 13.827V16H12.4018Z" fill="#CED0D6"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
@@ -1,8 +1,11 @@
|
||||
<idea-plugin visibility="internal">
|
||||
<dependencies>
|
||||
<!-- region Generated dependencies - run `Generate Product Layouts` to regenerate -->
|
||||
<module name="intellij.python.community"/>
|
||||
<module name="intellij.python.processOutput.common"/>
|
||||
<module name="intellij.python.requirements"/>
|
||||
<module name="intellij.python.sdk"/>
|
||||
<!-- endregion -->
|
||||
</dependencies>
|
||||
<extensions defaultExtensionNs="com.intellij">
|
||||
<python.processOutput.common.processOutputIconMapping implementation="com.intellij.python.community.impl.conda.CondaIconMapping"/>
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
command.name.add.package.to.conda.environments.yml=Add a package to conda environments.yml
|
||||
@@ -0,0 +1,19 @@
|
||||
// Copyright 2000-2026 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.python.community.impl.conda
|
||||
|
||||
import com.intellij.DynamicBundle
|
||||
import org.jetbrains.annotations.ApiStatus
|
||||
import org.jetbrains.annotations.Nls
|
||||
import org.jetbrains.annotations.PropertyKey
|
||||
|
||||
@ApiStatus.Internal
|
||||
object PyCondaBundle {
|
||||
private const val BUNDLE = "messages.PyCondaBundle"
|
||||
|
||||
private val INSTANCE = DynamicBundle(PyCondaBundle::class.java, BUNDLE)
|
||||
|
||||
@JvmStatic
|
||||
fun message(key: @PropertyKey(resourceBundle = BUNDLE) String, vararg params: Any): @Nls String {
|
||||
return INSTANCE.getMessage(key, *params)
|
||||
}
|
||||
}
|
||||
+17
-2
@@ -1,10 +1,25 @@
|
||||
// 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.packaging.conda.environmentYml
|
||||
// Copyright 2000-2026 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.python.community.impl.conda.environmentYml
|
||||
|
||||
import com.intellij.openapi.projectRoots.Sdk
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.python.community.impl.conda.icons.PythonCommunityImplCondaIcons
|
||||
import com.jetbrains.python.requirements.PyDependenciesFile
|
||||
import com.jetbrains.python.sdk.associatedModuleDir
|
||||
import org.jetbrains.annotations.ApiStatus
|
||||
import javax.swing.Icon
|
||||
|
||||
|
||||
@ApiStatus.Internal
|
||||
data class CondaEnvironmentYmlFile(override val virtualFile: VirtualFile) : PyDependenciesFile {
|
||||
override val icon: Icon
|
||||
get() = PythonCommunityImplCondaIcons.Yaml
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
fun Sdk.findCondaEnvironmentYmlFile(): CondaEnvironmentYmlFile? {
|
||||
return CondaEnvironmentYmlSdkUtils.findFile(this)?.let { CondaEnvironmentYmlFile(it) }
|
||||
}
|
||||
|
||||
/**
|
||||
* Migrate from the module persistent path to sdk path
|
||||
+2
@@ -24,4 +24,6 @@ public final class PythonPyprojectIcons {
|
||||
|
||||
/** 16x16 */ public static final @NotNull Icon PyProjectModule = load("icons/com/intellij/python/pyproject/expui/model/pyProjectModule.svg", 623489112, 2);
|
||||
}
|
||||
|
||||
/** 16x16 */ public static final @NotNull Icon Toml = load("icons/com/intellij/python/pyproject/expui/toml.svg", 945785471, 2);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M1 4C1 2.89543 1.89543 2 3 2H13C14.1046 2 15 2.89543 15 4V12C15 13.1046 14.1046 14 13 14H3C1.89543 14 1 13.1046 1 12V4Z" fill="#FFF4EB"/>
|
||||
<path d="M3.5 13.5H2.5C1.94772 13.5 1.5 13.0523 1.5 12.5V3.5C1.5 2.94771 1.94772 2.5 2.5 2.5H3.5" stroke="#E56D17" stroke-linecap="round"/>
|
||||
<path d="M12.5 13.5H13.5C14.0523 13.5 14.5 13.0523 14.5 12.5V3.5C14.5 2.94771 14.0523 2.5 13.5 2.5H12.5" stroke="#E56D17" stroke-linecap="round"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M7.5 5H5V4H11V5H8.5V12H7.5V5Z" fill="black"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 632 B |
+6
@@ -0,0 +1,6 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M1 4C1 2.89543 1.89543 2 3 2H13C14.1046 2 15 2.89543 15 4V12C15 13.1046 14.1046 14 13 14H3C1.89543 14 1 13.1046 1 12V4Z" fill="#45322B"/>
|
||||
<path d="M3.5 13.5H2.5C1.94772 13.5 1.5 13.0523 1.5 12.5V3.5C1.5 2.94771 1.94772 2.5 2.5 2.5H3.5" stroke="#C77D55" stroke-linecap="round"/>
|
||||
<path d="M12.5 13.5H13.5C14.0523 13.5 14.5 13.0523 14.5 12.5V3.5C14.5 2.94771 14.0523 2.5 13.5 2.5H12.5" stroke="#C77D55" stroke-linecap="round"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M7.5 5H5V4H11V5H8.5V12H7.5V5Z" fill="white"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 632 B |
@@ -259,7 +259,9 @@ data class PyProjectToml(
|
||||
* Attempts to find the `pyproject.toml` file in the provided module.
|
||||
* Returns null if not found.
|
||||
*/
|
||||
suspend fun findFile(module: Module): VirtualFile? = findAmongRoots(module, PY_PROJECT_TOML)
|
||||
suspend fun findPyProjectTomlFile(module: Module): PyProjectTomlFile? {
|
||||
return findAmongRoots(module, PY_PROJECT_TOML)?.let { PyProjectTomlFile(it) }
|
||||
}
|
||||
|
||||
suspend fun findInRoot(moduleBasePath: Path): Path? = withContext(Dispatchers.IO) {
|
||||
moduleBasePath.resolve(PY_PROJECT_TOML).takeIf { it.isRegularFile() }
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.intellij.python.pyproject
|
||||
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.python.pyproject.icons.PythonPyprojectIcons
|
||||
import com.jetbrains.python.requirements.PyDependenciesFile
|
||||
import javax.swing.Icon
|
||||
|
||||
|
||||
data class PyProjectTomlFile(override val virtualFile: VirtualFile) : PyDependenciesFile {
|
||||
override val icon: Icon = PythonPyprojectIcons.Toml
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
// Copyright 2000-2026 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.python.requirements.icons;
|
||||
|
||||
import com.intellij.ui.IconManager;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
/**
|
||||
* NOTE THIS FILE IS AUTO-GENERATED
|
||||
* DO NOT EDIT IT BY HAND, run "Generate icon classes" configuration instead
|
||||
*/
|
||||
public final class PythonRequirementsIcons {
|
||||
private static @NotNull Icon load(@NotNull String path, int cacheKey, int flags) {
|
||||
return IconManager.getInstance().loadRasterizedIcon(path, PythonRequirementsIcons.class.getClassLoader(), cacheKey, flags);
|
||||
}
|
||||
/** 16x16 */ public static final @NotNull Icon Requirements = load("icons/com/intellij/python/requirements/expui/requirements.svg", 2026575763, 2);
|
||||
}
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
@ApiStatus.Internal
|
||||
package com.intellij.python.requirements.icons;
|
||||
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M3.14453 10.0137C3.53799 10.0137 3.88262 10.0878 4.17773 10.2354C4.47823 10.3829 4.70773 10.5907 4.86621 10.8584C5.03016 11.1262 5.11225 11.4378 5.1123 11.793C5.1123 12.1866 5.01418 12.5343 4.81738 12.835C4.62058 13.1356 4.34928 13.3489 4.00488 13.4746L5.19434 16H4.0459L3.00488 13.6221H2.27539V16H1.25V10.0137H3.14453ZM2.27539 12.7285H3.14453C3.42861 12.7285 3.65248 12.6487 3.81641 12.4902C3.98586 12.3262 4.0703 12.1049 4.07031 11.8262C4.07031 11.5419 3.98587 11.3173 3.81641 11.1533C3.6525 10.9896 3.42847 10.9083 3.14453 10.9082H2.27539V12.7285Z" fill="#3574F0"/>
|
||||
<path d="M9.85645 10.8994H7.27344V12.4658H9.56934V13.3516H7.27344V15.1143H9.85645V16H6.26562V10.0137H9.85645V10.8994Z" fill="#3574F0"/>
|
||||
<path d="M13.4912 10C13.6387 10.0366 13.7766 10.0871 13.9043 10.1533C14.1886 10.3009 14.4108 10.5085 14.5693 10.7764C14.6883 10.9773 14.7624 11.2046 14.792 11.458C14.8022 11.5426 14.8066 11.6299 14.8066 11.7197V14.2939C14.8066 14.5107 14.7783 14.7092 14.7227 14.8896C14.7189 14.902 14.713 14.9136 14.709 14.9258L13.7812 13.417V11.7197C13.7812 11.5419 13.7497 11.3887 13.6875 11.2598C13.6505 11.1853 13.6025 11.12 13.5439 11.0635C13.4976 11.0155 13.4451 10.9758 13.3877 10.9424C13.2559 10.8707 13.0951 10.834 12.9043 10.834C12.7151 10.834 12.5563 10.8678 12.4277 10.9355C12.3649 10.9701 12.3078 11.0125 12.2568 11.0635L12.2031 11.126C12.1528 11.1911 12.1128 11.2646 12.084 11.3467C12.0467 11.4551 12.0273 11.5793 12.0273 11.7197V14.2939C12.0273 14.4397 12.049 14.5687 12.0908 14.6816C12.1305 14.7864 12.188 14.8762 12.2646 14.9502C12.3107 14.9979 12.363 15.037 12.4199 15.0703C12.552 15.1424 12.7129 15.1797 12.9043 15.1797C13.0105 15.1797 13.1064 15.1662 13.1934 15.1445L12.4893 14H13.5938L14.8193 15.999H13.7197L13.6904 15.9521C13.641 15.9703 13.59 15.9856 13.5381 16H12.2656C12.1376 15.9646 12.0169 15.9188 11.9043 15.8604C11.62 15.7128 11.3978 15.5052 11.2393 15.2373C11.0807 14.9694 11.002 14.6547 11.002 14.2939V11.7197C11.002 11.3535 11.0817 11.0388 11.2402 10.7764C11.3988 10.5087 11.6202 10.3008 11.9043 10.1533C12.032 10.0871 12.1698 10.0366 12.3174 10H13.4912Z" fill="#3574F0"/>
|
||||
<path d="M12.2041 2.01074C13.2128 2.113 14 2.96435 14 4V9H13V4C13 3.44772 12.5523 3 12 3H4C3.44772 3 3 3.44772 3 4V9H2V4C2 2.89543 2.89543 2 4 2H12L12.2041 2.01074Z" fill="#6C707E"/>
|
||||
<path d="M10.5 8C10.7761 8 11 8.22386 11 8.5C11 8.77614 10.7761 9 10.5 9H5.5C5.22386 9 5 8.77614 5 8.5C5 8.22386 5.22386 8 5.5 8H10.5Z" fill="#6C707E"/>
|
||||
<path d="M11 5.5C11 5.77614 10.7761 6 10.5 6H5.5C5.22386 6 5 5.77614 5 5.5C5 5.22386 5.22386 5 5.5 5H10.5C10.7761 5 11 5.22386 11 5.5Z" fill="#6C707E"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M12 3C12.5523 3 13 3.44772 13 4V9H10.5C10.7761 9 11 8.77614 11 8.5C11 8.22386 10.7761 8 10.5 8H5.5C5.22386 8 5 8.22386 5 8.5C5 8.77614 5.22386 9 5.5 9H3V4C3 3.44772 3.44772 3 4 3H12ZM5.5 5C5.22386 5 5 5.22386 5 5.5C5 5.77614 5.22386 6 5.5 6H10.5C10.7761 6 11 5.77614 11 5.5C11 5.22386 10.7761 5 10.5 5H5.5Z" fill="#EBECF0"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.0 KiB |
+9
@@ -0,0 +1,9 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M3.14453 10.0137C3.53799 10.0137 3.88262 10.0878 4.17773 10.2354C4.47823 10.3829 4.70773 10.5907 4.86621 10.8584C5.03016 11.1262 5.11225 11.4378 5.1123 11.793C5.1123 12.1866 5.01418 12.5343 4.81738 12.835C4.62058 13.1356 4.34928 13.3489 4.00488 13.4746L5.19434 16H4.0459L3.00488 13.6221H2.27539V16H1.25V10.0137H3.14453ZM2.27539 12.7285H3.14453C3.42861 12.7285 3.65248 12.6487 3.81641 12.4902C3.98586 12.3262 4.0703 12.1049 4.07031 11.8262C4.07031 11.5419 3.98587 11.3173 3.81641 11.1533C3.6525 10.9896 3.42847 10.9083 3.14453 10.9082H2.27539V12.7285Z" fill="#548AF7"/>
|
||||
<path d="M9.85645 10.8994H7.27344V12.4658H9.56934V13.3516H7.27344V15.1143H9.85645V16H6.26562V10.0137H9.85645V10.8994Z" fill="#548AF7"/>
|
||||
<path d="M13.4912 10C13.6387 10.0366 13.7766 10.0871 13.9043 10.1533C14.1886 10.3009 14.4108 10.5085 14.5693 10.7764C14.6883 10.9773 14.7624 11.2046 14.792 11.458C14.8022 11.5426 14.8066 11.6299 14.8066 11.7197V14.2939C14.8066 14.5107 14.7783 14.7092 14.7227 14.8896C14.7189 14.902 14.713 14.9136 14.709 14.9258L13.7812 13.417V11.7197C13.7812 11.5419 13.7497 11.3887 13.6875 11.2598C13.6505 11.1853 13.6025 11.12 13.5439 11.0635C13.4976 11.0155 13.4451 10.9758 13.3877 10.9424C13.2559 10.8707 13.0951 10.834 12.9043 10.834C12.7151 10.834 12.5563 10.8678 12.4277 10.9355C12.3649 10.9701 12.3078 11.0125 12.2568 11.0635L12.2031 11.126C12.1528 11.1911 12.1128 11.2646 12.084 11.3467C12.0467 11.4551 12.0273 11.5793 12.0273 11.7197V14.2939C12.0273 14.4397 12.049 14.5687 12.0908 14.6816C12.1305 14.7864 12.188 14.8762 12.2646 14.9502C12.3107 14.9979 12.363 15.037 12.4199 15.0703C12.552 15.1424 12.7129 15.1797 12.9043 15.1797C13.0105 15.1797 13.1064 15.1662 13.1934 15.1445L12.4893 14H13.5938L14.8193 15.999H13.7197L13.6904 15.9521C13.641 15.9703 13.59 15.9856 13.5381 16H12.2656C12.1376 15.9646 12.0169 15.9188 11.9043 15.8604C11.62 15.7128 11.3978 15.5052 11.2393 15.2373C11.0807 14.9694 11.002 14.6547 11.002 14.2939V11.7197C11.002 11.3535 11.0817 11.0388 11.2402 10.7764C11.3988 10.5087 11.6202 10.3008 11.9043 10.1533C12.032 10.0871 12.1698 10.0366 12.3174 10H13.4912Z" fill="#548AF7"/>
|
||||
<path d="M12.2041 2.01074C13.2128 2.113 14 2.96435 14 4V9H13V4C13 3.44772 12.5523 3 12 3H4C3.44772 3 3 3.44772 3 4V9H2V4C2 2.89543 2.89543 2 4 2H12L12.2041 2.01074Z" fill="#CED0D6"/>
|
||||
<path d="M10.5 8C10.7761 8 11 8.22386 11 8.5C11 8.77614 10.7761 9 10.5 9H5.5C5.22386 9 5 8.77614 5 8.5C5 8.22386 5.22386 8 5.5 8H10.5Z" fill="#CED0D6"/>
|
||||
<path d="M11 5.5C11 5.77614 10.7761 6 10.5 6H5.5C5.22386 6 5 5.77614 5 5.5C5 5.22386 5.22386 5 5.5 5H10.5C10.7761 5 11 5.22386 11 5.5Z" fill="#CED0D6"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M12 3C12.5523 3 13 3.44772 13 4V9H10.5C10.7761 9 11 8.77614 11 8.5C11 8.22386 10.7761 8 10.5 8H5.5C5.22386 8 5 8.22386 5 8.5C5 8.77614 5.22386 9 5.5 9H3V4C3 3.44772 3.44772 3 4 3H12ZM5.5 5C5.22386 5 5 5.22386 5 5.5C5 5.77614 5.22386 6 5.5 6H10.5C10.7761 6 11 5.77614 11 5.5C11 5.22386 10.7761 5 10.5 5H5.5Z" fill="#43454A"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.0 KiB |
+23
@@ -0,0 +1,23 @@
|
||||
package com.jetbrains.python.requirements
|
||||
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.python.requirements.icons.PythonRequirementsIcons
|
||||
import org.jetbrains.annotations.ApiStatus
|
||||
import javax.swing.Icon
|
||||
|
||||
@ApiStatus.Internal
|
||||
interface PyDependenciesFile {
|
||||
val virtualFile: VirtualFile
|
||||
val icon: Icon
|
||||
}
|
||||
|
||||
|
||||
@ApiStatus.Internal
|
||||
data class SetupPyFile(override val virtualFile: VirtualFile) : PyDependenciesFile {
|
||||
override val icon: Icon = PythonRequirementsIcons.Requirements
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
data class RequirementsTxtFile(override val virtualFile: VirtualFile) : PyDependenciesFile {
|
||||
override val icon: Icon = PythonRequirementsIcons.Requirements
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
@ApiStatus.Internal
|
||||
package com.intellij.python.sdk.icons;
|
||||
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
@@ -4,15 +4,21 @@ package com.jetbrains.python.sdk
|
||||
import com.intellij.execution.target.TargetBasedSdkAdditionalData
|
||||
import com.intellij.execution.target.TargetEnvironmentConfiguration
|
||||
import com.intellij.openapi.application.writeAction
|
||||
import com.intellij.openapi.diagnostic.thisLogger
|
||||
import com.intellij.openapi.module.Module
|
||||
import com.intellij.openapi.projectRoots.Sdk
|
||||
import com.intellij.openapi.util.Key
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.openapi.vfs.VirtualFileManager
|
||||
import com.jetbrains.python.sdk.flavors.PythonSdkFlavor
|
||||
import com.jetbrains.python.sdk.impl.buildPresentationInfo
|
||||
import com.jetbrains.python.sdk.legacy.PythonSdkUtil.isPythonSdk
|
||||
import com.jetbrains.python.target.PyTargetAwareAdditionalData
|
||||
import org.jetbrains.annotations.ApiStatus.Internal
|
||||
import java.nio.file.InvalidPathException
|
||||
import java.nio.file.Path
|
||||
import kotlin.io.path.Path
|
||||
import com.intellij.openapi.vfs.ex.temp.TempFileSystem
|
||||
|
||||
@get:Internal
|
||||
val BASE_DIR: Key<Path> = Key.create("PYTHON_PROJECT_BASE_PATH")
|
||||
@@ -112,4 +118,36 @@ val Sdk.targetEnvConfiguration: TargetEnvironmentConfiguration?
|
||||
|
||||
|
||||
@Internal
|
||||
fun Sdk.pyInterpreterPresentation(customName: String? = null): PythonInterpreterPresentation = buildPresentationInfo(customName)
|
||||
fun Sdk.pyInterpreterPresentation(customName: String? = null): PythonInterpreterPresentation = buildPresentationInfo(customName)
|
||||
|
||||
|
||||
private val SDK_ERROR_REPORTED = Key.create<Boolean>("pySdkErrorReported")
|
||||
|
||||
@get:Internal
|
||||
val Sdk.associatedModuleDir: VirtualFile?
|
||||
get() {
|
||||
val nioPath = associatedModuleNioPath ?: return null
|
||||
return VirtualFileManager.getInstance().findFileByNioPath(nioPath) ?: TempFileSystem.getInstance().findFileByNioFile(nioPath)
|
||||
}
|
||||
|
||||
@get:Internal
|
||||
val Sdk.associatedModuleNioPath: Path?
|
||||
get() =
|
||||
try {
|
||||
associatedModulePath?.let { Path(it) }
|
||||
}
|
||||
catch (e: InvalidPathException) {
|
||||
if (getUserData(SDK_ERROR_REPORTED) != true) {
|
||||
thisLogger().warn("Can't convert ${associatedModulePath} to path", e)
|
||||
putUserData(SDK_ERROR_REPORTED, true)
|
||||
}
|
||||
null
|
||||
}
|
||||
|
||||
@get:Internal
|
||||
val Sdk.associatedModulePath: String?
|
||||
// TODO: Support .project associations
|
||||
get() = associatedPathFromAdditionalData /*?: associatedPathFromDotProject*/
|
||||
|
||||
private val Sdk.associatedPathFromAdditionalData: String?
|
||||
get() = (sdkAdditionalData as? PythonSdkAdditionalData)?.associatedModulePath
|
||||
|
||||
+2
-2
@@ -22,8 +22,8 @@ import com.jetbrains.python.configuration.PyConfigurableInterpreterList
|
||||
import com.jetbrains.python.errorProcessing.PyResult
|
||||
import com.jetbrains.python.getOrNull
|
||||
import com.jetbrains.python.onSuccess
|
||||
import com.jetbrains.python.packaging.conda.environmentYml.CondaEnvironmentYmlSdkUtils
|
||||
import com.jetbrains.python.packaging.conda.environmentYml.format.CondaEnvironmentYmlParser
|
||||
import com.intellij.python.community.impl.conda.environmentYml.CondaEnvironmentYmlSdkUtils
|
||||
import com.intellij.python.community.impl.conda.environmentYml.format.CondaEnvironmentYmlParser
|
||||
import com.jetbrains.python.pathValidation.PlatformAndRoot
|
||||
import com.jetbrains.python.pathValidation.ValidationRequest
|
||||
import com.jetbrains.python.pathValidation.validateExecutableFile
|
||||
|
||||
@@ -3,9 +3,9 @@ package com.jetbrains.python.hatch.packaging
|
||||
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.projectRoots.Sdk
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.python.hatch.HatchService
|
||||
import com.intellij.python.hatch.getHatchService
|
||||
import com.intellij.python.pyproject.PyProjectTomlFile
|
||||
import com.jetbrains.python.errorProcessing.PyResult
|
||||
import com.jetbrains.python.hatch.sdk.HatchSdkAdditionalData
|
||||
import com.jetbrains.python.hatch.sdk.isHatch
|
||||
@@ -33,7 +33,7 @@ internal class HatchPackageManager(project: Project, sdk: Sdk) : PipPythonPackag
|
||||
return workingDirectory.getHatchService(hatchEnvironmentName = data.hatchEnvironmentName)
|
||||
}
|
||||
|
||||
override fun getDependencyFile(): VirtualFile? {
|
||||
override fun getDependencyFile(): PyProjectTomlFile? {
|
||||
val data = sdk.sdkAdditionalData as? HatchSdkAdditionalData ?: return null
|
||||
val workingDirectory = data.hatchWorkingDirectory ?: return null
|
||||
return resolvePyProjectToml(workingDirectory)
|
||||
|
||||
@@ -17,10 +17,11 @@ import com.jetbrains.python.packaging.common.PythonOutdatedPackage
|
||||
import com.jetbrains.python.packaging.common.PythonPackage
|
||||
import com.jetbrains.python.packaging.common.PythonRepositoryPackageSpecification
|
||||
import com.jetbrains.python.packaging.common.toPythonPackages
|
||||
import com.intellij.python.community.impl.conda.environmentYml.CondaEnvironmentYmlFile
|
||||
import com.jetbrains.python.packaging.management.PyWorkspaceMember
|
||||
import com.jetbrains.python.packaging.conda.environmentYml.CondaEnvironmentYmlSdkUtils
|
||||
import com.jetbrains.python.packaging.conda.environmentYml.format.CondaEnvironmentYmlParser
|
||||
import com.jetbrains.python.packaging.conda.environmentYml.format.EnvironmentYmlModifier
|
||||
import com.intellij.python.community.impl.conda.environmentYml.findCondaEnvironmentYmlFile
|
||||
import com.intellij.python.community.impl.conda.environmentYml.format.CondaEnvironmentYmlParser
|
||||
import com.intellij.python.community.impl.conda.environmentYml.format.EnvironmentYmlModifier
|
||||
import com.jetbrains.python.packaging.management.PythonPackageInstallRequest
|
||||
import com.jetbrains.python.packaging.management.PythonPackageManager
|
||||
import com.jetbrains.python.packaging.management.PythonPackageManagerEngine
|
||||
@@ -39,7 +40,7 @@ class CondaPackageManager(project: Project, sdk: Sdk) : PythonPackageManager(pro
|
||||
|
||||
override suspend fun syncLockedCommand(): PyResult<Unit> {
|
||||
val requirementsFile = getDependencyFile() ?: return PyResult.localizedError(PyBundle.message("python.sdk.conda.requirements.file.not.found"))
|
||||
return updateEnv(requirementsFile)
|
||||
return updateEnv(requirementsFile.virtualFile)
|
||||
}
|
||||
|
||||
private suspend fun updateEnv(envFile: VirtualFile): PyResult<Unit> {
|
||||
@@ -151,16 +152,14 @@ class CondaPackageManager(project: Project, sdk: Sdk) : PythonPackageManager(pro
|
||||
|
||||
override suspend fun listDeclaredPackages(): PyResult<List<PythonPackage>>? {
|
||||
val envFile = getDependencyFile() ?: return null
|
||||
val requirements = CondaEnvironmentYmlParser.fromFile(envFile) ?: return null
|
||||
val requirements = CondaEnvironmentYmlParser.fromFile(envFile.virtualFile) ?: return null
|
||||
return PyResult.success(requirements.toPythonPackages())
|
||||
}
|
||||
|
||||
override fun getDependencyFile(): VirtualFile? {
|
||||
return CondaEnvironmentYmlSdkUtils.findFile(sdk)
|
||||
}
|
||||
override fun getDependencyFile(): CondaEnvironmentYmlFile? = sdk.findCondaEnvironmentYmlFile()
|
||||
|
||||
override suspend fun addDependencyImpl(requirement: PyRequirement): Boolean {
|
||||
val envFile = getDependencyFile() ?: return false
|
||||
return EnvironmentYmlModifier.addRequirement(project, envFile, requirement.presentableText)
|
||||
return EnvironmentYmlModifier.addRequirement(project, envFile.virtualFile, requirement.presentableText)
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -5,8 +5,8 @@ import com.intellij.openapi.actionSystem.AnActionEvent
|
||||
import com.intellij.openapi.actionSystem.PlatformDataKeys
|
||||
import com.jetbrains.python.errorProcessing.PyResult
|
||||
import com.jetbrains.python.packaging.conda.CondaPackageManager
|
||||
import com.jetbrains.python.packaging.conda.environmentYml.CondaEnvironmentYmlSdkUtils.ENV_YAML_FILE_NAME
|
||||
import com.jetbrains.python.packaging.conda.environmentYml.CondaEnvironmentYmlSdkUtils.ENV_YML_FILE_NAME
|
||||
import com.intellij.python.community.impl.conda.environmentYml.CondaEnvironmentYmlSdkUtils.ENV_YAML_FILE_NAME
|
||||
import com.intellij.python.community.impl.conda.environmentYml.CondaEnvironmentYmlSdkUtils.ENV_YML_FILE_NAME
|
||||
import com.jetbrains.python.packaging.management.PythonPackageManagerAction
|
||||
import com.jetbrains.python.packaging.management.getPythonPackageManager
|
||||
import kotlin.text.Regex.Companion.escape
|
||||
|
||||
@@ -8,7 +8,6 @@ import com.intellij.openapi.Disposable
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.application.ModalityState
|
||||
import com.intellij.openapi.application.asContextElement
|
||||
import com.intellij.openapi.application.readAction
|
||||
import com.intellij.openapi.components.service
|
||||
import com.intellij.openapi.diagnostic.thisLogger
|
||||
import com.intellij.openapi.module.Module
|
||||
@@ -19,6 +18,7 @@ import com.intellij.openapi.util.Key
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.openapi.vfs.VirtualFileManager
|
||||
import com.intellij.python.pyproject.PY_PROJECT_TOML
|
||||
import com.intellij.python.pyproject.PyProjectTomlFile
|
||||
import com.intellij.serviceContainer.AlreadyDisposedException
|
||||
import com.intellij.util.cancelOnDispose
|
||||
import com.intellij.util.concurrency.annotations.RequiresBackgroundThread
|
||||
@@ -40,6 +40,7 @@ import com.jetbrains.python.packaging.packageRequirements.DependencyTreeProvider
|
||||
import com.jetbrains.python.packaging.packageRequirements.FlatPackageStructureNode
|
||||
import com.jetbrains.python.packaging.packageRequirements.PackageStructureNode
|
||||
import com.jetbrains.python.packaging.utils.PyPackageCoroutine
|
||||
import com.jetbrains.python.requirements.PyDependenciesFile
|
||||
import com.jetbrains.python.sdk.PythonSdkType
|
||||
import com.jetbrains.python.sdk.isReadOnly
|
||||
import com.jetbrains.python.sdk.readOnlyErrorMessage
|
||||
@@ -348,6 +349,7 @@ abstract class PythonPackageManager @ApiStatus.Internal constructor(
|
||||
@ApiStatus.Internal
|
||||
suspend fun listDeclaredPackagesCached(): PyResult<List<PythonPackage>>? {
|
||||
val stamps = getDependencyFiles()
|
||||
.map { it.virtualFile }
|
||||
.sortedBy { it.path }
|
||||
.map { it to it.modificationStamp }
|
||||
if (stamps.isEmpty()) return null
|
||||
@@ -360,7 +362,7 @@ abstract class PythonPackageManager @ApiStatus.Internal constructor(
|
||||
*/
|
||||
@ApiStatus.Internal
|
||||
@RequiresBackgroundThread
|
||||
open fun getDependencyFile(): VirtualFile? = null
|
||||
open fun getDependencyFile(): PyDependenciesFile? = null
|
||||
|
||||
/**
|
||||
* Returns every file whose modification should invalidate the declared-packages cache.
|
||||
@@ -370,7 +372,7 @@ abstract class PythonPackageManager @ApiStatus.Internal constructor(
|
||||
* file invalidate the cached declared-packages list.
|
||||
*/
|
||||
@ApiStatus.Internal
|
||||
protected open suspend fun getDependencyFiles(): List<VirtualFile> = listOfNotNull(getDependencyFile())
|
||||
protected open suspend fun getDependencyFiles(): List<PyDependenciesFile> = listOfNotNull(getDependencyFile())
|
||||
|
||||
/**
|
||||
* Adds a dependency to the project's dependency declaration file.
|
||||
@@ -470,13 +472,10 @@ fun PythonPackageManager.listDeclaredPackagesAsync(): List<PythonPackage>? = run
|
||||
*/
|
||||
@ApiStatus.Internal
|
||||
@RequiresBackgroundThread
|
||||
internal fun resolvePyProjectToml(workingDirectory: Path): VirtualFile? {
|
||||
internal fun resolvePyProjectToml(workingDirectory: Path): PyProjectTomlFile? {
|
||||
val pyprojectPath = workingDirectory.resolve(PY_PROJECT_TOML)
|
||||
return runBlockingMaybeCancellable {
|
||||
readAction {
|
||||
VirtualFileManager.getInstance().refreshAndFindFileByNioPath(pyprojectPath)
|
||||
}
|
||||
}
|
||||
val virtualFile = VirtualFileManager.getInstance().findFileByNioPath(pyprojectPath) ?: return null
|
||||
return PyProjectTomlFile(virtualFile)
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
|
||||
@@ -26,7 +26,9 @@ import com.jetbrains.python.packaging.management.PythonRepositoryManager
|
||||
import com.jetbrains.python.packaging.management.hasInstalledPackage
|
||||
import com.jetbrains.python.packaging.requirementsTxt.RequirementsTxtManipulationHelper
|
||||
import com.jetbrains.python.psi.LanguageLevel
|
||||
import com.jetbrains.python.requirements.PyDependenciesFile
|
||||
import com.jetbrains.python.sdk.PythonSdkAdditionalData
|
||||
import com.jetbrains.python.requirements.RequirementsTxtFile
|
||||
import com.jetbrains.python.sdk.associatedModuleDir
|
||||
import com.jetbrains.python.sdk.legacy.PythonSdkUtil
|
||||
import com.jetbrains.python.statistics.version
|
||||
@@ -52,7 +54,7 @@ open class PipPythonPackageManager(project: Project, sdk: Sdk) : PythonPackageMa
|
||||
override suspend fun syncLockedCommand(): PyResult<Unit> {
|
||||
val requirementsFile = getDependencyFile()
|
||||
return if (requirementsFile != null) {
|
||||
engine.syncRequirementsTxt(requirementsFile)
|
||||
engine.syncRequirementsTxt(requirementsFile.virtualFile)
|
||||
}
|
||||
else {
|
||||
engine.syncProject()
|
||||
@@ -77,21 +79,22 @@ open class PipPythonPackageManager(project: Project, sdk: Sdk) : PythonPackageMa
|
||||
override suspend fun listDeclaredPackages(): PyResult<List<PythonPackage>>? {
|
||||
val requirementsFile = getDependencyFile() ?: return null
|
||||
val requirements = readAction {
|
||||
PyRequirementParser.fromFile(requirementsFile)
|
||||
PyRequirementParser.fromFile(requirementsFile.virtualFile)
|
||||
}
|
||||
return PyResult.success(requirements.mapNotNull { it.toPythonPackage() })
|
||||
}
|
||||
|
||||
override fun getDependencyFile(): VirtualFile? {
|
||||
override fun getDependencyFile(): PyDependenciesFile? {
|
||||
val data = sdk.sdkAdditionalData as? PythonSdkAdditionalData ?: return null
|
||||
val requirementsPath = data.requiredTxtPath ?: Path.of(PythonSdkAdditionalData.REQUIREMENT_TXT_DEFAULT)
|
||||
return sdk.associatedModuleDir?.findFileByRelativePath(requirementsPath.toString())
|
||||
val requirementsTxtFile = sdk.associatedModuleDir?.findFileByRelativePath(requirementsPath.toString())
|
||||
return requirementsTxtFile?.let { RequirementsTxtFile(it) }
|
||||
}
|
||||
|
||||
override suspend fun addDependencyImpl(requirement: PyRequirement): Boolean {
|
||||
val requirementsFile = getDependencyFile() ?: return false
|
||||
return withContext(Dispatchers.EDT) {
|
||||
RequirementsTxtManipulationHelper.addToRequirementsTxt(project, requirementsFile, requirement.presentableText)
|
||||
RequirementsTxtManipulationHelper.addToRequirementsTxt(project, requirementsFile.virtualFile, requirement.presentableText)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,8 @@ import com.jetbrains.python.packaging.management.PythonPackageManager
|
||||
import com.jetbrains.python.packaging.management.PythonRepositoryManager
|
||||
import com.jetbrains.python.packaging.pip.PipRepositoryManager
|
||||
import com.jetbrains.python.sdk.associatedModulePath
|
||||
import com.jetbrains.python.sdk.pipenv.PipEnvFileHelper
|
||||
import com.jetbrains.python.sdk.pipenv.PipFileLockFile
|
||||
import com.jetbrains.python.sdk.pipenv.findPipFileLockFile
|
||||
import com.jetbrains.python.sdk.pipenv.runPipEnv
|
||||
import com.jetbrains.python.sdk.pipenv.PipEnvParser as SdkPipEnvParser
|
||||
import org.jetbrains.annotations.ApiStatus
|
||||
@@ -81,11 +82,9 @@ class PipEnvPackageManager(project: Project, sdk: Sdk) : PythonPackageManager(pr
|
||||
|
||||
override suspend fun listDeclaredPackages(): PyResult<List<PythonPackage>>? {
|
||||
val pipFileLock = getDependencyFile() ?: return null
|
||||
val requirements = SdkPipEnvParser.getPipFileLockRequirements(pipFileLock) ?: return null
|
||||
val requirements = SdkPipEnvParser.getPipFileLockRequirements(pipFileLock.virtualFile) ?: return null
|
||||
return PyResult.success(requirements.toPythonPackages())
|
||||
}
|
||||
|
||||
override fun getDependencyFile(): com.intellij.openapi.vfs.VirtualFile? {
|
||||
return PipEnvFileHelper.getPipFileLock(sdk)
|
||||
}
|
||||
override fun getDependencyFile(): PipFileLockFile? = sdk.findPipFileLockFile()
|
||||
}
|
||||
+3
-2
@@ -6,11 +6,12 @@ import com.jetbrains.python.errorProcessing.PyResult
|
||||
import com.jetbrains.python.packaging.management.PythonPackageManagerAction
|
||||
import com.jetbrains.python.packaging.management.getPythonPackageManager
|
||||
import com.jetbrains.python.packaging.pipenv.PipEnvPackageManager
|
||||
import com.jetbrains.python.sdk.pipenv.PipEnvFileHelper
|
||||
import com.jetbrains.python.sdk.pipenv.PIP_FILE
|
||||
import com.jetbrains.python.sdk.pipenv.PIP_FILE_LOCK
|
||||
import kotlin.text.Regex.Companion.escape
|
||||
|
||||
internal sealed class PipEnvPackageManagerAction : PythonPackageManagerAction<PipEnvPackageManager, String>() {
|
||||
override val fileNamesPattern: Regex = """^(${escape(PipEnvFileHelper.PIP_FILE)}|${escape(PipEnvFileHelper.PIP_FILE_LOCK)})$""".toRegex()
|
||||
override val fileNamesPattern: Regex = """^(${escape(PIP_FILE)}|${escape(PIP_FILE_LOCK)})$""".toRegex()
|
||||
|
||||
override fun getManager(e: AnActionEvent): PipEnvPackageManager? = e.getPythonPackageManager()
|
||||
}
|
||||
|
||||
@@ -30,7 +30,6 @@ import com.jetbrains.python.psi.PyUtil
|
||||
import com.jetbrains.python.psi.impl.PyPsiUtils
|
||||
import com.jetbrains.python.psi.resolve.PyResolveContext
|
||||
import com.jetbrains.python.psi.types.TypeEvalContext
|
||||
import com.jetbrains.python.sdk.rootManager
|
||||
import org.jetbrains.annotations.ApiStatus
|
||||
|
||||
@ApiStatus.Internal
|
||||
|
||||
+2
-2
@@ -31,7 +31,7 @@ import com.jetbrains.python.sdk.findAmongRoots
|
||||
import com.jetbrains.python.sdk.impl.PySdkBundle
|
||||
import com.jetbrains.python.sdk.impl.resolvePythonBinary
|
||||
import com.jetbrains.python.sdk.legacy.PythonSdkUtil
|
||||
import com.jetbrains.python.sdk.pipenv.PipEnvFileHelper
|
||||
import com.jetbrains.python.sdk.pipenv.PIP_FILE
|
||||
import com.jetbrains.python.sdk.pipenv.PyPipEnvSdkAdditionalData
|
||||
import com.jetbrains.python.sdk.pipenv.getPipEnvExecutable
|
||||
import com.jetbrains.python.sdk.pipenv.runPipEnv
|
||||
@@ -62,7 +62,7 @@ internal class PyPipfileSdkConfiguration : PyProjectSdkConfigurationExtension {
|
||||
private suspend fun checkManageableEnv(
|
||||
module: Module,
|
||||
): EnvCheckerResult = withBackgroundProgress(module.project, PyBundle.message("python.sdk.validating.environment")) {
|
||||
val pipfile = findAmongRoots(module, PipEnvFileHelper.PIP_FILE)?.name ?: return@withBackgroundProgress EnvCheckerResult.CannotConfigure
|
||||
val pipfile = findAmongRoots(module, PIP_FILE)?.name ?: return@withBackgroundProgress EnvCheckerResult.CannotConfigure
|
||||
val pipEnvExecutable = getPipEnvExecutable() ?: return@withBackgroundProgress EnvCheckerResult.CannotConfigure
|
||||
val canManage = pipEnvExecutable.isExecutable()
|
||||
val intentionName = PyBundle.message("sdk.create.pipenv.suggestion", pipfile)
|
||||
|
||||
+5
-5
@@ -78,8 +78,8 @@ internal class PyPoetrySdkConfiguration : PyProjectTomlConfigurationExtension {
|
||||
|
||||
val isPoetryProject = if (checkToml) {
|
||||
withContext(Dispatchers.IO) {
|
||||
PyProjectToml.findFile(module)
|
||||
?.let { toml -> getPyProjectTomlForPoetry(toml) } != null || poetryLockExists
|
||||
PyProjectToml.findPyProjectTomlFile(module)
|
||||
?.let { toml -> getPyProjectTomlForPoetry(toml.virtualFile) } != null || poetryLockExists
|
||||
}
|
||||
}
|
||||
else true
|
||||
@@ -126,9 +126,9 @@ internal class PyPoetrySdkConfiguration : PyProjectTomlConfigurationExtension {
|
||||
)
|
||||
)
|
||||
}
|
||||
val tomlFile = PyProjectToml.findFile(module)
|
||||
val versionSpecifiers = tomlFile?.let { vf ->
|
||||
readAction { vf.findPsiFile(module.project)?.resolvePythonVersionSpecifiers() }
|
||||
val tomlFile = PyProjectToml.findPyProjectTomlFile(module)
|
||||
val versionSpecifiers = tomlFile?.let { pyProjectTomlFile ->
|
||||
readAction { pyProjectTomlFile.virtualFile.findPsiFile(module.project)?.resolvePythonVersionSpecifiers() }
|
||||
} ?: PyVersionSpecifiers.ANY_SUPPORTED
|
||||
|
||||
val baseSystemPython = getSystemPython(
|
||||
|
||||
@@ -35,7 +35,7 @@ internal class PoetrySelectSdkProvider() : EvoSelectSdkProvider {
|
||||
getPoetryExecutable() ?:PyResult.localizedError(PyBundle.message("python.sdk.poetry.execution.exception.no.poetry.message"))
|
||||
|
||||
val pyProjectTomlFile = withContext(Dispatchers.IO) {
|
||||
PyProjectToml.findFile(evoModuleSdk.module)
|
||||
PyProjectToml.findPyProjectTomlFile(evoModuleSdk.module)?.virtualFile
|
||||
} ?: return@EvoTreeLazyNodeElement PyResult.localizedError(PyBundle.message("evolution.pyproject.toml.file.is.required.for.poetry"))
|
||||
|
||||
val envList = runPoetry(pyProjectTomlFile.parent.toNioPath(), "env", "list", "--full-path").getOr { return@EvoTreeLazyNodeElement it }
|
||||
@@ -44,7 +44,7 @@ internal class PoetrySelectSdkProvider() : EvoSelectSdkProvider {
|
||||
val envByFolders = environments.groupBy { it.parent }.toMutableMap()
|
||||
|
||||
|
||||
val (projectName, requiresPython) = withContext(Dispatchers.IO) {
|
||||
val (projectName, _) = withContext(Dispatchers.IO) {
|
||||
val toml = PyProjectToml.parse(pyProjectTomlFile.readText())
|
||||
(toml.project?.name) to (toml.project?.requiresPython)
|
||||
}
|
||||
|
||||
@@ -248,35 +248,6 @@ fun Sdk.isAssociatedWithAnotherModule(module: Module?): Boolean {
|
||||
return basePath != associatedPath
|
||||
}
|
||||
|
||||
@get:Internal
|
||||
val Sdk.associatedModulePath: String?
|
||||
// TODO: Support .project associations
|
||||
get() = associatedPathFromAdditionalData /*?: associatedPathFromDotProject*/
|
||||
|
||||
|
||||
@get:Internal
|
||||
val Sdk.associatedModuleNioPath: Path?
|
||||
get() =
|
||||
try {
|
||||
associatedModulePath?.let { Path(it) }
|
||||
}
|
||||
catch (e: InvalidPathException) {
|
||||
if (getUserData(SDK_ERROR_REPORTED) != true) {
|
||||
LOGGER.warn("Can't convert ${associatedModulePath} to path", e)
|
||||
putUserData(SDK_ERROR_REPORTED, true)
|
||||
}
|
||||
null
|
||||
}
|
||||
|
||||
private val SDK_ERROR_REPORTED = Key.create<Boolean>("pySdkErrorReported")
|
||||
|
||||
@get:Internal
|
||||
val Sdk.associatedModuleDir: VirtualFile?
|
||||
get() {
|
||||
val nioPath = associatedModuleNioPath ?: return null
|
||||
return VirtualFileManager.getInstance().findFileByNioPath(nioPath) ?: TempFileSystem.getInstance().findFileByNioFile(nioPath)
|
||||
}
|
||||
|
||||
@Internal
|
||||
fun Sdk.setup(existingSdks: List<Sdk>): Sdk? {
|
||||
val homeDir = homeDirectory ?: return null
|
||||
@@ -384,9 +355,6 @@ val Sdk.isReadOnly: Boolean
|
||||
val Sdk.readOnlyErrorMessage: String
|
||||
get() = PythonSdkReadOnlyProvider.getReadOnlyMessage(this) ?: PyBundle.message("python.sdk.read.only", name)
|
||||
|
||||
private val Sdk.associatedPathFromAdditionalData: String?
|
||||
get() = (sdkAdditionalData as? PythonSdkAdditionalData)?.associatedModulePath
|
||||
|
||||
val Sdk.sdkFlavor: PythonSdkFlavor<*> get() = getOrCreateAdditionalData().flavor
|
||||
|
||||
private fun Sdk.isLocatedInsideModule(module: Module): Boolean {
|
||||
|
||||
@@ -15,8 +15,8 @@ import com.jetbrains.python.PyBundle.message
|
||||
import com.jetbrains.python.conda.loadLocalPythonCondaPath
|
||||
import com.jetbrains.python.errorProcessing.PyResult
|
||||
import com.jetbrains.python.newProjectWizard.projectPath.ProjectPathFlows
|
||||
import com.jetbrains.python.packaging.conda.environmentYml.CondaEnvironmentYmlSdkUtils
|
||||
import com.jetbrains.python.packaging.conda.environmentYml.format.CondaEnvironmentYmlParser
|
||||
import com.intellij.python.community.impl.conda.environmentYml.CondaEnvironmentYmlSdkUtils
|
||||
import com.intellij.python.community.impl.conda.environmentYml.format.CondaEnvironmentYmlParser
|
||||
import com.jetbrains.python.sdk.add.v2.FileSystem
|
||||
import com.jetbrains.python.sdk.add.v2.PathHolder
|
||||
import com.jetbrains.python.sdk.add.v2.PythonToolViewModel
|
||||
|
||||
@@ -310,7 +310,7 @@ internal val <P : PathHolder> PythonAddInterpreterModel<P>.existingSdks: List<Sd
|
||||
get() = allInterpreters.value?.filterIsInstance<ExistingSelectableInterpreter<P>>()?.map { it.sdkWrapper.sdk } ?: emptyList()
|
||||
|
||||
internal suspend fun PythonAddInterpreterModel<*>.getBasePath(module: Module?): Path = withContext(Dispatchers.IO) {
|
||||
val pyProjectTomlBased = module?.let { PyProjectToml.findFile(it)?.toNioPathOrNull()?.parent }
|
||||
val pyProjectTomlBased = module?.let { PyProjectToml.findPyProjectTomlFile(it)?.virtualFile?.toNioPathOrNull()?.parent }
|
||||
|
||||
pyProjectTomlBased ?: module?.baseDir?.path?.let { Path.of(it) } ?: projectPathFlows.projectPathWithDefault.first()
|
||||
}
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
// Copyright 2000-2024 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.openapi.module.Module
|
||||
import com.intellij.openapi.projectRoots.Sdk
|
||||
import com.intellij.openapi.vfs.StandardFileSystems
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.jetbrains.python.sdk.associatedModulePath
|
||||
import com.jetbrains.python.sdk.findAmongRoots
|
||||
import org.jetbrains.annotations.ApiStatus.Internal
|
||||
|
||||
@Internal
|
||||
object PipEnvFileHelper {
|
||||
const val PIP_FILE: String = "Pipfile"
|
||||
const val PIP_FILE_LOCK: String = "Pipfile.lock"
|
||||
|
||||
fun getPipFileLock(sdk: Sdk): VirtualFile? =
|
||||
sdk.associatedModulePath?.let { StandardFileSystems.local().findFileByPath(it)?.findChild(PIP_FILE_LOCK) }
|
||||
|
||||
suspend fun pipFile(module: Module): VirtualFile? = findAmongRoots(module, PIP_FILE)
|
||||
}
|
||||
@@ -5,7 +5,6 @@ import com.intellij.notification.NotificationGroupManager
|
||||
import com.intellij.notification.NotificationListener
|
||||
import com.intellij.notification.NotificationType
|
||||
import com.intellij.openapi.application.EDT
|
||||
import com.intellij.openapi.application.edtWriteAction
|
||||
import com.intellij.openapi.application.writeAction
|
||||
import com.intellij.openapi.editor.Document
|
||||
import com.intellij.openapi.editor.Editor
|
||||
@@ -78,7 +77,7 @@ internal class PipEnvPipFileWatcher : EditorFactoryListener {
|
||||
private suspend fun notifyPipFileChanged(module: Module) {
|
||||
if (module.getUserData(notificationActive) == true) return
|
||||
val title = when {
|
||||
getPipFileLock(module) == null -> PyBundle.message("python.sdk.pipenv.pip.file.lock.not.found")
|
||||
findAmongRoots(module, PIP_FILE_LOCK) == null -> PyBundle.message("python.sdk.pipenv.pip.file.lock.not.found")
|
||||
else -> PyBundle.message("python.sdk.pipenv.pip.file.lock.out.of.date")
|
||||
}
|
||||
val content = PyBundle.message("python.sdk.pipenv.pip.file.notification.content")
|
||||
@@ -129,18 +128,15 @@ internal class PipEnvPipFileWatcher : EditorFactoryListener {
|
||||
|
||||
private suspend fun isPipFileEditor(editor: Editor): Boolean {
|
||||
val file = editor.document.virtualFile ?: return false
|
||||
if (file.name != PipEnvFileHelper.PIP_FILE) return false
|
||||
if (file.name != PIP_FILE) return false
|
||||
val project = editor.project ?: return false
|
||||
val module = file.getModule(project) ?: return false
|
||||
if (PipEnvFileHelper.pipFile(module) != file) return false
|
||||
if (findAmongRoots(module, PIP_FILE) != file) return false
|
||||
return module.pythonSdk?.isPipEnv == true
|
||||
}
|
||||
|
||||
private val Document.virtualFile: VirtualFile?
|
||||
get() = FileDocumentManager.getInstance().getFile(this)
|
||||
|
||||
private fun VirtualFile.getModule(project: Project): Module? =
|
||||
ModuleUtil.findModuleForFile(this, project)
|
||||
|
||||
private suspend fun getPipFileLock(module: Module): VirtualFile? = findAmongRoots(module, PipEnvFileHelper.PIP_FILE_LOCK)
|
||||
private fun VirtualFile.getModule(project: Project): Module? = ModuleUtil.findModuleForFile(this, project)
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
// Copyright 2000-2024 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.openapi.projectRoots.Sdk
|
||||
import com.intellij.openapi.vfs.StandardFileSystems
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.python.requirements.icons.PythonRequirementsIcons
|
||||
import com.jetbrains.python.requirements.PyDependenciesFile
|
||||
import com.jetbrains.python.sdk.associatedModulePath
|
||||
import org.jetbrains.annotations.ApiStatus.Internal
|
||||
import javax.swing.Icon
|
||||
|
||||
@Internal
|
||||
const val PIP_FILE: String = "Pipfile"
|
||||
|
||||
@Internal
|
||||
const val PIP_FILE_LOCK: String = "Pipfile.lock"
|
||||
|
||||
@Internal
|
||||
class PipFileLockFile(override val virtualFile: VirtualFile) : PyDependenciesFile {
|
||||
override val icon: Icon get() = PythonRequirementsIcons.Requirements
|
||||
}
|
||||
|
||||
|
||||
internal fun Sdk.findPipFileLockFile(): PipFileLockFile? {
|
||||
val virtualFile = associatedModulePath?.let { StandardFileSystems.local().findFileByPath(it)?.findChild(PIP_FILE_LOCK) }
|
||||
return virtualFile?.let { PipFileLockFile(it) }
|
||||
}
|
||||
@@ -76,7 +76,7 @@ suspend fun setupPipEnv(
|
||||
basePythonBinaryPath: PythonBinary?,
|
||||
installPackages: Boolean,
|
||||
): PyResult<@SystemDependent String> {
|
||||
val pipfile = projectPath.resolve(PipEnvFileHelper.PIP_FILE)
|
||||
val pipfile = projectPath.resolve(PIP_FILE)
|
||||
|
||||
if (!pipfile.exists()) {
|
||||
// Currently, if a Pipenv file exists inside the user's home directory, then it will NOT create a new Pipenv in the current project
|
||||
|
||||
@@ -4,7 +4,7 @@ package com.jetbrains.python.sdk.poetry
|
||||
import com.intellij.openapi.module.Module
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.projectRoots.Sdk
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.python.pyproject.PyProjectTomlFile
|
||||
import com.jetbrains.python.PyBundle
|
||||
import com.jetbrains.python.errorProcessing.PyResult
|
||||
import com.jetbrains.python.getOrNull
|
||||
@@ -219,7 +219,7 @@ class PoetryPackageManager(project: Project, sdk: Sdk) : PythonPackageManager(pr
|
||||
return PackageCollectionPackageStructureNode(declared, undeclared + standalonePackages)
|
||||
}
|
||||
|
||||
override fun getDependencyFile(): VirtualFile? {
|
||||
override fun getDependencyFile(): PyProjectTomlFile? {
|
||||
val projectPathStr = sdk.associatedModulePath ?: return null
|
||||
val projectPath = Path.of(projectPathStr)
|
||||
return resolvePyProjectToml(projectPath)
|
||||
|
||||
@@ -8,9 +8,9 @@ import com.intellij.openapi.progress.runBlockingMaybeCancellable
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.projectRoots.Sdk
|
||||
import com.intellij.openapi.roots.ModuleRootManager
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.python.community.impl.uv.common.UV_TOOL_ID
|
||||
import com.intellij.python.pyproject.PyProjectToml
|
||||
import com.intellij.python.pyproject.PyProjectTomlFile
|
||||
import com.intellij.python.pyproject.model.internal.workspaceBridge.getToolWorkspaceLayout
|
||||
import com.intellij.util.cancelOnDispose
|
||||
import com.jetbrains.python.PyBundle.message
|
||||
@@ -270,17 +270,17 @@ class UvPackageManager internal constructor(project: Project, sdk: Sdk, uvExecut
|
||||
override fun updateLockedAction(): suspend () -> PyResult<Unit> = suspend { syncLocked().mapSuccess { } }
|
||||
|
||||
private suspend fun resolvePackageName(module: Module): String {
|
||||
val pyProjectFile = PyProjectToml.findFile(module) ?: return module.name
|
||||
return PyProjectToml.parseCached(module.project, pyProjectFile)?.project?.name ?: module.name
|
||||
val pyProjectFile = PyProjectToml.findPyProjectTomlFile(module) ?: return module.name
|
||||
return PyProjectToml.parseCached(module.project, pyProjectFile.virtualFile)?.project?.name ?: module.name
|
||||
}
|
||||
|
||||
// TODO PY-87712 Double check for remotes
|
||||
override fun getDependencyFile(): VirtualFile? {
|
||||
override fun getDependencyFile(): PyProjectTomlFile? {
|
||||
val uvWorkingDirectory = runBlockingMaybeCancellable { uvExecutionContextDeferred.await().workingDir }
|
||||
return resolvePyProjectToml(uvWorkingDirectory)
|
||||
}
|
||||
|
||||
override suspend fun getDependencyFiles(): List<VirtualFile> {
|
||||
override suspend fun getDependencyFiles(): List<PyProjectTomlFile> {
|
||||
val rootFile = getDependencyFile() ?: return emptyList()
|
||||
val uvWorkingDirectory = uvExecutionContextDeferred.await().workingDir
|
||||
val memberModules = readAction {
|
||||
@@ -289,7 +289,7 @@ class UvPackageManager internal constructor(project: Project, sdk: Sdk, uvExecut
|
||||
} ?: return@readAction emptyList()
|
||||
rootModule.getToolWorkspaceLayout(UV_TOOL_ID)?.memberModules.orEmpty()
|
||||
}
|
||||
val memberFiles = memberModules.mapNotNull { PyProjectToml.findFile(it) }
|
||||
val memberFiles = memberModules.mapNotNull { PyProjectToml.findPyProjectTomlFile(it) }
|
||||
return listOf(rootFile) + memberFiles
|
||||
}
|
||||
|
||||
|
||||
@@ -16,9 +16,13 @@ import com.jetbrains.python.packaging.common.PythonPackageDetails
|
||||
import com.jetbrains.python.packaging.common.PythonRepositoryPackageSpecification
|
||||
import com.jetbrains.python.packaging.common.toPythonPackage
|
||||
import com.jetbrains.python.packaging.common.toPythonPackages
|
||||
import com.jetbrains.python.packaging.conda.environmentYml.format.CondaEnvironmentYmlParser
|
||||
import com.intellij.python.community.impl.conda.environmentYml.CondaEnvironmentYmlFile
|
||||
import com.intellij.python.community.impl.conda.environmentYml.format.CondaEnvironmentYmlParser
|
||||
import com.jetbrains.python.packaging.setupPy.SetupPyHelpers
|
||||
import com.jetbrains.python.psi.PyFile
|
||||
import com.jetbrains.python.requirements.PyDependenciesFile
|
||||
import com.jetbrains.python.requirements.RequirementsTxtFile
|
||||
import com.jetbrains.python.requirements.SetupPyFile
|
||||
import com.jetbrains.python.sdk.associatedModuleDir
|
||||
import org.jetbrains.annotations.TestOnly
|
||||
|
||||
@@ -80,14 +84,14 @@ class TestPythonPackageManager(project: Project, sdk: Sdk) : PythonPackageManage
|
||||
return PyResult.success(listInstalledPackagesSnapshot())
|
||||
}
|
||||
|
||||
override fun getDependencyFile(): VirtualFile? {
|
||||
override fun getDependencyFile(): PyDependenciesFile? {
|
||||
val providerType = sdk.getUserData(REQUIREMENTS_PROVIDER_KEY) ?: return null
|
||||
val moduleDir = sdk.associatedModuleDir ?: return null
|
||||
|
||||
return when (providerType) {
|
||||
RequirementsProviderType.REQUIREMENTS_TXT -> moduleDir.findChild("requirements.txt")
|
||||
RequirementsProviderType.SETUP_PY -> moduleDir.findChild("setup.py")
|
||||
RequirementsProviderType.ENVIRONMENT_YML -> moduleDir.findChild("environment.yml")
|
||||
RequirementsProviderType.REQUIREMENTS_TXT -> moduleDir.findChild("requirements.txt")?.let { RequirementsTxtFile(it) }
|
||||
RequirementsProviderType.SETUP_PY -> moduleDir.findChild("setup.py")?.let { SetupPyFile(it) }
|
||||
RequirementsProviderType.ENVIRONMENT_YML -> moduleDir.findChild("environment.yml")?.let { CondaEnvironmentYmlFile(it) }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user