Repository navigation
feat: Support PEP 723 scripts with --script - #6648
Conversation
pixi script for standalone Python scripts
8c7125c to
8242e11
Compare
pixi script for standalone Python scriptspixi script for standalone Python scripts
85ad787 to
5b861b7
Compare
67f32b3 to
0537df3
Compare
|
Apologies for all the noise re: referenced PRs. I got early access to GitHub stacked PRs and was trying to see if I could use to make this easier for review / have relevant discussions for each piece. The individual commits here are the same as the stack. |
0537df3 to
8b58c6c
Compare
8b58c6c to
3b68b23
Compare
|
I've started to take a look at how this works. I'm happy that the pep just works. Now that I'm trying it I was searching for examples where people use WDYT? @manzt @Hofer-Julian @baszalmstra |
Fully agreed. Let's also make sense to have a good story for the CLI. See also my comment here: #6632 (comment) |
Agreed. I see Its interoperability would be especially valuable for us at marimo, so users can share/execute standalone notebooks potentially authored by either uv or pixi. For instance, many of our learning materials are PEP 723 notebooks (authored with uv) which we could now point users to run on their own with whatever CLI they have installed. I see the formats as roughly analogous:
In principle, even a Python file could even support We could do a hard check for
Agreed on dropping |
I don't really understand what you mean with defaulting here. If we simply check whether it's |
|
The |
Then I disagree that this would default to PEP style :) But we also don't have to decide on that now. I would really appreciate it if you would trim this PR down to its bare minimum. It only needs to support what |
|
|
3b68b23 to
61d64a8
Compare
Make the shared `--script <PATH>` selector the entry point for removing dependencies from PEP 723 scripts. Route Conda and PyPI removals through the normal remove pipeline, while rejecting named features, environments, and non-run dependency types that the script model cannot represent. Keep absent sidecars absent and update an adjacent lockfile when one already exists. Remove the `pixi script remove` adapter and the now-empty `pixi script` command namespace. Address review feedback: - require explicit initialization instead of modifying arbitrary files; - keep Conda and PyPI selection explicit through the existing `--pypi` flag; - snapshot the complete script after both dependency types are removed; - preserve portable PEP 723 fields and unrelated `tool.*` content while removing a Pixi dependency table emptied by the edit; and - avoid creating a workspace lockfile or local `.pixi` directory.
87623df to
b721550
Compare
Separate ordinary workspace selection from the script-capable selector. Only init, run, add, remove, and lock expose `--script` at this point; commands without a meaningful PEP 723 operation no longer advertise or accept it merely because they support `--manifest-path`. Replace the recursive manifest-path coupling test with an explicit allowlist of script-capable commands. Remove runtime rejection branches from config, task, and workspace commands now that Clap excludes the selector before execution.
Add `--script <PATH>` to the workspace channel command group. Route add, list, and remove through the normal channel pipeline while rejecting named features and environments that the script model cannot represent. Teach PEP 723 rendering to synchronize explicitly edited workspace channel and platform arrays without materializing synthetic empty fields. Channel edits without an adjacent lockfile update only the manifest; an existing sidecar continues to use the requested lockfile policy. Address review feedback: - snapshot the complete script after channel addition and removal; - preserve portable metadata, Python source, and unrelated `tool.*` content; - keep an explicit empty channel list after removing the last channel; - list channels from the implicit default environment; and - avoid creating an adjacent lockfile, workspace lockfile, or local `.pixi` directory.
Add `--script <PATH>` to the workspace platform command group. Route add, edit, move, list, remove, and auto-detection through the normal platform pipeline while rejecting named features and environments that the script model cannot represent. Pass lockfile policy through the platform API so edits without an adjacent script lock update only inline metadata, while an existing sidecar continues to be updated normally. Address review feedback: - snapshot the complete script after add, edit, move, and removal; - preserve portable metadata, Python source, and unrelated `tool.*` content; - exercise rich platform metadata and declaration-order changes; - list platforms from the inline manifest; and - avoid creating an adjacent lockfile, workspace lockfile, or local `.pixi` directory.
Add `--script <PATH>` to `pixi tree` and both workspace export formats. Resolve the inline manifest as the default environment, while rejecting named environment selection that PEP 723 cannot represent. Lift the no-sidecar lock policy out of `pixi run` so read-only script consumers share the same behavior: solve in memory by default, honor an existing adjacent lock, and report a contextual error when `--locked` or `--frozen` names a lock that does not exist. Address review feedback: - snapshot the environment YAML rendered from mixed Conda and PyPI metadata; - exercise explicit-spec export both with and without an adjacent lock; - verify tree output from an in-memory solve and again under `--locked`; - preserve the complete script and its unrelated `tool.*` content; and - avoid creating an adjacent lock, workspace lock, or local `.pixi` state.
Carry `tool.pixi.target` edits from the synthetic pyproject document back to the inline metadata block. This makes platform-specific Conda dependencies round-trip through `pixi add --script` and lets removal discard the target hierarchy once its last dependency is gone. Store PyPI requirements with a dependency-specific index in the Pixi-specific `pypi-dependencies` table. A native project dependency cannot represent that index, and previously accepted `--index` input was silently discarded. Address review feedback: - snapshot the complete script with a target-specific Conda dependency; - cover indexed and editable PyPI dependency representations; - exercise a portable local source dependency; - snapshot removal of the last target dependency without empty tables; and - verify no adjacent lock, workspace lock, or local `.pixi` state is created.
Make `pixi run --script` reject `--environment` instead of silently using the script default, and reject `--skip-deps` because a PEP 723 script has no Pixi task graph. Validate both before workspace discovery so unsupported requests cannot create lockfiles or local state. Close the command-surface audit with parser coverage proving that workspace name, description, version, registration, requires-pixi, environment, feature, and task commands do not accept `--script`. Address review feedback: - exercise contextual add and remove errors for features and environments; - cover the hidden host and build dependency modes; - verify unsupported run options leave the complete script unchanged; and - assert no adjacent lock, workspace lock, or local `.pixi` state is created.
Rewrite the standalone Python script guide around `--script <PATH>` and extend it beyond the basic init/add/run flow. Cover portable PEP 723 fields, the Pixi-specific metadata subset, rich dependency forms, channel and platform management, dependency trees, exports, sidecar locks, cache isolation, and the workspace concepts that scripts intentionally do not support. Update the uv migration guide to map standalone scripts directly to `pixi run --script`, including the division between portable PyPI metadata and Pixi-specific Conda configuration. Regenerate the CLI reference from the current command tree. This adds `--script` to every supported command, records the reserved `-s` selector, removes the obsolete `pixi script` namespace and its pages, and leaves workspace-only commands without a script selector. Address review feedback: - document mixed Conda and PyPI scripts with a complete metadata example; - show indexed, editable, source, and platform-specific dependencies; - declare lock platforms through `pixi workspace platform` rather than a new lock flag; - explain in-memory resolution versus an adjacent sidecar lock; and - enumerate tree, export, channel, and platform operations explicitly.
b721550 to
c9e2cc4
Compare
|
Thanks you for all the feedback. I've updated the PR title/description and tried to address all comments. |
This PR remains draft until a Pixi release includes [prefix-dev/pixi#6648](prefix-dev/pixi#6648). The required upstream change has merged. The notebook-owned lifecycle in the previous PR describes operations in terms of a manifest and its realized environment. This PR supplies those operations with Pixi and makes the choice explicit at the CLI: ```console marimo edit --sandbox notebook.py # uv marimo edit --sandbox=pixi notebook.py # pixi ``` ```text NotebookSandbox(source, "pixi") -> PixiBackendAdapter -> add / remove / sync / packages / launch ``` Pixi reads the same PEP 723 metadata. Package changes use Pixi script commands, synchronization recovers the interpreter and environment root from structured output, and package inspection reads `pixi list` JSON. Launches layer the running marimo through `pixi exec`, so the shared manifest does not pin marimo to the machine that opened it. Selecting one manager does not import or probe the other. Pixi rejects Python interpreter overrides, which its script environments cannot honor, and falls back cleanly for app-host notebooks without script metadata. CLI, adapter, and fixture tests cover both managers; the guide documents the remaining Pixi limitations.
This PR remains draft until a Pixi release includes [prefix-dev/pixi#6648](prefix-dev/pixi#6648). The required upstream change has merged. The notebook-owned lifecycle in the previous PR describes operations in terms of a manifest and its realized environment. This PR supplies those operations with Pixi and makes the choice explicit at the CLI: ```console marimo edit --sandbox notebook.py # uv marimo edit --sandbox=pixi notebook.py # pixi ``` ```text NotebookSandbox(source, "pixi") -> PixiBackendAdapter -> add / remove / sync / packages / launch ``` Pixi reads the same PEP 723 metadata. Package changes use Pixi script commands, synchronization recovers the interpreter and environment root from structured output, and package inspection reads `pixi list` JSON. Launches layer the running marimo through `pixi exec`, so the shared manifest does not pin marimo to the machine that opened it. Selecting one manager does not import or probe the other. Pixi rejects Python interpreter overrides, which its script environments cannot honor, and falls back cleanly for app-host notebooks without script metadata. CLI, adapter, and fixture tests cover both managers; the guide documents the remaining Pixi limitations.
This PR follows the discussion in #6632 and reworks the earlier
manzt/pep-723prototype.Edited This PR originally added a
pixi scriptcommand and conda-exec support. After review, it now uses--scriptwith existing Pixi commands and supports PEP 723 withtool.pixi. This leavespixi scriptopen for other uses later.This PR adds support for standalone Python files with inline environment metadata.
Pixi creates a cached environment for the script. It does not use an enclosing workspace or activated environment.
PEP 723 declares the Python version and PyPI dependencies. Pixi also reads
tool.pixifor Conda packages and settings that PEP 723 cannot express.Other PEP 723 tools can use the standard fields. Pixi can also install the Conda dependencies.
Scripts use the existing Pixi commands.
--scriptis also available fortreeand the relevantworkspace channel,workspace platform, andworkspace exportcommands.Where both are present,
--scriptand--manifest-pathcannot be used together.--scriptis only added to commands that have useful behavior for a standalone script. It is not available for commands such as install, shell, task, or workspace configuration.Only
pixi init --scriptcreates a file or adds a PEP 723 block. Other commands require the metadata to already exist.Without a lockfile, Pixi resolves the environment without writing one.
pixi lock --scriptwritesexample.py.pixi.locknext to the script. Later commands reuse it. The environment itself stays in the Pixi cache.This PR does not add
tool.conda, conda-exec support, or a new Pixi metadata format.See the standalone scripts documentation for more examples.