Skip to content

fix: defer LazyChoices getter call until --help is used (Python 3.14 compat)#1720

Open
juliosuas wants to merge 1 commit intohttpie:masterfrom
juliosuas:fix/lazy-choices-help-python314
Open

fix: defer LazyChoices getter call until --help is used (Python 3.14 compat)#1720
juliosuas wants to merge 1 commit intohttpie:masterfrom
juliosuas:fix/lazy-choices-help-python314

Conversation

@juliosuas
Copy link
Copy Markdown

Summary

Closes #1641.

Python 3.14 added a _check_help() call inside ArgumentParser.add_argument() that reads action.help during parser construction. Previously, only parse_args(['--help']) triggered help formatting.

LazyChoices was designed to call getter() lazily — only when --help is passed — but Python 3.14 caused getter() to be invoked eagerly during add_argument(), breaking test_lazy_choices_help.

Root Cause

LazyChoices.help was a property that called self.load() (which calls getter()) whenever the help string was requested. In Python 3.14, argparse accesses action.help inside add_argument() via _check_help() → _expand_help() → _get_help_string() → action.help.

Fix

Two small changes:

1. httpie/cli/utils.py — Separate resolution from the property:

  • Add _resolve_help() method that calls getter() and formats the help (deferred)
  • Make the help property return self._help as-is without triggering loading
  • Add _help_resolved flag to track state

2. httpie/cli/argparser.py — Override format_help() in BaseHTTPieArgumentParser:

  • Before rendering help, call action._resolve_help() on all LazyChoices actions
  • This ensures getter() is called exactly once and only when --help is actually used

Verification

All test_lazy_choices_help assertions pass on Python 3.14:

  • getter not called during add_argument()
  • getter / help_formatter not called after parse_args([])
  • help_formatter not called when passing a value without --help

…compat)

Python 3.14 added a _check_help() call inside ArgumentParser.add_argument()
that reads action.help during parser construction. Previously, only
parse_args(['--help']) triggered help formatting.

LazyChoices was designed to call getter() lazily (only when --help is
passed), but with Python 3.14 the help property was accessed and triggered
getter() eagerly during add_argument(), breaking test_lazy_choices_help.

Fix:
1. In LazyChoices: separate _resolve_help() from the help property.
   The property now returns self._help as-is (None until resolved),
   without calling load() / getter(). A _help_resolved flag tracks
   whether resolution has happened.

2. In BaseHTTPieArgumentParser: override format_help() to call
   action._resolve_help() on all LazyChoices actions just before
   rendering the help text. This ensures getter() is called exactly
   once and only when --help is actually used.

Fixes test_lazy_choices_help on Python 3.14.

Closes httpie#1641
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.

test_lazy_choices_help fails on Python 3.14

1 participant