Skip to content

Feat: Create a cached lock file for uv run with scripts #9688

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

Closed
notatallshaw opened this issue Dec 6, 2024 · 12 comments
Closed

Feat: Create a cached lock file for uv run with scripts #9688

notatallshaw opened this issue Dec 6, 2024 · 12 comments
Assignees
Labels
needs-decision Undecided if this should be done

Comments

@notatallshaw
Copy link
Collaborator

This is a follow up to #7538, I wanted to make a clear feature request. Basically I don't want uv run ... to resolve when it's already done it once, unless I pass something like uv run --upgrade ....

The current behavior is problematic when the network is having transient issues or is very slow, for example a firewall decides to start blocking access to a package then uv run fails even though it previously installed all the dependencies, or if the network is very slow and is randomly dropping packets then every time you run uv run you end up with it saying ⠷ Resolving dependencies... for several seconds.

In general, I think the expected user experience (perhaps incorrectly) of uv run ... is there is no network activity required unless absolutely necessary.

FYI, I'm not currently impacted by this issue, so it's not a big priority for me, but I have seen it in the past, and in general it does feel like a better user experience.

@FishAlchemist
Copy link
Contributor

If it's not a frequent problem, would adding --offline to force UV to not access the network be a solution?

--offline
Disable network access.

When disabled, uv will only use locally cached data and locally available files.

@notatallshaw
Copy link
Collaborator Author

notatallshaw commented Dec 6, 2024

If it's not a frequent problem, would adding --offline to force UV to not access the network be a solution?

Yeah, that's what I do: #7538 (comment).

But that means I have to remember whether I've run a script before or not, and if I'm wrong I either get an error for the dependencies not being installed or if I'm having a network issue a slow resolution or a network error. So it's mental overhead and/or poor user experience.

And my understanding is for some users it is a frequent issue (consider some users might be permanently on spotty internet connections).

@notatallshaw
Copy link
Collaborator Author

notatallshaw commented Dec 6, 2024

Oh, I should mention this extends to uv tool run / uvx, I actually avoid that command because of this and instead use uv tool install, but there's no equivalent simple workaround for uv run.

@FishAlchemist
Copy link
Contributor

@notatallshaw If the network is unstable, I've encountered environments where I've been throttled. In such cases, I usually set the default offline mode to true and only specify --no-offline when I need to access the network.
Although --no-offline is not explicitly shown, it's a feature that the CLI happens to support.
If offline = true can be configured in a user-level settings file, then a cached lock file is unnecessary for my use case.

@konstin konstin changed the title Feat: Create a cached lock file for uv run Feat: Create a cached lock file for uv run with scripts Dec 6, 2024
@notatallshaw
Copy link
Collaborator Author

notatallshaw commented Dec 6, 2024

Although --no-offline is not explicitly shown, it's a feature that the CLI happens to support.

Yeah, I didn't even know that existed, it's not a user feature if it's not documented anywhere. It's also still not a great user experience, as again it puts the mental overhead on the user to remember if something has been run before or not.

I'm really not making the case that I need this, I'm making the case that the current behavior is a bad user experience for some and there's at least no documented solution.

@FishAlchemist
Copy link
Contributor

@notatallshaw I have a few questions about locking dependencies.
If you lock the dependencies for uv run script, when should the lock file be considered outdated?
If it's permanent, should users be aware that they're using outdated dependencies?
Additionally, if dependencies are locked, how can we prevent behavioral inconsistencies caused by different dependency versions on different devices?

@notatallshaw
Copy link
Collaborator Author

notatallshaw commented Dec 6, 2024

If you lock the dependencies for uv run script, when should the lock file be considered outdated?

I would prefer never, unless something forced the change (e.g. a change in requirements, providing --upgrade, or a change in uv's cache format). When I "run" something on my computer I don't expect the code it's running to change unless I've done something to change it (changed requirments, explicitly asked to update requirements, updated uv, etc.).

If it's permanent, should users be aware that they're using outdated dependencies?

This is an interesting user experience question, and I'm not sure of the answer. If I was designing uv I would give options to warn on outdated or automatically re-resolve each time, but not make them default. But I understand the uv team might have different design goals.

Additionally, if dependencies are locked, how can we prevent behavioral inconsistencies caused by different dependency versions on different devices?

I don't understand the context of this question. Since when is uv run supposed to be consistent across different machines?

If I run something on Windows machine I might require a dependency that someone running on Linux won't machine won't, and so my code exection may be different. And if I run something one machine at one time and a different machine at a different time it can now resolve to different versions. And if I run something on two machines at the same time they might resolve to different versions due to CDN or other caching.

Are there some guarantees uv is providing here that I'm not aware of?

And moreso, what about behavioral inconsistencies of running the same script on the same machine 10 minutes apart from each other?

@konstin konstin added the needs-decision Undecided if this should be done label Dec 6, 2024
@FishAlchemist
Copy link
Contributor

FishAlchemist commented Dec 6, 2024

if dependencies are locked, how can we prevent behavioral inconsistencies caused by different dependency versions on different devices?

Actually, I mean if the cache time is set very long, even on the same operating system and instruction set architecture, the dependency versions obtained by running the uv run script at different times will be different. Different dependency versions may cause differences in execution results, unless the initial dependency descriptions are written well enough.

For example, if a dependency on NumPy is specified without a version constraint, running uv run script in February would install version 1 of NumPy, but running it in August might install version 2.

# dependencies = [
#     "numpy",
# ]

Edit:
Note that the two executions of the uv run script were on different devices

@notatallshaw
Copy link
Collaborator Author

Agreed, and I would find this surprising that the script which I have been running successfully for months suddently starts failing because a dependency updated even though I never did anything that would indicate I want new dependencies.

Worse, what if it was a transative dependency, so even if I pinned all my main depdnencies I now need to start pinning transative dependencies in the dependencies block?

I understand the solution here I propose might not align the uv team's design goals, but the problems and user experience issues I pose here I think are quite real, maybe there is a better solution to them though.

@notatallshaw
Copy link
Collaborator Author

notatallshaw commented Dec 6, 2024

Here's me thinking out loud about a solution that would resolve both concerns, say I run uv run --lock my-script.py and if one didn't exist it would create a my-script.py.lock and if it did exist it would use that lock file for my-script.py dependencies if they hadn't changed, else it would update the my-script.py.lock.

This behavior is explicit rather than implicit and a user could take that lock file to different machines. Again just thinking out loud, so not tied to any of the specifics of this proposal.

@zanieb
Copy link
Member

zanieb commented Dec 11, 2024

Note we're also discussing this in #6318

@zanieb
Copy link
Member

zanieb commented Dec 11, 2024

Minor note regarding --no-offline

Yeah, I didn't even know that existed, it's not a user feature if it's not documented anywhere.

We have hidden inversions of nearly all of our boolean flags.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
needs-decision Undecided if this should be done
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants