-
Notifications
You must be signed in to change notification settings - Fork 3k
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
Support installing requirements from inline script metadata (PEP 723) #13052
base: main
Are you sure you want to change the base?
Conversation
This also lays the groundwork for potentially allowing the argument to be given multiple times, but I don't yet want to think about the additional complexity of multiple possibly-contradictory `requires-python` specifiers.
if options.scripts: | ||
if len(options.scripts) > 1: | ||
raise CommandError("--script can only be given once") | ||
|
||
script = options.scripts[0] | ||
script_metadata = pep723_metadata(script) | ||
|
||
script_requires_python = script_metadata.get("requires-python", "") | ||
|
||
if script_requires_python and not options.ignore_requires_python: | ||
target_python = make_target_python(options) | ||
|
||
if not check_requires_python( | ||
requires_python=script_requires_python, | ||
version_info=target_python.py_version_info, | ||
): | ||
raise UnsupportedPythonVersion( | ||
f"Script {script!r} requires a different Python: " | ||
f"{target_python.py_version} not in {script_requires_python!r}" | ||
) | ||
|
||
for req in script_metadata.get("dependencies", []): | ||
requirements.append( | ||
InstallRequirement(Requirement(req), comes_from=None) | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It feels ungraceful to put all of this logic here but I'm not really sure how I would plumb it into a separate function. Suggestions welcome
for req in script_metadata.get("dependencies", []): | ||
requirements.append( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ruff
is upset that I wrote a loop with .append()
here (PERF401
) but I don't know if a comprehension would really be justified here? I can maybe see the case for requirements.extend(...)
but it still seems like it'd be harder to read to me. Looking for feedback.
Edit: here's a diff of the extend()
version that passes the new tests:
diff --git a/src/pip/_internal/cli/req_command.py b/src/pip/_internal/cli/req_command.py
index 294dc9f40..1f972eba4 100644
--- a/src/pip/_internal/cli/req_command.py
+++ b/src/pip/_internal/cli/req_command.py
@@ -298,10 +298,10 @@ class RequirementCommand(IndexGroupCommand):
f"{target_python.py_version} not in {script_requires_python!r}"
)
- for req in script_metadata.get("dependencies", []):
- requirements.append(
- InstallRequirement(Requirement(req), comes_from=None)
- )
+ requirements.extend(
+ InstallRequirement(Requirement(req), comes_from=None)
+ for req in script_metadata.get("dependencies", [])
+ )
# If any requirement has hash options, enable hash checking.
if any(req.has_hash_options for req in requirements):
This changeset adds support for installing requirements declared in a script using inline metadata as defined by PEP 723
I'm sure this still needs changes, but I'm at the point where I'm ready for a maintainer to point out to me how much I've missed 😅
Closes #12891