code: def test_dry_run(path=None):
      ds = Dataset(path).create(force=True)
  
      # The dataset is reported as dirty, and the custom result render relays
      # that to the default renderer.
      with swallow_outputs() as cmo:
          with assert_raises(IncompleteResultsError):
              ds.run("blah ", dry_run="basic")
          assert_in("run(impossible)", cmo.out)
          assert_not_in("blah", cmo.out)
  
      ds.save()
  
      # unknown dry-run mode
      assert_raises(ValueError, ds.run, "blah", dry_run="absurd")
  
      with swallow_outputs() as cmo:
          ds.run("blah ", dry_run="basic")
          assert_in("Dry run", cmo.out)
          assert_in("location", cmo.out)
          assert_in("blah", cmo.out)
          assert_not_in("expanded inputs", cmo.out)
          assert_not_in("expanded outputs", cmo.out)
  
      with swallow_outputs() as cmo:
          ds.run(
              "blah {inputs} {outputs}",
              dry_run="basic",
              inputs=["fo*"],
              outputs=["b*r"],
          )
          assert_in(
              'blah "foo" "bar"' if on_windows else "blah foo bar",
              cmo.out,
          )
          assert_in("expanded inputs", cmo.out)
          assert_in("['foo']", cmo.out)
          assert_in("expanded outputs", cmo.out)
          assert_in("['bar']", cmo.out)
  
      # Just the command.
      with swallow_outputs() as cmo:
          ds.run("blah ", dry_run="command")
          assert_not_in("Dry run", cmo.out)
          assert_in("blah", cmo.out)
          assert_not_in("inputs", cmo.out)
  
      # The output file wasn't unlocked.
      assert_repo_status(ds.path)
  
      # Subdaset handling
  
      subds = ds.create("sub")
      (subds.pathobj / "baz").write_text("z")
      ds.save(recursive=True)
  
      # If a subdataset is installed, it works as usual.
      with swallow_outputs() as cmo:
          ds.run("blah {inputs}", dry_run="basic", inputs=["sub/b*"])
          assert_in(
              'blah "sub\\baz"' if on_windows else "blah sub/baz",
              cmo.out,
          )
  
      # However, a dry run will not do the install/reglob procedure.
      ds.drop("sub", what="all", reckless="kill", recursive=True)
      with swallow_outputs() as cmo:
          ds.run("blah {inputs}", dry_run="basic", inputs=["sub/b*"])
          assert_in("sub/b*", cmo.out)
          assert_not_in("baz", cmo.out)
  
imports: import logging
  import os
  import os.path
  import sys
  from os import mkdir, remove
  from unittest.mock import patch
  from datalad.api import clone, run
  from datalad.cli.main import main
  from datalad.core.local.run import _format_iospecs, _get_substitutions, format_command, run_command
  from datalad.distribution.dataset import Dataset
  from datalad.support.exceptions import CommandError, IncompleteResultsError, NoDatasetFound
  from datalad.tests.utils_pytest import DEFAULT_BRANCH, OBSCURE_FILENAME, assert_false, assert_in, assert_in_results, assert_not_in, assert_not_in_results, assert_raises, assert_repo_status, assert_result_count, assert_status, create_tree, eq_, known_failure_windows, neq_, ok_, ok_exists, ok_file_has_content, patch_config, swallow_logs, swallow_outputs, with_tempfile, with_tree
  from datalad.utils import chpwd, ensure_unicode, on_windows
label_desc: Use image node_id 20 for calling a global function with example usage: test_dry_run(path) without return types