diff --git a/exec_helpers/_api.py b/exec_helpers/_api.py
index 3283474..55c32ad 100644
--- a/exec_helpers/_api.py
+++ b/exec_helpers/_api.py
@@ -33,7 +33,6 @@ from exec_helpers import constants
 from exec_helpers import exceptions
 from exec_helpers import exec_result  # noqa  # pylint: disable=unused-import
 from exec_helpers import proc_enums
-from exec_helpers import _log_templates
 
 _type_exit_codes = typing.Union[int, proc_enums.ExitCodes]
 _type_expected = typing.Optional[typing.Iterable[_type_exit_codes]]
@@ -249,7 +248,7 @@ class ExecHelper(object):
                 verbose=verbose,
                 **kwargs
             )
-            message = _log_templates.CMD_RESULT.format(result=result)
+            message = "Command {result.cmd!r} exit code: {result.exit_code!s}".format(result=result)
             self.logger.log(
                 level=logging.INFO if verbose else logging.DEBUG,
                 msg=message
@@ -292,7 +291,8 @@ class ExecHelper(object):
         ret = self.execute(command, verbose, timeout, **kwargs)
         if ret['exit_code'] not in expected:
             message = (
-                _log_templates.CMD_UNEXPECTED_EXIT_CODE.format(
+                "{append}Command {result.cmd!r} returned exit code "
+                "{result.exit_code!s} while expected {expected!s}".format(
                     append=error_info + '\n' if error_info else '',
                     result=ret,
                     expected=expected
@@ -339,7 +339,8 @@ class ExecHelper(object):
             error_info=error_info, raise_on_err=raise_on_err, **kwargs)
         if ret['stderr']:
             message = (
-                _log_templates.CMD_UNEXPECTED_STDERR.format(
+                "{append}Command {result.cmd!r} STDERR while not expected\n"
+                "\texit code: {result.exit_code!s}".format(
                     append=error_info + '\n' if error_info else '',
                     result=ret,
                 ))
diff --git a/exec_helpers/_log_templates.py b/exec_helpers/_log_templates.py
index d3f8c3b..56cda0f 100644
--- a/exec_helpers/_log_templates.py
+++ b/exec_helpers/_log_templates.py
@@ -20,18 +20,10 @@ from __future__ import absolute_import
 from __future__ import division
 from __future__ import unicode_literals
 
-CMD_EXEC = "Executing command:\n{cmd!s}\n"
-CMD_RESULT = "Command exit code '{result.exit_code!s}':\n{result.cmd}\n"
-CMD_UNEXPECTED_EXIT_CODE = (
-    "{append}Command '{result.cmd}' returned exit code '{result.exit_code!s}' "
-    "while expected '{expected!s}'"
-)
-CMD_UNEXPECTED_STDERR = (
-    "{append}Command '{result.cmd}' STDERR while not expected\n"
-    "\texit code: '{result.exit_code!s}'"
-)
+CMD_EXEC = "Executing command:\n{cmd!r}\n"
+
 CMD_WAIT_ERROR = (
-    "Wait for '{result.cmd}' during {timeout!s}s: no return code!\n"
+    "Wait for {result.cmd!r} during {timeout!s}s: no return code!\n"
     '\tSTDOUT:\n'
     '{result.stdout_brief}\n'
     '\tSTDERR"\n'
diff --git a/exec_helpers/_ssh_client_base.py b/exec_helpers/_ssh_client_base.py
index 8ac7d88..e30ca28 100644
--- a/exec_helpers/_ssh_client_base.py
+++ b/exec_helpers/_ssh_client_base.py
@@ -50,7 +50,6 @@ from exec_helpers import _log_templates
 
 __all__ = ('SSHClientBase', )
 
-logger = logging.getLogger(__name__)
 logging.getLogger('paramiko').setLevel(logging.WARNING)
 logging.getLogger('iso8601').setLevel(logging.WARNING)
 
@@ -59,9 +58,6 @@ _type_ConnectSSH = typing.Union[
 ]
 _type_RSAKeys = typing.Iterable[paramiko.RSAKey]
 _type_exit_codes = typing.Union[int, proc_enums.ExitCodes]
-_type_multiple_results = typing.Dict[
-    typing.Tuple[str, int], exec_result.ExecResult
-]
 _type_execute_async = typing.Tuple[
     paramiko.Channel,
     paramiko.ChannelFile,
@@ -149,7 +145,7 @@ class _MemorizedSSH(type):
                 try:
                     ssh.execute('cd ~', timeout=5)
                 except BaseException:  # Note: Do not change to lower level!
-                    logger.debug('Reconnect {}'.format(ssh))
+                    ssh.logger.debug('Reconnect')
                     ssh.reconnect()
                 return ssh
             if (
@@ -158,7 +154,7 @@ class _MemorizedSSH(type):
             ):    # pragma: no cover
                 # If we have only cache reference and temporary getrefcount
                 # reference: close connection before deletion
-                logger.debug('Closing {} as unused'.format(cls.__cache[key]))
+                cls.__cache[key].logger.debug('Closing as unused')
                 cls.__cache[key].close()
             del cls.__cache[key]
         # noinspection PyArgumentList
@@ -186,7 +182,7 @@ class _MemorizedSSH(type):
                 CPYTHON and
                 sys.getrefcount(ssh) == n_count
             ):  # pragma: no cover
-                logger.debug('Closing {} as unused'.format(ssh))
+                ssh.logger.debug('Closing as unused')
                 ssh.close()
         mcs.__cache = {}
 
@@ -306,7 +302,9 @@ class SSHClientBase(six.with_metaclass(_MemorizedSSH, _api.ExecHelper)):
         .. note:: auth has priority over username/password/private_keys
         """
         super(SSHClientBase, self).__init__(
-            logger=logger.getChild(
+            logger=logging.getLogger(
+                self.__class__.__name__
+            ).getChild(
                 '{host}:{port}'.format(host=host, port=port)
             ),
         )
@@ -376,7 +374,7 @@ class SSHClientBase(six.with_metaclass(_MemorizedSSH, _api.ExecHelper)):
             auth=self.auth
         )
 
-    def __str__(self):
+    def __str__(self):  # pragma: no cover
         """Representation for debug purposes."""
         return '{cls}(host={host}, port={port}) for user {user}'.format(
             cls=self.__class__.__name__, host=self.hostname, port=self.port,
@@ -832,7 +830,7 @@ class SSHClientBase(six.with_metaclass(_MemorizedSSH, _api.ExecHelper)):
         expected=None,  # type: typing.Optional[typing.Iterable[int]]
         raise_on_err=True,  # type: bool
         **kwargs
-    ):  # type: (...) -> _type_multiple_results
+    ):  # type: (...) -> typing.Dict[typing.Tuple[str, int], exec_result.ExecResult]
         """Execute command on multiple remotes in async mode.
 
         :param remotes: Connections to execute on
diff --git a/exec_helpers/ssh_auth.py b/exec_helpers/ssh_auth.py
index 7ab9f98..63ca33b 100644
--- a/exec_helpers/ssh_auth.py
+++ b/exec_helpers/ssh_auth.py
@@ -187,9 +187,7 @@ class SSHAuth(object):
                     logger.exception('No password has been set!')
                     raise
                 else:
-                    logger.critical(
-                        'Unexpected PasswordRequiredException, '
-                        'when password is set!')
+                    logger.critical('Unexpected PasswordRequiredException, when password is set!')
                     raise
             except (paramiko.AuthenticationException,
                     paramiko.BadHostKeyException):

exec_helpers._ssh_client_base is incorrect logger prefix from private section
Should be `exec_helpers.ssh_client`
diff --git a/test/test_ssh_client.py b/test/test_ssh_client.py
index 3a3c4a3..9119773 100644
--- a/test/test_ssh_client.py
+++ b/test/test_ssh_client.py
@@ -53,7 +53,7 @@ port = 22
 username = 'user'
 password = 'pass'
 command = 'ls ~\nline 2\nline 3\nline с кирилицей'
-command_log = u"Executing command:\n{!s}\n".format(command.rstrip())
+command_log = u"Executing command:\n{!r}\n".format(command.rstrip())
 stdout_list = [b' \n', b'2\n', b'3\n', b' \n']
 stdout_str = b''.join(stdout_list).strip().decode('utf-8')
 stderr_list = [b' \n', b'0\n', b'1\n', b' \n']
@@ -64,7 +64,7 @@ encoded_cmd = base64.b64encode(
 print_stdin = 'read line; echo "$line"'
 
 
-@mock.patch('exec_helpers._ssh_client_base.logger', autospec=True)
+@mock.patch('logging.getLogger', autospec=True)
 @mock.patch('paramiko.AutoAddPolicy', autospec=True, return_value='AutoAddPolicy')
 @mock.patch('paramiko.SSHClient', autospec=True)
 class TestExecute(unittest.TestCase):
@@ -89,8 +89,7 @@ class TestExecute(unittest.TestCase):
 
     @staticmethod
     def gen_cmd_result_log_message(result):
-        return (u"Command exit code '{code!s}':\n{cmd!s}\n"
-                .format(cmd=result.cmd.rstrip(), code=result.exit_code))
+        return u"Command {result.cmd!r} exit code: {result.exit_code!s}".format(result=result)
 
     def test_001_execute_async(self, client, policy, logger):
         chan = mock.Mock()
@@ -116,7 +115,8 @@ class TestExecute(unittest.TestCase):
             mock.call.makefile_stderr('rb'),
             mock.call.exec_command('{}\n'.format(command))
         ))
-        log = logger.getChild('{host}:{port}'.format(host=host, port=port))
+        # raise ValueError(logger.mock_calls)
+        log = logger(ssh.__class__.__name__).getChild('{host}:{port}'.format(host=host, port=port))
         self.assertIn(
             mock.call.log(level=logging.DEBUG, msg=command_log),
             log.mock_calls
@@ -151,7 +151,7 @@ class TestExecute(unittest.TestCase):
             mock.call.makefile_stderr('rb'),
             mock.call.exec_command('{}\n'.format(command))
         ))
-        log = logger.getChild('{host}:{port}'.format(host=host, port=port))
+        log = logger(ssh.__class__.__name__).getChild('{host}:{port}'.format(host=host, port=port))
         self.assertIn(
             mock.call.log(level=logging.DEBUG, msg=command_log),
             log.mock_calls
@@ -235,7 +235,7 @@ class TestExecute(unittest.TestCase):
                 "sudo -S bash -c '"
                 "eval \"$(base64 -d <(echo \"{0}\"))\"'".format(encoded_cmd))
         ))
-        log = logger.getChild('{host}:{port}'.format(host=host, port=port))
+        log = logger(ssh.__class__.__name__).getChild('{host}:{port}'.format(host=host, port=port))
         self.assertIn(
             mock.call.log(level=logging.DEBUG, msg=command_log),
             log.mock_calls
@@ -271,7 +271,7 @@ class TestExecute(unittest.TestCase):
                 "sudo -S bash -c '"
                 "eval \"$(base64 -d <(echo \"{0}\"))\"'".format(encoded_cmd))
         ))
