Fix LazyChoices for Python 3.14+ β avoid eager getter call during parser registration#1894
Open
driphtyio wants to merge 1 commit into
Open
Fix LazyChoices for Python 3.14+ β avoid eager getter call during parser registration#1894driphtyio wants to merge 1 commit into
driphtyio wants to merge 1 commit into
Conversation
Remove self.choices = self to prevent argparse from eagerly validating default values at registration time (Python 3.14 behavior change). Move choice validation into __call__ instead. Fixes httpie#1641
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
On Python 3.14+, argparse validates that
defaultis inchoicesat argument registration time (inadd_argument()). TheLazyChoicesclass was settingself.choices = self, which caused argparse to call__contains__βload()βgetter()during parser construction β triggering the getter prematurely.This broke the invariant in
test_lazy_choices_helpthat the getter must not be called during parser initialization.Fixes #1641.
Solution
Two simple changes:
Removed
self.choices = selfβ without it,action.choicesstaysNone(argparse default), so Python 3.14's registration-time check is skipped entirely.Moved validation into
__call__β when a user-provided value reaches the action handler, we callself.load()(which triggers the getter) and raiseArgumentErrorif the value isn't valid.The lazy-loading contract is preserved: the getter is only called when a value is actually parsed or help is displayed.
Testing
test_lazy_choicesβ passes (invalid choice still raisesSystemExit)test_lazy_choices_helpβ passes (getter not called during init)test_parser_serializationβ passes