Files
openide/python/python-black/resources/intellij.python.black.xml
T
Vitaly Legchilkinandintellij-monorepo-bot 4c3506a591 PY-89017 Surface uv tool version / install / upgrade in UvInstallationTypeUiProvider
Mirror the "Tool version" / "Update" / "Install" affordances from
BinaryInstallationTypeUiProvider for the "Managed by uv" + "uv tool"
installation mode. After install/upgrade the resolved bin path
(`uv tool dir --bin`/`<name>`) is written into `settings.pathToExecutable`,
so downstream feature-execution goes through the same binary-mode code path
and the invocation-mode toggle stays purely cosmetic at run time. The uvx
mode is left as-is because uvx is ephemeral: there's no persistent install
state for the settings panel to surface.

UvTool CLI fills in the previously stubbed pieces:

  install(name)                     -> `uv tool install <name>`
  upgrade(name, dryRun = false)     -> `uv tool upgrade <name> [--dry-run]`
  listInstalled()                   -> parsed `uv tool list --show-paths`
  binDir()                          -> parsed `uv tool dir --bin`

Plus a top-level `parseUvToolUpgradeDryRun(stdout)` that extracts the
`-> vX.Y.Z` target from uv's upgrade dry-run output (null when uv reports
the tool is already up-to-date).

UvRuntime.kt gains a `createUvToolRuntime(uvExecutable: Path)` factory so
callers (the UI provider here, anything else later) don't reimplement the
`BinOnEel` / `ExecOptions` wrapping. The factory takes a resolved Path
rather than calling `getUvExecutableLocal()` itself, because that function
lives in intellij.python.community.impl and uv.backend can't depend on it
without a cycle.

UvInstallationTypeUiProvider adds a uvToolSection with a PropertyGraph
(installedVersion, latestVersion, loading) and a MutableSharedFlow
refreshTrigger. The collectLatest pipeline is hosted by launchOnShow
attached to the *uv-tool comment row* — not to the not-installed row's
warning icon — because the latter is gated by `!loading and
installedVersion.isNull()` and hides the moment loading flips to true,
cancelling the coroutine mid-fetch. The comment row's visibility
(`uvAvailable and isUvTool`) is stable across the whole load cycle.

Runtime plumbing:

  * intellij.python.community.impl.iml       — orderEntry on uv.backend
  * intellij.python.community.impl.xml       — plugin-descriptor <module>
    dep on intellij.python.uv.backend. Without this the iml-level
    compile dep is not enough: community.impl's PluginClassLoader
    parent chain is driven by the .xml, and UvRuntimeKt would be
    NoClassDefFoundError at settings-panel init.

Localization: six new PyBundle keys under `settings.installation.uv.tool.*`
for the version label, Update link, Install button, not-installed warning,
and the two progress titles.

PY-89017 Scaffold UV/UVX CLI wrappers on PyToolRuntime and add env tests

Introduce a typed command hierarchy under com.intellij.python.uv.backend.cli
mirroring the uv CLI tree: UvCli with subcommand accessors (auth, tool,
python, pip, cache, self) on a sealed UvCommand base bound to a
PyToolRuntime, plus a sibling UvxCli for `uvx`.

Populate the operations actually needed today - uv help / sync / init /
version, uv cache {clean,prune,dir,size}, uv self {update,version}, uv
python {list,dir}, uv tool {list,dir}, uv auth dir, uvx run, uvx --version -
and leave the remaining subcommands as TODO() stubs that document the
canonical uv surface.

Add PyToolRuntime.uvCli()/uvxCli() extensions in runtime/ and UvConstants
covering uv's documented environment variables. Wire the new module deps
(intellij.python.pytools, intellij.python.community.execService,
intellij.platform.eel.provider) in both BUILD.bazel and the .iml.

Add intellij.python.uv.tests at community/python/python-uv/tests/ modeled
on intellij.python.pyproject.tests: testSrc/ + testResources/ layout,
TestModuleProperties production-module="intellij.python.uv.backend". The
UvCliTest follows HatchCliTest's shape - @PyEnvTestCase, a companion-object
UvContext (uv-cache/uv-tool/uv-tool-bin dirs, UV_PYTHON pinned to the test
interpreter), @BeforeEach that scaffolds a project via uv init and binds
myRuntime to it, and one testXxx per uv command covering help, version,
sync, auth, cache, python, self, tool.

Wire the test module everywhere intellij.python.pyproject.tests is wired:
.idea/modules.xml (both ultimate and community), intellij.yaml Python
JUnit dev mode, python/junit5Tests/intellij.python.junit5Tests.iml,
junit5Tests.xml, the junit5Tests plugin.xml, and PyCharmProperties.

