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

feat(cli): ensure build backend is defined when running poetry build #10092

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

finswimmer
Copy link
Member

@finswimmer finswimmer commented Jan 22, 2025

Pull Request Check List

When we cannot find a [build-system] section or a build-backend within this section in a pyproject.toml we assume setuptools as the build backend This is fine according to PEP 517.

While this approach is valid for dependencies it would be surprising on poetry build, now that an isolated build happens if the build-system is not poetry-core.

Before #10059 poetry build had created the package even if no build backend was defined in the pyproject.toml. Now it would fallback to setuptools which would results in a broken package.

This PR checks if a there is a [build-system] section and has a build-backend defined in the pyproject.toml and would abort the build if it couldn't find it.

  • Added tests for changed code.
  • Updated documentation for changed code.

Summary by Sourcery

Tests:

  • Added a test to verify that the build command fails when no build system is defined in the pyproject.toml file.

Summary by Sourcery

Tests:

  • Added a test to verify that the build command fails when no build system is defined in the pyproject.toml file.

Copy link

sourcery-ai bot commented Jan 22, 2025

Reviewer's Guide by Sourcery

This pull request ensures that a build backend is defined in the pyproject.toml file when running poetry build. It prevents the build process from falling back to setuptools, which could result in a broken package. The changes include adding a check for the build backend and a new test case to verify the behavior.

Sequence diagram for poetry build command with build backend check

sequenceDiagram
    actor User
    participant CLI
    participant BuildCommand
    participant PyProject

    User->>CLI: poetry build
    CLI->>BuildCommand: execute build
    BuildCommand->>PyProject: check build-backend
    alt No build backend defined
        PyProject-->>BuildCommand: build-backend not found
        BuildCommand-->>CLI: return error (1)
        CLI-->>User: Show error message
    else Build backend defined
        PyProject-->>BuildCommand: build-backend found
        BuildCommand->>BuildCommand: proceed with build
        BuildCommand-->>CLI: return success (0)
        CLI-->>User: Build completed
    end
Loading

File-Level Changes

Change Details Files
Added a check to ensure a build backend is defined in pyproject.toml.
  • Added a _has_build_backend_defined method to check for the presence of a build backend in the pyproject.toml file.
  • Modified the build method to check if a build backend is defined and abort the build if it is not.
src/poetry/console/commands/build.py
Added a test case to verify that the build command fails when no build system is defined.
  • Added a new test case test_build_handler_raise_on_no_build_system to verify that the build command fails when no build system is defined in the pyproject.toml file.
tests/console/commands/test_build.py
Added new fixtures for testing the build command.
  • Added a pyproject.toml file without a build backend.
  • Added a pyproject.toml file without a build system.
  • Added a README.md file for the no_build_backend fixture.
  • Added a README.md file for the no_build_system fixture.
tests/fixtures/build_systems/no_build_backend/pyproject.toml
tests/fixtures/build_systems/no_build_system/pyproject.toml
tests/fixtures/build_systems/no_build_backend/README.md
tests/fixtures/build_systems/no_build_system/README.md

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time. You can also use
    this command to specify where the summary should be inserted.

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@finswimmer finswimmer force-pushed the no-build-system-defined branch from c1ce753 to 5634612 Compare January 22, 2025 05:59
Copy link

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

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

Hey @finswimmer - I've reviewed your changes - here's some feedback:

Overall Comments:

  • Please update the documentation to explain this new validation check and behavior change, since this changes how Poetry handles projects without a build-system defined.
Here's what I looked at during the review
  • 🟢 General issues: all looks good
  • 🟢 Security: all looks good
  • 🟢 Testing: all looks good
  • 🟢 Complexity: all looks good
  • 🟢 Documentation: all looks good

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@finswimmer finswimmer requested a review from a team January 22, 2025 06:05
@finswimmer finswimmer force-pushed the no-build-system-defined branch from 5634612 to 626abfc Compare January 22, 2025 06:19
@finswimmer finswimmer changed the title feat(cli): ensure build-system is defined when running poetry build feat(cli): ensure build backend is defined when running poetry build Jan 22, 2025
@finswimmer
Copy link
Member Author

@sourcery-ai review

Copy link

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

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

Hey @finswimmer - I've reviewed your changes - here's some feedback:

Overall Comments:

  • Please update the documentation to describe this new validation check for build backend configuration. This is a user-facing change that should be documented.
Here's what I looked at during the review
  • 🟡 General issues: 1 issue found
  • 🟢 Security: all looks good
  • 🟢 Testing: all looks good
  • 🟢 Complexity: all looks good
  • 🟢 Documentation: all looks good

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

def build(self, options: BuildOptions) -> int:
if not self.poetry.is_package_mode:
self.io.write_error_line(
"Building a package is not possible in non-package mode."
)
return 1

