mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-04-19 04:51:24 +07:00
fix additional data creation for remote interpreters; (#PY-76055) Fixed
GitOrigin-RevId: 064cbbaeb5f4241b718c9e51df0396b49971a365
This commit is contained in:
committed by
intellij-monorepo-bot
parent
23c1ddb6b2
commit
d67337d2c9
@@ -3,7 +3,6 @@ package com.jetbrains.python.sdk
|
||||
import org.jetbrains.annotations.ApiStatus
|
||||
import java.nio.file.InvalidPathException
|
||||
import java.nio.file.Path
|
||||
import java.nio.file.Paths
|
||||
|
||||
// TODO: Move to PythonSdkUtil when rewritten in Kotlin
|
||||
|
||||
@@ -11,10 +10,13 @@ import java.nio.file.Paths
|
||||
* Converts [str] to [Path] of str is real nio path. Returns null otherwise
|
||||
*/
|
||||
@ApiStatus.Internal
|
||||
fun tryResolvePath(str: String): Path? {
|
||||
if (PythonSdkUtil.isCustomPythonSdkHomePath(str)) return null
|
||||
fun tryResolvePath(str: String?): Path? {
|
||||
if (str == null || PythonSdkUtil.isCustomPythonSdkHomePath(str)) {
|
||||
return null
|
||||
}
|
||||
|
||||
try {
|
||||
return Paths.get(str)
|
||||
return Path.of(str)
|
||||
}
|
||||
catch (_: InvalidPathException) {
|
||||
}
|
||||
|
||||
@@ -39,6 +39,7 @@ import java.util.*;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import static com.jetbrains.python.sdk.PythonSdkUtilKtKt.tryResolvePath;
|
||||
import static com.jetbrains.python.sdk.flavors.PySdkFlavorUtilKt.getFileExecutionError;
|
||||
|
||||
|
||||
@@ -283,14 +284,14 @@ public abstract class PythonSdkFlavor<D extends PyFlavorData> {
|
||||
@Nullable
|
||||
public static PythonSdkFlavor<?> getFlavor(@Nullable String sdkPath) {
|
||||
if (sdkPath == null || PythonSdkUtil.isCustomPythonSdkHomePath(sdkPath)) return null;
|
||||
return tryDetectFlavorByLocalPath(Path.of(sdkPath));
|
||||
return tryDetectFlavorByLocalPath(sdkPath);
|
||||
}
|
||||
|
||||
/**
|
||||
* Detects {@link PythonSdkFlavor} for local python path
|
||||
*/
|
||||
@RequiresBackgroundThread(generateAssertion = false) //No warning yet as there are usages: to be fixed
|
||||
public static @Nullable PythonSdkFlavor<?> tryDetectFlavorByLocalPath(@NotNull Path sdkPath) {
|
||||
public static @Nullable PythonSdkFlavor<?> tryDetectFlavorByLocalPath(@NotNull String sdkPath) {
|
||||
// Iterate over all flavors starting with platform-independent (like venv): see `getApplicableFlavors` doc.
|
||||
// Order is important as venv must have priority over unix/windows
|
||||
for (PythonSdkFlavor<?> flavor : getApplicableFlavors(true)) {
|
||||
@@ -311,15 +312,14 @@ public abstract class PythonSdkFlavor<D extends PyFlavorData> {
|
||||
return null;
|
||||
}
|
||||
|
||||
Path path = Path.of(sdkPath);
|
||||
for (PythonSdkFlavor<?> flavor : getPlatformIndependentFlavors()) {
|
||||
if (flavor.isValidSdkPath(path)) {
|
||||
if (flavor.isValidSdkPath(sdkPath)) {
|
||||
return flavor;
|
||||
}
|
||||
}
|
||||
|
||||
for (PythonSdkFlavor<?> flavor : getPlatformFlavorsFromExtensions(true)) {
|
||||
if (flavor.isValidSdkPath(path)) {
|
||||
if (flavor.isValidSdkPath(sdkPath)) {
|
||||
return flavor;
|
||||
}
|
||||
}
|
||||
@@ -329,7 +329,12 @@ public abstract class PythonSdkFlavor<D extends PyFlavorData> {
|
||||
/**
|
||||
* It only validates path for local target, hence use {@link #sdkSeemsValid(Sdk, PyFlavorData, TargetEnvironmentConfiguration)} instead
|
||||
*/
|
||||
public boolean isValidSdkPath(@NotNull Path path) {
|
||||
public boolean isValidSdkPath(@NotNull String pathStr) {
|
||||
Path path = tryResolvePath(pathStr);
|
||||
if (path == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return Files.exists(path) && Files.isExecutable(path);
|
||||
}
|
||||
|
||||
|
||||
@@ -53,8 +53,9 @@ public class PyRemoteSdkAdditionalData extends PythonSdkAdditionalData implement
|
||||
|
||||
private static @Nullable PythonSdkFlavor<?> computeFlavor(@Nullable String sdkPath) {
|
||||
if (sdkPath != null) {
|
||||
// FIXME: converge with sdk flavor & use os.isWindows
|
||||
for (var flavor : getApplicableFlavors(sdkPath.contains("\\"))) {
|
||||
if (flavor.isValidSdkPath(Path.of(sdkPath))) {
|
||||
if (flavor.isValidSdkPath(sdkPath)) {
|
||||
return flavor;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -475,9 +475,19 @@ private fun Sdk.containsModuleName(module: Module?): Boolean {
|
||||
*/
|
||||
fun Sdk.getOrCreateAdditionalData(): PythonSdkAdditionalData {
|
||||
val existingData = sdkAdditionalData as? PythonSdkAdditionalData
|
||||
if (existingData != null) return existingData
|
||||
val homePath = Path.of(homePath ?: error("homePath is null for $this"))
|
||||
val flavor = PythonSdkFlavor.tryDetectFlavorByLocalPath(homePath) ?: error("No flavor detected for $homePath sdk")
|
||||
if (existingData != null) {
|
||||
return existingData
|
||||
}
|
||||
|
||||
if (homePath == null) {
|
||||
error("homePath is null for $this")
|
||||
}
|
||||
|
||||
val flavor = PythonSdkFlavor.tryDetectFlavorByLocalPath(homePath!!)
|
||||
if (flavor == null) {
|
||||
error("No flavor detected for $homePath sdk")
|
||||
}
|
||||
|
||||
val newData = PythonSdkAdditionalData(if (flavor.supportsEmptyData()) flavor else null)
|
||||
val modificator = sdkModificator
|
||||
modificator.sdkAdditionalData = newData
|
||||
|
||||
@@ -14,7 +14,6 @@ import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.io.File;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
@@ -44,8 +43,8 @@ public final class JythonSdkFlavor extends PythonSdkFlavor<PyFlavorData.Empty> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValidSdkPath(@NotNull Path path) {
|
||||
return StringUtil.toLowerCase(FileUtilRt.getNameWithoutExtension(path.getFileName().toString())).startsWith("jython");
|
||||
public boolean isValidSdkPath(@NotNull String pathStr) {
|
||||
return StringUtil.toLowerCase(FileUtilRt.getNameWithoutExtension(pathStr)).startsWith("jython");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -4,13 +4,12 @@ package com.jetbrains.python.sdk.flavors
|
||||
import com.intellij.openapi.util.io.FileUtil
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import java.io.File
|
||||
import java.nio.file.Path
|
||||
|
||||
class MayaSdkFlavor private constructor() : CPythonSdkFlavor<PyFlavorData.Empty>() {
|
||||
override fun getFlavorDataClass(): Class<PyFlavorData.Empty> = PyFlavorData.Empty::class.java
|
||||
|
||||
override fun isValidSdkPath(path: Path): Boolean {
|
||||
val name = FileUtil.getNameWithoutExtension(path.fileName.toString()).lowercase()
|
||||
override fun isValidSdkPath(pathStr: String): Boolean {
|
||||
val name = FileUtil.getNameWithoutExtension(pathStr).lowercase()
|
||||
return name.startsWith("mayapy")
|
||||
}
|
||||
|
||||
|
||||
@@ -11,8 +11,6 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.io.File;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
@@ -43,8 +41,8 @@ public final class PyPySdkFlavor extends PythonSdkFlavor<PyFlavorData.Empty> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValidSdkPath(@NotNull Path path) {
|
||||
return StringUtil.toLowerCase(FileUtilRt.getNameWithoutExtension(path.getFileName().toString())).startsWith("pypy");
|
||||
public boolean isValidSdkPath(@NotNull String pathStr) {
|
||||
return StringUtil.toLowerCase(FileUtilRt.getNameWithoutExtension(pathStr)).startsWith("pypy");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -16,7 +16,6 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.io.File;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
@@ -76,12 +75,12 @@ public final class VirtualEnvSdkFlavor extends CPythonSdkFlavor<PyFlavorData.Emp
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValidSdkPath(@NotNull Path path) {
|
||||
if (!super.isValidSdkPath(path)) {
|
||||
public boolean isValidSdkPath(@NotNull String pathStr) {
|
||||
if (!super.isValidSdkPath(pathStr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return PythonSdkUtil.getVirtualEnvRoot(path.toString()) != null;
|
||||
return PythonSdkUtil.getVirtualEnvRoot(pathStr) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -25,6 +25,7 @@ import java.io.File;
|
||||
import java.nio.file.Path;
|
||||
import java.util.*;
|
||||
|
||||
import static com.jetbrains.python.sdk.PythonSdkUtilKtKt.tryResolvePath;
|
||||
import static com.jetbrains.python.sdk.WinAppxToolsKt.getAppxFiles;
|
||||
import static com.jetbrains.python.sdk.WinAppxToolsKt.getAppxProduct;
|
||||
|
||||
@@ -87,33 +88,33 @@ public class WinPythonSdkFlavor extends CPythonSdkFlavor<PyFlavorData.Empty> {
|
||||
public boolean sdkSeemsValid(@NotNull Sdk sdk,
|
||||
PyFlavorData.@NotNull Empty flavorData,
|
||||
@Nullable TargetEnvironmentConfiguration targetConfig) {
|
||||
if (super.sdkSeemsValid(sdk, flavorData, targetConfig)) {
|
||||
return true;
|
||||
}
|
||||
if (targetConfig != null) {
|
||||
if (super.sdkSeemsValid(sdk, flavorData, targetConfig) || targetConfig != null) {
|
||||
// non-local, cant check for appx
|
||||
return true;
|
||||
}
|
||||
var path = sdk.getHomePath();
|
||||
return path != null && isLocalPathValidPython(Path.of(path));
|
||||
|
||||
var path = tryResolvePath(sdk.getHomePath());
|
||||
return path != null && isLocalPathValidPython(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValidSdkPath(final @NotNull Path path) {
|
||||
if (super.isValidSdkPath(path)) {
|
||||
public boolean isValidSdkPath(final @NotNull String pathStr) {
|
||||
if (super.isValidSdkPath(pathStr)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return isLocalPathValidPython(path);
|
||||
var path = tryResolvePath(pathStr);
|
||||
return path != null && isLocalPathValidPython(path);
|
||||
}
|
||||
|
||||
private boolean isLocalPathValidPython(@NotNull Path path) {
|
||||
if (myAppxCache.getValue().contains(path.toString())) {
|
||||
String pathStr = path.toString();
|
||||
if (myAppxCache.getValue().contains(pathStr)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
String product = getAppxProduct(path);
|
||||
return product != null && product.contains(APPX_PRODUCT) && isValidSdkPath(path);
|
||||
return product != null && product.contains(APPX_PRODUCT) && isValidSdkPath(pathStr);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -78,12 +78,12 @@ public final class CondaEnvSdkFlavor extends CPythonSdkFlavor<PyCondaFlavorData>
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValidSdkPath(@NotNull Path path) {
|
||||
if (!super.isValidSdkPath(path)) {
|
||||
public boolean isValidSdkPath(@NotNull String pathStr) {
|
||||
if (!super.isValidSdkPath(pathStr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return PythonSdkUtil.isConda(path.toString());
|
||||
return PythonSdkUtil.isConda(pathStr);
|
||||
}
|
||||
|
||||
public static @Nullable File getCondaEnvRoot(final @NotNull String binaryPath) {
|
||||
|
||||
@@ -3,11 +3,10 @@ package com.jetbrains.python.sdk.pipenv
|
||||
|
||||
import com.jetbrains.python.sdk.flavors.CPythonSdkFlavor
|
||||
import com.jetbrains.python.sdk.flavors.PyFlavorData
|
||||
import java.nio.file.Path
|
||||
|
||||
object PyPipEnvSdkFlavor : CPythonSdkFlavor<PyFlavorData.Empty>() {
|
||||
override fun getIcon() = PIPENV_ICON
|
||||
override fun getFlavorDataClass(): Class<PyFlavorData.Empty> = PyFlavorData.Empty::class.java
|
||||
|
||||
override fun isValidSdkPath(path: Path) = false
|
||||
override fun isValidSdkPath(pathStr: String) = false
|
||||
}
|
||||
@@ -3,7 +3,6 @@ package com.jetbrains.python.sdk.poetry
|
||||
|
||||
import com.jetbrains.python.sdk.flavors.CPythonSdkFlavor
|
||||
import com.jetbrains.python.sdk.flavors.PyFlavorData
|
||||
import java.nio.file.Path
|
||||
|
||||
|
||||
/**
|
||||
@@ -14,5 +13,5 @@ object PyPoetrySdkFlavor : CPythonSdkFlavor<PyFlavorData.Empty>() {
|
||||
override fun getIcon() = POETRY_ICON
|
||||
override fun getFlavorDataClass(): Class<PyFlavorData.Empty> = PyFlavorData.Empty::class.java
|
||||
|
||||
override fun isValidSdkPath(path: Path) = false
|
||||
override fun isValidSdkPath(pathStr: String) = false
|
||||
}
|
||||
@@ -1,14 +1,13 @@
|
||||
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.jetbrains.python.sdk
|
||||
|
||||
import com.intellij.openapi.projectRoots.Sdk
|
||||
import com.intellij.testFramework.ProjectRule
|
||||
import com.jetbrains.python.remote.PyRemoteSdkAdditionalData
|
||||
|
||||
import org.jdom.Element
|
||||
import org.junit.Assert
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.mockito.Mockito.mock
|
||||
import org.mockito.Mockito.`when`
|
||||
|
||||
class PySdkAdditionalDataTest {
|
||||
@JvmField
|
||||
@@ -27,4 +26,12 @@ class PySdkAdditionalDataTest {
|
||||
val loadedSut = PythonSdkAdditionalData.loadFromElement(element)
|
||||
Assert.assertEquals("UUID hasn't been loaded", sut.uuid, loadedSut.uuid)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun remoteAdditionalDataTest() {
|
||||
var data = PyRemoteSdkAdditionalData("!!!!!")
|
||||
|
||||
data = PyRemoteSdkAdditionalData("sftp://host:22/home/bin/python3")
|
||||
data = PyRemoteSdkAdditionalData("docker://django:latest/python")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user