Fix plugin-descriptor visibility and runtime dep graph so the test plugin
can reach uv.backend at load time:
  * intellij.python.uv.backend.xml: mark `<idea-plugin visibility="public">`
    and depend on intellij.python.pytools (which now transitively exposes
    execService).
  * intellij.python.pytools.xml: declare the missing runtime dep on
    intellij.python.community.execService - PyToolRuntime's primary
    constructor calls the top-level ExecService() factory, so pytools's
    PluginClassLoader needed execService as a parent to resolve ApiKt.

Drive-by: restore community/.idea/modules.xml - a stray
intellij.python.pytools.ui module entry was sitting after </project>,
breaking StAX parsing in jps-to-bazel-targets-only. Move it back inside
<modules> next to intellij.python.pytools.

PY-89017 Extract generic PyToolRuntime from HatchRuntime

Pull the tool-agnostic parts of HatchRuntime into a new PyToolRuntime in
intellij.python.pytools. PyToolRuntime is a concrete class (no inheritance)
that owns the tool binary, ExecOptions, and ExecService, and exposes
withEnv / withWorkingDirectory / withBasePythonBinaryPath / execute /
executeInteractive. The env-var name for the base-python override is a
parameter so each tool can pass its own (HATCH_PYTHON, UV_PYTHON, ...).

