class_docstr: Execute remote commands with Paramiko.
  
  .. seealso:: https://github.com/paramiko/paramiko
  
  This hook also lets you create ssh tunnel and serve as basis for SFTP file transfer.
  
  :param ssh_conn_id: :ref:`ssh connection id<howto/connection:ssh>` from airflow
      Connections from where all the required parameters can be fetched like
      username, password or key_file, though priority is given to the
      params passed during init.
  :param remote_host: remote host to connect
  :param username: username to connect to the remote_host
  :param password: password of the username to connect to the remote_host
  :param key_file: path to key file to use to connect to the remote_host
  :param port: port of remote host to connect (Default is paramiko SSH_PORT)
  :param conn_timeout: timeout (in seconds) for the attempt to connect to the remote_host.
      The default is 10 seconds. If provided, it will replace the `conn_timeout` which was
      predefined in the connection of `ssh_conn_id`.
  :param timeout: (Deprecated). timeout for the attempt to connect to the remote_host.
      Use conn_timeout instead.
  :param cmd_timeout: timeout (in seconds) for executing the command. The default is 10 seconds.
      Nullable, `None` means no timeout. If provided, it will replace the `cmd_timeout`
      which was predefined in the connection of `ssh_conn_id`.
  :param keepalive_interval: send a keepalive packet to remote host every
      keepalive_interval seconds
  :param banner_timeout: timeout to wait for banner from the server in seconds
  :param disabled_algorithms: dictionary mapping algorithm type to an
      iterable of algorithm identifiers, which will be disabled for the
      lifetime of the transport
  :param ciphers: list of ciphers to use in order of preference
