Types/type functions that do not support being re-initialized with themselves (e.g. pytz.timezone) break with default values in click 8.x.
In click 7.x, it was required to specify the default value for these types as a string, but if you did so, things would work okay. In click 8.x, this is no longer the case.
For example, this code works in click 7.x:
import click
import pytz
@click.command()
@click.option("--timezone", type=pytz.timezone, default="UTC")
def main(timezone: pytz.timezone) -> None:
print(timezone)
if __name__ == '__main__':
main()
but in 8.x, produces the following exception:
Traceback (most recent call last):
File "/Users/ben/Downloads/tz_click_test.py", line 12, in <module>
main()
File "/private/tmp/tz_venv/lib/python3.7/site-packages/click/core.py", line 1137, in __call__
return self.main(*args, **kwargs)
File "/private/tmp/tz_venv/lib/python3.7/site-packages/click/core.py", line 1061, in main
with self.make_context(prog_name, args, **extra) as ctx:
File "/private/tmp/tz_venv/lib/python3.7/site-packages/click/core.py", line 923, in make_context
self.parse_args(ctx, args)
File "/private/tmp/tz_venv/lib/python3.7/site-packages/click/core.py", line 1379, in parse_args
value, args = param.handle_parse_result(ctx, opts, args)
File "/private/tmp/tz_venv/lib/python3.7/site-packages/click/core.py", line 2364, in handle_parse_result
value = self.process_value(ctx, value)
File "/private/tmp/tz_venv/lib/python3.7/site-packages/click/core.py", line 2320, in process_value
value = self.type_cast_value(ctx, value)
File "/private/tmp/tz_venv/lib/python3.7/site-packages/click/core.py", line 2307, in type_cast_value
return convert(value)
File "/private/tmp/tz_venv/lib/python3.7/site-packages/click/types.py", line 75, in __call__
return self.convert(value, param, ctx)
File "/private/tmp/tz_venv/lib/python3.7/site-packages/click/types.py", line 170, in convert
return self.func(value)
File "/usr/local/lib/python3.7/site-packages/pytz/__init__.py", line 159, in timezone
if zone.upper() == 'UTC':
AttributeError: 'UTC' object has no attribute 'upper'
This appears to be because click 8.x now does type conversion twice for "default" values:
I'd be happy to help with a fix for this, but would like feedback on the preferred approach. A few that come to mind:
- update
Parameter.type_cast_value(...) to pass values through un-modified if they appear to be of the correct type
- similar, but for
FuncParamType.convert(...)
- skip the conversion at processing-time if the value source is
DEFAULT
It seems to me that the advantage of methods 1 and 2 would be that one could specify default values as the actual type (for more rigorous verification with static type checking tools), rather than needing to specify a string, but method 3 would (approximately!) restore parity with the click 7.x behavior.
Types/type functions that do not support being re-initialized with themselves (e.g.
pytz.timezone) break with default values inclick8.x.In
click7.x, it was required to specify the default value for these types as a string, but if you did so, things would work okay. In click 8.x, this is no longer the case.For example, this code works in
click7.x:but in 8.x, produces the following exception:
This appears to be because
click8.x now does type conversion twice for "default" values:I'd be happy to help with a fix for this, but would like feedback on the preferred approach. A few that come to mind:
Parameter.type_cast_value(...)to pass values through un-modified if they appear to be of the correct typeFuncParamType.convert(...)DEFAULTIt seems to me that the advantage of methods 1 and 2 would be that one could specify default values as the actual type (for more rigorous verification with static type checking tools), rather than needing to specify a string, but method 3 would (approximately!) restore parity with the click 7.x behavior.