16 from fnmatch
import fnmatchcase
26 from .config
import (Configuration, IntegerEntry, NewlineEntry, StringEntry,
28 from .logger
import logger
29 from .utils
import is_bytes, is_string, unicode, is_list_like
38 def __init__(self, host, alias, port, timeout, newline, prompt, term_type,
39 width, height, path_separator, encoding, escape_ansi, encoding_errors):
40 super(_ClientConfiguration, self).
__init__(
65 def __init__(self, host, alias=None, port=22, timeout=3, newline='LF',
66 prompt=None, term_type='vt100', width=80, height=24,
67 path_separator='/', encoding='utf8', escape_ansi=False, encoding_errors='strict'):
69 prompt, term_type, width, height,
70 path_separator, encoding, escape_ansi, encoding_errors)
81 raise NotImplementedError(
'This should be implemented in the subclass.')
91 raise NotImplementedError
99 sftp_client = property
112 scp_transfer_client = property
125 scp_all_client = property
149 raise NotImplementedError
152 raise NotImplementedError
155 raise NotImplementedError
158 raise NotImplementedError
168 logger.log_background_messages()
169 except AttributeError:
209 def login(self, username=None, password=None, allow_agent=False, look_for_keys=False, delay=None, proxy_cmd=None,
210 read_config=False, jumphost_connection=None, keep_alive_interval='0 seconds'):
211 keep_alive_interval = int(
TimeEntry(keep_alive_interval).value)
212 username = self.
_encode_encode(username)
213 if not password
or password ==
'""':
215 if password
and not allow_agent:
216 password = self.
_encode_encode(password)
218 self.
_login_login(username, password, allow_agent, look_for_keys, proxy_cmd, read_config,
219 jumphost_connection, keep_alive_interval)
220 except SSHClientException:
223 % self.
_decode_decode(username))
229 if not is_string(text):
231 return text.encode(self.
configconfig.encoding, self.
configconfig.encoding_errors)
234 return bytes.decode(self.
configconfig.encoding, self.
configconfig.encoding_errors)
236 def _login(self, username, password, allow_agent, look_for_keys, proxy_cmd, read_config,
237 jumphost_connection, keep_alive_interval):
238 raise NotImplementedError
241 if not self.
configconfig.prompt:
242 return self.
readread(delay)
243 elif self.
configconfig.prompt.startswith(
'REGEXP:'):
286 look_for_keys=False, delay=None, proxy_cmd=None,
287 jumphost_connection=None, read_config=False, keep_alive_interval='0 seconds'):
289 username = self.
_encode_encode(username)
292 keep_alive_interval = int(
TimeEntry(keep_alive_interval).value)
295 allow_agent, look_for_keys,
296 proxy_cmd, jumphost_connection,
297 read_config, keep_alive_interval)
298 except SSHClientException:
301 "'%s'." % self.
_decode_decode(username))
305 if not os.path.exists(keyfile):
309 open(keyfile).
close()
314 allow_agent, look_for_keys, proxy_cmd,
315 jumphost_index_or_alias, read_config, keep_alive_interval):
316 raise NotImplementedError
320 raise NotImplementedError(
'Not supported on this Python interpreter.')
323 raise NotImplementedError(
'Not supported on this Python interpreter.')
344 def execute_command(self, command, sudo=False, sudo_password=None, timeout=None, output_during_execution=False,
345 output_if_timeout=False, invoke_subsystem=False, forward_agent=False):
346 self.
start_commandstart_command(command, sudo, sudo_password, invoke_subsystem, forward_agent)
347 return self.
read_command_outputread_command_output(timeout=timeout, output_during_execution=output_during_execution,
348 output_if_timeout=output_if_timeout)
369 def start_command(self, command, sudo=False, sudo_password=None, invoke_subsystem=False, forward_agent=False):
370 command = self.
_encode_encode(command)
374 def _start_command(self, command, sudo=False, sudo_password=None, invoke_subsystem=False, forward_agent=False):
375 raise NotImplementedError
391 timeout = float(
TimeEntry(timeout).value)
393 return self.
_started_commands_started_commands.pop().read_outputs(timeout, output_during_execution, output_if_timeout)
405 def write(self, text, add_newline=False):
406 text = self.
_encode_encode(text)
430 return self.
_decode_decode(output)
434 max_time = time.time() + self.
configconfig.get(
'timeout').value
436 while time.time() < max_time:
455 server_output += self.
shellshellshell.read_byte()
456 return self.
_decode_decode(server_output)
457 except UnicodeDecodeError
as e:
458 if e.reason ==
'unexpected end of data':
479 return self.
_read_until_read_until(
lambda s: expected
in s, expected)
483 timeout =
TimeEntry(timeout)
if timeout
else self.
configconfig.get(
'timeout')
484 max_time = time.time() + timeout.value
485 while time.time() < max_time:
493 % (expected, timeout, output))
529 if not self.
configconfig.prompt:
532 if self.
configconfig.prompt.startswith(
'REGEXP:'):
541 if self.
configconfig.prompt.startswith(
'REGEXP:'):
542 pattern = re.compile(self.
configconfig.prompt[7:])
543 match = pattern.search(output)
544 length = match.end() - match.start()
546 length = len(self.
configconfig.prompt)
547 return output[:-length]
566 if is_string(regexp):
567 regexp = re.compile(regexp)
568 return self.
_read_until_read_until(
lambda s: regexp.search(s), regexp.pattern)
580 if is_string(regexp):
581 regexp = re.compile(regexp)
582 matcher = regexp.search
583 expected = regexp.pattern
585 timeout = self.
configconfig.get(
'timeout')
586 start_time = time.time()
587 while time.time() < float(timeout.value) + start_time:
589 if matcher(prefix + self.
_encode_encode(ret)):
592 "No match found for '%s' in %s\nOutput:\n%s"
593 % (expected, timeout, ret))
617 expected = self.
_encode_encode(expected)
620 max_time = time.time() + timeout.value
621 while time.time() < max_time:
622 self.
writewrite(text)
624 return self.
_read_until_read_until(
lambda s: expected
in self.
_encode_encode(s), expected,
625 timeout=interval.value)
626 except SSHClientException:
629 % (self.
_decode_decode(expected), timeout))
636 def put_file(self, source, destination='.', mode='0o744', newline='',
637 scp='OFF', scp_preserve_times=False):
639 return client.put_file(source, destination, scp_preserve_times, mode, newline,
640 self.
configconfig.path_separator)
651 recursive=False, scp='OFF', scp_preserve_times=False):
653 return client.put_directory(source, destination, scp_preserve_times, mode,
654 newline, self.
configconfig.path_separator, recursive)
661 def get_file(self, source, destination='.', scp='OFF', scp_preserve_times=False):
665 return client.get_file(sources, destination, scp_preserve_times, self.
configconfig.path_separator)
666 return client.get_file(source, destination, scp_preserve_times, self.
configconfig.path_separator)
669 sources = self.
execute_commandexecute_command(
'printf "%%s\\n" %s' % source)
670 result = sources[0].split(
'\n')
671 result[:] = [x
for x
in result
if x]
683 scp='OFF', scp_preserve_times=False):
685 return client.get_directory(source, destination, scp_preserve_times,
686 self.
configconfig.path_separator,
697 def list_dir(self, path, pattern=None, absolute=False):
736 has_glob = bool([ops
for ops
in '*?![' if(ops
in path)])
738 dir_dir = path[:(-len(path.split(self.
configconfig.path_separator)[-1]))]
741 if fnmatch.fnmatch(dirname, path.split(self.
configconfig.path_separator)[-1]):
756 if bool([ops
for ops
in '*?![' if(ops
in path)]):
757 file_dir = path[:(-len(path.split(self.
configconfig.path_separator)[-1]))]
761 for filename
in files:
762 if fnmatch.fnmatch(filename, path.split(self.
configconfig.path_separator)[-1]):
767 if scp.upper() ==
'ALL':
769 elif scp.upper() ==
'TRANSFER':
788 raise NotImplementedError
795 raise NotImplementedError
803 raise NotImplementedError
820 raise NotImplementedError
833 item = self.
_stat_stat(path)
836 return item.is_regular()
839 raise NotImplementedError
852 item = self.
_stat_stat(path)
855 return item.is_directory()
877 def list_dir(self, path, pattern=None, absolute=False):
883 items = filter_method(path)
891 if not self.
is_diris_dir(path):
896 return [item.name
for item
in self.
_list_list(path)]
899 raise NotImplementedError
902 return [name
for name
in items
if fnmatchcase(name, pattern)]
906 if absolute_path[1:3] ==
':\\':
907 absolute_path +=
'\\'
910 return [absolute_path + name
for name
in items]
935 for item
in self.
_list_list(path)
941 resolved_link = self.
_readlink_readlink(
'%s/%s' % (path, item))
942 return self.
is_diris_dir(
'%s/%s' % (path, resolved_link))
966 return [item.name
for item
in self.
_list_list(path)
if item.is_directory()]
968 def get_directory(self, source, destination, scp_preserve_time, path_separator='/',
970 destination = self.
build_destinationbuild_destination(source, destination, path_separator)
971 return self.
_get_directory_get_directory(source, destination, path_separator, recursive, scp_preserve_time)
998 recursive=False, scp_preserve_times=False):
1002 items = self.
list_dirlist_dir(source)
1005 remote = source + path_separator + item
1006 local = os.path.join(destination, item)
1007 if self.
is_fileis_file(remote):
1008 files += self.
get_fileget_file(remote, local, scp_preserve_times)
1010 files += self.
get_directoryget_directory(remote, local, scp_preserve_times, path_separator,
1013 if not os.path.exists(destination):
1014 os.makedirs(destination)
1015 files.append((source, destination))
1025 if os.path.exists(destination)
or destination ==
'.':
1026 fullpath_destination = os.path.join(destination, self.
get_parent_folderget_parent_folder(source, path_separator))
1027 if not os.path.exists(fullpath_destination):
1028 os.makedirs(fullpath_destination)
1029 return fullpath_destination
1034 if source.endswith(path_separator):
1035 return (source[:-len(path_separator)]).split(path_separator)[-1]
1037 return source.split(path_separator)[-1]
1040 if source.endswith(path_separator):
1041 source = source[:-len(path_separator)]
1067 def get_file(self, source, destination, scp_preserve_times, path_separator='/'):
1069 if not remote_files:
1070 msg =
"There were no source files matching '%s'." % source
1073 files = list(zip(remote_files, local_files))
1074 for src, dst
in files:
1075 self.
_get_file_get_file(src, dst, scp_preserve_times)
1079 if path_separator
in source:
1080 path, pattern = source.rsplit(path_separator, 1)
1082 path, pattern =
'', source
1085 if not self.
is_fileis_file(source):
1086 return [filename
for filename
in
1092 target_is_dir = destination.endswith(os.sep)
or destination ==
'.'
1093 if not target_is_dir
and len(source_files) > 1:
1095 'destination file.')
1096 destination = os.path.abspath(destination.replace(
'/', os.sep))
1099 return [os.path.join(destination, os.path.basename(name))
1100 for name
in source_files]
1101 return [destination]
1104 if not target_is_dir:
1105 destination = os.path.dirname(destination)
1106 if not os.path.exists(destination):
1107 os.makedirs(destination)
1109 def _get_file(self, source, destination, scp_preserve_times):
1110 raise NotImplementedError
1142 path_separator='/', recursive=False):
1146 if self.
is_diris_dir(destination):
1147 destination = destination + path_separator +\
1148 source.rsplit(os.path.sep)[-1]
1149 return self.
_put_directory_put_directory(source, destination, mode, newline,
1150 path_separator, recursive, scp_preserve_times)
1153 path_separator, recursive, scp_preserve_times=False):
1155 items = os.listdir(source)
1158 local_path = os.path.join(source, item)
1159 remote_path = destination + path_separator + item
1160 if os.path.isfile(local_path):
1161 files += self.
put_fileput_file(local_path, remote_path, scp_preserve_times,
1162 mode, newline, path_separator)
1163 elif recursive
and os.path.isdir(local_path):
1164 files += self.
_put_directory_put_directory(local_path, remote_path,
1166 path_separator, recursive, scp_preserve_times)
1169 files.append((source, destination))
1173 if not os.path.isdir(path):
1208 def put_file(self, sources, destination, scp_preserve_times, mode, newline, path_separator='/'):
1211 newline = {
'CRLF':
'\r\n',
'LF':
'\n'}.get(newline.upper(),
None)
1217 files = list(zip(local_files, remote_files))
1218 for source, destination
in files:
1219 self.
_put_file_put_file(source, destination, mode, newline, path_separator, scp_preserve_times)
1223 source = source.replace(
'/', os.sep)
1224 if not os.path.exists(source):
1225 sources = [f
for f
in glob.glob(source)]
1227 sources = [f
for f
in [source]]
1229 msg =
"There are no source files matching '%s'." % source
1234 if destination[1:3] ==
':' + path_separator:
1235 destination = path_separator + destination
1237 if destination ==
'.':
1238 destination = self.
_homedir_homedir +
'/'
1239 if len(sources) > 1
and destination[-1] !=
'/' and not self.
is_diris_dir(destination):
1240 raise ValueError(
'It is not possible to copy multiple source '
1241 'files to one destination file.')
1245 files = [path_separator.join([dir_path, filename])]
1247 files = [path_separator.join([dir_path, os.path.basename(path)])
1248 for path
in sources]
1249 return files, dir_path
1252 destination = destination.replace(
'\\',
'/')
1253 destination = ntpath.splitdrive(destination)[-1]
1258 if destination.startswith(path_separator):
1260 if path_separator ==
'\\' and path[1:3] ==
':\\':
1263 if not _isabs(destination):
1264 destination = path_separator.join([self.
_homedir_homedir, destination])
1265 if self.
is_diris_dir(destination):
1266 return destination,
''
1267 return destination.rsplit(path_separator, 1)
1270 if path.startswith(b
'/'):
1274 for dir_name
in path.split(b
'/'):
1276 current_dir = posixpath.join(current_dir, dir_name)
1278 self._client.stat(current_dir)
1280 if not isinstance(mode, int):
1282 self._client.mkdir(current_dir, mode)
1284 def _put_file(self, source, destination, mode, newline, path_separator, scp_preserve_times=False):
1286 with open(source,
'rb')
as local_file:
1289 data = local_file.read(4096)
1293 data = re.sub(br
'(\r\n|\r|\n)', newline.encode(self.
_encoding_encoding), data)
1295 position += len(data)
1299 raise NotImplementedError
1302 raise NotImplementedError
1305 raise NotImplementedError
1308 raise NotImplementedError
1311 raise NotImplementedError
1338 def run_in(self, shell, sudo=False, sudo_password=None, invoke_subsystem=False):
1339 self.
_shell_shell = shell
1340 if invoke_subsystem:
1348 raise NotImplementedError
1351 raise NotImplementedError
1354 raise NotImplementedError
1362 raise NotImplementedError
1380 return stat.S_ISREG(self.
modemode)
1387 return stat.S_ISDIR(self.
modemode)
1394 return stat.S_ISLNK(self.
modemode)
Base class for the remote command.
def read_outputs(self)
Returns the outputs of this command.
def run_in(self, shell, sudo=False, sudo_password=None, invoke_subsystem=False)
Runs this command in the given shell.
def _execute_with_sudo(self, sudo_password=None)
def __init__(self, command, encoding)
Base class for the SFTP implementation.
def _create_remote_file(self, destination, mode)
def _create_missing_remote_path(self, path, mode)
def _verify_remote_dir_exists(self, path)
def get_file(self, source, destination, scp_preserve_times, path_separator='/')
Downloads file(s) from the remote host to the local machine.
def get_parent_folder(self, source, path_separator)
def _format_destination_path(self, destination)
def _get_put_file_sources(self, source)
def _create_missing_local_dirs(self, destination, target_is_dir)
def _include_absolute_path(self, items, path)
def _is_dir_symlink(self, path, item)
def build_destination(self, source, destination, path_separator)
Add parent directory from source to destination path if destination is '.
def _put_file(self, source, destination, mode, newline, path_separator, scp_preserve_times=False)
def _get_get_file_sources(self, source, path_separator)
def _get_directory(self, source, destination, path_separator='/', recursive=False, scp_preserve_times=False)
Downloads directory(-ies) from the remote host to the local machine, optionally with subdirectories i...
def _get_file_names(self, path)
def _filter_by_pattern(self, items, pattern)
def _close_remote_file(self, remote_file)
def _get_directory_names(self, path)
def is_dir(self, path)
Checks if the path points to a directory on the remote host.
def _remove_ending_path_separator(self, path_separator, source)
def _get_put_file_destinations(self, sources, destination, path_separator)
def _list_filtered(self, path, filter_method, pattern=None, absolute=False)
def get_directory(self, source, destination, scp_preserve_time, path_separator='/', recursive=False)
def list_files_in_dir(self, path, pattern=None, absolute=False)
Gets the file names, or optionally the absolute paths, of the regular files on the given path on the ...
def put_file(self, sources, destination, scp_preserve_times, mode, newline, path_separator='/')
Uploads the file(s) from the local machine to the remote host.
def _verify_local_dir_exists(self, path)
def list_dirs_in_dir(self, path, pattern=None, absolute=False)
Gets the directory names, or optionally the absolute paths, on the given path on the remote host.
def _get_get_file_destinations(self, source_files, destination)
def __init__(self, encoding)
def list_dir(self, path, pattern=None, absolute=False)
Gets the item names, or optionally the absolute paths, on the given path on the remote host.
def _get_file(self, source, destination, scp_preserve_times)
def _absolute_path(self, path)
def _write_to_remote_file(self, remote_file, data, position)
def create_local_ssh_tunnel(self, local_port, remote_host, remote_port, client)
def is_file(self, path)
Checks if the path points to a regular file on the remote host.
def _get_item_names(self, path)
def put_directory(self, source, destination, scp_preserve_times, mode, newline, path_separator='/', recursive=False)
Uploads directory(-ies) from the local machine to the remote host, optionally with subdirectories inc...
def _parse_path_elements(self, destination, path_separator)
def _readlink(self, path)
def _put_directory(self, source, destination, mode, newline, path_separator, recursive, scp_preserve_times=False)
Base class for the SSH client implementation.
def put_file(self, source, destination='.', mode='0o744', newline='', scp='OFF', scp_preserve_times=False)
Calls :py:meth:AbstractSFTPClient.put_file` with the given arguments.
def is_dir(self, path)
Calls :py:meth:AbstractSFTPClient.is_dir with the given path.
def get_file(self, source, destination='.', scp='OFF', scp_preserve_times=False)
Calls :py:meth:AbstractSFTPClient.get_file with the given arguments.
def put_directory(self, source, destination='.', mode='0o744', newline='', recursive=False, scp='OFF', scp_preserve_times=False)
Calls :py:meth:AbstractSFTPClient.put_directory with the given arguments and the connection specific ...
def start_command(self, command, sudo=False, sudo_password=None, invoke_subsystem=False, forward_agent=False)
Starts the execution of the command on the remote host.
def _start_command(self, command, sudo=False, sudo_password=None, invoke_subsystem=False, forward_agent=False)
def login_with_public_key(self, username, keyfile, password, allow_agent=False, look_for_keys=False, delay=None, proxy_cmd=None, jumphost_connection=None, read_config=False, keep_alive_interval='0 seconds')
Logs into the remote host using the public key authentication.
def get_directory(self, source, destination='.', recursive=False, scp='OFF', scp_preserve_times=False)
Calls :py:meth:AbstractSFTPClient.get_directory with the given arguments and the connection specific ...
def close(self)
Closes the connection.
def _create_sftp_client(self)
def scp_transfer_client(self)
def list_dir(self, path, pattern=None, absolute=False)
Calls :py:meth:.AbstractSFTPClient.list_dir with the given arguments.
def list_dirs_in_dir(self, path, pattern=None, absolute=False)
Calls :py:meth:AbstractSFTPClient.list_dirs_in_dir with the given arguments.
def read(self, delay=None)
Reads all output available in the current shell.
def read_until_prompt(self, strip_prompt=False)
Reads output from the current shell until the prompt is encountered or the timeout expires.
def _read_login_output(self, delay)
def read_command_output(self, timeout=None, output_during_execution=False, output_if_timeout=False)
Reads the output of the previous started command.
shell
Gets the shell for the connection.
def _read_until(self, matcher, expected, timeout=None)
def enable_logging(path)
Enables logging of SSH events to a file.
def _strip_prompt(self, output)
scp_transfer_client
Gets the SCP client for the file transfer.
def read_char(self)
Reads a single Unicode character from the current shell.
def get_banner_without_login(host, port=22)
def login(self, username=None, password=None, allow_agent=False, look_for_keys=False, delay=None, proxy_cmd=None, read_config=False, jumphost_connection=None, keep_alive_interval='0 seconds')
Logs into the remote host using password authentication.
scp_all_client
Gets the SCP client for the file transfer.
sftp_client
Gets the SFTP client for the connection.
def write_until_expected(self, text, expected, timeout, interval)
Writes text repeatedly in the current shell until the expected appears in the output or the timeout e...
def _create_scp_all_client(self)
def _login_with_public_key(self, username, keyfile, password, allow_agent, look_for_keys, proxy_cmd, jumphost_index_or_alias, read_config, keep_alive_interval)
def __init__(self, host, alias=None, port=22, timeout=3, newline='LF', prompt=None, term_type='vt100', width=80, height=24, path_separator='/', encoding='utf8', escape_ansi=False, encoding_errors='strict')
def read_until_newline(self)
Reads output from the current shell until a newline character is encountered or the timeout expires.
def list_files_in_dir(self, path, pattern=None, absolute=False)
Calls :py:meth:AbstractSFTPClient.list_files_in_dir with the given arguments.
def write(self, text, add_newline=False)
Writes text in the current shell.
def read_until_regexp_with_prefix(self, regexp, prefix)
Read and return from output until regexp matches prefix + output.
def read_until(self, expected)
Reads output from the current shell until the expected text is encountered or the timeout expires.
def execute_command(self, command, sudo=False, sudo_password=None, timeout=None, output_during_execution=False, output_if_timeout=False, invoke_subsystem=False, forward_agent=False)
Executes the command on the remote host.
def is_file(self, path)
Calls :py:meth:AbstractSFTPClient.is_file with the given path.
def _get_files_for_scp_all(self, source)
def _login(self, username, password, allow_agent, look_for_keys, proxy_cmd, read_config, jumphost_connection, keep_alive_interval)
def _verify_key_file(self, keyfile)
def _delayed_read(self, delay)
def _create_client(self, scp)
def read_until_regexp(self, regexp)
Reads output from the current shell until the regexp matches or the timeout expires.
def _create_scp_transfer_client(self)
Base class for the shell implementation.
def write(self, text)
Writes the text in the current shell.
def read(self)
Reads all the output from the shell.
def read_byte(self)
Reads a single byte from the shell.
Wrapper class for the language specific file information objects.
def is_directory(self)
Checks if this file is a directory.
def __init__(self, name, mode)
def is_link(self)
Checks if this file is a symbolic link.
def is_regular(self)
Checks if this file is a regular file.
def __init__(self, host, alias, port, timeout, newline, prompt, term_type, width, height, path_separator, encoding, escape_ansi, encoding_errors)
A simple configuration class.
Integer value to be stored in stored in :py:class:Configuration.
New line sequence to be stored in :py:class:Configuration.
String value to be stored in :py:class:Configuration.
Time string to be stored in :py:class:Configuration.