code: def _drop_dataset(
      ds, paths, what, reckless, recursive, recursion_limit, jobs
  ):
      lgr.debug("Start dropping for %s", ds)
      # we know that any given path is part of `ds` and not any of its
      # subdatasets!
  
      # by-passing this completely with reckless=kill
      if recursive and not reckless == "kill":
          # process subdatasets first with recursion
          for sub in ds.subdatasets(
              # must be resolved!
              path=paths or None,
              # nothing to drop with unavailable subdatasets
              state="present",
              # we can use the full recursion depth, only the first layer
              # of calls to _drop_dataset() must/can have recursive=True
              recursive=recursive,
              recursion_limit=recursion_limit,
              # start reporting with the leaves
              bottomup=True,
              result_xfm="datasets",
              on_failure="ignore",
              return_type="generator",
              result_renderer="disabled",
          ):
              yield from _drop_dataset(
                  ds=sub,
                  # everything, the entire subdataset is matching a given path
                  paths=None,
                  what=what,
                  reckless=reckless,
                  recursive=False,
                  recursion_limit=None,
                  jobs=jobs,
              )
  
      if not ds.pathobj.exists():
          # basic protection against something having wiped it out already.
          # should not happen, but better than a crash, if it does
          yield dict(
              action="drop",
              path=ds.path,
              status="notneeded",
              message="does not exist",
              type="dataset",
          )
          return
  
      if paths is not None and paths != [ds.pathobj] and what == "all":
          if recursive and reckless == "kill":
              # check if any paths contains a subdataset, and if so, drop it to
              # ensure its not left behind
              for sub in ds.subdatasets(
                  # just check for subds at the provided path
                  path=paths,
                  state="present",
                  recursive=recursive,
                  recursion_limit=recursion_limit,
                  result_xfm="datasets",
                  on_failure="ignore",
                  return_type="generator",
                  result_renderer="disabled",
              ):
                  if sub is not None:
                      # there is a subdataset underneath the given path
                      yield from _drop_dataset(
                          ds=sub,
                          # everything underneath the subds can go
                          paths=None,
                          what=what,
                          reckless=reckless,
                          recursive=False,
                          recursion_limit=None,
                          jobs=jobs,
                      )
          # so we have paths constraints that prevent dropping the full dataset
          lgr.debug(
              "Only dropping file content for given paths in %s, "
              "allthough instruction was to drop %s",
              ds,
              what,
          )
          what = "filecontent"
  
      repo = ds.repo
      is_annex = isinstance(repo, AnnexRepo)
  
      # first critical checks that might prevent further operation
      had_fatality = False
      for res in _fatal_pre_drop_checks(
          ds, repo, paths, what, reckless, is_annex
      ):
          had_fatality = True
          yield res
      if had_fatality:
          return
  
      # next check must come AFTER the modification checks above, otherwise
      # remove() could not rely on the modification detection above
      if (
          paths is not None
          and paths != [ds.pathobj]
          and what == "datasets"
      ):
          # so we have paths constraints that prevent dropping the full dataset
          # there is nothing to do here, but to drop keys, which we must not
          # done
          return
  
      # now conditional/informative checks
      yield from _pre_drop_checks(
          ds, repo, paths, what, reckless, is_annex
      )
  
      if is_annex and what == "filecontent":
          yield from _drop_files(
              ds,
              repo,
              # give paths or '.' with no constraint
              paths=[str(p.relative_to(ds.pathobj)) for p in paths]
              if paths
              else ".",
              force=reckless in ("availability", "kill"),
              jobs=jobs,
          )
          # end it here for safety, the rest of the function deals with
          # dropping more and more fundamentally
          return
  
      drop_all_errored = False
      if (
          is_annex
          and what in ("allkeys", "datasets", "all")
          and not reckless == "kill"
      ):
          for r in _drop_allkeys(
              ds, repo, force=reckless in ("availability",), jobs=jobs
          ):
              res = dict(
                  action="drop",
                  type="key",
                  # use the path of the containing dataset
                  # using the location of the key does not add any
                  # practical value, and is expensive to obtain
                  path=ds.path,
                  status="ok" if r.get("success") else "error",
                  key=r.get("key"),
              )
              # pull any note, and rename recommended parameter to
              # avoid confusion
              message = r.get("note", "").replace(
                  "--force", "--reckless availability"
              )
              if message:
                  res["message"] = message
              error_messages = r.get("error-messages")
              if error_messages:
                  res["error_message"] = "\n".join(
                      m.strip() for m in error_messages
                  )
              # play safe, if there is no status, assume error
              if res.get("status", "error") != "ok":
                  drop_all_errored = True
              yield res
  
      if drop_all_errored:
          # end it here, if there is any indication that wiping out the
          # repo is unsafe
          return
  
      if what in ("all", "datasets"):
          yield from _kill_dataset(ds)
      lgr.debug("Done dropping for %s", ds)
      return
  
imports: import logging
  from itertools import chain
  import warnings
  from datalad.core.local.status import get_paths_by_ds
  from datalad.distribution.dataset import Dataset, EnsureDataset, datasetmethod, require_dataset
  from datalad.interface.base import Interface, build_doc, eval_results
  from datalad.interface.common_opts import jobs_opt, recursion_flag, recursion_limit
  from datalad.interface.results import annexjson2result, results_from_annex_noinfo, success_status_map
  from datalad.runner.exception import CommandError
  from datalad.support.annexrepo import AnnexRepo
  from datalad.support.constraints import EnsureChoice, EnsureNone, EnsureStr
  from datalad.support.exceptions import CapturedException
  from datalad.support.param import Parameter
  from datalad.utils import ensure_list, rmtree
label_desc: Use image node_id 2 for calling a global function with example usage: _drop_dataset(ds, paths, what, reckless, recursive, recursion_limit, jobs) without return types