- Auto-detect type=UNPROCESSED for flag_value of non-basic types so programmer-provided Python objects are passed through unchanged instead of being stringified
- Add NoSuchCommand exception with suggestions for misspelled commands
- Add click.get_pager_file for file-like access to an output pager
- Add capture parameter to CliRunner with two modes: sys (default) and fd for redirecting file descriptors
- ParamType is now a generic abstract base class parameterized by its converted value type, with narrowed return types on convert methods for concrete types and specific TypedDict subclasses from to_info_dict
- CompositeParamType and number-range base classes are now generic with abstract methods
- Refactor convert_type to extract type inference into a private _guess_type helper with typing.overload signatures
- Parameter is now an abstract base class that cannot be instantiated directly, and Parameter.name is now str instead of str | None
- Parameter.get_error_hint ctx parameter is now typed as Context | None to match runtime behavior
- Split string values from default_map for parameters with nargs > 1 or Tuple type to match environment variable behavior
- Error hints now use Command.get_help_option_names to pick non-shadowed help option names, showing all surviving names instead of potentially invalid ones
- Use os.startfile on Windows to open URLs in open_url instead of the start built-in
- Use ValueError message when conversion in FuncParamType would fail
- TextWrapper and wrap_text now measure line width in visible characters, ignoring ANSI escape sequences
- Show custom error messages from types when prompt with hide_input=True fails validation instead of showing a generic message
- Revert the exposure of original file descriptor via fileno() on redirected CliRunner streams in default capture mode
- Fix readline functionality on non-Windows platforms by passing prompt text directly to readline for proper backspace and line editing behavior
- Fix Fish shell completion errors when option help text contains newlines
- Fix HelpFormatter.write_usage emitting only a blank line when called without args by writing the usage prefix and program name even when no arguments follow
This is the Click 8.4.0 feature release. A feature release may include new features, remove previously deprecated code, add new deprecation, or introduce potentially breaking changes.
We encourage everyone to upgrade. You can read more about our Version Support Policy on our website.
PyPI: https://pypi.org/project/click/8.4.0/ Changes: https://click.palletsprojects.com/page/changes/#version-8-4-0 Milestone https://github.com/pallets/click/milestone/30
-
ParamTypetyping improvements. #3371- :class:
ParamTypeis now a generic abstract base class, parameterized by its converted value type. - :meth:
~ParamType.convertreturn types are narrowed on all concrete types (strfor :class:STRING,intfor :class:INT, etc.). - :meth:
~ParamType.to_info_dictreturns specific :class:~typing.TypedDictsubclasses instead ofdict[str, Any]. - :class:
CompositeParamTypeand the number-range base are now generic with abstract methods.
- :class:
-
Refactor
convert_typeto extract type inference into a private_guess_typehelper, and add :func:typing.overloadsignatures. #3372 -
Parametertyping improvements. #2805- :class:
Parameteris now an abstract base class, making explicit that it cannot be instantiated directly. - :attr:
Parameter.nameis nowstrinstead ofstr | None. Whenexpose_value=False, the name is set to""instead ofNone. - The
ctxparameter of :meth:Parameter.get_error_hintis now typed asContext | None, matching the runtime behavior.
- :class:
-
Split string values from
default_mapfor parameters withnargs > 1or :class:Tupletype, matching environment variable behavior. #2745 #3364 -
Auto-detect
type=UNPROCESSEDforflag_valueof non-basic types (notstr,int,float, orbool), so programmer-provided Python objects like classes and enum members are passed through unchanged instead of being stringified. Previouslytype=click.UNPROCESSEDhad to be set explicitly. #2012 #3363 -
The error hint now uses
Command.get_help_option_namesto pick non-shadowed help option names, soTry '... -h'no longer points to a subcommand option that shadows-h. All surviving names are shown (-h/--help). #2790 #3208 -
Fix readline functionality on non-Windows platforms. Prompt text is now passed directly to readline instead of being printed separately, allowing proper backspace, line editing, and line wrapping behavior. #2968 #2969
-
Use :func:
os.startfileon Windows to open URLs in :func:open_url, replacing thestartbuilt-in which cannot be invoked withoutshell=True. #3164 #3186 -
Fix Fish shell completion errors when option help text contains newlines. #3043 #3126
-
Add :class:
NoSuchCommandexception with suggestions for misspelled commands. #3107 #3228 -
Use :class:
ValueErrormessage when conversion in :class:FuncParamTypewould fail. #3105 #3211 -
Add
click.get_pager_filefor file-like access to an output pager. #1572 #3405 -
:class:
~click.formatting.TextWrapperand :func:~click.formatting.wrap_textnow measure line width in visible characters, ignoring ANSI escape sequences. #3420 -
Fix :meth:
HelpFormatter.write_usageemitting only a blank line when called withoutargs. The usage prefix and program name are now written even when no arguments follow, and the trailing separator space is stripped so the line ends at the program name. #3360 #3434 -
Show custom error messages from types when :func:
promptwithhide_input=Truefails validation, instead of always showing a generic message. Built-in type messages mask the input value. #2809 #3256 -
Add
captureparameter to :class:CliRunnerwith two modes:sys(default) andfd.fdredirects file descriptors1and2via :func:os.dup2so output that bypassessys.stdout(stale stream references, C extensions, subprocesses,faulthandler) is captured with proper isolation. #854 #2412 #2468 #2497 #2761 #2827 #2865 -
Revert the
8.3.3change that exposed the original file descriptor viafileno()on the redirectedCliRunnerstreams in the default capture mode.os.dup2(w, sys.stdout.fileno())calls inside a CLI no longer mutate the host runner's stdout, which broke Pytest'sfd-level capture teardown. C-level consumers that need a realfdshould usecapture="fd". #3384 #3391 -
Mark additional built-in strings with
gettext()to extend translation coverage. #2902 -
Fix feature switch groups (several
flag_valueoptions sharing one parameter name) silently dropping an explicitdefaultwhen a sibling option without an explicit default was declared first. Arbitration is now source-aware: a more explicit :class:ParameterSourcealways wins, and withinParameterSource.DEFAULT, an option that received an explicitdefault=keyword wins over a sibling whose default was auto-derived. The 8.3.x first-wins fallback for remaining ties was reverted to the pre-8.3.x last-wins fallback. #3403 #3404 -
Fix missing space between option help text and the
(DEPRECATED)label, and localize the option label so it matches the command label. The label and theDeprecationWarningreason suffix are now produced by shared helpers. #3423 -
Document short option stacking (
-abcis parsed as-a -b -c) and clarify that multi-character short option names are not supported. #2779 #3431