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

Model groups as a property of requirements #9545

Merged
merged 1 commit into from
Dec 4, 2024
Merged

Conversation

charliermarsh
Copy link
Member

Summary

Today, our dependency group implementation is a little awkward... For each package P, we check if P contains dependencies for each enabled group, then add a dependency on P with the group enabled. There are a few issues here:

  1. It's sort of backwards... We add a dependency from the base package P to P with the group enabled. Then P with the group enabled adds a dependency on the base package.
  2. We can't, e.g., enable different groups for different packages. (We don't have a way for users to specify this on the CLI, but there's no reason that it should be impossible in the resolver.)
  3. It's inconsistent with how extras work, which leads to confusing differences in the resolver.

Instead, our internal requirement type can now include dependency groups, which makes dependency groups look much, much more like extras in the resolver.

@charliermarsh charliermarsh added the internal A refactor or improvement that is not user-facing label Dec 1, 2024
@charliermarsh charliermarsh force-pushed the charlie/transitive branch 2 times, most recently from 215cce4 to 7413668 Compare December 1, 2024 01:41
@charliermarsh charliermarsh force-pushed the charlie/group branch 2 times, most recently from 42353b6 to 0f2d004 Compare December 1, 2024 02:26
And because foo depends on anyio==4.1.0, we can conclude that bar and foo are incompatible.
And because your workspace requires bar and foo, we can conclude that your workspace's requirements are unsatisfiable.
╰─▶ Because bar:dev depends on anyio==4.2.0 and foo depends on anyio==4.1.0, we can conclude that foo and bar:dev are incompatible.
And because your workspace requires bar:dev and foo, we can conclude that your workspace's requirements are unsatisfiable.
Copy link
Member Author

Choose a reason for hiding this comment

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

\cc @zanieb -- I think you pointed out this general problem long ago.

Copy link
Member

Choose a reason for hiding this comment

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

Nice :D

Base automatically changed from charlie/transitive to main December 1, 2024 13:42
} else {
Either::Right(requirement.extras.clone().into_iter().map(Some))
Either::Right(iter::once((None, None)))
Copy link
Member

Choose a reason for hiding this comment

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

As with #9582, I suspect you'll want to do the same thing for groups as I did for extras: conditionally add the base package dependency if the group is declared as conflicting.

Copy link
Member Author

Choose a reason for hiding this comment

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

Done.

.extras
.clone()
.into_iter()
.map(|extra| (Some(extra), None)),
Copy link
Member

Choose a reason for hiding this comment

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

If requirement.groups isn't empty at this point, does this mean that all of those groups get skipped?

Copy link
Member Author

Choose a reason for hiding this comment

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

The assumption is that they’re mutually exclusive

Copy link
Member

Choose a reason for hiding this comment

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

Interesting. Hard to tell from the type definition. But encoding that invariant in the types is probably annoying.

Copy link
Member Author

Choose a reason for hiding this comment

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

I could do it? It's a bit tedious because these also get serialized so we'd want to maintain backwards compatibility, but I could do it. Somewhat prefer to just document it clearly though.

Copy link
Member

Choose a reason for hiding this comment

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

Documenting it seems fine, yeah.

I am pretty much always torn about how much to encode in the types. I do like it, because I find it makes refactoring without fear a lot easier. It prevents you from getting the case analysis wrong. But as you rightly point out, it's a pain. And if the invariants change, it can make refactoring a pain (albeit higher confidence) too.

It's a constant balancing act.

Copy link
Member Author

Choose a reason for hiding this comment

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

Added.

@charliermarsh charliermarsh force-pushed the charlie/group branch 2 times, most recently from 7904a3d to 4848055 Compare December 3, 2024 23:29
@charliermarsh charliermarsh enabled auto-merge (squash) December 4, 2024 00:46
@charliermarsh charliermarsh merged commit 1ecdc1a into main Dec 4, 2024
64 checks passed
@charliermarsh charliermarsh deleted the charlie/group branch December 4, 2024 00:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
internal A refactor or improvement that is not user-facing
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants