class_docstr: An adapter to use interchanegably with SSH connection
code: def put(
      self, source, destination, recursive=False, preserve_attrs=False
  ):
      import shutil
  
      copy_fn = shutil.copy2 if preserve_attrs else shutil.copy
      if recursive:
          args = [source, destination]
          kwargs = {"copy_function": copy_fn}
          try:
              shutil.copytree(*args, **kwargs)
          except FileExistsError:
              # SSHConnection.put() is okay with copying a tree if the
              # destination directory already exists. With Python 3.8, we can
              # make copytree() do the same with dirs_exist_ok=True. But for
              # now, just rely on `cp`.
              cmd = ["cp", "-R"]
              if preserve_attrs:
                  cmd.append("-p")
              self(cmd + args)
      else:
          copy_fn(source, destination)
  
imports: import logging
  import os
  from os.path import curdir
  import shlex
  from os.path import join
  from os.path import normpath, relpath
  from looseversion import LooseVersion
  from datalad import ssh_manager
  from datalad.cmd import CommandError, StdOutErrCapture, WitlessRunner
  from datalad.consts import TIMESTAMP_FMT, WEB_META_LOG
  from datalad.core.local.diff import diff_dataset
  from datalad.distribution.dataset import Dataset, EnsureDataset, datasetmethod, require_dataset, resolve_path
  from datalad.distribution.siblings import Siblings, _DelayedSuper
  from datalad.interface.base import Interface, build_doc, eval_results
  from datalad.interface.common_opts import annex_group_opt, annex_groupwanted_opt, annex_wanted_opt, as_common_datasrc, inherit_opt, publish_by_default, publish_depends, recursion_flag, recursion_limit
  from datalad.support.annexrepo import AnnexRepo
  from datalad.support.constraints import EnsureBool, EnsureChoice, EnsureNone, EnsureStr
  from datalad.support.exceptions import CapturedException, InsufficientArgumentsError, MissingExternalDependency
  from datalad.support.external_versions import external_versions
  from datalad.support.network import RI, PathRI, is_ssh
  from datalad.support.param import Parameter
  from datalad.ui import ui
  from datalad.utils import _path_, ensure_list, make_tempfile, on_windows
  from datalad.utils import quote_cmdlinearg
  from datalad.utils import slash_join
label_desc: Use image node_id 4 for calling the _RunnerAdapter obj's underlying member method code with example usage: obj.put(source, destination, recursive, preserve_attrs) without return types