PEP 751: now with graphs!

:+1: No disagreement from me – a format like that proposed in prior iterations of the PEP would definitely be an improvement over requirements.txt (to solve the lack of standardization, lack of secure-by-default installs, etc.)

The “arguments against” that I laid out above mostly stem from asking the question: if it’s not used “natively” by uv or Poetry, when / why would users of those tools use this format? And, consequently, it important that this is a standard? Or should it just be a feature of pip?

(But, again, I am still supportive of it being a standard.)

2 Likes

You of all people should know that we can’t assume pip is the only installer any more :slight_smile: But more importantly, requirements.txt is the requirements-like format that’s a feature of pip - if we’re not going to standardise the new version, then we can just stick with requirement files


I’m supportive of a simpler “secure requirements” format being a standard, but I want us to be very clear about the use cases, and what would be required from project management tools like uv, Poetry, PDM, hatch, etc., for the new format to achieve its goal of addressing those use cases.

For example, if a use case is “a project can set up Dependabot checking and Dependabot will be able to determine the project’s dependencies without needing to understand every workflow tool individually”, then how will that work if the project’s chosen workflow tool doesn’t maintain an up to date pyproject.lock file, but requires an explicit export step?

Put this another way (continuing with the Dependabot example) - what is uv’s expected solution right now for projects that use uv to work with Dependabot? Will that change if we have a “requirements-style” lockfile standard? If it won’t, then Dependabot isn’t a very good motivating use case for the new lockfile standard
 :slightly_frowning_face:

Repeat as often as necessary for the other motivating use cases for the new format :slightly_smiling_face:

3 Likes

Yeah, that’s the problem I’m concerned about with only standardizing an “export format”. I can export a requirements.txt from PDM’s or uv’s lock right now, but Dependabot will just issue useless PRs updating it instead of the lock file. So what’s the point?

That’s why I thought about some way for tools like Dependabot to make a standard {executable} list-deps and {executable} update-dep-version {dep} {min-version}. On the other hand, Dependabot could fix this problem on their end by allowing a project to create a workflow to install their tool of choice and generate an update. That honestly sounds better, but also unlikely to happen.

As a user of workflow tools (Poetry & uv) I also don’t think that Dependabot is a great motivating example if we are trending towards “This new standard can’t fully satisfy the needs of Poetry.lock and uv.lock”.

Users of Poetry/uv still need to check in Poetry/uv specific lockfiles. Checking in another lockfile just for Dependabot would be a big DRY issue. Also, Dependabot would submit PRs to update the pyproject.lock but not Poetry/uv’s lockfiles so only the alerts would be useful, not the PRs.

As I’ve been following this PEP (as a user), I’ve been wondering if perhaps taking the option of “let’s wait” might not be terrible given that it seems like unifying everyone at this point looks very difficult.

For Dependabot specifically, I’d expect that for a tool as popular as uv, Dependabot will add support (the issue has 214 :+1: ) like they did for Poetry when it got to a certain popularity

As someone who works with people new to Python a lot, I do worry a bit about the teachability cost of yet another lockfile that doesn’t fully replace the needs of existing workflow tools. There’d then be three things to make new users aware of even if they stick with a single workflow tool (e.g., uv)

  • requirements.txt (since old formats don’t go away)
  • pyproject.lock
  • uv.lock

I wonder if waiting for tools like uv to mature and revisiting this in the future could be an option?

1 Like

Another option is simply to declare the Dependabot scenario out of scope - after all, people manage at the moment with only requirement files. The problem is, if we have to reduce the scope too much, there’s no justification for a standard lockfile format any more.

Is poetry not mature yet? I don’t think the problem is about tools needing time to mature, it’s more about there being multiple tools, with multiple philosophies. We could wait for one tool to become dominant, but at that point there’s no need to standardise - services like Dependabot won’t need to support multiple tools.

IMO, if we don’t manage to standardise something in this round, we can pretty much assume there will be no standardised lockfile for the foreseeable future. Which may be fine, but we shouldn’t kid ourselves that we’re just “waiting a while”.

2 Likes

I’m using “Dependabot” as a stand in for any tool that wants to inspect the dependencies of a project without needing to add specific support for every possible project management tool. If we’re saying tools that introspect dependencies are out of scope, what is in scope?

If every tool needs to support every project management tool individually, then that immediately puts any new project management tool at a disadvantage in the future. That’s the current state of things now, but ideally a standardization would level the playing field for novel development.

1 Like

Were earlier revisions looking to do that for you? I.e. was the “set of packages” approach seemingly going to work for you? I ask because if it would then I think @frostming and PDM might be supportive as well, which would mean uv is still exporting a file but everyone else is aligned.

The file format is versioned for a reason; extending it later is always possible.

Does that actually have to be explicit after the first time? Nothing is stopping a tool from recording the fact that the user wants a cross-compatible export of their lock data and so any time the tool-specific file is updated the exported version is updated as well.

Let’s take this even a step farther back: why do any tools other than pip support requirements.txt files when they have their own lock file format? My guess is because it’s the closest thing we have to having an explicit list of things to install that every tool supports. Otherwise no one would be able to get a foothold as no one is going to want to rely on that workflow tool that no e.g., cloud host will support because they don’t want to put the time in to support some other bespoke file format (it I’m wrong I hope a tool author will correct me).

To me that says there’s a need for a standard and it’s currently being filled by a convention.

Yes, because I have literally spent years on this. Waiting longer isn’t going to magically make this any easier unless all but one project shuts down and we are okay letting a tool makes decisions via convention (which we did in the past and we didn’t like it).

Yeah, I don’t see this going better sometime in the future either.

8 Likes

Yes, so this is essentially the “minimum viable standard” - we accept that all we will do is replace the requirements.txt format with a properly standardised version, and leave it at that. We won’t solve any new problems that way, but we will (hopefully) cover all of the use cases that are currently handled by requirements files.

(Sorry, I know this is just restating what you’ve said previously, but I think it’s worth emphasising in the light of @charliermarsh’s comment)

For the same reason they use requirements.txt. If you assume that everywhere uv deals with requirements files you should update to also deal with the new lockfile standard, that’s basically what the “requirements 2.0” form of the lockfile proposal would look like. Does that help put things into context?

1 Like

I’ll give one small use case for why I both use uv and today only produce requirements.txt type file with uv pip compile. My current work place has some security audit tools. Those tools work on requirements.txt file but not other lock files. So for compliance my team needs requirements like file. If I were to add uv.lock I’d be stuck having both.

Although honestly if we invent new pyproject.lock file I’m weakly skeptical of our audit tools adding support for it anytime soon. It’ll probably come eventually if it becomes widely used standard.

Yeah, we support it as an escape hatch. It lets you take the output of the workflow tool, and operate it from other tools and other workflows.

Concretely, it was asked for here, with motivations being (1) install in an environment where uv is unavailable, and (2) Dependabot.

Another comment mentions that they can then run safety over the file (and get Dependabot support). And then, within uv, they can run uv pip install --target from the exported requirements file to get a zip archive for AWS Lambda. (So, they export uv.lock to requirements.txt via uv export, then uv pip install from the requirements.txt, since the uv pip interface doesn’t operate on uv.lock.)

Again, I’m fine with a standard that replaces requirements.txt for this kind of interoperability! It makes sense. Our goal, though, is to solve these problems over time so that users don’t need to uv export. Taking Lambda as an example: we might want to create a dedicated uv command that bundles all of your dependencies as a zip, so that you don’t need to export-and-install with --target.

(I get that this is up to the tool but I wouldn’t be thrilled with this outcome, as a tool author and a user. Keeping them in-sync sounds like a pain
 I think there’s also some complexity here given that projects represent a wide range of scenarios (extras, dependency groups, resolver configuration), but the lockfile itself represents a single scenario – so in your original example, it’d be updating five lockfiles every time?)

As soon as you need to support extras and groups (like in Poetry), doesn’t that cause problems with those earlier revisions? Or am I misunderstanding the suggested format?

I was looking at the 2023 JetBrains Survey to gather some data about linting and stumbled upon this chart, which feels relevant here:

Even if you total up the alternative formats which currently support a lockfile, that’s ~30% to pip’s 77%. I worry that we’re losing sight of what people are actually using — most users aren’t using universal resolution. Similarly, I think much of uv’s growth has been its compatibility with the requirements.txt format.

(I guess we’ll probably get the 2024 data sometime in early 2025? That may help inform how much of uv’s userbase is using the universal lockfile.)

I don’t think this is fair. Yes, Poetry is a mature project management tool but there are limitations in their universal lockfile. Solutions to these limitations are new and changing rapidly. I don’t think that anyone, including uv, has a universal lockfile that’s clearly mature enough for standardization.

While I think it’d be great if we could standardize both universal and single-platform lockfiles in one go, I feel like this discussion has made it apparent that there is significantly more complexity in the universal case and a higher risk of failing to actually improve interoperability. I think there’s a much simpler path to standardizing a format with the same goals as requirements.txt, but with a modern take on topics like security and reproducibility.

I agree with the sentiments above that it would be pretty disappointing for this effort to go nowhere. Perhaps it would be worth focusing again on how we can design a new single-platform format which doesn’t inhibit us from introducing a multi-platform format in the future? I think this still has some problems with how or if you specify the “groups” that are being included in the file — I don’t think there’s been a clear solution proposed for that, other than arbitrary strings which breaks interoperability.

Please feel free to point out if I’m missing some critical prior discussion, it’s challenging to follow this whole thread :slight_smile:

3 Likes

I know you are, but others like @davidism aren’t so thrilled if the outcome is “yet another file to keep track of” if we can help it.

Thanks for the segue
 :grin:

While I was trying to fall asleep last night (yes, this whole endeavour consumes way too much of my mental energy), I started to think about how this compared to pyproject.toml and why that seems to be successful (and please don’t argue with me if you think it isn’t; that would be a distraction for this topic). And I thought about the three things pyproject.toml gives you:

  1. [project] allows for some tool portability which also helps to prevent lock-in.
  2. [project] allows for some data analysis most of the time (but with dynamic and [tool] there are escape hatches for tools that need them which technically hurt this and point 2, but people seem generally okay with the trade-off).
  3. [build-system] allows for programmatic understanding of how work with a source tree, in this case to create a wheel.

I think the mistake I have made is trying to meet all three points with lock files. I tried to make this happen with the separation of lockers and installers. But the split ends up hampering lockers so much that they can’t really operate very much outside of the spec and that prevents lockers from filing in gaps or innovating. And that leads us to the current situation where no one is getting what they want from the PEP because there’s always that next use-case to support.

So what if we stop trying to separate lockers from installers, instead letting tools write lock files with some tool-specific info that no one else might be able to work with? That tosses out point 1, but I don’t know if tool lock-in matters that much for something that’s meant to be written by code and not by hand.

You can still have point 2 where basic information can generally be available, maybe even in most cases, but in some instances some data will be tool-specific. But based on our experience with dynamic and [tool] in pyproject.toml it doesn’t seem to be a massive concern that you can’t always access all data upfront statically (Brainstorming: Eliminating Dynamic Metadata - #110 by ncoghlan notwithstanding).

Point 3 is possible if we make lock files document what tool to install and how to run the tool that created them (think [build-system] but with a CLI API). And this doesn’t necessarily need to be extensive and cover all use-cases, but I’m sure we can think of some common use-cases for what should be specified in the API. And thanks to lock files not meant to be hand-written we don’t have to worry about being too verbose or anything.

Does reframing things from this perspective and ditching the locker/installer dichotomy hold enough promise to suggest we could still maybe get that “any and all scenario” lock file dream to come true? I would bring back allowing for multiple lock files as exporting with no [tool] tables would be like having a standardized requirements.txt file for when that’s critical to someone. The PEP would be changed as necessary so that there was flexibility at all key points for tools to tweak things as necessary when they needed it while covering the common scenarios.

3 Likes

Can you please give a more concrete example of this new proposal?

1 Like

I’m not sure I follow - isn’t that what the [tool] section is for already? Are you simply suggesting that we will no longer require that a lockfile with a [tool] section can be installed by a tool other than the one that produced it?

Where would pip fit in this new framing? I don’t see pip as ever being a “locker” in the sense of doing a locking operation so what is pip if not an installer that isn’t also a locker? I don’t see pip implementing something that reads a lockfile, determines the file was produced by uv, installs uv and runs uv sync, in order to install from a lockfile. So the [build-system] analogy breaks down for me at that point.

I’m not against the idea - I just don’t feel that I understand what you’re getting at well enough to have a view on it yet.

1 Like

Would an example here be something like: the spec defines a flat list of packages – name, version, where to find it. But then everything else is up to the locker / installer? E.g., for uv, we’d put all the dependency metadata and graph in [tool.uv]?

(Just as an example: this would allow tools that need to ask about “what dependencies might be included”, like Dependabot, to function.)

Given Brett’s statement, wouldn’t pip reasonably both read and write a “plain” lock file in this format as an alternative to requirements.txt? Certainly a lock file that doesn’t interact with pip would be doomed for failure.

My question is what attempt will be there to have a minimal level of interoperability with the tool-specific lock files? It has to be more than “zero”, otherwise it’s no different from keeping uv.lock, poetry.lock, etc. in parallel with a next-generation of requirements.txt. And would @pf_moore accept this if pip has to error out if handed a, e.g., uv-flavored lock file?

If not “nothing” then what basic data should be required to be in the common section of the lock file? Certainly some sort of listing of packages. Do we include markers? Should tools be encouraged to make the “common” package listing self-consistent?

As a user, I picture that the “common” section should target some minimum “basic” installation (no extras or optional groups) suitable for CI or to run an application, but supporting at least the major platforms. This avoids the need to deal with potentially conflicting extras or specifying groups.

That said, I can imagine that trying to implement that is probably much easier said than done.

3 Likes

Pip doesn’t write requirement files, which is why I don’t expect it to write lockfiles either. I can see pip installing from a lockfile, but only if it can do so “natively” (i.e., without needing to know which tool wrote the lockfile)

That’s my point. I think it would have to be “zero” because pip won’t include tool-specific knowledge (we’re still working on removing the places we did that for setuptools :slightly_frowning_face:). The best I could imagine would be aborting if the lockfile had a [tool] section.

I honestly thought this was what pip freeze is for. Is there no expectation for pip to provide a similar output for this format?

Agreed that pip (or any tool) should not be expected to have any specific knowledge for any other tool. I interpreted @brettcannon’s proposal to strive towards some basic level of interoperability, but perhaps I misunderstood.

2 Likes

Ah, sorry. pip freeze does produce requirements-style output. The information necessary to produce a lockfile (specifically, the URL of the file used to install a package) isn’t available, so we can’t produce lockfile-style output from that. If PEP 710 gets approved and implemented, we will be able to produce lockfile output, but only as long as all the packages in the environment have provenance data, which in practical terms means newly created enviornments, built with tools that support PEP 710.

Also, I’ll point out that a standalone tool could just as easily (with PEP 710) create a lockfile that specifies how to recreate a given environment. There’s nothing really in pip freeze that requires that it be part of pip. So while pip probably would at some point gain a pip freeze --format=lockfile command, it doesn’t mean that pip necessarily has to be a locker.

I’m hoping that’s the case, but that’s why I asked for clarification - I’m not completely sure what Brett intended here.

2 Likes