Skip to content
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

Parse pyproject.toml statically where possible #1964

Merged
merged 19 commits into from
Mar 25, 2024

Conversation

hauntsaninja
Copy link
Contributor

@hauntsaninja hauntsaninja commented Aug 10, 2023

Contributor checklist
  • Included tests for the changes.
  • PR title is short, clear, and ready to be included in the user-facing changelog.
Maintainer checklist
  • Verified one of these labels is present: backwards incompatible, feature, enhancement, deprecation, bug, dependency, docs or skip-changelog as they determine changelog listing.
  • Assign the PR to an existing or new milestone for the target version (following Semantic Versioning).

@webknjaz
Copy link
Member

Plz use pathlib everywhere instead of low-level os calls.

@hauntsaninja
Copy link
Contributor Author

Sure, was just matching style to preexisting code

@hauntsaninja
Copy link
Contributor Author

Just to be explicit: atugushev suggested I don't work on this PR until #1681 is merged. This makes sense to me, since the two conflict.

@webknjaz
Copy link
Member

webknjaz commented Dec 3, 2023

Hey @hauntsaninja, that PR was merged about a month ago. So it seems like this one can be considered unblocked.

@hauntsaninja
Copy link
Contributor Author

Thanks for the nudge, I've rebased the changes on top of main

@webknjaz
Copy link
Member

webknjaz commented Dec 3, 2023

Ah, I was just cleaning up the old notification emails and noticed this..

Since this looks up the [build-system] section, I think @apljungquist should be invited to review too.

@hauntsaninja hauntsaninja marked this pull request as ready for review December 3, 2023 07:41
Copy link
Member

@webknjaz webknjaz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that such changes require tests. Could you add some?

piptools/build.py Show resolved Hide resolved
@@ -41,6 +48,67 @@ class ProjectMetadata:
build_requirements: tuple[InstallRequirement, ...]


def maybe_statically_parse_project_metadata(
src_file: pathlib.Path,
) -> ProjectMetadata | None:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's better not to use None as a magic sentinel value that the caller shouldn't forget to check for.
Instead, how about raising a LookupError. The handling would be cleaner, then.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given that we're using a static type checker, I think that would actually be less safe. mypy will complain if you do not handle None, but it will not complain if you do not handle the exception

comes_from = f"{package_name} ({src_file}::build-system.requires)"
build_requirements = [
InstallRequirement(Requirement(req), comes_from)
for req in pyproject_contents.get("build-system", {}).get("requires", [])
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't return complete build deps. It should call the corresponding hooks or not inject the build deps at all. An incomplete list would be harmful, expectations-wise.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed!

@webknjaz
Copy link
Member

webknjaz commented Dec 3, 2023

Could you also include more information regarding the motivation, use case, possible side effects, usage examples etc. into the PR description? Make sure all of those are also present as tests.

@webknjaz webknjaz added enhancement Improvements to functionality pyproject.toml Related to pyproject.toml support labels Dec 3, 2023
@webknjaz
Copy link
Member

webknjaz commented Dec 3, 2023

Oh, and it looks like the contributor checklist might've been overlooked, could you verify?

@chrysle chrysle added the awaiting response Awaiting response from a contributor label Jan 7, 2024
@hauntsaninja
Copy link
Contributor Author

Thanks for the initial review! I pushed a bunch of changes; this should now be much closer to shippable

:param isolated: Whether to run invoke the backend in the current
environment or to create an isolated one and invoke it
there.
:param quiet: Whether to suppress the output of subprocesses.
"""

if attempt_static_parse:
if build_targets:
Copy link
Contributor Author

@hauntsaninja hauntsaninja Jan 7, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let me know if you prefer to do this implicitly based on the value of build_targets, instead of having a separate param. I did it this way because it feels a little easier to test / harder to mess up

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like how you did it.

@chrysle chrysle removed the awaiting response Awaiting response from a contributor label Jan 19, 2024
piptools/build.py Show resolved Hide resolved
piptools/build.py Show resolved Hide resolved
piptools/build.py Outdated Show resolved Hide resolved
tests/test_build.py Show resolved Hide resolved
piptools/build.py Outdated Show resolved Hide resolved
piptools/build.py Outdated Show resolved Hide resolved
piptools/build.py Outdated Show resolved Hide resolved
@chrysle chrysle requested a review from webknjaz January 29, 2024 14:30
Copy link
Contributor

@chrysle chrysle left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@chrysle
Copy link
Contributor

chrysle commented Mar 9, 2024

@webknjaz Could you review again? This is a larger change, so I wouldn't like to merge this on my own.

Copy link
Contributor

@chrysle chrysle left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have got two minor suggestions, and a larger design question. If @webknjaz does not respond in the near future, I think I'll merge.

piptools/build.py Outdated Show resolved Hide resolved
for req in project_table.get("dependencies", [])
]
for extra, reqs in (
pyproject_contents.get("project", {}).get("optional-dependencies", {}).items()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we support Poetry for static metadata parsing?

Copy link
Contributor Author

@hauntsaninja hauntsaninja Mar 24, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If someone is interested in that, it can be a follow-up PR. It's been tough enough getting this one in, so I want to just stick with the standards based thing in this one

piptools/build.py Outdated Show resolved Hide resolved
@hauntsaninja
Copy link
Contributor Author

Thank you for the reviews!

@chrysle
Copy link
Contributor

chrysle commented Mar 25, 2024

Thanks, I was about to suggest the same! Could you rebase properly?

@hauntsaninja
Copy link
Contributor Author

fixed the test and ungoofed the git!

@chrysle chrysle enabled auto-merge March 25, 2024 19:48
@chrysle chrysle added this pull request to the merge queue Mar 25, 2024
Merged via the queue into jazzband:main with commit b692edb Mar 25, 2024
36 checks passed
@hauntsaninja hauntsaninja deleted the static-pyproj branch March 25, 2024 20:06
@chrysle
Copy link
Contributor

chrysle commented Mar 25, 2024

Great, thank you for the contribution!

@charliermarsh
Copy link

charliermarsh commented Mar 25, 2024

Just as a heads up, since we struggle with a similar thing in uv, I think this will error on Hatch projects that use Hatch's context formatting. Here's an example: https://github.com/astral-sh/uv/blob/ae35a215c67a161e759769b832b99740f4ecad69/scripts/packages/root_editable/pyproject.toml.

If I run from main, I get:

❯ pip-compile ../uv/scripts/packages/root_editable/pyproject.toml
Traceback (most recent call last):
  File "/Users/crmarsh/workspace/pip-tools/.venv/bin/pip-compile", line 8, in <module>
    sys.exit(cli())
             ^^^^^
  File "/Users/crmarsh/workspace/pip-tools/.venv/lib/python3.12/site-packages/click/core.py", line 1157, in __call__
    return self.main(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/crmarsh/workspace/pip-tools/.venv/lib/python3.12/site-packages/click/core.py", line 1078, in main
    rv = self.invoke(ctx)
         ^^^^^^^^^^^^^^^^
  File "/Users/crmarsh/workspace/pip-tools/.venv/lib/python3.12/site-packages/click/core.py", line 1434, in invoke
    return ctx.invoke(self.callback, **ctx.params)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/crmarsh/workspace/pip-tools/.venv/lib/python3.12/site-packages/click/core.py", line 783, in invoke
    return __callback(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/crmarsh/workspace/pip-tools/.venv/lib/python3.12/site-packages/click/decorators.py", line 33, in new_func
    return f(get_current_context(), *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/crmarsh/workspace/pip-tools/piptools/scripts/compile.py", line 365, in cli
    metadata = build_project_metadata(
               ^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/crmarsh/workspace/pip-tools/piptools/build.py", line 155, in build_project_metadata
    project_metadata = maybe_statically_parse_project_metadata(src_file)
                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/crmarsh/workspace/pip-tools/piptools/build.py", line 92, in maybe_statically_parse_project_metadata
    InstallRequirement(Requirement(req), comes_from)
                       ^^^^^^^^^^^^^^^^
  File "/Users/crmarsh/workspace/pip-tools/.venv/lib/python3.12/site-packages/pip/_vendor/packaging/requirements.py", line 117, in __init__
    raise InvalidRequirement(f"Invalid URL: {req.url}")
pip._vendor.packaging.requirements.InvalidRequirement: Invalid URL: {root:uri}/../black_editable

@hauntsaninja
Copy link
Contributor Author

hauntsaninja commented Mar 25, 2024

Hmm that's a violation of standards. It should probably declare dependencies as dynamic, or not use PEP 621

@charliermarsh
Copy link

Yeah, there's a discussion on it here if you'd like to chime in: pypa/hatch#1331

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement Improvements to functionality pyproject.toml Related to pyproject.toml support
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants