code: def _get_procedure_implementation(name="*", ds=None):
      """get potential procedures: path, name, configuration, and a help message
  
      The order of consideration is user-level, system-level, extra locations, dataset,
      datalad extensions, datalad. Therefore local definitions/configurations take
      precedence over ones, that come from outside (via a datalad-extension or a
      dataset with its .datalad/config). If a dataset had precedence (as it was
      before), the addition (or just an update) of a (sub-)dataset would otherwise
      surprisingly cause you to execute code different from what you defined
      within ~/.gitconfig or your local repository's .git/config.
      So, local definitions take precedence over remote ones and more specific
      ones over more general ones.
  
      Yields
      ------
      tuple
        path, name, format string, help message
      """
  
      ds = (
          ds if isinstance(ds, Dataset) else Dataset(ds) if ds else None
      )
  
      # 1. check system and user account for procedure
      for loc in (
          cfg.obtain("datalad.locations.user-procedures"),
          cfg.obtain("datalad.locations.system-procedures"),
          cfg.get("datalad.locations.extra-procedures", get_all=True),
      ):
          for dir in ensure_list(loc):
              for m, n in _get_file_match(dir, name):
                  yield (
                      m,
                      n,
                  ) + _get_proc_config(n)
      # 2. check dataset for procedure
      if ds is not None and ds.is_installed():
          # could be more than one
          dirs = ensure_list(
              ds.config.obtain("datalad.locations.dataset-procedures")
          )
          for dir in dirs:
              # TODO `get` dirs if necessary
              for m, n in _get_file_match(op.join(ds.path, dir), name):
                  yield (
                      m,
                      n,
                  ) + _get_proc_config(n, ds=ds)
          # 2.1. check subdatasets recursively
          for subds in ds.subdatasets(
              return_type="generator",
              result_xfm="datasets",
              result_renderer="disabled",
          ):
              for m, n, f, h in _get_procedure_implementation(
                  name=name, ds=subds
              ):
                  yield m, n, f, h
  
      # 3. check extensions for procedure
      from datalad.support.entrypoints import iter_entrypoints
  
      for epname, epmodule, _ in iter_entrypoints("datalad.extensions"):
          res = files(epmodule) / "resources" / "procedures"
          if res.is_dir():
              with as_file(res) as p:
                  for m, n in _get_file_match(p, name):
                      yield (
                          m,
                          n,
                      ) + _get_proc_config(n)
      # 4. at last check datalad itself for procedure
      with as_file(files("datalad") / "resources" / "procedures") as p:
          for m, n in _get_file_match(p, name):
              yield (
                  m,
                  n,
              ) + _get_proc_config(n)
  
imports: import logging
  import os
  import os.path
  import stat
  import sys
  from argparse import REMAINDER
  from glob import iglob
  import datalad.support.ansi_colors
  from datalad import cfg
  from datalad.core.local.run import Run
  from datalad.distribution.dataset import Dataset, EnsureDataset, datasetmethod, require_dataset
  from datalad.interface.base import Interface, build_doc, eval_results
  from datalad.interface.results import get_status_dict
  from datalad.support.constraints import EnsureNone
  from datalad.support.exceptions import InsufficientArgumentsError, NoDatasetFound
  from datalad.support.param import Parameter
  from datalad.utils import ensure_list, guard_for_format, join_cmdline, quote_cmdlinearg, split_cmdline
label_desc: Use image node_id 3 for calling a global function with example usage: _get_procedure_implementation(name, ds) without return types