docs: def attrs(
      maybe_cls=None, type=None, context=None, translate=None, **attrs_kwargs
  ):
      """Wrap an attr enabled class."""
      if isinstance(type, (list, tuple, set)):
          types = list(type)
      else:
          types = [type] if type is not None else []
      context = context or {}
      translate = translate or {}
  
      def wrap(cls):
          """Decorate an attr enabled class."""
          jsonld_cls = attr.s(cls, **attrs_kwargs)
  
          if not issubclass(jsonld_cls, JSONLDMixin):
              jsonld_cls = attr.s(
                  make_type(cls.__name__, (jsonld_cls, JSONLDMixin), {}),
                  **attrs_kwargs
              )
  
          # Merge types
          for subcls in jsonld_cls.mro():
              subtype = getattr(subcls, '_jsonld_type', None)
              if subtype:
                  if isinstance(subtype, (tuple, list)):
                      types.extend(subtype)
                  else:
                      types.append(subtype)
  
              for key, value in getattr(subcls, '_jsonld_context', {}).items():
                  if key in context and context[key] != value:
                      raise TypeError()
                  context.setdefault(key, value)
  
          for a in attr.fields(jsonld_cls):
              key = a.name
              ctx = a.metadata.get(KEY)
              if ctx is None:
                  continue
  
              if ':' in ctx:
                  prefix, _ = ctx.split(':', 1)
                  if prefix in context:
                      context[key] = ctx
                      continue
  
              if isinstance(ctx, dict) or ctx not in context:
                  context[key] = ctx
  
              if KEY_CLS in a.metadata:
                  merge_ctx = a.metadata[KEY_CLS]._jsonld_context
                  for ctx_key, ctx_value in merge_ctx.items():
                      context.setdefault(ctx_key, ctx_value)
                      if context[ctx_key] != ctx_value:
                          raise TypeError(
                              'Can not merge {0} and {1} because of {2}'.format(
                                  jsonld_cls, a.metadata[KEY_CLS], ctx_key
                              )
                          )
  
          jsonld_cls.__module__ = cls.__module__
          jsonld_cls._jsonld_type = types[0] if len(types) == 1 else list(
              sorted(set(types))
          )
          jsonld_cls._jsonld_context = context
          jsonld_cls._jsonld_translate = translate
          jsonld_cls._jsonld_fields = {
              a.name
              for a in attr.fields(jsonld_cls) if KEY in a.metadata
          }
  
          context_doc = '\n'.join(
              '   ' + line for line in json.dumps(context, indent=2).split('\n')
          )
          jsonld_cls.__doc__ = DOC_TPL.format(
              cls=cls,
              type=json.dumps(jsonld_cls._jsonld_type),
              context=context_doc,
          )
  
          # Register class for given JSON-LD @type
          try:
              type_ = ld.expand({
                  '@type': jsonld_cls._jsonld_type,
                  '@context': context
              })[0]['@type']
              if isinstance(type_, list):
                  type_ = tuple(sorted(type_))
          except Exception:
              # FIXME make sure all classes have @id defined
              return jsonld_cls
  
          if type_ in jsonld_cls.__type_registry__:
              raise TypeError(
                  'Type {0!r} is already registered for class {1!r}.'.format(
                      jsonld_cls._jsonld_type,
                      jsonld_cls.__type_registry__[jsonld_cls._jsonld_type],
                  )
              )
          jsonld_cls.__type_registry__[type_] = jsonld_cls
          return jsonld_cls
  
      if maybe_cls is None:
          return wrap
      return wrap(maybe_cls)