code: def duecredit_dataset(dataset):
      """Duecredit cite a dataset if Duecredit is active
  
      ATM it is an ad-hoc implementation which largely just supports
      extraction of citation information from BIDS extractor
      (datalad-neuroimaging extension) only ATM.
      Generic implementation would require minor harmonization and/or
      support of extraction of relevant information by each extractor.
      """
  
      try:
          # probably with metalad RFing we would gain better control
          # over reporting of warnings etc, ATM the warnings are produced
          # directly within get_ds_aggregate_db_locations down below and
          # we have no other way but pacify all of them.
          with swallow_logs(logging.ERROR) as cml:
              res = dataset.metadata(
                  reporton="datasets",  # Interested only in the dataset record
                  result_renderer="disabled",  # No need
                  return_type="item-or-list",  # Expecting a single record
              )
      except Exception as exc:
          lgr.debug(
              "Failed to obtain metadata for %s. Will not provide duecredit entry: %s",
              dataset,
              CapturedException(exc),
          )
          return
  
      if not isinstance(res, dict):
          lgr.debug(
              "Got record which is not a dict, no duecredit for now"
          )
          return
  
      metadata = res.get("metadata", {})
  
      # Descend following the dots -- isn't there a helper already - TODO?
      def get_field(struct, field):
          if isinstance(field, (tuple, list)):
              first = lambda values: (el for el in values if el)
              return next(
                  first(get_field(struct, f) for f in field), None
              )
          if not field:
              return None
          # I think it is better to be case insensitive
          field = field.lower()
          value = struct
          for subfield in field.split("."):
              # lower case all the keys
              value = {k.lower(): v for k, v in value.items()}
              value = value.get(subfield, None)
              if not value:
                  return None
          return value
  
      for (
          cite_field,
          desc_field,
          version_field,
          cite_type,
      ) in CITATION_CANDIDATES:
          cite_rec = get_field(metadata, cite_field)
          if cite_field is not None:
              if not cite_rec:
                  continue
              # we found it! ;)
          else:
              # Catch all
              cite_rec = "DataLad dataset at %s" % dataset.path
  
          desc = get_field(metadata, desc_field) if desc_field else None
          desc = desc or "DataLad dataset %s" % dataset.id
  
          # DueCredit's path defines grouping of entries, so with
          # "datalad." we bring them all under datalad's roof!
          # And as for unique suffix, there is no better one but the ID,
          # but that one is too long so let's take the first part of UUID
          path = "datalad:%s" % (dataset.id.split("-", 1)[0])
  
          version = (
              get_field(metadata, version_field)
              if version_field
              else None
          )
          version = version or dataset.repo.describe()
  
          due.cite(
              (cite_type or Text)(cite_rec),
              path=path,
              version=version,
              description=desc,
          )
          return
  
imports: from .due import due, Doi, Text
  from ..utils import never_fail, swallow_logs
  from datalad.support.exceptions import CapturedException
  import logging
label_desc: Use image node_id 1 for calling a global function with example usage: duecredit_dataset(dataset) and returns: value, next, None, None