I’m changing some argparse code to no longer require a unit for a numeric value, since the unit is always the same ("m"). I’d like the code to emit a deprecation warning only when called with the "m" suffix on the parameter value. That is, ./foo.py --bar=1m should emit a deprecation warning saying the "m" suffix is deprecated, and ./foo.py --bar=1 should not emit such a warning. How can I do this?
I tried to set type=str_to_bar:
def str_to_bar(value: str) -> Decimal:
number_value = value.removesuffix("m")
if number_value != value:
structlog.get_logger().warning(
"Specifying bar with a trailing 'm' character will not be supported in future versions. "
"Please use a plain decimal number like '0.3' instead.",
DeprecationWarning,
)
return Decimal(number_value)
Unfortunately, argparse treats the DeprecationWarning as fatal, so that’s not an option.
>Solution :
Deprecation warnings should be emitted using warnings.warn, not loggers. This way, it is left up to the user whether they want to escalate the warning to an error, silence it, or capture it and redirect to the logging framework.
The confusing failure mode you’re seeing is because of an unintended interaction between structlog and argparse. The structlog warning call will raise a TypeError due to the DeprecationWarning argument, and argparse will attempt to handle that TypeError, thinking the exception indicates an invalid value was provided for the argument.
>>> structlog.get_logger().warning("foo", DeprecationWarning)
...
TypeError: not all arguments converted during string formatting