From fe50a4c488fbc6571d6f2473c47b9d2137e6db32 Mon Sep 17 00:00:00 2001 From: Alexey Stepanov Date: Tue, 4 Sep 2018 11:10:33 +0200 Subject: [PATCH 1/2] Fix documentation (docstrings and RST) Signed-off-by: Alexey Stepanov --- README.rst | 18 +++++++------- doc/source/ExecResult.rst | 16 ++++++------- doc/source/SSHClient.rst | 12 +++++----- doc/source/Subprocess.rst | 8 +++---- doc/source/exceptions.rst | 10 ++++---- exec_helpers/_ssh_client_base.py | 40 ++++++++++++++++++++----------- exec_helpers/api.py | 21 +++++++--------- exec_helpers/exec_result.py | 16 ++++++------- exec_helpers/ssh_client.py | 8 ++----- exec_helpers/subprocess_runner.py | 9 ++++--- 10 files changed, 83 insertions(+), 75 deletions(-) diff --git a/README.rst b/README.rst index c426618..1f33084 100644 --- a/README.rst +++ b/README.rst @@ -129,7 +129,7 @@ This methods are almost the same for `SSHCleint` and `Subprocess`, except specif result = helper.execute( command, # type: str verbose=False, # type: bool - timeout=1 * 60 * 60, # type: typing.Optional[int] + timeout=1 * 60 * 60, # type: typing.Union[int, float, None] **kwargs ) @@ -139,7 +139,7 @@ This methods are almost the same for `SSHCleint` and `Subprocess`, except specif result = helper.check_call( command, # type: str verbose=False, # type: bool - timeout=1 * 60 * 60, # type: typing.Optional[int] + timeout=1 * 60 * 60, # type: type: typing.Union[int, float, None] error_info=None, # type: typing.Optional[str] expected=None, # type: typing.Optional[typing.Iterable[int]] raise_on_err=True, # type: bool @@ -151,7 +151,7 @@ This methods are almost the same for `SSHCleint` and `Subprocess`, except specif result = helper.check_stderr( command, # type: str verbose=False, # type: bool - timeout=1 * 60 * 60, # type: typing.Optional[int] + timeout=1 * 60 * 60, # type: type: typing.Union[int, float, None] error_info=None, # type: typing.Optional[str] raise_on_err=True, # type: bool ) @@ -187,10 +187,10 @@ Execution result object has a set of useful properties: * `stderr` -> `typing.Tuple[bytes]`. Raw stderr output. * `stdout_bin` -> `bytearray`. Binary stdout output. * `stderr_bin` -> `bytearray`. Binary stderr output. -* `stdout_str` -> `six.text_types`. Text representation of output. -* `stderr_str` -> `six.text_types`. Text representation of output. -* `stdout_brief` -> `six.text_types`. Up to 7 lines from stdout (3 first and 3 last if >7 lines). -* `stderr_brief` -> `six.text_types`. Up to 7 lines from stderr (3 first and 3 last if >7 lines). +* `stdout_str` -> `str`. Text representation of output. +* `stderr_str` -> `str`. Text representation of output. +* `stdout_brief` -> `str`. Up to 7 lines from stdout (3 first and 3 last if >7 lines). +* `stderr_brief` -> `str`. Up to 7 lines from stderr (3 first and 3 last if >7 lines). * `stdout_json` - STDOUT decoded as JSON. @@ -211,7 +211,7 @@ Possible to call commands in parallel on multiple hosts if it's not produce huge results = SSHClient.execute_together( remotes, # type: typing.Iterable[SSHClient] command, # type: str - timeout=1 * 60 * 60, # type: typing.Optional[int] + timeout=1 * 60 * 60, # type: type: typing.Union[int, float, None] expected=None, # type: typing.Optional[typing.Iterable[int]] raise_on_err=True # type: bool ) @@ -229,7 +229,7 @@ For execute through SSH host can be used `execute_through_host` method: command, # type: str auth=None, # type: typing.Optional[SSHAuth] target_port=22, # type: int - timeout=1 * 60 * 60, # type: typing.Optional[int] + timeout=1 * 60 * 60, # type: type: typing.Union[int, float, None] verbose=False, # type: bool get_pty=False, # type: bool ) diff --git a/doc/source/ExecResult.rst b/doc/source/ExecResult.rst index fb8362c..0b9f495 100644 --- a/doc/source/ExecResult.rst +++ b/doc/source/ExecResult.rst @@ -15,7 +15,7 @@ API: ExecResult :param cmd: command :type cmd: ``str`` :param stdin: STDIN - :type stdin: ``typing.Optional[str]`` + :type stdin: ``typing.Union[bytes, str, bytearray, None]`` :param stdout: binary STDOUT :type stdout: ``typing.Optional[typing.Iterable[bytes]]`` :param stderr: binary STDERR @@ -40,17 +40,17 @@ API: ExecResult .. py:attribute:: stdin - ``typing.Text`` + ``typing.Optional[str]`` Stdin input as string. .. py:attribute:: stdout - ``typing.Tuple[bytes]`` + ``typing.Tuple[bytes, ...]`` Stdout output as list of binaries. .. py:attribute:: stderr - ``typing.Tuple[bytes]`` + ``typing.Tuple[bytes, ...]`` Stderr output as list of binaries. .. py:attribute:: stdout_bin @@ -65,22 +65,22 @@ API: ExecResult .. py:attribute:: stdout_str - ``typing.Text`` + ``str`` Stdout output as string. .. py:attribute:: stderr_str - ``typing.Text`` + ``str`` Stderr output as string. .. py:attribute:: stdout_brief - ``typing.Text`` + ``str`` Brief stdout output (mostly for exceptions). .. py:attribute:: stderr_brief - ``typing.Text`` + ``str`` Brief stderr output (mostly for exceptions). .. py:attribute:: exit_code diff --git a/doc/source/SSHClient.rst b/doc/source/SSHClient.rst index 37cf9ac..895ea71 100644 --- a/doc/source/SSHClient.rst +++ b/doc/source/SSHClient.rst @@ -128,7 +128,7 @@ API: SSHClient and SSHAuth. :param command: Command for execution :type command: ``str`` :param stdin: pass STDIN text to the process - :type stdin: ``typing.Union[typing.AnyStr, bytearray, None]`` + :type stdin: ``typing.Union[str, bytes, bytearray, None]`` :param open_stdout: open STDOUT stream for read :type open_stdout: bool :param open_stderr: open STDERR stream for read @@ -153,7 +153,7 @@ API: SSHClient and SSHAuth. :param verbose: Produce log.info records for command call and output :type verbose: ``bool`` :param timeout: Timeout for command execution. - :type timeout: ``typing.Union[int, None]`` + :type timeout: ``typing.Union[int, float, None]`` :rtype: ExecResult :raises ExecHelperTimeoutError: Timeout exceeded @@ -168,7 +168,7 @@ API: SSHClient and SSHAuth. :param verbose: Produce log.info records for command call and output :type verbose: ``bool`` :param timeout: Timeout for command execution. - :type timeout: ``typing.Union[int, None]`` + :type timeout: ``typing.Union[int, float, None]`` :param error_info: Text for error details, if fail happens :type error_info: ``typing.Optional[str]`` :param expected: expected return codes (0 by default) @@ -190,7 +190,7 @@ API: SSHClient and SSHAuth. :param verbose: Produce log.info records for command call and output :type verbose: ``bool`` :param timeout: Timeout for command execution. - :type timeout: ``typing.Union[int, None]`` + :type timeout: ``typing.Union[int, float, None]`` :param error_info: Text for error details, if fail happens :type error_info: ``typing.Optional[str]`` :param raise_on_err: Raise exception on unexpected return code @@ -217,7 +217,7 @@ API: SSHClient and SSHAuth. :param verbose: Produce log.info records for command call and output :type verbose: ``bool`` :param timeout: Timeout for command execution. - :type timeout: ``typing.Union[int, None]`` + :type timeout: ``typing.Union[int, float, None]`` :param get_pty: open PTY on target machine :type get_pty: ``bool`` :rtype: ExecResult @@ -234,7 +234,7 @@ API: SSHClient and SSHAuth. :param command: Command for execution :type command: ``str`` :param timeout: Timeout for command execution. - :type timeout: ``typing.Union[int, None]`` + :type timeout: ``typing.Union[int, float, None]`` :param expected: expected return codes (0 by default) :type expected: ``typing.Optional[typing.Iterable[]]`` :param raise_on_err: Raise exception on unexpected return code diff --git a/doc/source/Subprocess.rst b/doc/source/Subprocess.rst index d9b76a5..9f6d10a 100644 --- a/doc/source/Subprocess.rst +++ b/doc/source/Subprocess.rst @@ -46,7 +46,7 @@ API: Subprocess :param command: Command for execution :type command: str :param stdin: pass STDIN text to the process - :type stdin: ``typing.Union[typing.AnyStr, bytearray, None]`` + :type stdin: ``typing.Union[str, bytes, bytearray, None]`` :param open_stdout: open STDOUT stream for read :type open_stdout: ``bool`` :param open_stderr: open STDERR stream for read @@ -69,7 +69,7 @@ API: Subprocess :param verbose: Produce log.info records for command call and output :type verbose: ``bool`` :param timeout: Timeout for command execution. - :type timeout: ``typing.Union[int, None]`` + :type timeout: ``typing.Union[int, float, None]`` :rtype: ExecResult :raises ExecHelperTimeoutError: Timeout exceeded @@ -88,7 +88,7 @@ API: Subprocess :param verbose: Produce log.info records for command call and output :type verbose: ``bool`` :param timeout: Timeout for command execution. - :type timeout: ``typing.Union[int, None]`` + :type timeout: ``typing.Union[int, float, None]`` :param error_info: Text for error details, if fail happens :type error_info: ``typing.Optional[str]`` :param expected: expected return codes (0 by default) @@ -111,7 +111,7 @@ API: Subprocess :param verbose: Produce log.info records for command call and output :type verbose: ``bool`` :param timeout: Timeout for command execution. - :type timeout: ``typing.Union[int, None]`` + :type timeout: ``typing.Union[int, float, None]`` :param error_info: Text for error details, if fail happens :type error_info: ``typing.Optional[str]`` :param raise_on_err: Raise exception on unexpected return code diff --git a/doc/source/exceptions.rst b/doc/source/exceptions.rst index 5d50d24..3568efd 100644 --- a/doc/source/exceptions.rst +++ b/doc/source/exceptions.rst @@ -36,7 +36,7 @@ API: exceptions .. py:attribute:: timeout - ``int`` + ``typing.Union[int, float]`` .. py:attribute:: result @@ -46,12 +46,12 @@ API: exceptions .. py:attribute:: stdout - ``typing.Text`` + ``str`` stdout string or brief string .. py:attribute:: stderr - ``typing.Text`` + ``str`` stdout string or brief string .. py:exception:: CalledProcessError(ExecCalledProcessError) @@ -92,12 +92,12 @@ API: exceptions .. py:attribute:: stdout - ``typing.Text`` + ``str`` stdout string or brief string .. py:attribute:: stderr - ``typing.Text`` + ``str`` stdout string or brief string .. py:exception:: ParallelCallExceptions(ExecCalledProcessError) diff --git a/exec_helpers/_ssh_client_base.py b/exec_helpers/_ssh_client_base.py index 9f91442..764ba99 100644 --- a/exec_helpers/_ssh_client_base.py +++ b/exec_helpers/_ssh_client_base.py @@ -16,6 +16,7 @@ """SSH client helper based on Paramiko. Base class.""" +import abc import base64 import collections import concurrent.futures @@ -58,7 +59,7 @@ CPYTHON = 'CPython' == platform.python_implementation() -class _MemorizedSSH(type): +class _MemorizedSSH(abc.ABCMeta): """Memorize metaclass for SSHClient. This class implements caching and managing of SSHClient connections. @@ -112,16 +113,23 @@ def __call__( # type: ignore auth: typing.Optional[ssh_auth.SSHAuth] = None, verbose: bool = True, ) -> 'SSHClientBase': - """Main memorize method: check for cached instance and return it. + """Main memorize method: check for cached instance and return it. API follows target __init__. + :param host: remote hostname :type host: str + :param port: remote ssh port :type port: int - :type username: str - :type password: str - :type private_keys: list - :type auth: ssh_auth.SSHAuth + :param username: remote username. + :type username: typing.Optional[str] + :param password: remote password + :type password: typing.Optional[str] + :param private_keys: private keys for connection + :type private_keys: typing.Optional[typing.Iterable[paramiko.RSAKey]] + :param auth: credentials for connection + :type auth: typing.Optional[ssh_auth.SSHAuth] + :param verbose: show additional error/warning messages :type verbose: bool - :rtype: SSHClient + :rtype: SSHClientBase """ if (host, port) in cls.__cache: key = host, port @@ -164,7 +172,7 @@ def __call__( # type: ignore def clear_cache(mcs: typing.Type['_MemorizedSSH']) -> None: """Clear cached connections for initialize new instance on next call. - getrefcount is used to check for usage. + getrefcount is used to check for usage, so connections closed on CPYTHON only. """ n_count = 3 # PY3: cache, ssh, temporary @@ -210,8 +218,8 @@ def __init__( ) -> None: """Context manager for call commands with sudo. - :type ssh: SSHClient - :type enforce: bool + :type ssh: SSHClientBase + :type enforce: typing.Optional[bool] """ self.__ssh = ssh self.__sudo_status = ssh.sudo_mode @@ -241,7 +249,7 @@ def __init__( ) -> None: """Context manager for keepalive management. - :type ssh: SSHClient + :type ssh: SSHClientBase :type enforce: bool :param enforce: Keep connection alive after context manager exit """ @@ -465,8 +473,8 @@ def _clear_cache(cls: typing.Type['SSHClientBase']) -> None: def __del__(self) -> None: """Destructor helper: close channel and threads BEFORE closing others. - Due to threading in paramiko, default destructor could generate asserts - on close, so we calling channel close before closing main ssh object. + Due to threading in paramiko, default destructor could generate asserts on close, + so we calling channel close before closing main ssh object. """ try: self.__ssh.close() @@ -540,6 +548,7 @@ def sudo( :param enforce: Enforce sudo enabled or disabled. By default: None :type enforce: typing.Optional[bool] + :rtype: typing.ContextManager """ return self.__get_sudo(ssh=self, enforce=enforce) @@ -551,6 +560,7 @@ def keepalive( :param enforce: Enforce keepalive enabled or disabled. :type enforce: bool + :rtype: typing.ContextManager .. Note:: Enter and exit ssh context manager is produced as well. .. versionadded:: 1.2.1 @@ -572,7 +582,7 @@ def execute_async( :param command: Command for execution :type command: str :param stdin: pass STDIN text to the process - :type stdin: typing.Union[str, bytes, bytearray, None] + :type stdin: typing.Union[bytes, str, bytearray, None] :param open_stdout: open STDOUT stream for read :type open_stdout: bool :param open_stderr: open STDERR stream for read @@ -623,6 +633,7 @@ def execute_async( cmd = "sudo -S bash -c 'eval \"$(base64 -d <(echo \"{0}\"))\"'".format(encoded_cmd) chan.exec_command(cmd) # nosec # Sanitize on caller side if stdout.channel.closed is False: + # noinspection PyTypeChecker self.auth.enter_password(_stdin) _stdin.flush() else: @@ -716,6 +727,7 @@ def poll_pipes(stop: threading.Event) -> None: stop_event = threading.Event() # pylint: disable=assignment-from-no-return + # noinspection PyNoneFunctionAssignment future = poll_pipes(stop=stop_event) # type: concurrent.futures.Future # pylint: enable=assignment-from-no-return diff --git a/exec_helpers/api.py b/exec_helpers/api.py index 56f7ac0..9ccdfda 100644 --- a/exec_helpers/api.py +++ b/exec_helpers/api.py @@ -19,6 +19,7 @@ .. versionchanged:: 1.3.5 make API public to use as interface """ +import abc import logging import re import threading @@ -30,7 +31,7 @@ from exec_helpers import proc_enums -class ExecHelper: +class ExecHelper(metaclass=abc.ABCMeta): """ExecHelper global API.""" __slots__ = ( @@ -126,6 +127,7 @@ def mask(text: str, rules: str) -> str: return cmd + @abc.abstractmethod def execute_async( self, command: str, @@ -141,7 +143,7 @@ def execute_async( :param command: Command for execution :type command: str :param stdin: pass STDIN text to the process - :type stdin: typing.Union[str, bytes, bytearray, None] + :type stdin: typing.Union[bytes, str, bytearray, None] :param open_stdout: open STDOUT stream for read :type open_stdout: bool :param open_stderr: open STDERR stream for read @@ -158,6 +160,7 @@ def execute_async( """ raise NotImplementedError # pragma: no cover + @abc.abstractmethod def _exec_command( self, command: str, @@ -180,7 +183,7 @@ def _exec_command( :param stderr: STDERR pipe or file-like object :type stderr: typing.Any :param timeout: Timeout for command execution - :type timeout: int + :type timeout: typing.Union[int, float, None] :param verbose: produce verbose log record on command call :type verbose: bool :param log_mask_re: regex lookup rule to mask command for logger. @@ -202,14 +205,12 @@ def execute( ) -> exec_result.ExecResult: """Execute command and wait for return code. - Timeout limitation: read tick is 100 ms. - :param command: Command for execution :type command: str :param verbose: Produce log.info records for command call and output :type verbose: bool :param timeout: Timeout for command execution. - :type timeout: typing.Union[int, None] + :type timeout: typing.Union[int, float, None] :rtype: ExecResult :raises ExecHelperTimeoutError: Timeout exceeded @@ -255,14 +256,12 @@ def check_call( ) -> exec_result.ExecResult: """Execute command and check for return code. - Timeout limitation: read tick is 100 ms. - :param command: Command for execution :type command: str :param verbose: Produce log.info records for command call and output :type verbose: bool :param timeout: Timeout for command execution. - :type timeout: typing.Union[int, None] + :type timeout: typing.Union[int, float, None] :param error_info: Text for error details, if fail happens :type error_info: typing.Optional[str] :param expected: expected return codes (0 by default) @@ -304,14 +303,12 @@ def check_stderr( ) -> exec_result.ExecResult: """Execute command expecting return code 0 and empty STDERR. - Timeout limitation: read tick is 100 ms. - :param command: Command for execution :type command: str :param verbose: Produce log.info records for command call and output :type verbose: bool :param timeout: Timeout for command execution. - :type timeout: typing.Union[int, None] + :type timeout: typing.Union[int, float, None] :param error_info: Text for error details, if fail happens :type error_info: typing.Optional[str] :param raise_on_err: Raise exception on unexpected return code diff --git a/exec_helpers/exec_result.py b/exec_helpers/exec_result.py index 6ff4ae7..0fc62de 100644 --- a/exec_helpers/exec_result.py +++ b/exec_helpers/exec_result.py @@ -55,7 +55,7 @@ def __init__( :param cmd: command :type cmd: str :param stdin: string STDIN - :type stdin: typing.Union[str, bytes, bytearray, None] + :type stdin: typing.Union[bytes, str, bytearray, None] :param stdout: binary STDOUT :type stdout: typing.Optional[typing.Iterable[bytes]] :param stderr: binary STDERR @@ -104,7 +104,7 @@ def lock(self) -> threading.RLock: def timestamp(self) -> typing.Optional[datetime.datetime]: """Timestamp. - :rtype: typing.Optional(datetime.datetime) + :rtype: typing.Optional[datetime.datetime] """ return self.__timestamp @@ -119,7 +119,7 @@ def _get_bytearray_from_array(src: typing.Iterable[bytes]) -> bytearray: @staticmethod def _get_str_from_bin(src: bytearray) -> str: - """Join data in list to the string, with python 2&3 compatibility. + """Join data in list to the string. :type src: bytearray :rtype: str @@ -230,7 +230,7 @@ def read_stderr( """Read stderr file-like object to stdout. :param src: source - :type src: typing.Iterable + :type src: typing.Optional[typing.Iterable] :param log: logger :type log: typing.Optional[logging.Logger] :param verbose: use log.info instead of log.debug @@ -323,7 +323,7 @@ def exit_code(self) -> typing.Union[int, proc_enums.ExitCodes]: def exit_code(self, new_val: typing.Union[int, proc_enums.ExitCodes]) -> None: """Return(exit) code of command. - :type new_val: int + :type new_val: typing.Union[int, proc_enums.ExitCodes] If valid exit code is set - object became read-only. """ if self.timestamp: @@ -339,7 +339,7 @@ def __deserialize(self, fmt: str) -> typing.Any: """Deserialize stdout as data format. :type fmt: str - :rtype: object + :rtype: typing.Any :raises NotImplementedError: fmt deserialization not implemented :raises DeserializeValueError: Not valid source format """ @@ -365,7 +365,7 @@ def __deserialize(self, fmt: str) -> typing.Any: def stdout_json(self) -> typing.Any: """JSON from stdout. - :rtype: object + :rtype: typing.Any """ with self.lock: return self.__deserialize(fmt='json') @@ -374,7 +374,7 @@ def stdout_json(self) -> typing.Any: def stdout_yaml(self) -> typing.Any: """YAML from stdout. - :rtype: Union(list, dict, None) + :rtype: typing.Any """ with self.lock: return self.__deserialize(fmt='yaml') diff --git a/exec_helpers/ssh_client.py b/exec_helpers/ssh_client.py index a76f9eb..34d8b47 100644 --- a/exec_helpers/ssh_client.py +++ b/exec_helpers/ssh_client.py @@ -108,11 +108,7 @@ def download(self, destination: str, target: str) -> bool: if self.exists(destination): self._sftp.get(destination, target) else: - self.logger.debug( - "Can't download %s because it doesn't exist", destination - ) + self.logger.debug("Can't download %s because it doesn't exist", destination) else: - self.logger.debug( - "Can't download %s because it is a directory", destination - ) + self.logger.debug("Can't download %s because it is a directory", destination) return os.path.exists(target) diff --git a/exec_helpers/subprocess_runner.py b/exec_helpers/subprocess_runner.py index 43c1f76..de4d787 100644 --- a/exec_helpers/subprocess_runner.py +++ b/exec_helpers/subprocess_runner.py @@ -16,6 +16,7 @@ """Python subprocess.Popen wrapper.""" +import abc import collections import concurrent.futures import errno @@ -34,7 +35,7 @@ logger = logging.getLogger(__name__) # type: logging.Logger -class SingletonMeta(type): +class SingletonMeta(abc.ABCMeta): """Metaclass for Singleton. Main goals: not need to implement __new__ in singleton classes @@ -100,9 +101,9 @@ def _exec_command( :param interface: Control interface :type interface: subprocess.Popen :param stdout: STDOUT pipe or file-like object - :type stdout: typing.Any + :type stdout: typing.Optional[typing.IO] :param stderr: STDERR pipe or file-like object - :type stderr: typing.Any + :type stderr: typing.Optional[typing.IO] :param timeout: Timeout for command execution :type timeout: typing.Union[int, float, None] :param verbose: produce verbose log record on command call @@ -139,7 +140,9 @@ def poll_stderr() -> None: result = exec_result.ExecResult(cmd=cmd_for_log) # pylint: disable=assignment-from-no-return + # noinspection PyNoneFunctionAssignment stdout_future = poll_stdout() # type: concurrent.futures.Future + # noinspection PyNoneFunctionAssignment stderr_future = poll_stderr() # type: concurrent.futures.Future # pylint: enable=assignment-from-no-return From c26d55511ebd2b6f7dd8ab9c7641897fc386bda1 Mon Sep 17 00:00:00 2001 From: Alexey Stepanov Date: Tue, 4 Sep 2018 12:11:24 +0200 Subject: [PATCH 2/2] cleanup last part of py2.7 support Signed-off-by: Alexey Stepanov --- exec_helpers/api.py | 2 +- exec_helpers/exceptions.py | 12 +++--------- exec_helpers/proc_enums.py | 2 +- 3 files changed, 5 insertions(+), 11 deletions(-) diff --git a/exec_helpers/api.py b/exec_helpers/api.py index 9ccdfda..4ca59e8 100644 --- a/exec_helpers/api.py +++ b/exec_helpers/api.py @@ -27,7 +27,7 @@ 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 exec_result from exec_helpers import proc_enums diff --git a/exec_helpers/exceptions.py b/exec_helpers/exceptions.py index e44e686..84f4848 100644 --- a/exec_helpers/exceptions.py +++ b/exec_helpers/exceptions.py @@ -136,9 +136,7 @@ def __init__( super(CalledProcessError, self).__init__(message) @property - def returncode( - self - ) -> typing.Union[int, proc_enums.ExitCodes]: + def returncode(self) -> typing.Union[int, proc_enums.ExitCodes]: """Command return code.""" return self.result.exit_code @@ -188,9 +186,7 @@ def __init__( :param results: all results :type results: typing.Dict[typing.Tuple[str, int], ExecResult] :param expected: expected return codes - :type expected: typing.Optional[typing.List[ - typing.List[typing.Union[int, proc_enums.ExitCodes]] - ] + :type expected: typing.Optional[typing.List[typing.Union[int, proc_enums.ExitCodes]]] """ expected = expected or [proc_enums.ExitCodes.EX_OK] self.expected = proc_enums.exit_codes_to_enums(expected) @@ -240,9 +236,7 @@ def __init__( :param results: all results :type results: typing.Dict[typing.Tuple[str, int], ExecResult] :param expected: expected return codes - :type expected: typing.Optional[typing.List[ - typing.List[typing.Union[int, proc_enums.ExitCodes]] - ] + :type expected: typing.Optional[typing.List[typing.Union[int, proc_enums.ExitCodes]]] """ expected = expected or [proc_enums.ExitCodes.EX_OK] self.expected = proc_enums.exit_codes_to_enums(expected) diff --git a/exec_helpers/proc_enums.py b/exec_helpers/proc_enums.py index 41b785d..dd72f21 100644 --- a/exec_helpers/proc_enums.py +++ b/exec_helpers/proc_enums.py @@ -20,7 +20,7 @@ """ import enum -import typing # noqa # pylint: disable=unused-import +import typing __all__ = ( 'SigNum',