Skip to content

Conversation

@sirosen
Copy link
Contributor

@sirosen sirosen commented Sep 22, 2025

When options are being parsed, multiple options may evaluate to have defaults of UNSET, and some may evaluate to have explicitly set defaults of None. The normalization of UNSET -> None is now deferred until all options have been parsed, so that it is possible to accurately evaluate and save the first non-UNSET default value.

A new test exercises this functionality by pointing two flags at the same parameter declaration, and showing that their behavior is not order sensitive when only one of the flags has a default.

resolves #3071


The PR template says to add a note in CHANGES.rst for the change, but there's no header for the next release, so I wasn't sure where to put a change note. If a maintainer gives me a pointer in terms of what to do, I'm happy to amend with a change note. 🙂

@kdeldycke
Copy link
Collaborator

Your unit tests clearly demonstrate the issue and your changes don't trigger any other tests covering the default behavior. So for me this is enough to prove that your PR is really fixing the issue.

I'm pretty sure there is a more elegant way to solve it but for inclusion in a 8.3.1 hotfix release, this is good to me. We'll have plenty of time to refactor the code later. At this stage, I consider Click is still in the accumulation phase of external use-cases. So more unit tests the better! :)

@kdeldycke kdeldycke added this to the 8.3.1 milestone Sep 23, 2025
@kdeldycke kdeldycke changed the title Fix default handling to defer UNSET normalization Fix default handling to defer UNSET normalization Sep 23, 2025
@sirosen
Copy link
Contributor Author

sirosen commented Sep 23, 2025

I'm pretty sure there is a more elegant way to solve it

I agree, but the way I see it that's a change for 8.4 or 9.0 .

There are too many different places which are independently responsible for choosing between UNSET and None. I think the right solve is to separate the data which is stored (where you might have UNSET) from the data which is viewed.

For example, changes like this:

class Option(Parameter):
    _default: t.Any | UNSET

    @property
    def default(self):
        if self._default is UNSET:
            return None
        return self._default

But I don't know how that looks across all usage sites.

@Rowlando13
Copy link
Collaborator

@sirosen I added the new section for you. In the future, you can just add a new section. If it is not there, it just means the maintainer who released forgot to add it after releasing.

@kdeldycke
Copy link
Collaborator

There are too many different places which are independently responsible for choosing between UNSET and None. I think the right solve is to separate the data which is stored (where you might have UNSET) from the data which is viewed.

100% this. I could not find an way to do this cleanly in #3030 so I had to draw the line. Addressing this is indeed a refactor.

In the mean time, your fix is in line with the policy we adopted:

So once you tweaked the code comments in the review I left you, this PR is to me good to be merged in a 8.3.1 hotfix release.

sirosen and others added 3 commits September 24, 2025 09:17
When options are being parsed, multiple options may evaluate to have
defaults of `UNSET`, and some may evaluate to have explicitly set
defaults of `None`. The normalization of `UNSET -> None` is now
deferred until all options have been parsed, so that it is possible
to accurately evaluate and save the first non-UNSET default value.

A new test exercises this functionality by pointing two flags at the
same parameter declaration, and showing that their behavior is not order
sensitive when only one of the flags has a default.

resolves pallets#3071
Per review feedback:

- Remove an extraneous comment
- Expand another, more significant comment

Co-authored-by: Kevin Deldycke <159718+kdeldycke@users.noreply.github.com>
@sirosen sirosen force-pushed the fix-unset-default-treatment branch from ec9a4e9 to 189068a Compare September 24, 2025 14:20
@sirosen
Copy link
Contributor Author

sirosen commented Sep 24, 2025

I rebased and added the missing changelog note. I think this is ready!

@Rowlando13 Rowlando13 merged commit 27aaed3 into pallets:stable Sep 24, 2025
10 checks passed
@sirosen sirosen deleted the fix-unset-default-treatment branch September 24, 2025 17:08
@kdeldycke
Copy link
Collaborator

Good call @Rowlando13 on merging this! :)

@kdeldycke kdeldycke linked an issue Sep 25, 2025 that may be closed by this pull request
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Oct 10, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

default=True on feature flags is order-sensitive

3 participants