code: def __init__(
      self,
      ssh_conn_id: str | None = None,
      remote_host: str = "",
      username: str | None = None,
      password: str | None = None,
      key_file: str | None = None,
      port: int | None = None,
      timeout: int | None = None,
      conn_timeout: int | None = None,
      cmd_timeout: int | ArgNotSet | None = NOTSET,
      keepalive_interval: int = 30,
      banner_timeout: float = 30.0,
      disabled_algorithms: dict | None = None,
      ciphers: list[str] | None = None,
      **kwargs,
  ) -> None:
      super().__init__(**kwargs)
      self.ssh_conn_id = ssh_conn_id
      self.remote_host = remote_host
      self.username = username
      self.password = password
      self.key_file = key_file
      self.pkey = None
      self.port = port
      self.timeout = timeout
      self.conn_timeout = conn_timeout
      self.cmd_timeout = cmd_timeout
      self.keepalive_interval = keepalive_interval
      self.banner_timeout = banner_timeout
      self.disabled_algorithms = disabled_algorithms
      self.ciphers = ciphers
      self.host_proxy_cmd = None
  
      # Default values, overridable from Connection
      self.compress = True
      self.no_host_key_check = True
      self.allow_host_key_change = False
      self.host_key = None
      self.look_for_keys = True
  
      # Placeholder for deprecated __enter__
      self.client: paramiko.SSHClient | None = None
  
      # Use connection to override defaults
      if self.ssh_conn_id is not None:
          conn = self.get_connection(self.ssh_conn_id)
          if self.username is None:
              self.username = conn.login
          if self.password is None:
              self.password = conn.password
          if not self.remote_host:
              self.remote_host = conn.host
          if self.port is None:
              self.port = conn.port
  
          if conn.extra is not None:
              extra_options = conn.extra_dejson
              if "key_file" in extra_options and self.key_file is None:
                  self.key_file = extra_options.get("key_file")
  
              private_key = extra_options.get("private_key")
              private_key_passphrase = extra_options.get(
                  "private_key_passphrase"
              )
              if private_key:
                  self.pkey = self._pkey_from_private_key(
                      private_key, passphrase=private_key_passphrase
                  )
  
              if "timeout" in extra_options:
                  warnings.warn(
                      "Extra option `timeout` is deprecated."
                      "Please use `conn_timeout` instead."
                      "The old option `timeout` will be removed in a future version.",
                      category=AirflowProviderDeprecationWarning,
                      stacklevel=2,
                  )
                  self.timeout = int(extra_options["timeout"])
  
              if (
                  "conn_timeout" in extra_options
                  and self.conn_timeout is None
              ):
                  self.conn_timeout = int(extra_options["conn_timeout"])
  
              if (
                  "cmd_timeout" in extra_options
                  and self.cmd_timeout is NOTSET
              ):
                  if extra_options["cmd_timeout"]:
                      self.cmd_timeout = int(
                          extra_options["cmd_timeout"]
                      )
                  else:
                      self.cmd_timeout = None
  
              if (
                  "compress" in extra_options
                  and str(extra_options["compress"]).lower() == "false"
              ):
                  self.compress = False
  
              host_key = extra_options.get("host_key")
              no_host_key_check = extra_options.get("no_host_key_check")
  
              if no_host_key_check is not None:
                  no_host_key_check = (
                      str(no_host_key_check).lower() == "true"
                  )
                  if host_key is not None and no_host_key_check:
                      raise ValueError(
                          "Must check host key when provided"
                      )
  
                  self.no_host_key_check = no_host_key_check
  
              if (
                  "allow_host_key_change" in extra_options
                  and str(
                      extra_options["allow_host_key_change"]
                  ).lower()
                  == "true"
              ):
                  self.allow_host_key_change = True
  
              if (
                  "look_for_keys" in extra_options
                  and str(extra_options["look_for_keys"]).lower()
                  == "false"
              ):
                  self.look_for_keys = False
  
              if "disabled_algorithms" in extra_options:
                  self.disabled_algorithms = extra_options.get(
                      "disabled_algorithms"
                  )
  
              if "ciphers" in extra_options:
                  self.ciphers = extra_options.get("ciphers")
  
              if host_key is not None:
                  if host_key.startswith("ssh-"):
                      key_type, host_key = host_key.split(None)[:2]
                      key_constructor = self._host_key_mappings[
                          key_type[4:]
                      ]
                  else:
                      key_constructor = paramiko.RSAKey
                  decoded_host_key = decodebytes(
                      host_key.encode("utf-8")
                  )
                  self.host_key = key_constructor(data=decoded_host_key)
                  self.no_host_key_check = False
  
      if self.timeout:
          warnings.warn(
              "Parameter `timeout` is deprecated."
              "Please use `conn_timeout` instead."
              "The old option `timeout` will be removed in a future version.",
              category=AirflowProviderDeprecationWarning,
              stacklevel=2,
          )
  
      if self.conn_timeout is None:
          self.conn_timeout = (
              self.timeout if self.timeout else TIMEOUT_DEFAULT
          )
  
      if self.cmd_timeout is NOTSET:
          self.cmd_timeout = CMD_TIMEOUT
  
      if self.pkey and self.key_file:
          raise AirflowException(
              "Params key_file and private_key both provided.  Must provide no more than one."
          )
  
      if not self.remote_host:
          raise AirflowException("Missing required param: remote_host")
  
      # Auto detecting username values from system
      if not self.username:
          self.log.debug(
              "username to ssh to host: %s is not specified for connection id"
              " %s. Using system's default provided by getpass.getuser()",
              self.remote_host,
              self.ssh_conn_id,
          )
          self.username = getuser()
  
      user_ssh_config_filename = os.path.expanduser("~/.ssh/config")
      if os.path.isfile(user_ssh_config_filename):
          ssh_conf = paramiko.SSHConfig()
          with open(user_ssh_config_filename) as config_fd:
              ssh_conf.parse(config_fd)
          host_info = ssh_conf.lookup(self.remote_host)
          if host_info and host_info.get("proxycommand"):
              self.host_proxy_cmd = host_info["proxycommand"]
  
          if not (self.password or self.key_file):
              if host_info and host_info.get("identityfile"):
                  self.key_file = host_info["identityfile"][0]
  
      self.port = self.port or SSH_PORT
  
imports: from __future__ import annotations
  import os
  import warnings
  from base64 import decodebytes
  from functools import cached_property
  from io import StringIO
  from select import select
  from typing import Any, Sequence
  import paramiko
  from paramiko.config import SSH_PORT
  from sshtunnel import SSHTunnelForwarder
  from tenacity import Retrying, stop_after_attempt, wait_fixed, wait_random
  from airflow.exceptions import AirflowException, AirflowProviderDeprecationWarning
  from airflow.hooks.base import BaseHook
  from airflow.utils.platform import getuser
  from airflow.utils.types import NOTSET, ArgNotSet
label_desc: Use image node_id 2 to create a new SSHHook object from inherited base classes: BaseHook with example: obj = SSHHook(ssh_conn_id, remote_host, username, password, key_file, port, timeout, conn_timeout, cmd_timeout, keepalive_interval, banner_timeout, disabled_algorithms, ciphers)