PY-88515 Prepare pytest env tests

JUnit4 Python environment tests create SDKs through PyEnvironment.prepareSdk(), but legacy Python run configurations still resolve the interpreter through ProjectJdkTable before starting the process. Register SDKs owned by PyEnvTaskRunner for the duration of each environment attempt and remove only those SDKs afterwards.

The same baseline run can use Python 3.9 environments without setuptools, so the pytest helper must not require pkg_resources just to check installed entry points. Treat missing pkg_resources as an empty entry-point set and load the bundled TeamCity plugin.

(cherry picked from commit 276e68f3213be816fe5cb8807a41e66d62a47961)

IJ-MR-206446

GitOrigin-RevId: 2e1a0381c8bde91368edc02378800e99584116d7
This commit is contained in:
Anton Efimchuk
2026-07-08 18:21:15 +00:00
committed by intellij-monorepo-bot
parent 7e7f4a7b35
commit 6f1d1ed9c5
2 changed files with 45 additions and 7 deletions
+7 -3
View File
@@ -10,9 +10,13 @@ import warnings
if sys.version_info[:2] >= (3, 10):
from importlib.metadata import entry_points as iter_entry_points
else:
with warnings.catch_warnings():
warnings.simplefilter("ignore", category=DeprecationWarning)
from pkg_resources import iter_entry_points
try:
with warnings.catch_warnings():
warnings.simplefilter("ignore", category=DeprecationWarning)
from pkg_resources import iter_entry_points
except ImportError:
def iter_entry_points(group):
return ()
from _jb_runner_tools import jb_patch_separator, jb_doc_args, JB_DISABLE_BUFFERING, \
start_protocol, parse_arguments, set_parallel_mode, jb_finish_tests, \
+38 -4
View File
@@ -3,8 +3,11 @@ package com.jetbrains.env;
import com.google.common.collect.Sets;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.application.WriteAction;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.projectRoots.ProjectJdkTable;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.python.test.env.common.PredefinedPyEnvironments;
import com.intellij.python.test.env.core.PyEnvironmentFactory;
@@ -76,6 +79,7 @@ public class PyEnvTaskRunner {
for (PyTestEnvironment environment : environments) {
final String envDescription = environment.getDescription();
Sdk registeredSdk = null;
LOG.warn(String.format("Running on environment: %s", envDescription));
@@ -85,6 +89,9 @@ public class PyEnvTaskRunner {
// Prepare SDK for this environment
final Sdk sdk = environment.prepareSdk();
if (registerSdkIfNeeded(sdk)) {
registeredSdk = sdk;
}
if (skipOnFlavors != null) {
final PythonSdkFlavor flavor = PythonSdkFlavor.getFlavor(sdk);
@@ -135,12 +142,17 @@ public class PyEnvTaskRunner {
}
try {
removeRegisteredSdk(registeredSdk);
}
finally {
// Teardown should be called on the main thread because fixture teardown checks for
// thread leaks, and blocked main thread is considered as leaked.
testTask.tearDown();
}
catch (final Exception e) {
throw new RuntimeException("Couldn't tear down task", e);
try {
testTask.tearDown();
}
catch (final Exception e) {
throw new RuntimeException("Couldn't tear down task", e);
}
}
}
}
@@ -161,6 +173,28 @@ public class PyEnvTaskRunner {
.toList();
}
private static boolean registerSdkIfNeeded(@NotNull Sdk sdk) {
return WriteAction.compute(() -> {
if (!ContainerUtil.exists(ProjectJdkTable.getInstance().getAllJdks(), existingSdk ->
FileUtil.pathsEqual(existingSdk.getHomePath(), sdk.getHomePath()))) {
ProjectJdkTable.getInstance().addJdk(sdk);
return true;
}
return false;
});
}
private static void removeRegisteredSdk(@Nullable Sdk sdk) {
if (sdk == null) {
return;
}
WriteAction.run(() -> {
if (ContainerUtil.exists(ProjectJdkTable.getInstance().getAllJdks(), existingSdk -> existingSdk == sdk)) {
ProjectJdkTable.getInstance().removeJdk(sdk);
}
});
}
/**
* Wrapper for PyTestEnvironment that provides ordering and filtering logic.
* <p>