code: def decorator(d):
      
      defaults = d.__defaults__
      if defaults and defaults[0] is None:
          # Can be applied as @decorator or @decorator(kwargs) because
          # first argument is None
          def decorate(fn=None, **kwargs):
              if fn is None:
                  return _functools.partial(decorate, **kwargs)
              else:
                  decorated = d(fn, **kwargs)
                  _functools.update_wrapper(decorated, fn)
                  return decorated
      else:
          # Can only be applied as @decorator
          def decorate(fn):
              decorated = d(fn)
              _functools.update_wrapper(decorated, fn)
              return decorated
      _functools.update_wrapper(decorate, d)
      return decorate
docs: Creates a proper decorator.
  
      If the default for the first (function) argument is None, creates a
      version which be invoked as either @decorator or @decorator(kwargs...).
  
      See examples below.