diff --git a/python/ide/impl/BUILD.bazel b/python/ide/impl/BUILD.bazel
index 4aadedaa1625..c68bd55f2e82 100644
--- a/python/ide/impl/BUILD.bazel
+++ b/python/ide/impl/BUILD.bazel
@@ -346,6 +346,8 @@ jvm_library(
"//libraries/kotlinx/collections-immutable:libraries-kotlinx-collections-immutable_test_lib",
"//platform/util/concurrency",
"//platform/util/concurrency:concurrency_test_lib",
+ "//platform/welcome-screen",
+ "//platform/welcome-screen:welcome-screen_test_lib",
],
)
### auto-generated section `build intellij.pycharm.community.ide.impl.tests` end
diff --git a/python/ide/impl/intellij.pycharm.community.ide.impl.tests.iml b/python/ide/impl/intellij.pycharm.community.ide.impl.tests.iml
index 0a8f70b0cb5c..233a8312afe6 100644
--- a/python/ide/impl/intellij.pycharm.community.ide.impl.tests.iml
+++ b/python/ide/impl/intellij.pycharm.community.ide.impl.tests.iml
@@ -97,6 +97,7 @@
+
\ No newline at end of file
diff --git a/python/ide/impl/src/com/intellij/pycharm/community/ide/impl/welcomeScreen/PyCharmWelcomeScreenProjectProvider.kt b/python/ide/impl/src/com/intellij/pycharm/community/ide/impl/welcomeScreen/PyCharmWelcomeScreenProjectProvider.kt
index fa3f0e082c1c..1d39a015bc86 100644
--- a/python/ide/impl/src/com/intellij/pycharm/community/ide/impl/welcomeScreen/PyCharmWelcomeScreenProjectProvider.kt
+++ b/python/ide/impl/src/com/intellij/pycharm/community/ide/impl/welcomeScreen/PyCharmWelcomeScreenProjectProvider.kt
@@ -7,6 +7,7 @@ import com.intellij.openapi.project.ex.ProjectEx
import com.intellij.openapi.util.registry.Registry
import com.intellij.openapi.wm.ex.WelcomeScreenProjectProvider
import com.intellij.platform.PlatformProjectOpenProcessor
+import com.intellij.platform.ide.nonModalWelcomeScreen.isNonModalWelcomeScreenEnabled
import com.intellij.pycharm.community.ide.impl.miscProject.impl.MISC_PROJECT_WITH_WELCOME_NAME
import com.intellij.pycharm.community.ide.impl.miscProject.impl.miscProjectDefaultPath
import com.jetbrains.python.orLogException
@@ -38,8 +39,14 @@ internal class PyCharmWelcomeScreenProjectProvider : WelcomeScreenProjectProvide
// We explicitly want to open existing project if the file already belongs to it
override fun shouldOpenInWelcomeScreenIfFileBelongsToProject(filePath: Path): Boolean = false
+ /**
+ * The non-modal Welcome screen must be on. The file opening path creates the Welcome screen project through
+ * [com.intellij.openapi.wm.ex.NoProjectStateHandler], and the only handler declines when the setting is off.
+ */
override fun canOpenFilesFromSystemFileManager(filePath: Path): Boolean {
- return Registry.`is`("welcome.screen.open.files", false) && filePath.extension == "ipynb"
+ return isNonModalWelcomeScreenEnabled &&
+ Registry.`is`("welcome.screen.open.files", false) &&
+ filePath.extension == "ipynb"
}
override suspend fun doCreateOrOpenWelcomeScreenProject(path: Path): Project {
diff --git a/python/ide/impl/testResources/intellij.pycharm.community.ide.impl.tests.xml b/python/ide/impl/testResources/intellij.pycharm.community.ide.impl.tests.xml
index b2a1ad91dc55..c8829469e9aa 100644
--- a/python/ide/impl/testResources/intellij.pycharm.community.ide.impl.tests.xml
+++ b/python/ide/impl/testResources/intellij.pycharm.community.ide.impl.tests.xml
@@ -28,6 +28,7 @@
+
\ No newline at end of file
diff --git a/python/ide/impl/tests/com/intellij/python/junit5Tests/unit/PyCharmWelcomeScreenProjectProviderTest.kt b/python/ide/impl/tests/com/intellij/python/junit5Tests/unit/PyCharmWelcomeScreenProjectProviderTest.kt
new file mode 100644
index 000000000000..b683dd0b22cc
--- /dev/null
+++ b/python/ide/impl/tests/com/intellij/python/junit5Tests/unit/PyCharmWelcomeScreenProjectProviderTest.kt
@@ -0,0 +1,60 @@
+// 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.junit5Tests.unit
+
+import com.intellij.openapi.options.advanced.AdvancedSettings
+import com.intellij.platform.ide.nonModalWelcomeScreen.NON_MODAL_WELCOME_SCREEN_SETTING_ID
+import com.intellij.pycharm.community.ide.impl.welcomeScreen.PyCharmWelcomeScreenProjectProvider
+import com.intellij.testFramework.junit5.RegistryKey
+import com.intellij.testFramework.junit5.SystemProperty
+import com.intellij.testFramework.junit5.TestApplication
+import org.junit.jupiter.api.Assertions.assertFalse
+import org.junit.jupiter.api.Assertions.assertTrue
+import org.junit.jupiter.api.Test
+import org.junit.jupiter.api.io.TempDir
+import java.nio.file.Path
+
+/**
+ * The two gates must agree. If the provider claims a file while the non-modal Welcome screen is off,
+ * the file opening path finds no `NoProjectStateHandler` and the IDE fails with an internal error (PY-91932).
+ */
+@TestApplication
+@SystemProperty(propertyKey = "idea.force.disable.non.modal.welcome.screen", propertyValue = "false")
+internal class PyCharmWelcomeScreenProjectProviderTest {
+ private val provider = PyCharmWelcomeScreenProjectProvider()
+
+ @Test
+ @RegistryKey(key = "welcome.screen.open.files", value = "true")
+ fun `notebook is claimed when both settings are enabled`(@TempDir tempDir: Path) = withNonModalWelcomeScreen(true) {
+ assertTrue(provider.canOpenFilesFromSystemFileManager(tempDir.resolve("notebook.ipynb")))
+ }
+
+ @Test
+ @RegistryKey(key = "welcome.screen.open.files", value = "true")
+ fun `notebook is not claimed when the non-modal welcome screen is disabled`(@TempDir tempDir: Path) = withNonModalWelcomeScreen(false) {
+ assertFalse(provider.canOpenFilesFromSystemFileManager(tempDir.resolve("notebook.ipynb")))
+ }
+
+ @Test
+ @RegistryKey(key = "welcome.screen.open.files", value = "false")
+ fun `notebook is not claimed when the registry key is disabled`(@TempDir tempDir: Path) = withNonModalWelcomeScreen(true) {
+ assertFalse(provider.canOpenFilesFromSystemFileManager(tempDir.resolve("notebook.ipynb")))
+ }
+
+ @Test
+ @RegistryKey(key = "welcome.screen.open.files", value = "true")
+ fun `a file that is not a notebook is not claimed`(@TempDir tempDir: Path) = withNonModalWelcomeScreen(true) {
+ assertFalse(provider.canOpenFilesFromSystemFileManager(tempDir.resolve("script.py")))
+ assertFalse(provider.canOpenFilesFromSystemFileManager(tempDir))
+ }
+
+ private fun withNonModalWelcomeScreen(value: Boolean, action: () -> Unit) {
+ val previousValue = AdvancedSettings.getBoolean(NON_MODAL_WELCOME_SCREEN_SETTING_ID)
+ try {
+ AdvancedSettings.setBoolean(NON_MODAL_WELCOME_SCREEN_SETTING_ID, value)
+ action()
+ }
+ finally {
+ AdvancedSettings.setBoolean(NON_MODAL_WELCOME_SCREEN_SETTING_ID, previousValue)
+ }
+ }
+}