class_docstr: Get and set dataset, dataset-clone-local, or global configuration
  
  This command works similar to git-config, but some features are not
  supported (e.g., modifying system configuration), while other features
  are not available in git-config (e.g., multi-configuration queries).
  
  Query and modification of three distinct configuration scopes is
  supported:
  
  - 'branch': the persistent configuration in .datalad/config of a dataset
    branch
  - 'local': a dataset clone's Git repository configuration in .git/config
  - 'global': non-dataset-specific configuration (usually in $USER/.gitconfig)
  
  Modifications of the persistent 'branch' configuration will not be saved
  by this command, but have to be committed with a subsequent `save`
  call.
  
  Rules of precedence regarding different configuration scopes are the same
  as in Git, with two exceptions: 1) environment variables can be used to
  override any datalad configuration, and have precedence over any other
  configuration scope (see below). 2) the 'branch' scope is considered in
  addition to the standard git configuration scopes. Its content has lower
  precedence than Git configuration scopes, but it is committed to a branch,
  hence can be used to ship (default and branch-specific) configuration with
  a dataset.
  
  Besides storing configuration settings statically via this command or ``git
  config``, DataLad also reads any :envvar:`DATALAD_*` environment on process
  startup or import, and maps it to a configuration item.  Their values take
  precedence over any other specification. In variable names ``_`` encodes a
  ``.`` in the configuration name, and ``__`` encodes a ``-``, such that
  ``DATALAD_SOME__VAR`` is mapped to ``datalad.some-var``.  Additionally, a
  :envvar:`DATALAD_CONFIG_OVERRIDES_JSON` environment variable is
  queried, which may contain configuration key-value mappings as a
  JSON-formatted string of a JSON-object::
  
    DATALAD_CONFIG_OVERRIDES_JSON='{"datalad.credential.example_com.user": "jane", ...}'
  
  This is useful when characters are part of the configuration key that
  cannot be encoded into an environment variable name. If both individual
  configuration variables *and* JSON-overrides are used, the former take
  precedent over the latter, overriding the respective *individual* settings
  from configurations declared in the JSON-overrides.
  
  This command supports recursive operation for querying and modifying
  configuration across a hierarchy of datasets.
code: def __call__(
      action="dump",
      spec=None,
      *,
      scope=None,
      dataset=None,
      recursive=False,
      recursion_limit=None,
  ):
      # check conditions
      # - global and recursion makes no sense
  
      if action == "dump":
          if scope:
              raise ValueError(
                  "Scope selection is not supported for dumping"
              )
  
      # normalize variable specifications
      specs = []
      for s in ensure_list(spec):
          if isinstance(s, tuple):
              specs.append((str(s[0]), str(s[1])))
          elif "=" not in s:
              specs.append((str(s),))
          else:
              specs.append(tuple(s.split("=", 1)))
  
      if action == "set":
          missing_values = [s[0] for s in specs if len(s) < 2]
          if missing_values:
              raise ValueError(
                  "Values must be provided for all configuration "
                  "settings. Missing: {}".format(missing_values)
              )
          invalid_names = [s[0] for s in specs if "." not in s[0]]
          if invalid_names:
              raise ValueError(
                  'Name must contain a section (i.e. "section.name"). '
                  "Invalid: {}".format(invalid_names)
              )
  
      ds = None
      if scope != "global" or recursive:
          try:
              ds = require_dataset(
                  dataset, check_installed=True, purpose="configure"
              )
          except NoDatasetFound:
              if action != "dump" or dataset:
                  raise
  
      res_kwargs = dict(
          action="configuration",
          logger=lgr,
      )
      if ds:
          res_kwargs["refds"] = ds.path
      yield from configuration(action, scope, specs, res_kwargs, ds)
  
      if not recursive:
          return
  
      for subds in ds.subdatasets(
          state="present",
          recursive=True,
          recursion_limit=recursion_limit,
          on_failure="ignore",
          return_type="generator",
          result_renderer="disabled",
      ):
          yield from configuration(
              action, scope, specs, res_kwargs, Dataset(subds["path"])
          )
  
imports: import logging
  from textwrap import wrap
  import datalad.support.ansi_colors
  from datalad import cfg
  from datalad.distribution.dataset import Dataset, EnsureDataset, datasetmethod, require_dataset
  from datalad.interface.base import Interface, build_doc, eval_results
  from datalad.interface.common_cfg import definitions
  from datalad.interface.common_opts import recursion_flag, recursion_limit
  from datalad.interface.results import get_status_dict
  from datalad.interface.utils import default_result_renderer
  from datalad.support.constraints import EnsureChoice, EnsureNone
  from datalad.support.exceptions import CommandError, NoDatasetFound
  from datalad.support.param import Parameter
  from datalad.utils import Path, ensure_list
label_desc: Use image node_id 1 for calling the Configuration obj's underlying member method code with example usage: obj.__call__(action, spec) without return types