code: def datasetmethod(f, name=None, dataset_argname="dataset"):
      """Decorator to bind functions to Dataset class.
  
      The decorated function is still directly callable and additionally serves
      as method `name` of class Dataset.  To achieve this, the first positional
      argument is redirected to original keyword argument 'dataset_argname'. All
      other arguments stay in order (and keep their names, of course). That
      means, that the signature of the bound function is name(self, a, b) if the
      original signature is name(a, dataset, b) for example.
  
      The decorator has no effect on the actual function decorated with it.
      """
  
      if not name:
          name = f.__name__
  
      @wraps(f)
      def apply_func(instance, *args, **kwargs):
          # Wrapper function to assign arguments of the bound function to
          # original function.
          #
          # Note
          # ----
          # This wrapper is NOT returned by the decorator, but only used to bind
          # the function `f` to the Dataset class.
          kwargs = kwargs.copy()
  
          # due to use of functools.wraps and inability of of getarspec to get
          # those, we use .signature.
          # More information in de-wrapt PR https://github.com/datalad/datalad/pull/6190
          from datalad.utils import get_sig_param_names
  
          f_args, f_kwonlyargs = get_sig_param_names(
              f, ("pos_any", "kw_only")
          )
  
          # If bound function is used with wrong signature (especially by
          # explicitly passing a dataset), let's raise a proper exception instead
          # of a 'list index out of range', that is not very telling to the user.
          # In case whenever kwonlyargs are used, 'dataset' would not be listed
          # among args, so we would account for it (possibly) be there.
          if len(args) >= len(f_args) + int(bool(f_kwonlyargs)):
              non_dataset_args = ["self"] + [
                  a for a in f_args if a != dataset_argname
              ]
              raise TypeError(
                  f"{name}() takes at most {len(f_args)} arguments ({len(args)} given): "
                  f"{non_dataset_args}"
              )
          if dataset_argname in kwargs:
              raise TypeError(
                  f"{name}() got an unexpected keyword argument {dataset_argname}"
              )
          kwargs[dataset_argname] = instance
          if dataset_argname in f_kwonlyargs:
              # * was used to enforce kwargs, so we just would pass things as is
              pass
          else:
              # so it is "old" style, where it is a regular kwargs - we pass everything
              # via kwargs
              # TODO: issue a DX oriented warning that we advise to separate out kwargs,
              # dataset included, with * from positional args?
              ds_index = f_args.index(dataset_argname)
              for i in range(0, len(args)):
                  if i < ds_index:
                      kwargs[f_args[i]] = args[i]
                  elif i >= ds_index:
                      kwargs[f_args[i + 1]] = args[i]
              args = []
          return f(*args, **kwargs)
  
      setattr(Dataset, name, apply_func)
      # set the ad-hoc attribute so that @build_doc could also bind built doc
      # to the dataset method
      if getattr(f, "_dataset_method", None):
          raise RuntimeError(
              f"_dataset_method of {f} is already set to {f._dataset_method}"
          )
      setattr(f, "_dataset_method", apply_func)
      return f
  
imports: import inspect
  import logging
  from functools import wraps
  from os.path import curdir, exists, join, normpath, pardir
  from weakref import WeakValueDictionary
  from datalad import cfg
  from datalad.config import ConfigManager
  from datalad.core.local.repo import repo_from_path
  from datalad.support.annexrepo import AnnexRepo
  from datalad.support.constraints import Constraint
  from datalad.support.due import due
  from datalad.support.due_utils import duecredit_dataset
  from datalad.support.exceptions import NoDatasetFound
  from datalad.dataset.repo import path_based_str_repr, PathBasedFlyweight
  from datalad.support.gitrepo import GitRepo
  from datalad.support import path
  import datalad.utils
  from datalad.utils import getpwd, optional_args, get_dataset_root, get_sig_param_names, get_dataset_root, Path, PurePath, ensure_list
label_desc: Use image node_id 1 for calling a global function with example usage: datasetmethod(f, name, dataset_argname) and returns: f, f