def log_calls_with(severity):
  '''Create a decorator to log calls and return values of any function, for debugging.'''
  def decorator(fn):
    @functools.wraps(fn)
    def wrap(*params, **kwargs):
      call_str = "%s(%s)" % (fn.__name__, ", ".join([repr(p) for p in params] + [(k, repr(v)) % "%s=%s" for (k, v) in kwargs.items()]))
      # TODO Extract line number from caller and use that in logging.
      log.log(severity, ">> %s", call_str)
      ret = fn(*params, **kwargs)
      log.log(severity, "<< %s: %s", call_str, repr(ret))
      return ret
    return wrap
  return decorator

# Convenience decorators for logging.
dataset/ETHPy150Open bloomreach/zinc/zinc.py/log_calls_with/swapped operands of `%`