How would you like to declare runtime dependencies and Python requirements for PEP 723?

Based on how this conversation is going, I think so.

I don’t think anyone meant to suggest otherwise; this is seeing if we can agree on the colour of the bikeshed enough to move forward with PEP 723. This is not about starting a new discussion about an entirely new approach. For that I would ask that you start a new topic.

2 Likes

FYI, my favorite way to write this is:

# /// pyproject
# run.requires-python = ">=3.12"
# run.dependencies = ["requests", "textual>=0.44.1"]
# ///

That makes option 1 (and 3 somewhat) nearly as simple as option 2. Also, I think you can’t get out of section back to the top level once you are in one in TOML, which forces option 2 to always be at the top if you have any sections (like [tool.ruff], etc) (not sure if that’s good or bad).

By the way, I would vote for option 3 if that meant we could make the name field allowed as dynamic in pyproject.toml. I hate that that’s forced to be statically defined, as it means I’m eventually going to have to provide [tool.scikit-build.project] or similar and duplicate all the configuration, just to allow multiple packages to be generated for a single source file, which was a common need for complex setup.py packages. :confused:

1 Like

I think it depends on how much you want to keep this simple.

Feel free to start a separate conversation to change that if your experience is showing it to be a hindrance.

1 Like

The poll doesn’t mention [tool] sections, and in all the debate I think they’ve been forgotten.

What (if anything) is the current thinking? Given that we’re talking about having a section header other than pyproject, my suggestions would be:

  1. Have a /// tool section for tool config.
  2. Drop the idea of tool config altogether.
  3. Keep tool config in the /// pyproject section even if dependency data isn’t there.

I see no justification for putting tool config in a new section dedicated to runtime dependency data.

3 Likes

Please excuse a relative outsider dropping in with simplistic views, but:
To me, running the project should be python -m import_name or python script.py. (Unfortunately, the details probably require standardizing what the “main import name” for a project is. For scripts, it’s trivial.)

What pipx does seems rather complicated to me: runs a default entrypoint, and for that it needs a packaged project (to have entrypoint metadata). Could it run __main__ (or script.py) if the default entrypoint isn’t available? (There’s even a default error message if a package doesn’t have __main__: foo is a package and cannot be directly executed.)
I see entrypoints as an advanced feature, best kept for CLI commands without the python -m (or pipx) in front, defining multiple commands or commands with arbitrary names.

I chose option 3. If a project doesn’t have a name, it can’t be packaged, but it can still be run. And if a single-file script has metadata, its a project.

6 Likes

This is what I was thinking, basically the block names would correspond to top-level tables in pyproject.toml and therefore if we ever consider scripts as projects that key would actually be project.

I’m trying to remove the idea that script metadata is the same as project metadata, not extend it. Trying to make a parallel with “projects that don’t produce a wheel” when we don’t know how we want to treat such projects yet, is precisely what left us in this uncomfortable interim situation. I still think we should handle script metadata in isolation, and leave it to whoever writes future PEPs to integrate things with established standards (which at that point will include PEP 723). I’m not saying we actively make it difficult to integrate later, just that we don’t make integration a goal now.

But this is just re-hashing all the reasons we weren’t able to reach a compromise between PEPs 722 and 723, so we’re not adding anything new here. We don’t agree, so it’s going to be ultimately down to Brett to decide which viewpoint to approve. (I thought he had when he conditionally approved PEP 723, but it looks like the question is still open given that people want to implement the PEP before its approval is confirmed, and we’re now talking about changing the spec as well…)

1 Like

We are in fact trying to do the same thing! The issue is that I only view the project table as project metadata whereas you seem to be interpreting any overlap with what might be in pyproject.toml as project metadata.

1 Like

(Feel free to ignore this, it’s getting off-topic, but I’d still really like to reach a common understanding, so I’d like to get to the bottom of why we’re misunderstanding each other).

Not really. I’m saying that we have no idea what “project metadata” might look like outside of the narrow case of building a wheel. We can’t even agree on what it means to “run” such a project, let alone what a project’s name or version should be in that case.

So I’m trying to say, can we please look at scripts in isolation and not presume we know what “project metadata” will look like? You’re presuming the project table is project metadata. I’m saying you can’t know that, given that we haven’t agreed that the [project] table will even be allowed for non-wheel projects. I’m not offering an alternative interpretation, I’m trying to ask that we don’t use the term “project metadata” at all[1].


  1. at least, not until the “projects that don’t build a wheel” discussion reaches some conclusion ↩︎

1 Like

If we look at scripts in isolation as you say (which I am okay with once again) there is still a desire for the tool table as expressed by maintainers of Mypy, Ruff, etc.

4 Likes

Would it be easier to just ignore the pyproject lingo and use “toml” as the explicit block header?

# /// toml
# dependencies = [“…
# [tool.ruff]
# etc…
# ///
1 Like

Oh, I think I see now. When you said

I thought you meant that script metadata should be equated to project metadata. Whereas what you were saying is that by not using project at this time, we avoid the issue of tying anything to what projects might do, while still leaving the door open for a future PEP to allow project-like metadata for scripts. Is that right?

If so, I guess I don’t care much about what happens in the future (I personally think we’ll never have a close enough equivalent to justify using project, but as I said that’s something we can ignore for now).

As for the tool table, I’d consider it differently (but with the same end result). There’s a desire for tools to have somewhere to put tool-specific config in scripts. By reserving a /// tool section, we give them a namespace, and by refusing to define any semantics we leave the interpretation open and avoid all the questions around merging config values, etc. But I don’t consider that to be /// tool “corresponding to” [tool], simply “we reserve one section of the namespace for tools” and we might as well use the same textual name for it. It’s a subtle, but in my view important, nuance.

Maybe, but “toml” isn’t that meaningful (it focuses on the syntax, not the meaning) and it has the problem that top-level values like dependencies must go first.

I will say, though - at what point do we admit that this isn’t actually PEP 723 any more, and we’ve simply gone back to square one with a completely new proposal? Personally, I certainly feel like I’m trying to redesign PEP 722 with the one change being that it should use TOML, because the survey established that PEP 722’s arguments against TOML weren’t valid.

2 Likes

I understand the point you’re making but it’s maybe too nuanced for future decision-making. Meaning, any future proposal that made /// tool diverge from [tool] will be subject to the (very reasonable IMO) criticism that it’s confusing to use the same name to mean different things (in very similar contexts, albeit not the same context). So reserving the section name and allowing tools to use it will be establishing the correspondence in practice.

4 Likes

The current content of 723 suggests that I can have a [tool] table. I think that may be valuable to retain in some form, but have basically no opinion about what it looks like (other than a basic “brevity is nice when possible”).

It’s not only valuable for tools like linters. It’s also a place where implementations can put their non-standardized configs. e.g.

# /// pyproject
# ...
# [tool.pip-run]
# mode = "ephemeral"
# ///

I’m a little concerned about how tools may layer configs, something which has been raised and discussed in greater depth elsewhere. But I wanted to point out that if the capability exists to have [tool] configs in a script, it will have direct applicability for script runners.

I think that’s a great take! My stance is only that this is a reading of “run a project”, and nobody has explicitly discussed and established this.
Like you hint, there are a lot of details to hash out. (e.g. How do we discover the import name when the project is not a package?)

1 Like

If we’re trying to pick a color of the bikeshed here, here’s a proposal…

# /// script
# dependencies = ["httpx"]
#
# [tool.magic]
# style = "interesting"
#
# [tool.linter]
# strict = true
# ///

This is literally script metadata, after all. Let’s call it that. That clearly indicates that it’s separate from project metadata or even how things are run or what a project is.

With this, you can have only linter configuration and it doesn’t look out of place.

# /// script
# [tool.linter]
# include = ["I"]
# ///

Or, you can only have the “how to run this” metadata and it doesn’t look out of place.

# /// script
# dependencies = ["httpx"]
# ///

If we want to have tool configuration at all, I’m struggling to understand why it should not look like TOML configuration that users have in other contexts already. Doing it differently in different contexts with the same markup language but with extra steps serves to increase cognitive load IMO.

Please, let’s not reinvent the concept of how to do namespaces by doing it at a layer above the TOML configuration, a configuration format whose structure is namespaces and key-value pairs. The /// foo syntax is more boilerplate than TOML’s [table] syntax, and doing it multiple times in the same script is… frivolous IMO.

19 Likes

@pradyunsg I like this, and personally think requiring the requires-python and dependencies to be before tool configs, top level, is a good thing!

1 Like

I like this, and as you say it’s basically a bikeshed colour, so I don’t think it’s worth much debate. Anything would work, this is nice, great - job done.

However, there’s an ongoing poll with 5 days left to run, which might come up with a different result (this is essentially option 2). I think we have to wait for the poll to complete before actually doing anything. People who like this idea and haven’t already voted option 2 can vote (or change their vote) if they want to support it.

The one point someone made is that top-level values in TOML must come before any sections. That seems fine to me, but it is a (small) limitation and it might be inconvenient in some situations[1]. It’s worth noting explicitly, though.

I think “it’s up to the tool” covers this. We provide the namespace, tools decide for themselves how layering works, what’s appropriate for a project and what’s appropriate for a script, etc. If users want consistency and tools don’t provide it, that’s something for the tools to address based on user feedback. No need for the standards process to get involved at all.


  1. not that I can really think of any ↩︎

2 Likes

As I see things: if we don’t think about it now, that creates a serious risk of making it difficult to integrate later, completely by accident, due to some unknown unknown.

I’m starting to feel like it might be necessary, honestly.

Tools can’t really be prevented from using their own mechanisms in addition to supporting standards. I think it’s up to the individual tool to figure something out, and this is the price for not doing everything via standard mechanisms. There has to come a point where the tool authors get the blame for user confusion rather than what PyPA says about standards. People were able to understand that Poetry was doing its own thing rather than properly implementing PEP 621, for example. So, yes, I agree with @pf_moore here.

1 Like

I’d actually vote for option 2 if that is option 2. Technically option 2 doesn’t use “script”. With “pyproject” I prefer [run], with script I prefer nothing (very, very slightly, since run.dependencies is only four more characters). But the poll doesn’t reflect that.

1 Like