# Inspiration
PEP 723 support
| Tool | Date added | Version |
| ------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| [`pipx run`](https://pipx.pypa.io/latest/docs/#pipx-run) | [2024-01-12](https://github.com/pypa/pipx/releases/tag/1.4.2) | [1.4.2](https://pipx.pypa.io/latest/changelog/#:~:text=Update%20pipx%20run%20on%20scripts%20using%20///%20script%20and%20no%20run%20table%20following%20the%20updated%20version%20of%20PEP%20723) |
| [`pip-run`](https://github.com/jaraco/pip-run) | [2024-01-20](https://pip-run.readthedocs.io/en/latest/history.html#v12-5-0) | [12.5.0](https://pip-run.readthedocs.io/en/latest/history.html#v12-5-0) |
| [`hatch env run`](https://hatch.pypa.io/latest/cli/reference/#hatch-run) | [2024-05-02](https://hatch.pypa.io/latest/history/hatch/#hatch-v1.10.0:~:text=The%20run%20command%20can%20now%20execute%20scripts%20that%20define%20inline%20metadata%20for%20dependencies%20and%20Python%20version%20constraints) | [1.10.0](https://hatch.pypa.io/latest/history/hatch/#hatch-v1.10.0:~:text=The%20run%20command%20can%20now%20execute%20scripts%20that%20define%20inline%20metadata%20for%20dependencies%20and%20Python%20version%20constraints) |
| [`pdm run`](https://pdm-project.org/en/latest/reference/cli/#run) | [2024-06-26](https://pipx.pypa.io/latest/changelog/#:~:text=Update%20pipx%20run%20on%20scripts%20using%20///%20script%20and%20no%20run%20table%20following%20the%20updated%20version%20of%20PEP%20723) | [2.16.0](https://pipx.pypa.io/latest/changelog/#:~:text=Update%20pipx%20run%20on%20scripts%20using%20///%20script%20and%20no%20run%20table%20following%20the%20updated%20version%20of%20PEP%20723) |
| [`uv run`](https://docs.astral.sh/uv/reference/cli/#uv-run) | [2024-08-24](https://astral.sh/blog/uv-unified-python-packaging) | [0.3](https://astral.sh/blog/uv-unified-python-packaging) |
[`poetry run`](https://python-poetry.org/docs/cli/#run) is only for entry points.
## pipx
```
usage: pipx run [-h] [--quiet] [--verbose] [--global] [--no-cache] [--path]
[--pypackages] [--spec SPEC] [--python PYTHON]
[--fetch-missing-python] [--system-site-packages]
[--index-url INDEX_URL] [--editable] [--pip-args PIP_ARGS]
app ...
```
### pip-run
```
usage: Arguments to pip-run prior to `--` are used to specify the requirements
to make available, just as arguments to pip install. For example:
pip-run -r requirements.txt "requests>=2.0"
That will launch python after installing the deps in requirements.txt
and also a late requests. Packages are always installed to a temporary
location and cleaned up when the process exits.
Arguments after `--` are passed to the Python interpreter. So to launch
`script.py`:
pip-run -- script.py
For simplicity, the `--` may be omitted and Python arguments will
be inferred starting with the first Python file that exists:
pip-run script.py
To invoke another executable instead of Python, prefix the argument
with a `!`:
pip-run cowsay -- !cowsay "hello!"
If the `--` is omitted or nothing is passed, the python interpreter
will be launched in interactive mode:
pip-run
>>>
For more examples and details, see https://pypi.org/project/pip-run.
options:
-h, --help show this help message and exit
```
## Hatch
```
Usage:
hatch env run [OPTIONS] ARGS...
Options:
Name Type Description Default
--env, -e text The environments to target Sentinel.UNSET
--include, -i text The matrix variables to include Sentinel.UNSET
--exclude, -x text The matrix variables to exclude Sentinel.UNSET
--filter, -f text The JSON data used to select environments None
--force-continue boolean Run every command and if there were any errors exit with the first code False
--ignore-compat boolean Ignore incompatibility when selecting specific environments False
--help boolean Show this message and exit. False
```
## PDM
```
Options:
-h, --help: Show this help message and exit.
-v, --verbose: Use -v for detailed output and -vv for more detailed
-q, --quiet: Suppress output
-g, --global: Use the global project, supply the project root with -p option
-p, --project: Specify another path as the project root, which changes the base ofpyproject.toml and __pypackages__ [env var: PDM_PROJECT]
-k, --skip: Skip some tasks and/or hooks by their comma-separated names. Can be supplied multiple times. Use:all to skip all hooks. Use:pre and:post to skip all pre or post hooks.
--venv NAME: Run the command in the virtual environment with the given key. [env var: PDM_IN_VENV]
-l, --list: Show all available scripts defined inpyproject.toml
-j, --json: Output all scripts infos in JSON
Execution Parameters:
-s, --site-packages: Load site-packages from the selected interpreter
--recreate: Recreate the script environment for self-contained scripts
script: The command to run
args: Arguments that will be passed to the command
```
## uv
```
Run a command or script
Usage: uv run [OPTIONS] [COMMAND]
Options:
--extra <EXTRA>
Include optional dependencies from the specified
extra name
--all-extras
Include all optional dependencies
--no-extra <NO_EXTRA>
Exclude the specified optional dependencies, if
`--all-extras` is supplied
--no-dev
Disable the development dependency group [env:
UV_NO_DEV=]
--group <GROUP>
Include dependencies from the specified
dependency group
--no-group <NO_GROUP>
Disable the specified dependency group [env:
UV_NO_GROUP=]
--no-default-groups
Ignore the default dependency groups [env:
UV_NO_DEFAULT_GROUPS=]
--only-group <ONLY_GROUP>
Only include dependencies from the specified
dependency group
--all-groups
Include dependencies from all dependency groups
-m, --module
Run a Python module
--only-dev
Only include the development dependency group
--no-editable
Install any editable dependencies, including the
project and any workspace members, as
non-editable [env: UV_NO_EDITABLE=]
--exact
Perform an exact sync, removing extraneous
packages
--env-file <ENV_FILE>
Load environment variables from a `.env` file
[env: UV_ENV_FILE=]
--no-env-file
Avoid reading environment variables from a
`.env` file [env: UV_NO_ENV_FILE=]
-w, --with <WITH>
Run with the given packages installed
--with-editable <WITH_EDITABLE>
Run with the given packages installed in
editable mode
--with-requirements <WITH_REQUIREMENTS>
Run with the packages listed in the given files
--isolated
Run the command in an isolated virtual
environment [env: UV_ISOLATED=]
--active
Prefer the active virtual environment over the
project's virtual environment
--no-sync
Avoid syncing the virtual environment [env:
UV_NO_SYNC=]
--locked
Assert that the `uv.lock` will remain unchanged
[env: UV_LOCKED=]
--frozen
Run without updating the `uv.lock` file [env:
UV_FROZEN=]
-s, --script
Run the given path as a Python script
--gui-script
Run the given path as a Python GUI script
--all-packages
Run the command with all workspace members
installed
--package <PACKAGE>
Run the command in a specific package in the
workspace
--no-project
Avoid discovering the project or workspace
--python-platform <PYTHON_PLATFORM>
The platform for which requirements should be
installed [possible values: windows, linux,
macos, x86_64-pc-windows-msvc,
aarch64-pc-windows-msvc, i686-pc-windows-msvc,
x86_64-unknown-linux-gnu, aarch64-apple-darwin,
x86_64-apple-darwin, aarch64-unknown-linux-gnu,
aarch64-unknown-linux-musl,
x86_64-unknown-linux-musl,
riscv64-unknown-linux, x86_64-manylinux2014,
x86_64-manylinux_2_17, x86_64-manylinux_2_28,
x86_64-manylinux_2_31, x86_64-manylinux_2_32,
x86_64-manylinux_2_33, x86_64-manylinux_2_34,
x86_64-manylinux_2_35, x86_64-manylinux_2_36,
x86_64-manylinux_2_37, x86_64-manylinux_2_38,
x86_64-manylinux_2_39, x86_64-manylinux_2_40,
aarch64-manylinux2014, aarch64-manylinux_2_17,
aarch64-manylinux_2_28, aarch64-manylinux_2_31,
aarch64-manylinux_2_32, aarch64-manylinux_2_33,
aarch64-manylinux_2_34, aarch64-manylinux_2_35,
aarch64-manylinux_2_36, aarch64-manylinux_2_37,
aarch64-manylinux_2_38, aarch64-manylinux_2_39,
aarch64-manylinux_2_40, aarch64-linux-android,
x86_64-linux-android, wasm32-pyodide2024,
arm64-apple-ios, arm64-apple-ios-simulator,
x86_64-apple-ios-simulator]
Index options:
--index <INDEX>
The URLs to use when resolving dependencies, in
addition to the default index [env: UV_INDEX=]
--default-index <DEFAULT_INDEX>
The URL of the default package index (by
default: <https://pypi.org/simple>) [env:
UV_DEFAULT_INDEX=]
-i, --index-url <INDEX_URL>
(Deprecated: use `--default-index` instead) The
URL of the Python package index (by default:
<https://pypi.org/simple>) [env: UV_INDEX_URL=]
--extra-index-url <EXTRA_INDEX_URL>
(Deprecated: use `--index` instead) Extra URLs
of package indexes to use, in addition to
`--index-url` [env: UV_EXTRA_INDEX_URL=]
-f, --find-links <FIND_LINKS>
Locations to search for candidate distributions,
in addition to those found in the registry
indexes [env: UV_FIND_LINKS=]
--no-index
Ignore the registry index (e.g., PyPI), instead
relying on direct URL dependencies and those
provided via `--find-links`
--index-strategy <INDEX_STRATEGY>
The strategy to use when resolving against
multiple index URLs [env: UV_INDEX_STRATEGY=]
[possible values: first-index,
unsafe-first-match, unsafe-best-match]
--keyring-provider <KEYRING_PROVIDER>
Attempt to use `keyring` for authentication for
index URLs [env: UV_KEYRING_PROVIDER=] [possible
values: disabled, subprocess]
Resolver options:
-U, --upgrade
Allow package upgrades, ignoring pinned versions
in any existing output file. Implies `--refresh`
-P, --upgrade-package <UPGRADE_PACKAGE>
Allow upgrades for a specific package, ignoring
pinned versions in any existing output file.
Implies `--refresh-package`
--resolution <RESOLUTION>
The strategy to use when selecting between the
different compatible versions for a given
package requirement [env: UV_RESOLUTION=]
[possible values: highest, lowest,
lowest-direct]
--prerelease <PRERELEASE>
The strategy to use when considering pre-release
versions [env: UV_PRERELEASE=] [possible values:
disallow, allow, if-necessary, explicit,
if-necessary-or-explicit]
--fork-strategy <FORK_STRATEGY>
The strategy to use when selecting multiple
versions of a given package across Python
versions and platforms [env: UV_FORK_STRATEGY=]
[possible values: fewest, requires-python]
--exclude-newer <EXCLUDE_NEWER>
Limit candidate packages to those that were
uploaded prior to the given date [env:
UV_EXCLUDE_NEWER=]
--exclude-newer-package <EXCLUDE_NEWER_PACKAGE>
Limit candidate packages for specific packages
to those that were uploaded prior to the given
date
--no-sources
Ignore the `tool.uv.sources` table when
resolving dependencies. Used to lock against the
standards-compliant, publishable package
metadata, as opposed to using any workspace,
Git, URL, or local path sources [env:
UV_NO_SOURCES=]
Installer options:
--reinstall
Reinstall all packages, regardless of whether
they're already installed. Implies `--refresh`
--reinstall-package <REINSTALL_PACKAGE>
Reinstall a specific package, regardless of
whether it's already installed. Implies
`--refresh-package`
--link-mode <LINK_MODE>
The method to use when installing packages from
the global cache [env: UV_LINK_MODE=] [possible
values: clone, copy, hardlink, symlink]
--compile-bytecode
Compile Python files to bytecode after
installation [env: UV_COMPILE_BYTECODE=]
Build options:
-C, --config-setting <CONFIG_SETTING> Settings
to
pass
to
the
PEP
517
build
backend,
specified
as
`KEY=VALUE`
pairs
--config-settings-package <CONFIG_SETTINGS_PACKAGE> Settings
to
pass
to
the
PEP
517
build
backend
for
a
specific
package,
specified
as
`PACKAGE:KEY=VALUE`
pairs
--no-build-isolation Disable
isolation
when
building
source
distributions
[env:
UV_NO_BUILD_ISOLATION=]
--no-build-isolation-package <NO_BUILD_ISOLATION_PACKAGE> Disable
isolation
when
building
source
distributions
for
a
specific
package
--no-build Don't
build
source
distributions
[env:
UV_NO_BUILD=]
--no-build-package <NO_BUILD_PACKAGE> Don't
build
source
distributions
for
a
specific
package
[env:
UV_NO_BUILD_PACKAGE=]
--no-binary Don't
install
pre-built
wheels
[env:
UV_NO_BINARY=]
--no-binary-package <NO_BINARY_PACKAGE> Don't
install
pre-built
wheels
for
a
specific
package
[env:
UV_NO_BINARY_PACKAGE=]
Cache options:
-n, --no-cache
Avoid reading from or writing to the cache,
instead using a temporary directory for the
duration of the operation [env: UV_NO_CACHE=]
--cache-dir <CACHE_DIR>
Path to the cache directory [env: UV_CACHE_DIR=]
--refresh
Refresh all cached data
--refresh-package <REFRESH_PACKAGE>
Refresh cached data for a specific package
Python options:
-p, --python <PYTHON>
The Python interpreter to use for the run
environment. [env: UV_PYTHON=]
--managed-python
Require use of uv-managed Python versions [env:
UV_MANAGED_PYTHON=]
--no-managed-python
Disable use of uv-managed Python versions [env:
UV_NO_MANAGED_PYTHON=]
--no-python-downloads
Disable automatic downloads of Python. [env:
"UV_PYTHON_DOWNLOADS=never"]
Global options:
-q, --quiet...
Use quiet output
-v, --verbose...
Use verbose output
--color <COLOR_CHOICE>
Control the use of color in output [possible
values: auto, always, never]
--native-tls
Whether to load TLS certificates from the
platform's native certificate store [env:
UV_NATIVE_TLS=]
--offline
Disable network access [env: UV_OFFLINE=]
--allow-insecure-host <ALLOW_INSECURE_HOST>
Allow insecure connections to a host [env:
UV_INSECURE_HOST=]
--no-progress
Hide all progress outputs [env: UV_NO_PROGRESS=]
--directory <DIRECTORY>
Change to the given directory prior to running
the command [env: UV_WORKING_DIR=]
--project <PROJECT>
Discover a project in the given directory [env:
UV_PROJECT=]
--config-file <CONFIG_FILE>
The path to a `uv.toml` file to use for
configuration [env: UV_CONFIG_FILE=]
--no-config
Avoid discovering configuration files
(`pyproject.toml`, `uv.toml`) [env:
UV_NO_CONFIG=]
-h, --help
Display the concise help for this command
Use `uv help run` for more details.
```
# Purpose
For simplest way to execute code in an implicit, ephemeral virtual environment (i.e. the Python interpreter is an implementation detail).
This could be limited to just inline script metadata if that would help with acceptance.
# Ideas
Need to consider [[Caching app files while being ignored by backup apps]] for the implicit virtual environments.
- Supporting `pyproject.toml`
- `--group`/`--with`: Specifies the dependency group to use (only applicable when a directory path is specified, maybe zip file if it ships with a `pyproject.toml`)
- Care about extras, e.g. `--extra` or implicitly specified via `--group`/`--with`?
- `uv` uses `--extra`
- Making it the same name as for dependency groups helps transition from an extra to a group when a project makes such a move
- Execute what's in `bin/` for the virtual environment if command name is specified?
- Fall back to `-m` if nothing found in `bin/` matching the name (and it wasn't a valid path)?
- Automatically do an editable install?
- Basically run [[sync]] ?
- What happens when there is inline script metadata and `pyproject.toml`?
- If a file path is specified:
- If the file is a zip file, do anything special like look for inline script metadata in `__main__.py`? A lock file?
- If [inline script metadata](https://packaging.python.org/en/latest/specifications/inline-script-metadata/) is specified, use that
- Otherwise assume metadata of no dependencies and any Python version
- If a directory path is specified:
- For convenience when a [directory contains a `__main__.py` file](https://docs.python.org/3/using/cmdline.html)
- Use inline script metadata, `pyproject.toml`, or `pylock.toml`?
- Provide a way to specify whether `launch` or `run` are the default when no subcommand specified?
- Don't read the shebang; only rely on the metadata to limit the Python version