docs: def ascwl(
      inst,
      recurse=True,
      filter=None,
      dict_factory=dict,
      retain_collection_types=False,
      basedir=None,
  ):
      """Return the ``attrs`` attribute values of *inst* as a dict.
  
      Support ``jsonldPredicate`` in a field metadata for generating
      mappings from lists.
  
      Adapted from ``attr._funcs``.
      """
      attrs = fields(inst.__class__)
      rv = dict_factory()
  
      def convert_value(v):
          """Convert special types."""
          if isinstance(v, Path):
              v = str(v)
              return os.path.relpath(v, str(basedir)) if basedir else v
          return v
  
      for a in attrs:
          if a.name.startswith('__'):
              continue
  
          a_name = a.name.rstrip('_')
          v = getattr(inst, a.name)
          if filter is not None and not filter(a, v):
              continue
          if recurse is True:
              if has(v.__class__):
                  rv[a_name] = ascwl(
                      v,
                      recurse=True,
                      filter=filter,
                      dict_factory=dict_factory,
                      basedir=basedir,
                  )
  
              elif isinstance(v, (tuple, list, set)):
                  cf = v.__class__ if retain_collection_types is True else list
                  rv[a_name] = cf([
                      ascwl(
                          i,
                          recurse=True,
                          filter=filter,
                          dict_factory=dict_factory,
                          basedir=basedir,
                      ) if has(i.__class__) else i for i in v
                  ])
  
                  if 'jsonldPredicate' in a.metadata:
                      k = a.metadata['jsonldPredicate'].get('mapSubject')
                      if k:
                          vv = dict_factory()
                          for i in rv[a_name]:
                              kk = i.pop(k)
                              vv[kk] = i
                          rv[a_name] = vv
  
              elif isinstance(v, dict):
                  df = dict_factory
                  rv[a_name] = df((
                      ascwl(
                          kk,
                          dict_factory=df,
                          basedir=basedir,
                      ) if has(kk.__class__) else convert_value(kk),
                      ascwl(
                          vv,
                          dict_factory=df,
                          basedir=basedir,
                      ) if has(vv.__class__) else vv
                  ) for kk, vv in iteritems(v))
              else:
                  rv[a_name] = convert_value(v)
          else:
              rv[a_name] = convert_value(v)
  
      if isinstance(inst, CWLClass):
          rv['class'] = inst.__class__.__name__
  
      return rv