Skip to content

Instantly share code, notes, and snippets.

@kissgyorgy
Last active November 13, 2021 00:02
Show Gist options
  • Save kissgyorgy/d080ad6d1aba50d89f76 to your computer and use it in GitHub Desktop.
Save kissgyorgy/d080ad6d1aba50d89f76 to your computer and use it in GitHub Desktop.
Python: decorator for converting parameters from possible yes/no values to bool
import inspect
import functools
from distutils.util import strtobool
def tobool(yesno):
"""Convert all kinds of possible "yes" values to True/False."""
return bool(strtobool(yesno))
def bool_param(*bool_args):
"""Convert given parameter possible yes/no values to True/False."""
def convert_params_to_bool(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
for bool_arg in bool_args:
try:
# first see if we got it as a keyword argument
ba = kwargs.pop(bool_arg)
kwargs[bool_arg] = tobool(ba)
except KeyError:
argspec = inspect.getargspec(func)
index = argspec.args.index(bool_arg)
# convert to mutable type, so we can modify it in place
args = list(args)
try:
# if did not get as a keyword arg, try to lookup if
# it has been given as positional argument
args[index] = tobool(args[index])
except IndexError:
# Not given as kwarg, neither arg, so we need default
# value corresponding to bool_arg variable
defaults = argspec.defaults or []
num_args = len(argspec.args) - len(defaults)
def_index = num_args - index
try:
kwargs[bool_arg] = tobool(defaults[def_index])
except IndexError:
# conform to python built in message when incorrect
# number of parameters have been given
message = ('{}() takes exactly {} arguments ({} given)'
.format(func.__name__, num_args, len(args)))
raise TypeError(message)
return func(*args, **kwargs)
return wrapper
return convert_params_to_bool
@bool_param('param1')
def test1(param1, param2='noconvert'):
print('PARAM1:', type(param1), param1)
print('PARAM2:', type(param2), param2)
@bool_param('param1')
def test2(param1='yes', param2='noconvert'):
print('PARAM1:', type(param1), param1)
print('PARAM2:', type(param2), param2)
@bool_param('param1', 'param2')
def test3(param1='no', param2='yes'):
print('PARAM1:', type(param1), param1)
print('PARAM2:', type(param2), param2)
>>> test1('yes')
PARAM1: <type 'bool'> True
PARAM2: <type 'unicode'> noconvert
>>> test2()
PARAM1: <type 'bool'> True
PARAM2: <type 'unicode'> noconvert
>>> test3()
PARAM1: <type 'bool'> False
PARAM2: <type 'bool'> True
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment