docs: def guard(trafaret=None, **kwargs):
      """
      Decorator for protecting function with trafarets
  
      >>> @guard(a=String, b=Int, c=String)
      ... def fn(a, b, c="default"):
      ...     '''docstring'''
      ...     return (a, b, c)
      ...
      >>> fn.__module__ = None
      >>> help(fn)
      Help on function fn:
      <BLANKLINE>
      fn(*args, **kwargs)
          guarded with <Dict(a=<String>, b=<Int>, c=<String>)>
      <BLANKLINE>
          docstring
      <BLANKLINE>
      >>> fn("foo", 1)
      ('foo', 1, 'default')
      >>> extract_error(fn, "foo", 1, 2)
      {'c': 'value is not a string'}
      >>> extract_error(fn, "foo")
      {'b': 'is required'}
      >>> g = guard(Dict())
      >>> c = Forward()
      >>> c << Dict(name=str, children=List[c])
      >>> g = guard(c)
      >>> g = guard(Int())
      Traceback (most recent call last):
      ...
      RuntimeError: trafaret should be instance of Dict or Forward
      """
      if (
          trafaret
          and not isinstance(trafaret, Dict)
          and not isinstance(trafaret, Forward)
      ):
          raise RuntimeError("trafaret should be instance of Dict or Forward")
      elif trafaret and kwargs:
          raise RuntimeError("choose one way of initialization,"
                             " trafaret or kwargs")
      if not trafaret:
          trafaret = Dict(**kwargs)
  
      def wrapper(fn):
          argspec = getargspec(fn)
  
          @functools.wraps(fn)
          def decor(*args, **kwargs):
              fnargs = argspec.args
              if fnargs and fnargs[0] in ['self', 'cls']:
                  obj = args[0]
                  fnargs = fnargs[1:]
                  checkargs = args[1:]
              else:
                  obj = None
                  checkargs = args
  
              try:
                  call_args = dict(
                      itertools.chain(zip(fnargs, checkargs), kwargs.items())
                  )
                  for name, default in zip(reversed(fnargs),
                                           reversed(argspec.defaults or ())):
                      if name not in call_args:
                          call_args[name] = default
                  converted = trafaret(call_args)
              except DataError as err:
                  raise GuardError(error=err.error)
              return fn(obj, **converted) if obj else fn(**converted)
          decor.__doc__ = "guarded with %r\n\n" % trafaret + (decor.__doc__ or "")
          return decor
      return wrapper