if not self._has_build_backend_defined():
Copy link

Choose a reason for hiding this comment

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

suggestion: Consider making the error message more specific about whether the build-system section is missing or just the build-backend key

This would help users identify and fix configuration issues more quickly.

Suggested implementation:

    def _get_build_system_status(self) -> tuple[bool, bool]:
        pyproject_data = self.poetry.file.read()
        has_build_system = "build-system" in pyproject_data
        has_build_backend = "build-backend" in pyproject_data.get("build-system", {})
        return has_build_system, has_build_backend
        has_build_system, has_build_backend = self._get_build_system_status()
        if not has_build_system:
            self.io.write_error_line(
                "Missing [build-system] section in pyproject.toml. Please add this section with a build-backend."
            )
            return 1
        if not has_build_backend:
            self.io.write_error_line(
                "Missing build-backend key in [build-system] section. Please define one in pyproject.toml."
            )

@@ -114,13 +114,22 @@ def _get_builder(self) -> Callable[..., None]:

return self._build

def _has_build_backend_defined(self) -> bool:
return "build-backend" in self.poetry.file.read().get("build-system", {})
Copy link
Member

Choose a reason for hiding this comment

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

Would be good to move this to be something like self.poetry.pytpoject.build_system.is_fallback.

But that will need an additional property in https://github.com/python-poetry/poetry-core/blob/d97577e664d59173482a78f70e8f743cc5468851/src/poetry/core/pyproject/tables.py#L12

But for now something like this should work.

Suggested change
return "build-backend" in self.poetry.file.read().get("build-system", {})
return "build-backend" in self.poetry.pyproject.data.get("build-system", {})

Copy link
Member Author

Choose a reason for hiding this comment

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

Ah, I wasn't aware of the data attribute of pyproject 👍

I thought about a flag as well. But I don't wanted to change poetry-core before. And we would pollute again poetry-core with something we only need in poetry. Actually we only need it for poetry build.

def build(self, options: BuildOptions) -> int:
if not self.poetry.is_package_mode:
self.io.write_error_line(
"Building a package is not possible in non-package mode."
)
return 1

if not self._has_build_backend_defined():
Copy link
Member

Choose a reason for hiding this comment

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

Won't this also be a surprise to users as this breaks previous behavior in the same way setuptools are being used? Not sure how many people leave out the section intentionally.

That said, I'd also say that the current use of setuptools is in accordance with PEP518.

Tools should not require the existence of the [build-system] table. A pyproject.toml file may be used to store configuration details other than build-related data and thus lack a [build-system] table legitimately. If the file exists but is lacking the [build-system] table then the default values as specified above should be used. If the table is specified but is missing required fields then the tool should consider it an error.

Copy link
Member Author

Choose a reason for hiding this comment

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

Won't this also be a surprise to users as this breaks previous behavior in the same way setuptools are being used?

It will surprise people for sure. But now they get an error message. Without it poetry build would build a package, but it won't contain the data people expect. So "fail fast" is a better surprise ;)

Copy link
Member

@abn abn Jan 22, 2025

Choose a reason for hiding this comment

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

The problem is, how do you determine if they intended to use setuptools by relying on PEP518 default?

It is not unreasonable to imagine that Poetry is used for dev but the package needs setuptools for build.

Copy link
Member

Choose a reason for hiding this comment

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

But this is an edge enough case that it might be okay to enforce a build-system definition.

@finswimmer finswimmer force-pushed the no-build-system-defined branch from 626abfc to 46f3513 Compare January 22, 2025 11:53
@dimbleby
Copy link
Contributor

dimbleby commented Jan 22, 2025

we assume setuptools as the build backend This is fine according to PEP 517.

it's not only "fine" - it's what PEP517 says tools should do.

Now it would fallback to setuptools which would results in a broken package.

only results in a broken package if the pyproject.toml is not understood by setuptools, presumably? In the new PEP621 world that is not going to be a problem.

Perhaps a warning would make sense, but I suggest that erroring out where the specs say tools should not error out is overshooting.

@finswimmer
Copy link
Member Author

finswimmer commented Jan 22, 2025

In the new PEP621 world that is not going to be a problem.

In the PEP 621 world, yes. But if the project doesn't (fully) use the project section it is a problem.

As an alternative we could trigger a non-isolated build if no build-backend is given and (optional) show a warning that it would be good idea to add one to the pyproject.toml. Than poetry would behave just like before #10059.

@abn
Copy link
Member

abn commented Jan 22, 2025

Allowing the build to continue into isolated with a warning is safe enough, I reckon.

Let's not add more logic unless we need it.

That said I can already see the issues titled "why is poetry using setuptools" etc.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants