astral-sh / uv

An extremely fast Python package and project manager, written in Rust.
https://docs.astral.sh/uv
Apache License 2.0
22.97k stars 665 forks source link

Virtual environment support for `uv run` #3836

Closed Vigilans closed 3 months ago

Vigilans commented 4 months ago

As mentioned in https://github.com/astral-sh/uv/issues/3097, uv run may support working with virtual environment, where:

charliermarsh commented 4 months ago

Thanks!

charliermarsh commented 3 months ago

What about something like this:

Vigilans commented 3 months ago

The first two rules are fairly reasonable! For the third rule, is https://github.com/astral-sh/uv/issues/3404 and https://github.com/astral-sh/uv/pull/3585 relevant regarding workspace = false option?

Though I haven't figured out how a pyproject.toml will impact pip API (the uv pip commands?) yet, in uv run it will cause uv to install current project as package, and disabling it may make not much difference once editable build is installed? (btw, I found in my project uv run ls always try to build and reinstall my project, is that intended?)

charliermarsh commented 3 months ago

I am wondering if workspace = false and managed = false mean different things... You might have a project that's nested in a workspace, but shouldn't be considered part of the workspace, but should still be managed with uv.

btw, I found in my project uv run ls always try to build and reinstall my project, is that intended?

(Do you have dynamic metadata in your project? If so, yes, but we may change that behavior.)

Vigilans commented 3 months ago

(Do you have dynamic metadata in your project? If so, yes, but we may change that behavior.)

Yes, we have requirements.txt (generated with uv pip freeze | uv pip compile -) used for pyroject.toml using

[tool.setuptools.dynamic]
dependencies = {file = ["requirements.txt"]}
charliermarsh commented 3 months ago

Yeah, we have to rebuild your project every time if you have dynamic metadata right now, since we have no way of knowing if it's up-to-date.

zanieb commented 3 months ago

We add an option to mark a pyproject.toml as "not managed by uv" / "not part of a workspace" (like managed = false or workspace = false) so that you can use this in codebases that have a pyproject.toml but want to use the pip AP

Would this be equivalent to uv run --isolated?

charliermarsh commented 3 months ago

Nope! uv run --isolated runs a command in an isolated, ephemeral environment.

zanieb commented 3 months ago

Ah hm, should --isolated being double duty of ignoring configuration and forcing an ephemeral environment? I think the flag name makes sense for the latter in this command but I worry about expanding the concept / purpose. (I think this is a pretty minor concern)

charliermarsh commented 3 months ago

We could remove it and add a dedicated flag (--ephemeral or whatever), but we still need a solution to running in a venv when a pyproject.toml is present.

charliermarsh commented 3 months ago

Ah hm, should --isolated being double duty of ignoring configuration and forcing an ephemeral environment?

(This is already how it behaves today, just to clarify.)

Vigilans commented 3 months ago

we still need a solution to running in a venv when a pyproject.toml is present.

Should any explicit flag of python interpreter discovery takes precedence over discovered workspace? That enables user to explicitly specify a venv to use it when in a folder with pyproject.toml (but makes the code in the PR more complicated though).

charliermarsh commented 3 months ago

Unfortunately --python does have a valid meaning and usage in workspaces. If you run --python 3.8, and the venv uses a mismatched version, we'll re-create it.

zanieb commented 3 months ago

we still need a solution to running in a venv when a pyproject.toml is present.

Perhaps the answer I'm looking for will fall out of that.

Given the semantics in Ruff, I'd expect --isolated to ignore the pyproject.toml and other configuration files but not change other other behavior like ignoring existing environments. I designed the uv run isolated feature purely to do the latter but yeah it ended up doing both because it's the obvious flag name. I don't think the behavior is unreasonable though. I need to think a bit more about the pyproject.toml-not-a-workspace design :)

charliermarsh commented 3 months ago

Yeah, if --isolated respected an existing venv, then we'd probably find ourselves wanting a flag to do what --isolated does now.

Let me know your thoughts when you can, this work is blocked on feedback on the ideas I proposed.

Vigilans commented 3 months ago

I'd expect --isolated to ignore the pyproject.toml and other configuration files but not change other other behavior like ignoring existing environments.

I think this will be a very useful behavior. For end-users, implicit would help, while for scripts explicitness helps much.

For my use case, I majorly use conda run/uv run in automated shell scripts, especially in Dockerfile where activating an environment is not convenient, while explicitly specifying an environment to run is a more working solution.

So, for such scripts, I'd expect an explicit flag (--isolated or something) to tell uv to consistently run in project mode / venv mode, without taking care of what current directory uv is running in.

charliermarsh commented 3 months ago

We now fallback to virtual environments if you're not in a project.