diff options
-rw-r--r-- | CHANGES.rst | 2 | ||||
-rw-r--r-- | src/click/core.py | 20 | ||||
-rw-r--r-- | tests/test_options.py | 19 |
3 files changed, 25 insertions, 16 deletions
diff --git a/CHANGES.rst b/CHANGES.rst index c6094b7..7c6e4a7 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -22,6 +22,8 @@ Unreleased adding underline. :pr:`2058` - An option with ``count=True`` will not show "[x>=0]" in help text. :issue:`2072` +- Default values are not cast to the parameter type twice during + processing. :issue:`2085` Version 8.0.1 diff --git a/src/click/core.py b/src/click/core.py index 52b3022..6cdba37 100644 --- a/src/click/core.py +++ b/src/click/core.py @@ -2192,6 +2192,9 @@ class Parameter: :param call: If the default is a callable, call it. Disable to return the callable instead. + .. versionchanged:: 8.0.2 + Type casting is no longer performed when getting a default. + .. versionchanged:: 8.0.1 Type casting can fail in resilient parsing mode. Invalid defaults will not prevent showing help text. @@ -2207,20 +2210,10 @@ class Parameter: if value is None: value = self.default - if callable(value): - if not call: - # Don't type cast the callable. - return value - + if call and callable(value): value = value() - try: - return self.type_cast_value(ctx, value) - except BadParameter: - if ctx.resilient_parsing: - return value - - raise + return value def add_to_parser(self, parser: OptionParser, ctx: Context) -> None: raise NotImplementedError() @@ -2305,8 +2298,7 @@ class Parameter: return False def process_value(self, ctx: Context, value: t.Any) -> t.Any: - if value is not None: - value = self.type_cast_value(ctx, value) + value = self.type_cast_value(ctx, value) if self.required and self.value_is_missing(value): raise MissingParameter(ctx=ctx, param=self) diff --git a/tests/test_options.py b/tests/test_options.py index 180468b..06a70b4 100644 --- a/tests/test_options.py +++ b/tests/test_options.py @@ -252,7 +252,7 @@ def test_multiple_default_composite_type(): assert isinstance(opt.type, click.Tuple) assert opt.type.types == [click.INT, click.STRING] ctx = click.Context(click.Command("test")) - assert opt.get_default(ctx) == ((1, "a"),) + assert opt.type_cast_value(ctx, opt.get_default(ctx)) == ((1, "a"),) def test_parse_multiple_default_composite_type(runner): @@ -323,12 +323,27 @@ def test_intrange_default_help_text(type, expect): def test_count_default_type_help(): """A count option with the default type should not show >=0 in help.""" - option = click.Option(["--couunt"], count=True, help="some words") + option = click.Option(["--count"], count=True, help="some words") context = click.Context(click.Command("test")) result = option.get_help_record(context)[1] assert result == "some words" +def test_file_type_help_default(): + """The default for a File type is a filename string. The string + should be displayed in help, not an open file object. + + Type casting is only applied to defaults in processing, not when + getting the default value. + """ + option = click.Option( + ["--in"], type=click.File(), default=__file__, show_default=True + ) + context = click.Context(click.Command("test")) + result = option.get_help_record(context)[1] + assert __file__ in result + + def test_toupper_envvar_prefix(runner): @click.command() @click.option("--arg") |