-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Using uv run
as a task runner
#5903
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Relevant comment from another issue: #5632 (comment) |
PDM supports this: https://pdm-project.org/latest/usage/scripts/ |
Yeah we plan to support something like this! We haven't spent time on the design yet. |
The pyproject standard already supports |
|
Perhaps naming this section |
Or maybe |
This is the main thing I missed coming from hatch: https://hatch.pypa.io/dev/config/environment/overview/#scripts |
+1 to @nikhilweee suggestions. I think “command” reflects the intent/concept. Hatch has an “environment” concept and supports running commands namespaced to an environment like so
where “test” is a user-defined environment (with a dependency group) and “cov” is a user-defined command for that environment. [tool.hatch.envs.test]
dependencies = [
"pytest",
"pytest-cov",
"pytest-mock",
"freezegun",
]
[tool.hatch.envs.test.scripts]
cov = 'pytest --cov-report=term-missing --cov-config=pyproject.toml --cov=src'
[[tool.hatch.envs.test.matrix]]
python = ["3.8", "3.9", "3.10", "3.11", "3.12"] I would be curious to hear the use cases of nesting dependency groups and commands into “environments” like this rather than defining them at the top-level (i.e. |
since it has not been mentioned yet, adding as a possible inspiration for design of tasks also pixi: https://pixi.sh/latest/features/advanced_tasks/ |
I happen to be writing a cross-project task runner that supports a bunch of formats (e.g. rye, pdm, package.json, Cargo.toml; even uv's workspace config). For what it's worth, almost all python runners use |
Also related to this thread, I wish uvx was
I know Regarding |
@inoa-jboliveira I opened a dedicated issue for that #7186 |
Putting together some thoughts about semantics. This issue is about adding support for running arbitrary instructions specified in What do we call these instructions?Lots of existing tools refer to them as "scripts".
It seems advantageous to just go with the term "scripts" because it is the de-facto standard. As noted by another user #5903 (comment), this would also reduce friction for users coming to Another option is to use the term "tasks"
Another option is to call them "executables". We could also use "commands", although I wasn't able to find existing tools which use this term. After settling on a name, an obvious thing to do is to let users define instructions in the How do we invoke these instructions?There are two options here.
How should these instructions be specified?PDM's documentation around user scripts is pretty evolved, with support for a bunch of features.
Rye has its own format, which is a subset of PDM features.
I hope this serves as a starter for discussing additional details for this feature. |
(Nice comment, thank you!) |
One nice thing about PDM is that if a command is not recognized as a built-in, it is treated as |
IMHO, Alas, one can argue that the |
I wonder if would be a good time to maybe standardise this? I don't know if a pep is required, but since we have some many package managers for python it would be nice if we can have one way to define these instructions |
Late to this thread, but I really like the idea of
It'd be great if Example snippets from ...
@task
def lint(ctx):
"""
Run linting checks using ruff and mypy
"""
ctx.run("ruff format --check src test tasks.py", echo=True)
ctx.run("ruff check src test tasks.py", echo=True, pty=True)
ctx.run("mypy src test tasks.py", echo=True, pty=True)
@task(name="lint:fix")
def lint_fix(ctx):
"""
Fix linting issues using ruff
"""
ctx.run("ruff check --fix src test tasks.py", echo=True, pty=True)
ctx.run("ruff format src test tasks.py", echo=True)
@task
def develop(ctx):
ctx.run(f"uv pip install -r {LOCK_FILE} -e .", echo=True)
...
@task(default=True, pre=[develop, lint, test, build_docs, publish])
def release(ctx):
"""
Release the package
"""
pass |
I've been following this thread, but now I wanted to give a newbie perspective to the community. I've been playing with npm and having a "scripts" section as an out-of-the-box feature, it's a massive gain in terms of maintainability and ease of development. analog to this feature, I would agree that uv can add support to something similar to that. I would follow this example [tool.uv.run|aliases|commands]
default = "uvx --from=rust-just just" # uvr
lint = "uv run scripts/lint.py" # uvr lint
test = "echo 'hello from uv'" # uvr test or maybe even not add a |
I've also been subscribed/following this feature for awhile. I ended up discovering how to install a project as a package, which gives you But WOW for someone new learning how to set that up it would be rough. There have been so many iterations on python packaging that you really need to understand a lot to get it working. It also seems uncommon to set up python application projects (not distributable libraries) up like this in the first place, so you're not going to see mention of it in various tutorials. For some skill context, I'd consider myself an intermediate Python developer who has spent the last several years only in web dev projects. No distributable libraries. It's been bizarre to me that I got this far without knowing about packaging, but I wouldn't be surprised if the large majority of Python devs are in the same boat. The package.json (side note, I cannot emphasize enough how grateful I am to the work being done on |
i find this feature request rather misguided. UV is an excellent environment and project management tool, but introducing such trivial functionality is unnecessary and counterproductive. as people mentioned before, the request aims to address cross-platform issues, but handling these collaboration challenges is a fundamental skill any competent developer should possess. Features that don't bring substantial productivity improvements only burden the maintainers while encouraging poor development practices. Python is renowned for its philosophy of explicitness—In keeping with Python's commitment to clarity, developers should understand the specific scripts they're working with instead of hiding them behind excessive layers of abstraction. I'm commenting because I can't stand seeing discussions about features that won't bring actual benefits and only create more work for maintainers. Does this issue really affect your actual efficiency when using the uv tool? btw, I love uvx ,it does be useful and clean, uxr is the most stupid thought I've ever seen.sorry bro uvx is enough man be appreciate on the current UV and focus on the actual and practical features please |
@AtticusZeller you aren't a member of Other users of
No benefits for you does not imply no benefits for anyone/everyone. That is a fallacy. Your comment does not meaningfully contribute to the discussion at hand. Please refrain from commenting like this on GitHub. |
I'd like to add shell completion to this design discussion. There was a quite a bit of discussion earlier in the thread about minimizing typing via aliases and the I'm not sure how it should work, but if it were possible to do something like In general I agree that having a task runner built into |
In case other people may find it useful, this is how I do it with [project]
name = "myproject"
requires-python = ">=3.12"
authors = [{name = "Author Name", email = "[email protected]"}]
description = "Example package config file"
[project.scripts]
my_package_entrypoint = "myproject.__main__:main"
task-runner = "poethepoet:main"
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
[dependency-groups]
task_runner = ["poethepoet>=0.33.1"]
linting = ["black>=25.1.0", "isort>=6.0.1", "ruff>=0.11.2"]
[tool.uv]
package = true
default-groups = "all"
[tool.poe.tasks]
black = "black ."
isort = "isort ."
ruff = "ruff check -q myproject/"
linters = ["black", "isort", "ruff"]
[tool.ruff]
select = ["ALL"] With this you can run |
any updates? |
That's a great and well organized workaround @paulovcmedeiros. Especially if |
I also appreciated @paulovcmedeiros' solution, but I hit a snag: it only works for packages, as they are the only types of project that support entrypoints. If you're wanting to use tasks with a non-packaged application, you can't redefine the name of the entrypoint from My solution to this was to use the So the [project]
name = "myproject"
description = "Clever description here"
requires-python = ">=3.10"
[dependency-groups]
dev = [
"go-task-bin>=3.42.1",
"ruff>=0.11.5",
] And the version: '3'
tasks:
format:
desc: Format all files
cmds:
- ruff format |
I have been using For example: [tool.poe.tasks]
dev = "uv run src/main.py"
build = "uv run pyinstaller --clean ./Server.spec"
build-debug = "uv run pyinstaller --clean ./Server-debug.spec" and use it like As strictly a matter of preference for the api for |
@JBloss1517 you must have |
$ uv init
$ uv add --dev poethepoet
$ source .venv/bin/activate
$ poe --version
Poe the Poet - A task runner that works well with poetry.
version 0.33.1 No, once you have activated the virtual environment. Also, the [tool.uv] # ensure this table exists somewhere in your pyproject.toml. It can be empty.
[tool.poe.tasks]
dev = "src/main.py"
build = "pyinstaller --clean ./Server.spec"
build-debug = "pyinstaller --clean ./Server-debug.spec" |
@Lordfirespeed great to know! Thanks for the info. |
Just as a note, recent versions of poe have first class support for uv. This means poe will run |
Re: design Comparison of a few task runners from the perspective of people who know I left blank areas that I was unsure. Feel free to correct me.
Some notes
|
@phitoduck For "No extra install" - Just and Task are as easy to install as Poe the Poet as the binaries are avaliable on PyPi. So they can be used with
|
Whoooooa 🤯. I had no idea! Sadly, you do lose tab-completion if you invoke Bringing this back to uv's design--If Edit: wow, I feel like I have to report back what I found since it relates to some of the previous comments about If you use # install `poe` globally
uv tool install poethepoet
# make sure ~/.local/bin is in your $PATH
uv tool update-shell
# Output for me: Executable directory /Users/ericriddoch/.local/bin is already in PATH (but if it weren't it'd be added, so this is idempotent!)
# enable tab completion of poe tasks in pyproject.toml; there's a similar cmd for those that don't use OhMyZSH--an onboarding script could just run all of them
# https://poethepoet.natn.io/installation.html#shell-completion
mkdir -p ~/.oh-my-zsh/completions
poe _zsh_completion > ~/.oh-my-zsh/completions/_poe
# reset the shell to reflect all these $PATH changes
eval $SHELL Now typing As others have pointed out, This is exactly what I was looking for as a ML Platform engineer trying to make onboarding to our DS repos simple/consistent. As far as I'm concerned, I'd be thrilled if |
For those of us migrating over from Rye, one of its nice features is the built-in task runner using
rye run
and[tool.rye.scripts]
. For example:It could have some more features - here is a selection of feature requests from the community:
tool.rye.scripts
rye#930A lot of these requested features are things that other 3rd party tools currently offer. I thought it might be useful to highlight a few other tools here, in particular because they also integrate with the
pyproject.toml
ecosystem and can be used with uv today.Poe the Poet
https://github.com/nat-n/poethepoet
taskipy
https://github.com/taskipy/taskipy
Perhaps these can serve as some inspiration for a future
uv run
task runner and also in the meantime offer a solution for people coming over from Rye looking for a way to run tasks.The text was updated successfully, but these errors were encountered: