mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-04-19 21:11:28 +07:00
Python: Make version-specific methods static is PythonSdkFlavor: they aren't flavor-specific.
It is always `--version` and `Python [version]`, no need to have virtual overridable methods. One doesn't need to know the flavor to get a python version. (cherry picked from commit 63b16768f1dd299cb4cefb5fd935c44614d6ffb6) IJ-CR-151990 GitOrigin-RevId: ebc2eb5428c10048cc6f17a6e5c99632b3f7d2cc
This commit is contained in:
committed by
intellij-monorepo-bot
parent
6a0c236e0b
commit
f54ea8affd
@@ -333,7 +333,7 @@ private suspend fun filterLatestUsablePython(flavorsToPythons: List<Pair<PythonS
|
||||
for ((flavor, paths) in flavorsToPythons) {
|
||||
for (pythonPath in paths) {
|
||||
val versionString = validatePythonAndGetVersion(pythonPath, flavor) ?: continue
|
||||
val languageLevel = flavor.getLanguageLevelFromVersionString(versionString)
|
||||
val languageLevel =PythonSdkFlavor.getLanguageLevelFromVersionStringStatic(versionString)
|
||||
|
||||
// Highest possible, no need to search further
|
||||
if (languageLevel == LanguageLevel.getLatest()) {
|
||||
@@ -375,7 +375,7 @@ private suspend fun validatePythonAndGetVersion(pythonBinary: PythonBinary, flav
|
||||
fileLogger.warn("$pythonBinary didn't return in $timeout, skipping")
|
||||
}
|
||||
0 -> {
|
||||
return@withContext flavor.getVersionString(pythonBinary.pathString)
|
||||
return@withContext PythonSdkFlavor.getVersionStringStatic(pythonBinary.pathString)
|
||||
}
|
||||
else -> {
|
||||
fileLogger.warn("$pythonBinary exited with code ${exitCode}, skipping")
|
||||
|
||||
@@ -32,5 +32,6 @@
|
||||
<orderEntry type="library" name="jackson-databind" level="project" />
|
||||
<orderEntry type="library" name="jackson-module-kotlin" level="project" />
|
||||
<orderEntry type="module" module-name="intellij.platform.ide.progress" />
|
||||
<orderEntry type="library" scope="TEST" name="JUnit5" level="project" />
|
||||
</component>
|
||||
</module>
|
||||
@@ -47,6 +47,12 @@ import static com.jetbrains.python.sdk.flavors.PySdkFlavorUtilKt.getFileExecutio
|
||||
*/
|
||||
public abstract class PythonSdkFlavor<D extends PyFlavorData> {
|
||||
public static final ExtensionPointName<PythonSdkFlavor<?>> EP_NAME = ExtensionPointName.create("Pythonid.pythonSdkFlavor");
|
||||
/**
|
||||
* <code>
|
||||
* Python 3.11
|
||||
* </code>
|
||||
*/
|
||||
private static final String PYTHON_VERSION_STRING_PREFIX = "Python ";
|
||||
/**
|
||||
* To prevent log pollution and slowness, we cache every {@link #isFileExecutable(String, TargetEnvironmentConfiguration)} call
|
||||
* and only log it once
|
||||
@@ -58,6 +64,12 @@ public abstract class PythonSdkFlavor<D extends PyFlavorData> {
|
||||
|
||||
private static final Pattern VERSION_RE = Pattern.compile("(Python \\S+).*");
|
||||
private static final Logger LOG = Logger.getInstance(PythonSdkFlavor.class);
|
||||
/**
|
||||
* <code>
|
||||
* python --version
|
||||
* </code>
|
||||
*/
|
||||
public static final String PYTHON_VERSION_ARG = "--version";
|
||||
|
||||
|
||||
/**
|
||||
@@ -324,19 +336,31 @@ public abstract class PythonSdkFlavor<D extends PyFlavorData> {
|
||||
return Files.exists(path) && Files.isExecutable(path);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use {@link #getVersionStringStatic(String)}
|
||||
* @param sdkHome
|
||||
* @return
|
||||
*/
|
||||
@Deprecated(forRemoval = true)
|
||||
@Nullable
|
||||
@RequiresBackgroundThread(generateAssertion = false) //because of process output
|
||||
public String getVersionString(@Nullable String sdkHome) {
|
||||
return getVersionStringStatic(sdkHome);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@RequiresBackgroundThread(generateAssertion = false) //because of process output
|
||||
public static String getVersionStringStatic(@Nullable String sdkHome) {
|
||||
if (sdkHome == null) {
|
||||
return null;
|
||||
}
|
||||
final String runDirectory = new File(sdkHome).getParent();
|
||||
final ProcessOutput processOutput = PySdkUtil.getProcessOutput(runDirectory, new String[]{sdkHome, getVersionOption()}, 10000);
|
||||
final ProcessOutput processOutput = PySdkUtil.getProcessOutput(runDirectory, new String[]{sdkHome, PYTHON_VERSION_ARG}, 10000);
|
||||
return getVersionStringFromOutput(processOutput);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getVersionStringFromOutput(@NotNull ProcessOutput processOutput) {
|
||||
public static String getVersionStringFromOutput(@NotNull ProcessOutput processOutput) {
|
||||
if (processOutput.getExitCode() != 0) {
|
||||
String errors = processOutput.getStderr();
|
||||
if (StringUtil.isEmpty(errors)) {
|
||||
@@ -353,12 +377,16 @@ public abstract class PythonSdkFlavor<D extends PyFlavorData> {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getVersionStringFromOutput(@NotNull String output) {
|
||||
public static String getVersionStringFromOutput(@NotNull String output) {
|
||||
return PatternUtil.getFirstMatch(Arrays.asList(StringUtil.splitByLines(output)), VERSION_RE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use {@link #PYTHON_VERSION_ARG}
|
||||
*/
|
||||
@Deprecated(forRemoval = true)
|
||||
public @NotNull String getVersionOption() {
|
||||
return "-V";
|
||||
return PYTHON_VERSION_ARG;
|
||||
}
|
||||
|
||||
public @NotNull Collection<String> getExtraDebugOptions() {
|
||||
@@ -382,13 +410,26 @@ public abstract class PythonSdkFlavor<D extends PyFlavorData> {
|
||||
|
||||
@NotNull
|
||||
public LanguageLevel getLanguageLevel(@NotNull Sdk sdk) {
|
||||
return getLanguageLevelFromVersionString(sdk.getVersionString());
|
||||
return getLanguageLevelFromVersionStringStatic(sdk.getVersionString());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@RequiresBackgroundThread(generateAssertion = false) //because of process output
|
||||
public LanguageLevel getLanguageLevel(@NotNull String sdkHome) {
|
||||
return getLanguageLevelFromVersionString(getVersionString(sdkHome));
|
||||
return getLanguageLevelFromVersionStringStatic(getVersionString(sdkHome));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns wrong language level when argument is null which isn't probably what you except.
|
||||
* Be sure to check argument for null
|
||||
*
|
||||
* @deprecated use {@link #getLanguageLevelFromVersionStringStatic(String)}
|
||||
*/
|
||||
@Deprecated(forRemoval = true)
|
||||
@NotNull
|
||||
public LanguageLevel getLanguageLevelFromVersionString(@Nullable String version) {
|
||||
return getLanguageLevelFromVersionStringStatic(version);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -396,10 +437,9 @@ public abstract class PythonSdkFlavor<D extends PyFlavorData> {
|
||||
* Be sure to check argument for null
|
||||
*/
|
||||
@NotNull
|
||||
public LanguageLevel getLanguageLevelFromVersionString(@Nullable String version) {
|
||||
final String prefix = getName() + " ";
|
||||
if (version != null && version.startsWith(prefix)) {
|
||||
return LanguageLevel.fromPythonVersion(version.substring(prefix.length()));
|
||||
public static LanguageLevel getLanguageLevelFromVersionStringStatic(@Nullable String version) {
|
||||
if (version != null && version.startsWith(PYTHON_VERSION_STRING_PREFIX)) {
|
||||
return LanguageLevel.fromPythonVersion(version.substring(PYTHON_VERSION_STRING_PREFIX.length()));
|
||||
}
|
||||
return LanguageLevel.getDefault();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.intellij.python.junit5Tests.unit
|
||||
|
||||
import com.jetbrains.python.psi.LanguageLevel
|
||||
import com.jetbrains.python.sdk.flavors.PythonSdkFlavor
|
||||
import org.junit.jupiter.api.Assertions
|
||||
import org.junit.jupiter.api.Test
|
||||
|
||||
class PyVersionTest {
|
||||
|
||||
@Test
|
||||
fun testVersion() {
|
||||
val pythons = mapOf(
|
||||
"Python 3.10" to LanguageLevel.PYTHON310,
|
||||
"Python 3.11.2" to LanguageLevel.PYTHON311,
|
||||
"Python 3.8.0" to LanguageLevel.PYTHON38
|
||||
)
|
||||
for ((versionString, level) in pythons) {
|
||||
val calculatedLevel = PythonSdkFlavor.getLanguageLevelFromVersionStringStatic(versionString)
|
||||
Assertions.assertEquals(level, calculatedLevel, "wrong level for $versionString")
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -45,11 +45,11 @@ public final class PyRemoteInterpreterUtil {
|
||||
ProcessOutput processOutput;
|
||||
try {
|
||||
try {
|
||||
String[] command = {data.getInterpreterPath(), flavor.getVersionOption()};
|
||||
String[] command = {data.getInterpreterPath(), PythonSdkFlavor.PYTHON_VERSION_ARG};
|
||||
processOutput = PyRemoteProcessStarterManagerUtil.getManager(data).executeRemoteProcess(myProject, command, null,
|
||||
data, new PyRemotePathMapper());
|
||||
if (processOutput.getExitCode() == 0) {
|
||||
final String version = flavor.getVersionStringFromOutput(processOutput);
|
||||
final String version = PythonSdkFlavor.getVersionStringFromOutput(processOutput);
|
||||
if (version != null || nullForUnparsableVersion) {
|
||||
result.set(version);
|
||||
return;
|
||||
|
||||
@@ -73,7 +73,7 @@ object PySdkToInstallManager {
|
||||
}
|
||||
.filter {
|
||||
val detectedLevel = PythonSdkFlavor.getFlavor(it)?.let { flavor ->
|
||||
flavor.getLanguageLevelFromVersionString(flavor.getVersionString(it.homePath!!))
|
||||
PythonSdkFlavor.getLanguageLevelFromVersionStringStatic(PythonSdkFlavor.getVersionStringStatic(it.homePath!!))
|
||||
}
|
||||
languageLevel?.equals(detectedLevel) ?: true
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ import com.intellij.openapi.util.Disposer
|
||||
import com.jetbrains.python.PythonHelper
|
||||
import com.jetbrains.python.run.*
|
||||
import com.jetbrains.python.run.target.HelpersAwareTargetEnvironmentRequest
|
||||
import com.jetbrains.python.sdk.flavors.PythonSdkFlavor
|
||||
|
||||
class PyTargetsIntrospectionFacade(val sdk: Sdk, val project: Project) {
|
||||
private val pyRequest: HelpersAwareTargetEnvironmentRequest =
|
||||
@@ -34,11 +35,11 @@ class PyTargetsIntrospectionFacade(val sdk: Sdk, val project: Project) {
|
||||
val cmdBuilder = TargetedCommandLineBuilder(targetEnvRequest)
|
||||
sdk.configureBuilderToRunPythonOnTarget(cmdBuilder)
|
||||
val sdkFlavor = sdk.sdkFlavor
|
||||
cmdBuilder.addParameter(sdkFlavor.versionOption)
|
||||
cmdBuilder.addParameter(PythonSdkFlavor.PYTHON_VERSION_ARG)
|
||||
val cmd = cmdBuilder.build()
|
||||
|
||||
val environment = targetEnvRequest.prepareEnvironment(TargetProgressIndicatorAdapter(indicator))
|
||||
return sdkFlavor.getVersionStringFromOutput(cmd.execute(environment, indicator))
|
||||
return PythonSdkFlavor.getVersionStringFromOutput(cmd.execute(environment, indicator))
|
||||
}
|
||||
|
||||
@Throws(ExecutionException::class)
|
||||
|
||||
@@ -476,7 +476,7 @@ public final class PythonSdkType extends SdkType {
|
||||
return null;
|
||||
}
|
||||
final PythonSdkFlavor flavor = PythonSdkFlavor.getFlavor(sdkHome);
|
||||
return flavor != null ? flavor.getVersionString(sdkHome) : null;
|
||||
return flavor != null ? PythonSdkFlavor.getVersionStringStatic(sdkHome) : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -16,6 +16,7 @@ import com.intellij.openapi.util.Ref
|
||||
import com.intellij.remote.RemoteSdkException
|
||||
import com.intellij.util.ui.UIUtil
|
||||
import com.jetbrains.python.PyBundle
|
||||
import com.jetbrains.python.sdk.flavors.PythonSdkFlavor
|
||||
|
||||
@Throws(RemoteSdkException::class)
|
||||
fun PyTargetAwareAdditionalData.getInterpreterVersion(project: Project?, nullForUnparsableVersion: Boolean = true): String? {
|
||||
@@ -38,7 +39,7 @@ fun PyTargetAwareAdditionalData.getInterpreterVersion(project: Project?,
|
||||
try {
|
||||
val targetedCommandLineBuilder = TargetedCommandLineBuilder(targetEnvironmentRequest)
|
||||
targetedCommandLineBuilder.setExePath(interpreterPath)
|
||||
targetedCommandLineBuilder.addParameter(flavor.versionOption)
|
||||
targetedCommandLineBuilder.addParameter(PythonSdkFlavor.PYTHON_VERSION_ARG)
|
||||
val targetEnvironment = targetEnvironmentRequest.prepareEnvironment(TargetProgressIndicatorAdapter(indicator))
|
||||
val targetedCommandLine = targetedCommandLineBuilder.build()
|
||||
val process = targetEnvironment.createProcess(targetedCommandLine, indicator)
|
||||
@@ -46,7 +47,7 @@ fun PyTargetAwareAdditionalData.getInterpreterVersion(project: Project?,
|
||||
val capturingProcessHandler = CapturingProcessHandler(process, Charsets.UTF_8, commandLineString)
|
||||
val processOutput = capturingProcessHandler.runProcess()
|
||||
if (processOutput.exitCode == 0) {
|
||||
val version = flavor.getVersionStringFromOutput(processOutput)
|
||||
val version = PythonSdkFlavor.getVersionStringFromOutput(processOutput)
|
||||
if (version != null || nullForUnparsableVersion) {
|
||||
result.set(version)
|
||||
return
|
||||
|
||||
@@ -47,7 +47,7 @@ sealed class PythonType<T : Any>(private val tag: @NonNls String? = null) {
|
||||
?: error("No python in $path")
|
||||
val flavor = PythonSdkFlavor.tryDetectFlavorByLocalPath(binary.toString())
|
||||
?: error("Unknown flavor: $binary")
|
||||
flavor.getVersionString(binary.toString())?.let { path to flavor.getLanguageLevelFromVersionString(it) }
|
||||
flavor.getVersionString(binary.toString())?.let { path to PythonSdkFlavor.getLanguageLevelFromVersionStringStatic(it) }
|
||||
?: error("Can't get language level for $flavor , $binary")
|
||||
}
|
||||
.sortedByDescending { (_, languageLevel) -> languageLevel }
|
||||
|
||||
@@ -29,7 +29,7 @@ internal suspend fun getPythonVersion(sdk: Sdk, request: TargetEnvironmentReques
|
||||
internal suspend fun getPythonVersion(commandLineBuilder: TargetedCommandLineBuilder,
|
||||
flavor: PythonSdkFlavor<*>,
|
||||
request: TargetEnvironmentRequest): String? {
|
||||
commandLineBuilder.addParameter(flavor.versionOption)
|
||||
commandLineBuilder.addParameter(PythonSdkFlavor.PYTHON_VERSION_ARG)
|
||||
val commandLine = commandLineBuilder.build()
|
||||
val result = request
|
||||
.prepareEnvironment(TargetProgressIndicator.EMPTY)
|
||||
@@ -41,7 +41,7 @@ internal suspend fun getPythonVersion(commandLineBuilder: TargetedCommandLineBui
|
||||
val out = result.stdOut.decodeToString()
|
||||
Assert.assertEquals(err, 0, result.exitCode)
|
||||
val versionString = out.ifBlank { err }.trim()
|
||||
return flavor.getVersionStringFromOutput(versionString)
|
||||
return PythonSdkFlavor.getVersionStringFromOutput(versionString)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -53,7 +53,7 @@ public class PySdkFlavorTest extends PyTestCase {
|
||||
|
||||
@NotNull
|
||||
private Sdk createMockSdk(@NotNull PythonSdkFlavor flavor, @NotNull String versionOutput) {
|
||||
final String versionString = flavor.getVersionStringFromOutput(versionOutput);
|
||||
final String versionString = PythonSdkFlavor.getVersionStringFromOutput(versionOutput);
|
||||
final Sdk sdk = ProjectJdkTable.getInstance().createSdk("Test", PythonSdkType.getInstance());
|
||||
SdkModificator sdkModificator = sdk.getSdkModificator();
|
||||
sdkModificator.setHomePath("/path/to/sdk");
|
||||
|
||||
Reference in New Issue
Block a user