HatchRuntime becomes a typealias for PyToolRuntime. The two hatch-specific
operations stay next to the tool: hatchCli() as a Kotlin extension on
PyToolRuntime, and resolvePythonVirtualEnvironment as a plain top-level
suspend function (it didn't actually use the runtime receiver).

WorkingDirectoryNotFoundHatchError moves out of the HatchError hierarchy
into a generic PyToolRuntimeError family (WorkingDirectoryNotFoundError,
BasePythonExecutableNotFoundError) whose messages live in PyToolsBundle.
BasePythonExecutableNotFoundHatchError and EnvironmentCreationHatchError
stay in hatch because they have hatch-specific semantics/callers.
createHatchRuntime now returns Result<HatchRuntime, PyError> because the
working-directory path fails with a generic PyToolRuntimeError while
executable detection still fails with a HatchError.

Module wiring: intellij.python.pytools gains exec-service + platform.eel
+ platform.eel.provider; intellij.python.hatch gains a module-level and a
v2 plugin-xml dependency on intellij.python.pytools (without the plugin-xml
entry the runtime classloader chain is missing and HatchRuntime.kt blows
up with NoClassDefFoundError at plugin startup).

PY-89017 Rename intellij.python.community.impl.uv.{backend,common} to intellij.python.uv.{backend,common}

Drop the community.impl segment from both uv module names and from the
corresponding com.intellij.python.community.impl.uv.* packages. The
auto-generated icon class becomes PythonUvCommonIcons and its resource
path moves to images/intellij/python/uv/common/. All iml/xml consumers
(community.impl, pycharm.community.ide.impl, python.sdk.ui, pluginCore
plugin.xml, python.junit5Tests, python.dap, PyCharmStructureTest, both
.idea/modules.xml) and internal imports in community.impl + python-sdk-ui
are updated to the new names. No behavior change.

PY-89017 Warn when uv is missing in the Managed-by-uv installation section

The Managed-by-uv provider now probes getUvExecutableLocal() on show. When uv
is absent, the uv tool / uvx segmented button and its comments are hidden and
a warning row with an Install uv action takes their place. The action reuses
the new-project-wizard bootstrap: pick the best detected system Python from
SystemPythonService, wrap it with BinOnEel, and run installExecutableViaPythonScript
with -n uv inside a modal progress. On success the installed uv path is
persisted via setUvExecutableLocal and uvAvailable flips so the regular uv
UI becomes visible again; errors go through ShowingMessageErrorSync.

No project SDK is required — the wizard flow is project-agnostic, and bootstrap
here is the same: any system Python works, and uv is standalone afterwards.

PY-89017 Extract Black into intellij.python.black module

Move the com.jetbrains.python.black package from intellij.python.community.impl
into a new content module, intellij.python.black, so the formatter's settings
UI can reuse installationSection() from intellij.python.pytools.ui. Adding
that dependency to community.impl would close the pytools.ui -> community.impl
cycle, whereas python-black -> pytools.ui is one-way.

BlackFormatterConfigurable is rewritten on top of installationSection(), which
removes the hand-rolled execution-mode combobox, SDK selector, path field, and
install panel (PySdkChooser.kt is no longer needed and is removed).

BlackPyTool is now registered at com.intellij.python.pytools.pyTool and kept in
the com.jetbrains.python.black package, following the Ruff/Pyright convention
with a getInstance() companion; BlackPyToolExecutionAdapter bridges the tool's
persisted settings to the PyToolExecutionConfiguration contract.

XML registrations for projectConfigurable, formattingService, actionOnSave,
actionOnSaveInfoProvider, notificationGroup, and the black.formatter.support
registry key move into intellij.python.black.xml; community.impl.xml keeps
only statistics.notificationIdsHolder for BlackFormatterIntegrationIdsHolder.
The holder loses its internal modifier because BlackFormattingService and
BlackFormatterAdvertiserService, now in python-black, consume its constants
across the module boundary. CliOptionFlag.description() is made public for
the same reason.

intellij.python.tests picks up a TEST-scope dependency on intellij.python.black
so existing python/testSrc/...black tests continue to compile.

PY-89017 Refactor SDK combobox and tool package UI in BinaryInstallationTypeUiProvider

- Fix SDK combobox not triggering on null selection (Module Default)
  by replacing ItemListener-based onChanged with ActionListener
- Replace MutableStateFlow with MutableSharedFlow refresh trigger
  to avoid deduplication when re-selecting the same SDK
- Simplify SDK name-to-Sdk mapping with linkedMapOf
- Use declarative visibleIf with PropertyGraph for version/install rows
- Show animated loading indicator while resolving package state
- Show install button with warning only when package is not installed

PY-89017 Add InstallInfo, executableNames to PyTool, clean up installation UI

Move installHelp, executableNames, alternativePackageNames from API
parameters to PyTool interface properties. Remove isModuleLevel from
installation UI chain. Add fallback warning for unavailable installation
types with warning icon on segment button.

PY-89017 Extract installation type UI to EP, add checkbox-separator design

Add InstallationTypeUiProvider EP with Binary and UV implementations in
separate files. Gate UV provider behind python.pytools.uv.enabled registry
flag. Add UV mode comments for uv tool/uvx options.

Redesign Enable/Override checkbox rows with inline JSeparator line.
Extract buildFeatures() and applyLspState() helpers in PyLspToolConfigurable.

PY-89017 Add InstallationType enum and UV mode UI to installation section

Add InstallationType (BINARY, UV) as a property of ExecutableDiscoveryMode.
Add UV_TOOL and UVX modes. Restructure installationSection to show
binary/UV content panels based on the Type switcher, with proper
mode tracking via ExecutableDiscoveryModeSelector.

PY-89017 Convert PyTool enum to extension point interface

Replace the hardcoded PyTool enum with an EP interface. Each tool module
now provides its own implementation class with companion getInstance():
RuffPyTool, PyrightPyTool, BasedpyrightPyTool, TyPyTool, PyreflyPyTool.

Use PyPackageName for packageName/installPackageName fields. Remove
PyToolTag enum. Register EP as com.intellij.python.pytools.pyTool with
qualifiedName in the plugin descriptor.

PY-89017 Extract tool configuration and UI to python-pytools modules

Move PyLspTool -> PyTool, PyLspExecutionConfiguration -> PyToolExecutionConfiguration,
ExecutableDiscoveryMode, PyLspToolSettings, PyLspToolConfiguration to python-pytools.

Create python-pytools-ui module with InstallationSection, executionSettings,
lspExecutablePathSelector, sdkByNameDefaultAware, and PyToolsUiBundle.

Update all consumer modules (ruff, pyright, ty, pyrefly, type-engine, lsp-core)
to import from the new locations. Delete old externaltools package.

PY-89017 Add python-pytools module

New module `intellij.python.pytools` in community/python with package
com.intellij.python.pytools, message bundle, and Python-colored tool icon.

PY-89017 Add Installation collapsible group and Enable section to LSP tool settings

Restructure the right panel: wrap execution settings in a collapsible
"Installation" group with a "Type" switcher (Installed as binary / Managed
by uv), and move the Enable checkbox + features below a separator.

PY-89017 Improve module list layout in Python Tools settings

Use JBSplitter with proportion persistence in ModuleAwareProjectConfigurable
so user resizes are remembered across settings reopens.

Reduce right panel minimum width: use COLUMNS_MEDIUM for SDK combobox,
remove forced label column minimum, replace indent with rowsRange,
and make the install warning label resizable with right alignment.

GitOrigin-RevId: 8fe6ef451542bf73236f0fcffeb1c2fec0798380
2026-05-22 10:52:12 +00:00

23 lines
1.1 KiB
XML

<idea-plugin visibility="public">
<dependencies>
<!-- region Generated dependencies - run `Generate Product Layouts` to regenerate -->
<module name="intellij.platform.vcs.impl"/>
<module name="intellij.python.community"/>
<module name="intellij.python.community.execService"/>
<module name="intellij.python.pytools"/>
<module name="intellij.python.pytools.ui"/>
<module name="intellij.python.sdk"/>
<!-- endregion -->
</dependencies>
<extensions defaultExtensionNs="com.intellij">
<!-- Deprecated registry key-->
<registryKey key="black.formatter.support.enabled" defaultValue="true" description="Enable Black formatter support"/>
<python.pytools.pyTool implementation="com.intellij.python.black.BlackPyTool"/>
<projectSettings service="com.intellij.python.black.configuration.BlackFormatterConfiguration"/>
<formattingService implementation="com.intellij.python.black.BlackFormattingService"/>
<statistics.notificationIdsHolder implementation="com.intellij.python.black.statistics.BlackFormatterIntegrationIdsHolder"/>
</extensions>
</idea-plugin>