-        log = logger.getChild('{host}:{port}'.format(host=host, port=port))
+        log = logger(ssh.__class__.__name__).getChild('{host}:{port}'.format(host=host, port=port))
         self.assertIn(
             mock.call.log(level=logging.DEBUG, msg=command_log),
             log.mock_calls
@@ -303,7 +303,7 @@ class TestExecute(unittest.TestCase):
             mock.call.makefile_stderr('rb'),
             mock.call.exec_command('{}\n'.format(command))
         ))
-        log = logger.getChild('{host}:{port}'.format(host=host, port=port))
+        log = logger(ssh.__class__.__name__).getChild('{host}:{port}'.format(host=host, port=port))
         self.assertIn(
             mock.call.log(level=logging.DEBUG, msg=command_log),
             log.mock_calls
@@ -335,7 +335,7 @@ class TestExecute(unittest.TestCase):
             mock.call.makefile_stderr('rb'),
             mock.call.exec_command('{}\n'.format(command))
         ))
-        log = logger.getChild('{host}:{port}'.format(host=host, port=port))
+        log = logger(ssh.__class__.__name__).getChild('{host}:{port}'.format(host=host, port=port))
         self.assertIn(
             mock.call.log(level=logging.DEBUG, msg=command_log),
             log.mock_calls
@@ -380,7 +380,7 @@ class TestExecute(unittest.TestCase):
                 "sudo -S bash -c '"
                 "eval \"$(base64 -d <(echo \"{0}\"))\"'".format(encoded_cmd))
         ))
-        log = logger.getChild('{host}:{port}'.format(host=host, port=port))
+        log = logger(ssh.__class__.__name__).getChild('{host}:{port}'.format(host=host, port=port))
         self.assertIn(
             mock.call.log(level=logging.DEBUG, msg=command_log),
             log.mock_calls
@@ -410,7 +410,7 @@ class TestExecute(unittest.TestCase):
             mock.call.makefile_stderr('rb'),
             mock.call.exec_command('{}\n'.format(command))
         ))
-        log = logger.getChild('{host}:{port}'.format(host=host, port=port))
+        log = logger(ssh.__class__.__name__).getChild('{host}:{port}'.format(host=host, port=port))
         self.assertIn(
             mock.call.log(level=logging.INFO, msg=command_log),
             log.mock_calls
@@ -420,7 +420,7 @@ class TestExecute(unittest.TestCase):
         cmd = "USE='secret=secret_pass' do task"
         log_mask_re = r"secret\s*=\s*([A-Z-a-z0-9_\-]+)"
         masked_cmd = "USE='secret=<*masked*>' do task"
-        cmd_log = u"Executing command:\n{!s}\n".format(masked_cmd)
+        cmd_log = u"Executing command:\n{!r}\n".format(masked_cmd)
 
         chan = mock.Mock()
         open_session = mock.Mock(return_value=chan)
@@ -445,7 +445,7 @@ class TestExecute(unittest.TestCase):
             mock.call.makefile_stderr('rb'),
             mock.call.exec_command('{}\n'.format(cmd))
         ))
-        log = logger.getChild('{host}:{port}'.format(host=host, port=port))
+        log = logger(ssh.__class__.__name__).getChild('{host}:{port}'.format(host=host, port=port))
         self.assertIn(
             mock.call.log(level=logging.DEBUG, msg=cmd_log),
             log.mock_calls
@@ -620,7 +620,7 @@ class TestExecute(unittest.TestCase):
         open_session.assert_called_once()
         stdin.assert_not_called()
 
-        log = logger.getChild('{host}:{port}'.format(host=host, port=port))
+        log = logger(ssh.__class__.__name__).getChild('{host}:{port}'.format(host=host, port=port))
         log.warning.assert_called_once_with('STDIN Send failed: closed channel')
 
         self.assertIn(chan, result)
@@ -777,7 +777,7 @@ class TestExecute(unittest.TestCase):
         execute_async.assert_called_once_with(command, verbose=False)
         chan.assert_has_calls((mock.call.status_event.is_set(), ))
         message = self.gen_cmd_result_log_message(result)
-        log = logger.getChild('{host}:{port}'.format(host=host, port=port)).log
+        log = logger(ssh.__class__.__name__).getChild('{host}:{port}'.format(host=host, port=port)).log
         log.assert_has_calls(
             [
                 mock.call(
@@ -824,7 +824,7 @@ class TestExecute(unittest.TestCase):
         chan.assert_has_calls((mock.call.status_event.is_set(), ))
 
         message = self.gen_cmd_result_log_message(result)
-        log = logger.getChild('{host}:{port}'.format(host=host, port=port)).log
+        log = logger(ssh.__class__.__name__).getChild('{host}:{port}'.format(host=host, port=port)).log
         log.assert_has_calls(
             [
                 mock.call(
@@ -872,7 +872,7 @@ class TestExecute(unittest.TestCase):
         execute_async.assert_called_once_with(
             command, verbose=False, open_stdout=False)
         message = self.gen_cmd_result_log_message(result)
-        log = logger.getChild('{host}:{port}'.format(host=host, port=port)).log
+        log = logger(ssh.__class__.__name__).getChild('{host}:{port}'.format(host=host, port=port)).log
         log.assert_has_calls(
             [
                 mock.call(
@@ -916,7 +916,7 @@ class TestExecute(unittest.TestCase):
         execute_async.assert_called_once_with(
             command, verbose=False, open_stderr=False)
         message = self.gen_cmd_result_log_message(result)
-        log = logger.getChild('{host}:{port}'.format(host=host, port=port)).log
+        log = logger(ssh.__class__.__name__).getChild('{host}:{port}'.format(host=host, port=port)).log
         log.assert_has_calls(
             [
                 mock.call(
@@ -968,7 +968,7 @@ class TestExecute(unittest.TestCase):
             open_stderr=False
         )
         message = self.gen_cmd_result_log_message(result)
-        log = logger.getChild('{host}:{port}'.format(host=host, port=port)).log
+        log = logger(ssh.__class__.__name__).getChild('{host}:{port}'.format(host=host, port=port)).log
         log.assert_has_calls(
             [
                 mock.call(level=logging.DEBUG, msg=message),
@@ -1003,7 +1003,7 @@ class TestExecute(unittest.TestCase):
         execute_async.assert_called_once_with(command, verbose=False)
         chan.assert_has_calls((mock.call.status_event.is_set(), ))
         message = self.gen_cmd_result_log_message(result)
-        log = logger.getChild('{host}:{port}'.format(host=host, port=port)).log
+        log = logger(ssh.__class__.__name__).getChild('{host}:{port}'.format(host=host, port=port)).log
         self.assertIn(
             mock.call(level=logging.DEBUG, msg=message),
             log.mock_calls
@@ -1069,7 +1069,7 @@ class TestExecute(unittest.TestCase):
             cmd, log_mask_re=log_mask_re, verbose=False)
         chan.assert_has_calls((mock.call.status_event.is_set(),))
         message = self.gen_cmd_result_log_message(result)
-        log = logger.getChild('{host}:{port}'.format(host=host, port=port)).log
+        log = logger(ssh.__class__.__name__).getChild('{host}:{port}'.format(host=host, port=port)).log
         log.assert_has_calls(
             [
                 mock.call(
@@ -1297,7 +1297,7 @@ class TestExecute(unittest.TestCase):
             error_info=None, raise_on_err=raise_on_err)
 
 
-@mock.patch('exec_helpers._ssh_client_base.logger', autospec=True)
+@mock.patch('logging.getLogger', autospec=True)
 @mock.patch('paramiko.AutoAddPolicy', autospec=True, return_value='AutoAddPolicy')
 @mock.patch('paramiko.SSHClient', autospec=True)
 @mock.patch('paramiko.Transport', autospec=True)
@@ -1528,7 +1528,7 @@ class TestExecuteThrowHost(unittest.TestCase):
         ))
 
 
-@mock.patch('exec_helpers._ssh_client_base.logger', autospec=True)
+@mock.patch('logging.getLogger', autospec=True)
 @mock.patch('paramiko.AutoAddPolicy', autospec=True, return_value='AutoAddPolicy')
 @mock.patch('paramiko.SSHClient', autospec=True)
 class TestSftp(unittest.TestCase):
diff --git a/test/test_ssh_client_init.py b/test/test_ssh_client_init.py
index 8117eff..a5f400d 100644
--- a/test/test_ssh_client_init.py
+++ b/test/test_ssh_client_init.py
@@ -381,9 +381,10 @@ class TestSSHClientInit(unittest.TestCase):
         _ssh.attach_mock(mock.Mock(return_value=_sftp), 'open_sftp')
 
         with mock.patch(
-            'exec_helpers._ssh_client_base.logger',
+            'logging.getLogger',
             autospec=True
-        ) as ssh_logger:
+        ) as get_logger:
+            ssh_logger = get_logger(exec_helpers.SSHClient.__name__)
 
             ssh = exec_helpers.SSHClient(
                 host=host,
@@ -408,13 +409,13 @@ class TestSSHClientInit(unittest.TestCase):
 
             ssh.close()
 
-        log = ssh_logger.getChild(
-            '{host}:{port}'.format(host=host, port=port)
-        )
-        log.assert_has_calls((
-            mock.call.exception('Could not close ssh connection'),
-            mock.call.exception('Could not close sftp connection'),
-        ))
+            log = ssh_logger.getChild(
+                '{host}:{port}'.format(host=host, port=port)
+            )
+            log.assert_has_calls((
+                mock.call.exception('Could not close ssh connection'),
+                mock.call.exception('Could not close sftp connection'),
+            ))
 
     def test_014_init_reconnect(self, client, policy, logger):
         """Test reconnect
@@ -619,9 +620,10 @@ class TestSSHClientInit(unittest.TestCase):
         client.return_value = _ssh
 
         with mock.patch(
-            'exec_helpers._ssh_client_base.logger',
+            'logging.getLogger',
             autospec=True
-        ) as ssh_logger:
+        ) as get_logger:
+            ssh_logger = get_logger(exec_helpers.SSHClient.__name__)
 
             ssh = exec_helpers.SSHClient(
                 host=host, auth=exec_helpers.SSHAuth(password=password))
@@ -631,14 +633,14 @@ class TestSSHClientInit(unittest.TestCase):
                 # noinspection PyStatementEffect
                 ssh._sftp
                 # pylint: enable=pointless-statement
-        log = ssh_logger.getChild(
-            '{host}:{port}'.format(host=host, port=port)
-        )
-        log.assert_has_calls((
-            mock.call.debug('SFTP is not connected, try to connect...'),
-            mock.call.warning(
-                'SFTP enable failed! SSH only is accessible.'),
-        ))
+            log = ssh_logger.getChild(
+                '{host}:{port}'.format(host=host, port=port)
+            )
+            log.assert_has_calls((
+                mock.call.debug('SFTP is not connected, try to connect...'),
+                mock.call.warning(
+                    'SFTP enable failed! SSH only is accessible.'),
+            ))
 
     def test_022_init_sftp_repair(self, client, policy, logger):
         _sftp = mock.Mock()
@@ -652,9 +654,10 @@ class TestSSHClientInit(unittest.TestCase):
         client.return_value = _ssh
 
         with mock.patch(
-            'exec_helpers._ssh_client_base.logger',
+            'logging.getLogger',
             autospec=True
-        ) as ssh_logger:
+        ) as get_logger:
+            ssh_logger = get_logger(exec_helpers.SSHClient.__name__)
 
             ssh = exec_helpers.SSHClient(
                 host=host, auth=exec_helpers.SSHAuth(password=password)
@@ -670,12 +673,12 @@ class TestSSHClientInit(unittest.TestCase):
 
             sftp = ssh._sftp
             self.assertEqual(sftp, open_sftp())
-        log = ssh_logger.getChild(
-            '{host}:{port}'.format(host=host, port=port)
-        )
-        log.assert_has_calls((
-            mock.call.debug('SFTP is not connected, try to connect...'),
-        ))
+            log = ssh_logger.getChild(
+                '{host}:{port}'.format(host=host, port=port)
+            )
+            log.assert_has_calls((
+                mock.call.debug('SFTP is not connected, try to connect...'),
+            ))
 
     @mock.patch('exec_helpers.exec_result.ExecResult', autospec=True)
     def test_023_init_memorize(
diff --git a/test/test_sshauth.py b/test/test_sshauth.py
index 0c4ce5f..60c1cfe 100644
--- a/test/test_sshauth.py
+++ b/test/test_sshauth.py
@@ -36,10 +36,7 @@ import exec_helpers
 
 
 def gen_private_keys(amount=1):
-    keys = []
-    for _ in range(amount):
-        keys.append(paramiko.RSAKey.generate(1024))
-    return keys
+    return [paramiko.RSAKey.generate(1024) for _ in range(amount)]
 
 
 def gen_public_key(private_key=None):
diff --git a/test/test_subprocess_runner.py b/test/test_subprocess_runner.py
index ef3449a..04555c7 100644
--- a/test/test_subprocess_runner.py
+++ b/test/test_subprocess_runner.py
@@ -32,7 +32,7 @@ import exec_helpers
 from exec_helpers import subprocess_runner
 
 command = 'ls ~\nline 2\nline 3\nline с кирилицей'
-command_log = u"Executing command:\n{!s}\n".format(command.rstrip())
+command_log = u"Executing command:\n{!r}\n".format(command.rstrip())
 stdout_list = [b' \n', b'2\n', b'3\n', b' \n']
 stderr_list = [b' \n', b'0\n', b'1\n', b' \n']
 print_stdin = 'read line; echo "$line"'
@@ -105,8 +105,7 @@ class TestSubprocessRunner(unittest.TestCase):
 
     @staticmethod
     def gen_cmd_result_log_message(result):
-        return ("Command exit code '{code!s}':\n{cmd!s}\n"
-                .format(cmd=result.cmd.rstrip(), code=result.exit_code))
+        return u"Command {result.cmd!r} exit code: {result.exit_code!s}".format(result=result)
 
     def test_001_call(
         self,
@@ -369,7 +368,7 @@ class TestSubprocessRunner(unittest.TestCase):
         cmd = "USE='secret=secret_pass' do task"
         log_mask_re = r"secret\s*=\s*([A-Z-a-z0-9_\-]+)"
         masked_cmd = "USE='secret=<*masked*>' do task"
-        cmd_log = u"Executing command:\n{!s}\n".format(masked_cmd)
+        cmd_log = u"Executing command:\n{!r}\n".format(masked_cmd)
 
         popen_obj, exp_result = self.prepare_close(
             popen,
@@ -424,7 +423,7 @@ class TestSubprocessRunner(unittest.TestCase):
         cmd = "USE='secret=secret_pass' do task"
         log_mask_re = r"secret\s*=\s*([A-Z-a-z0-9_\-]+)"
         masked_cmd = "USE='secret=<*masked*>' do task"
-        cmd_log = u"Executing command:\n{!s}\n".format(masked_cmd)
+        cmd_log = u"Executing command:\n{!r}\n".format(masked_cmd)
 
         popen_obj, exp_result = self.prepare_close(
             popen,

pip install -e .[dev]
parse_log_pytest
requirements.txt
pytest pytest-cov pytest-html mock
apt-get update apt-get install -y gcc
3.9
requirements/base.txt
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
advanced-descriptors==4.0.3
bcrypt==4.3.0
cffi==1.17.1
coverage==7.8.0
cryptography==44.0.2
exceptiongroup==1.2.2
-e git+https://github.com/python-useful-helpers/exec-helpers.git@63166d1ac340be47d64488a5b84a9d6fa317e8fe#egg=exec_helpers
iniconfig==2.1.0
Jinja2==3.1.6
MarkupSafe==3.0.2
mock==5.2.0
packaging==24.2
paramiko==3.5.1
pluggy==1.5.0
pycparser==2.22
PyNaCl==1.5.0
pytest==8.3.5
pytest-cov==6.0.0
pytest-html==4.1.1
pytest-metadata==3.1.1
PyYAML==6.0.2
six==1.17.0
tenacity==9.0.0
threaded==4.2.0
tomli==2.2.1

name: exec-helpers
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - ca-certificates=2025.2.25=h06a4308_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.4.4=h6a678d5_1
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=3.0.16=h5eee18b_0
  - pip=25.0=py39h06a4308_0
  - python=3.9.21=he870216_1
  - readline=8.2=h5eee18b_0
  - setuptools=75.8.0=py39h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - tzdata=2025a=h04d1e81_0
  - wheel=0.45.1=py39h06a4308_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - advanced-descriptors==4.0.3
      - bcrypt==4.3.0
      - cffi==1.17.1
      - coverage==7.8.0
      - cryptography==44.0.2
      - exceptiongroup==1.2.2
      - exec-helpers==1.2.1
      - iniconfig==2.1.0
      - jinja2==3.1.6
      - markupsafe==3.0.2
      - mock==5.2.0
      - packaging==24.2
      - paramiko==3.5.1
      - pluggy==1.5.0
      - pycparser==2.22
      - pynacl==1.5.0
      - pytest==8.3.5
      - pytest-cov==6.0.0
      - pytest-html==4.1.1
      - pytest-metadata==3.1.1
      - pyyaml==6.0.2
      - six==1.17.0
      - tenacity==9.0.0
      - threaded==4.2.0
      - tomli==2.2.1
prefix: /opt/conda/envs/exec-helpers

test/test_ssh_client.py::TestExecute::test_001_execute_async test/test_ssh_client.py::TestExecute::test_002_execute_async_pty test/test_ssh_client.py::TestExecute::test_004_execute_async_sudo test/test_ssh_client.py::TestExecute::test_005_execute_async_with_sudo_enforce test/test_ssh_client.py::TestExecute::test_006_execute_async_with_no_sudo_enforce test/test_ssh_client.py::TestExecute::test_007_execute_async_with_sudo_none_enforce test/test_ssh_client.py::TestExecute::test_008_execute_async_sudo_password test/test_ssh_client.py::TestExecute::test_009_execute_async_verbose test/test_ssh_client.py::TestExecute::test_010_execute_async_mask_command test/test_ssh_client.py::TestExecute::test_014_check_stdin_closed test/test_ssh_client.py::TestExecute::test_019_execute test/test_ssh_client.py::TestExecute::test_020_execute_verbose test/test_ssh_client.py::TestExecute::test_021_execute_no_stdout test/test_ssh_client.py::TestExecute::test_022_execute_no_stderr test/test_ssh_client.py::TestExecute::test_023_execute_no_stdout_stderr test/test_ssh_client.py::TestExecute::test_024_execute_timeout test/test_ssh_client.py::TestExecute::test_026_execute_mask_command test/test_ssh_client_init.py::TestSSHClientInit::test_013_init_clear_failed test/test_ssh_client_init.py::TestSSHClientInit::test_021_init_no_sftp test/test_ssh_client_init.py::TestSSHClientInit::test_022_init_sftp_repair test/test_subprocess_runner.py::TestSubprocessRunner::test_001_call test/test_subprocess_runner.py::TestSubprocessRunner::test_002_call_verbose test/test_subprocess_runner.py::TestSubprocessRunner::test_005_execute_no_stdout test/test_subprocess_runner.py::TestSubprocessRunner::test_006_execute_no_stderr test/test_subprocess_runner.py::TestSubprocessRunner::test_007_execute_no_stdout_stderr test/test_subprocess_runner.py::TestSubprocessRunner::test_008_execute_mask_global test/test_subprocess_runner.py::TestSubprocessRunner::test_009_execute_mask_local
test/test_ssh_client.py::TestExecute::test_003_execute_async_no_stdout_stderr test/test_ssh_client.py::TestExecute::test_011_check_stdin_str test/test_ssh_client.py::TestExecute::test_012_check_stdin_bytes test/test_ssh_client.py::TestExecute::test_013_check_stdin_bytearray test/test_ssh_client.py::TestExecute::test_015_keepalive test/test_ssh_client.py::TestExecute::test_016_no_keepalive test/test_ssh_client.py::TestExecute::test_017_keepalive_enforced test/test_ssh_client.py::TestExecute::test_018_no_keepalive_enforced test/test_ssh_client.py::TestExecute::test_025_execute_timeout_fail test/test_ssh_client.py::TestExecute::test_027_execute_together test/test_ssh_client.py::TestExecute::test_028_execute_together_exceptions test/test_ssh_client.py::TestExecute::test_029_check_call test/test_ssh_client.py::TestExecute::test_030_check_call_expected test/test_ssh_client.py::TestExecute::test_031_check_stderr test/test_ssh_client.py::TestExecuteThrowHost::test_01_execute_through_host_no_creds test/test_ssh_client.py::TestExecuteThrowHost::test_02_execute_through_host_auth test/test_ssh_client.py::TestExecuteThrowHost::test_03_execute_through_host_get_pty test/test_ssh_client.py::TestSftp::test_download test/test_ssh_client.py::TestSftp::test_exists test/test_ssh_client.py::TestSftp::test_isdir test/test_ssh_client.py::TestSftp::test_isfile test/test_ssh_client.py::TestSftp::test_mkdir test/test_ssh_client.py::TestSftp::test_open test/test_ssh_client.py::TestSftp::test_rm_rf test/test_ssh_client.py::TestSftp::test_stat test/test_ssh_client.py::TestSftp::test_upload_dir test/test_ssh_client.py::TestSftp::test_upload_file test/test_ssh_client_init.py::TestSSHClientInit::test_001_init_host test/test_ssh_client_init.py::TestSSHClientInit::test_002_init_alternate_port test/test_ssh_client_init.py::TestSSHClientInit::test_003_init_username test/test_ssh_client_init.py::TestSSHClientInit::test_004_init_username_password test/test_ssh_client_init.py::TestSSHClientInit::test_005_init_username_password_empty_keys test/test_ssh_client_init.py::TestSSHClientInit::test_006_init_username_single_key test/test_ssh_client_init.py::TestSSHClientInit::test_007_init_username_password_single_key test/test_ssh_client_init.py::TestSSHClientInit::test_008_init_username_multiple_keys test/test_ssh_client_init.py::TestSSHClientInit::test_009_init_username_password_multiple_keys test/test_ssh_client_init.py::TestSSHClientInit::test_010_init_auth test/test_ssh_client_init.py::TestSSHClientInit::test_011_init_auth_break test/test_ssh_client_init.py::TestSSHClientInit::test_012_init_context test/test_ssh_client_init.py::TestSSHClientInit::test_014_init_reconnect test/test_ssh_client_init.py::TestSSHClientInit::test_015_init_password_required test/test_ssh_client_init.py::TestSSHClientInit::test_016_init_password_broken test/test_ssh_client_init.py::TestSSHClientInit::test_017_init_auth_impossible_password test/test_ssh_client_init.py::TestSSHClientInit::test_018_init_auth_impossible_key test/test_ssh_client_init.py::TestSSHClientInit::test_019_init_auth_pass_no_key test/test_ssh_client_init.py::TestSSHClientInit::test_020_init_auth_brute_impossible test/test_ssh_client_init.py::TestSSHClientInit::test_023_init_memorize test/test_ssh_client_init.py::TestSSHClientInit::test_024_init_memorize_close_unused test/test_ssh_client_init.py::TestSSHClientInit::test_025_init_memorize_reconnect test/test_sshauth.py::TestSSHAuth::test_equality_copy test/test_sshauth.py::TestSSHAuth::test_init_username_key test/test_sshauth.py::TestSSHAuth::test_init_username_only test/test_sshauth.py::TestSSHAuth::test_init_username_password test/test_sshauth.py::TestSSHAuth::test_init_username_password_key test/test_sshauth.py::TestSSHAuth::test_init_username_password_key_keys test/test_sshauth.py::TestSSHAuth::test_init_username_password_keys test/test_subprocess_runner.py::TestSubprocessRunner::test_003_context_manager test/test_subprocess_runner.py::TestSubprocessRunner::test_004_check_stdin_str test/test_subprocess_runner.py::TestSubprocessRunner::test_004_execute_timeout_fail test/test_subprocess_runner.py::TestSubprocessRunner::test_005_check_stdin_bytes test/test_subprocess_runner.py::TestSubprocessRunner::test_006_check_stdin_bytearray test/test_subprocess_runner.py::TestSubprocessRunner::test_007_check_stdin_fail_broken_pipe test/test_subprocess_runner.py::TestSubprocessRunner::test_008_check_stdin_fail_closed_win test/test_subprocess_runner.py::TestSubprocessRunner::test_009_check_stdin_fail_write test/test_subprocess_runner.py::TestSubprocessRunner::test_010_check_stdin_fail_close_pipe test/test_subprocess_runner.py::TestSubprocessRunner::test_011_check_stdin_fail_close_pipe_win test/test_subprocess_runner.py::TestSubprocessRunner::test_012_check_stdin_fail_close test/test_subprocess_runner.py::TestSubprocessRunner::test_013_execute_timeout_done test/test_subprocess_runner.py::TestSubprocessRunnerHelpers::test_001_check_call test/test_subprocess_runner.py::TestSubprocessRunnerHelpers::test_002_check_call_expected test/test_subprocess_runner.py::TestSubprocessRunnerHelpers::test_003_check_stderr
exec_helpers/_log_templates.py exec_helpers/_api.py exec_helpers/_ssh_client_base.py exec_helpers/ssh_auth.py
exec_helpers/_log_templates.py exec_helpers/_api.py exec_helpers/_ssh_client_base.py exec_helpers/ssh_auth.py