Skip to content

Comments

Fix lookup_default returning UNSET sentinel instead of None#3202

Closed
veeceey wants to merge 2 commits intopallets:mainfrom
veeceey:fix/issue-3145
Closed

Fix lookup_default returning UNSET sentinel instead of None#3202
veeceey wants to merge 2 commits intopallets:mainfrom
veeceey:fix/issue-3145

Conversation

@veeceey
Copy link

@veeceey veeceey commented Feb 8, 2026

Summary

Fixes #3145.

Since Click 8.3.0, Context.lookup_default returns the internal Sentinel.UNSET object instead of None when a parameter has no entry in the default map. This is a regression from the pre-8.3.0 behavior, where None was returned. The leak of the internal sentinel breaks:

  • Subclasses of Context that override lookup_default and check if default is not None
  • Any external code that calls lookup_default directly and expects None for missing defaults

Changes

  • Extract _lookup_default (private): contains the original logic and returns UNSET for internal callers (Parameter.get_default and Parameter.consume_value) that need to distinguish "not set" from an explicit None value.
  • Wrap lookup_default (public): delegates to _lookup_default and converts UNSET to None before returning, restoring the documented Any | None return type contract.
  • Add regression test covering all cases: no default_map, missing key, present key, callable default, and a Context subclass matching the pattern from the issue report.

All 1320 existing tests continue to pass.

Test plan

  • New test test_lookup_default_returns_none_not_sentinel passes
  • Full test suite passes (1320 passed, 22 skipped, 1 xfailed)
  • Verify the reproducer script from the issue no longer triggers AssertionError

🤖 Generated with Claude Code

Varun Chawla and others added 2 commits February 8, 2026 15:01
Fixes pallets#3145. Since 8.3.0 Context.lookup_default leaked the internal
UNSET sentinel to callers instead of returning None when no default
was found. This broke subclasses and external code that relied on the
documented return type (Any | None).

Extract a private _lookup_default method that returns UNSET for
internal callers that need to distinguish "not set" from None, and
have the public lookup_default convert UNSET to None before returning.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

lookup_default returns Sentinel.UNSET instead of None

3 participants