Not typically, no.
Generally, I don’t. Or if I do, copy and paste is enough.
Well, doing things the way I do works better for me. Not least because of the point that everyone keeps missing here - I don’t have to install them. I just create them and run them. And if I find something that I want to change, I fix it and I’m done. There’s no “source directory” that I have to keep in line, or anything like that. This isn’t production-quality code, managed as a full-fledged project, it’s helpers, one-offs, and quick wrappers.
Yes. What sort of maintenance do you imagine I do?
Here’s an example of the sort of thing I mean. Note that this uses just the stdlib, but that’s precisely because managing dependencies is a PITA.
from urllib.request import urlopen
import json
from argparse import ArgumentParser
from datetime import datetime
p = ArgumentParser()
p.add_argument("pkg", nargs="*")
args = p.parse_args()
def print_version(pkg):
with urlopen(f"https://pypi.org/pypi/{pkg}/json") as f:
data = json.load(f)
ver = data["info"]["version"]
reldate = min(datetime.fromisoformat(f['upload_time']) for f in data['releases'][ver])
print(f"{pkg}: {ver} ({reldate:%Y/%m/%d})")
for pkg in args.pkg:
print_version(pkg)
I’d have used click and requests if I could.
Or there’s
import importlib.metadata
from packaging.requirements import Requirement
import re
def normalize(name):
return re.sub(r"[-_.]+", "-", name).lower()
dependencies = set()
all_packages = set()
for dist in importlib.metadata.distributions():
name = normalize(dist.metadata["name"])
all_packages.add(name)
if dist.requires:
for req in dist.requires:
dep = normalize(Requirement(req).name)
dependencies.add(dep)
top_level = all_packages - dependencies
for name in sorted(top_level):
print(f"{name}=={importlib.metadata.version(name)}")
(which does use dependencies, and needs some annoying infrastructure that I always forget to maintain because of that).
Also, a list of dependencies is not the same thing as an “inline pyproject.toml
”. There’s no version for any of these scripts, the only name is the filename, and there’s no docstring or readme. They are purely personal utilities.
It would be of literally no use to me. But having said that, if you could specify a script’s dependencies in the script, like this PEP allows, it would be easier to write such a tool if it’s of use to you.
By the way - please excuse the fact that this reads as if I’m proposing this PEP purely to support my personal workflow. That’s not the case - I know many people who work like this, and plenty of people have commented on this thread in support of this type of approach. But it’s easier to give specific examples if I pick cases from my own usage.
I’ll be honest, reading your response gives me a very strong sense of what the survey feedback means when it says that users feel that the packaging community don’t listen to them. I’m trying to explain what my use case is, and why existing solutions don’t work for me. And rather than considering the problem I’m describing, you are trying to tell me that I’m going about things wrong. It may be that you’re tying to understand my use case better, but it feels like you’re telling me I shouldn’t be trying to do what I’m doing. It’s one thing to say that the packaging ecosystem shouldn’t support what I’m trying to do, but trying to say that I shouldn’t be doing it in the first place, so there’s no problem to solve, is very different (and not the message I think we should be giving to our users).
But this is pretty much off-topic. The PEP isn’t about something vague and general like “how to build and manage a set of standalone utilities in Python”, it’s about the much more specific topic of “How can a single-file script declare its dependencies”. I guess your view is “that functionality isn’t needed”. OK. But others have confirmed that they would benefit from it, and the existence of tools like pip-run
and pipx
suggest the same. I’ll review the “Motivation” section of the PEP and strengthen it if I think it will help, and then we can let the PEP-delegate decide if I’ve made the case sufficiently.