exec-helpers 8.0.0.post0__tar.gz → 8.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. {exec-helpers-8.0.0.post0 → exec_helpers-8.1.0}/.pre-commit-config.yaml +4 -4
  2. {exec-helpers-8.0.0.post0 → exec_helpers-8.1.0}/PKG-INFO +7 -6
  3. {exec-helpers-8.0.0.post0 → exec_helpers-8.1.0}/README.rst +6 -5
  4. {exec-helpers-8.0.0.post0 → exec_helpers-8.1.0}/exec_helpers/__init__.py +18 -21
  5. {exec-helpers-8.0.0.post0 → exec_helpers-8.1.0}/exec_helpers/__init__.pyi +16 -19
  6. {exec-helpers-8.0.0.post0 → exec_helpers-8.1.0}/exec_helpers/_helpers.py +18 -16
  7. {exec-helpers-8.0.0.post0 → exec_helpers-8.1.0}/exec_helpers/_ssh_base.py +326 -308
  8. {exec-helpers-8.0.0.post0 → exec_helpers-8.1.0}/exec_helpers/_ssh_helpers.py +57 -57
  9. {exec-helpers-8.0.0.post0 → exec_helpers-8.1.0}/exec_helpers/_subprocess_helpers.py +3 -3
  10. {exec-helpers-8.0.0.post0 → exec_helpers-8.1.0}/exec_helpers/_version.py +2 -2
  11. {exec-helpers-8.0.0.post0 → exec_helpers-8.1.0}/exec_helpers/api.py +209 -186
  12. {exec-helpers-8.0.0.post0 → exec_helpers-8.1.0}/exec_helpers/async_api/__init__.py +2 -2
  13. {exec-helpers-8.0.0.post0 → exec_helpers-8.1.0}/exec_helpers/async_api/__init__.pyi +3 -5
  14. {exec-helpers-8.0.0.post0 → exec_helpers-8.1.0}/exec_helpers/async_api/api.py +191 -170
  15. {exec-helpers-8.0.0.post0 → exec_helpers-8.1.0}/exec_helpers/async_api/exec_result.py +12 -12
  16. {exec-helpers-8.0.0.post0 → exec_helpers-8.1.0}/exec_helpers/async_api/subprocess.py +120 -109
  17. {exec-helpers-8.0.0.post0 → exec_helpers-8.1.0}/exec_helpers/exceptions.py +37 -108
  18. {exec-helpers-8.0.0.post0 → exec_helpers-8.1.0}/exec_helpers/exec_result.py +150 -83
  19. {exec-helpers-8.0.0.post0 → exec_helpers-8.1.0}/exec_helpers/proc_enums.py +7 -7
  20. {exec-helpers-8.0.0.post0 → exec_helpers-8.1.0}/exec_helpers/ssh.py +12 -12
  21. {exec-helpers-8.0.0.post0 → exec_helpers-8.1.0}/exec_helpers/ssh_auth.py +51 -51
  22. {exec-helpers-8.0.0.post0 → exec_helpers-8.1.0}/exec_helpers/subprocess.py +120 -109
  23. {exec-helpers-8.0.0.post0 → exec_helpers-8.1.0}/exec_helpers.egg-info/PKG-INFO +7 -6
  24. exec_helpers-8.1.0/flake8_requirements.txt +14 -0
  25. exec_helpers-8.1.0/mypy_requirements.txt +1 -0
  26. {exec-helpers-8.0.0.post0 → exec_helpers-8.1.0}/pyproject.toml +68 -6
  27. exec-helpers-8.0.0.post0/flake8_requirements.txt +0 -4
  28. exec-helpers-8.0.0.post0/mypy_requirements.txt +0 -1
  29. {exec-helpers-8.0.0.post0 → exec_helpers-8.1.0}/.editorconfig +0 -0
  30. {exec-helpers-8.0.0.post0 → exec_helpers-8.1.0}/.readthedocs.yaml +0 -0
  31. {exec-helpers-8.0.0.post0 → exec_helpers-8.1.0}/CI_REQUIREMENTS.txt +0 -0
  32. {exec-helpers-8.0.0.post0 → exec_helpers-8.1.0}/LICENSE +0 -0
  33. {exec-helpers-8.0.0.post0 → exec_helpers-8.1.0}/MANIFEST.in +0 -0
  34. {exec-helpers-8.0.0.post0 → exec_helpers-8.1.0}/build_requirements.txt +0 -0
  35. {exec-helpers-8.0.0.post0 → exec_helpers-8.1.0}/classifiers.txt +0 -0
  36. {exec-helpers-8.0.0.post0 → exec_helpers-8.1.0}/exec_helpers/_log_templates.py +0 -0
  37. {exec-helpers-8.0.0.post0 → exec_helpers-8.1.0}/exec_helpers/constants.py +0 -0
  38. {exec-helpers-8.0.0.post0 → exec_helpers-8.1.0}/exec_helpers/py.typed +0 -0
  39. {exec-helpers-8.0.0.post0 → exec_helpers-8.1.0}/exec_helpers.egg-info/SOURCES.txt +0 -0
  40. {exec-helpers-8.0.0.post0 → exec_helpers-8.1.0}/exec_helpers.egg-info/dependency_links.txt +0 -0
  41. {exec-helpers-8.0.0.post0 → exec_helpers-8.1.0}/exec_helpers.egg-info/not-zip-safe +0 -0
  42. {exec-helpers-8.0.0.post0 → exec_helpers-8.1.0}/exec_helpers.egg-info/requires.txt +0 -0
  43. {exec-helpers-8.0.0.post0 → exec_helpers-8.1.0}/exec_helpers.egg-info/top_level.txt +0 -0
  44. {exec-helpers-8.0.0.post0 → exec_helpers-8.1.0}/pytest_requirements.txt +0 -0
  45. {exec-helpers-8.0.0.post0 → exec_helpers-8.1.0}/requirements.txt +0 -0
  46. {exec-helpers-8.0.0.post0 → exec_helpers-8.1.0}/setup.cfg +0 -0
  47. {exec-helpers-8.0.0.post0 → exec_helpers-8.1.0}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  repos:
2
2
  - repo: https://github.com/pre-commit/pre-commit-hooks
3
- rev: v4.5.0
3
+ rev: v4.6.0
4
4
  hooks:
5
5
  - id: check-yaml
6
6
  - id: end-of-file-fixer
@@ -8,7 +8,7 @@ repos:
8
8
  - id: mixed-line-ending
9
9
 
10
10
  - repo: https://github.com/pycqa/isort
11
- rev: 5.12.0
11
+ rev: 5.13.2
12
12
  hooks:
13
13
  - id: isort
14
14
  name: isort (python)
@@ -20,7 +20,7 @@ repos:
20
20
  types: [pyi]
21
21
 
22
22
  - repo: https://github.com/psf/black
23
- rev: 23.7.0
23
+ rev: 24.4.2
24
24
  hooks:
25
25
  - id: black
26
26
  # It is recommended to specify the latest version of Python
@@ -30,7 +30,7 @@ repos:
30
30
 
31
31
  - repo: https://github.com/astral-sh/ruff-pre-commit
32
32
  # Ruff version.
33
- rev: v0.1.5
33
+ rev: v0.4.6
34
34
  hooks:
35
35
  - id: ruff
36
36
  args: [ --fix, --exit-non-zero-on-fix ]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: exec-helpers
3
- Version: 8.0.0.post0
3
+ Version: 8.1.0
4
4
  Summary: Execution helpers for simplified usage of subprocess and ssh.
5
5
  Home-page: https://github.com/python-useful-helpers/exec-helpers
6
6
  Author-email: Alexey Stepanov <penguinolog@gmail.com>
@@ -156,7 +156,7 @@ Creation from scratch:
156
156
  password='password', # str | None
157
157
  key=None, # type: paramiko.PKey | None
158
158
  keys=None, # type: Iterable[paramiko.PKey] | None
159
- key_filename=None, # type: List[str] | None
159
+ key_filename=None, # type: list[str] | None
160
160
  passphrase=None, # str | None
161
161
  )
162
162
 
@@ -286,9 +286,10 @@ Execution result object has a set of useful properties:
286
286
 
287
287
  * `cmd` - Command
288
288
  * `exit_code` - Command return code. If possible to decode using enumerators for Linux -> it used.
289
+ * `ok` -> `bool`. Command return code is 0 (EX_OK).
289
290
  * `stdin` -> `str`. Text representation of stdin.
290
- * `stdout` -> `Tuple[bytes]`. Raw stdout output.
291
- * `stderr` -> `Tuple[bytes]`. Raw stderr output.
291
+ * `stdout` -> `tuple[bytes]`. Raw stdout output.
292
+ * `stderr` -> `tuple[bytes]`. Raw stderr output.
292
293
  * `stdout_bin` -> `bytearray`. Binary stdout output.
293
294
  * `stderr_bin` -> `bytearray`. Binary stderr output.
294
295
  * `stdout_str` -> `str`. Text representation of output.
@@ -319,7 +320,7 @@ Possible to call commands in parallel on multiple hosts if it's not produce huge
319
320
 
320
321
  .. code-block:: python
321
322
 
322
- results: Dict[Tuple[str, int], ExecResult] = SSHClient.execute_together(
323
+ results: dict[tuple[str, int], ExecResult] = SSHClient.execute_together(
323
324
  remotes, # type: Iterable[SSHClient]
324
325
  command, # type: str | Iterable[str]
325
326
  timeout=1 * 60 * 60, # type: type: int | float | None
@@ -332,7 +333,7 @@ Possible to call commands in parallel on multiple hosts if it's not produce huge
332
333
  log_mask_re=None, # str | None
333
334
  exception_class=ParallelCallProcessError # type[ParallelCallProcessError]
334
335
  )
335
- results # type: dict[Tuple[str, int], exec_result.ExecResult]
336
+ results # type: dict[tuple[str, int], exec_result.ExecResult]
336
337
 
337
338
  Results is a dict with keys = (hostname, port) and and results in values.
338
339
  By default execute_together raises exception if unexpected return code on any remote.
@@ -110,7 +110,7 @@ Creation from scratch:
110
110
  password='password', # str | None
111
111
  key=None, # type: paramiko.PKey | None
112
112
  keys=None, # type: Iterable[paramiko.PKey] | None
113
- key_filename=None, # type: List[str] | None
113
+ key_filename=None, # type: list[str] | None
114
114
  passphrase=None, # str | None
115
115
  )
116
116
 
@@ -240,9 +240,10 @@ Execution result object has a set of useful properties:
240
240
 
241
241
  * `cmd` - Command
242
242
  * `exit_code` - Command return code. If possible to decode using enumerators for Linux -> it used.
243
+ * `ok` -> `bool`. Command return code is 0 (EX_OK).
243
244
  * `stdin` -> `str`. Text representation of stdin.
244
- * `stdout` -> `Tuple[bytes]`. Raw stdout output.
245
- * `stderr` -> `Tuple[bytes]`. Raw stderr output.
245
+ * `stdout` -> `tuple[bytes]`. Raw stdout output.
246
+ * `stderr` -> `tuple[bytes]`. Raw stderr output.
246
247
  * `stdout_bin` -> `bytearray`. Binary stdout output.
247
248
  * `stderr_bin` -> `bytearray`. Binary stderr output.
248
249
  * `stdout_str` -> `str`. Text representation of output.
@@ -273,7 +274,7 @@ Possible to call commands in parallel on multiple hosts if it's not produce huge
273
274
 
274
275
  .. code-block:: python
275
276
 
276
- results: Dict[Tuple[str, int], ExecResult] = SSHClient.execute_together(
277
+ results: dict[tuple[str, int], ExecResult] = SSHClient.execute_together(
277
278
  remotes, # type: Iterable[SSHClient]
278
279
  command, # type: str | Iterable[str]
279
280
  timeout=1 * 60 * 60, # type: type: int | float | None
@@ -286,7 +287,7 @@ Possible to call commands in parallel on multiple hosts if it's not produce huge
286
287
  log_mask_re=None, # str | None
287
288
  exception_class=ParallelCallProcessError # type[ParallelCallProcessError]
288
289
  )
289
- results # type: dict[Tuple[str, int], exec_result.ExecResult]
290
+ results # type: dict[tuple[str, int], exec_result.ExecResult]
290
291
 
291
292
  Results is a dict with keys = (hostname, port) and and results in values.
292
293
  By default execute_together raises exception if unexpected return code on any remote.
@@ -20,7 +20,7 @@ import importlib
20
20
  import typing
21
21
  import warnings
22
22
 
23
- try: # noqa: SIM105
23
+ try: # noqa: FURB107,SIM105,RUF100
24
24
  from ._version import version as __version__ # noqa: F401
25
25
  except ImportError:
26
26
  pass
@@ -28,31 +28,28 @@ except ImportError:
28
28
  if typing.TYPE_CHECKING:
29
29
  from collections.abc import Sequence
30
30
 
31
+
31
32
  # noinspection PyUnresolvedReferences
32
33
  __all__ = (
33
34
  # pylint: disable=undefined-all-variable
34
- # lazy load
35
- # API
36
- "async_api",
37
- "ExitCodes",
38
- "ExecResult",
35
+ "CalledProcessError",
36
+ "ExecCalledProcessError",
39
37
  "ExecHelper",
40
- "mask_command",
41
- # Expensive
42
- "Subprocess",
43
- "SSHClient",
44
- "SSHAuth",
45
- "SSHConfig",
46
- "HostsSSHConfigs",
47
- # Exceptions
48
- "exceptions",
49
38
  "ExecHelperError",
50
- "ExecCalledProcessError",
51
- "CalledProcessError",
52
- "ParallelCallExceptionsError",
53
- "ParallelCallProcessError",
54
39
  "ExecHelperNoKillError",
55
40
  "ExecHelperTimeoutError",
41
+ "ExecResult",
42
+ "ExitCodes",
43
+ "HostsSSHConfigs",
44
+ "ParallelCallExceptionsError",
45
+ "ParallelCallProcessError",
46
+ "SSHAuth",
47
+ "SSHClient",
48
+ "SSHConfig",
49
+ "Subprocess",
50
+ "async_api",
51
+ "exceptions",
52
+ "mask_command",
56
53
  )
57
54
 
58
55
  __locals: dict[str, typing.Any] = locals() # use mutable access for pure lazy loading
@@ -90,8 +87,8 @@ _deprecated: dict[str, str] = {}
90
87
  def __getattr__(name: str) -> typing.Any:
91
88
  """Get attributes lazy.
92
89
 
93
- :return: attribute by name
94
- :raises AttributeError: attribute is not defined for lazy load
90
+ :return: Attribute by name.
91
+ :raises AttributeError: Attribute is not defined for the lazy load.
95
92
  """
96
93
  if name in _deprecated:
97
94
  warnings.warn(
@@ -12,6 +12,8 @@
12
12
  # License for the specific language governing permissions and limitations
13
13
  # under the License.
14
14
 
15
+ # pylint: disable=missing-module-docstring
16
+
15
17
  import typing
16
18
 
17
19
  from . import async_api
@@ -39,33 +41,28 @@ except ImportError:
39
41
 
40
42
  # noinspection PyUnresolvedReferences
41
43
  __all__ = (
42
- # pylint: disable=undefined-all-variable
43
- # lazy load
44
- # API
45
- "async_api",
46
- "ExitCodes",
47
- "ExecResult",
44
+ "CalledProcessError",
45
+ "ExecCalledProcessError",
48
46
  "ExecHelper",
49
- "mask_command",
50
- # Expensive
51
- "Subprocess",
52
- "SSHClient",
53
- "SSHAuth",
54
- "SSHConfig",
55
- "HostsSSHConfigs",
56
- # Exceptions
57
47
  "ExecHelperError",
58
- "ExecCalledProcessError",
59
- "CalledProcessError",
60
- "ParallelCallExceptionsError",
61
- "ParallelCallProcessError",
62
48
  "ExecHelperNoKillError",
63
49
  "ExecHelperTimeoutError",
50
+ "ExecResult",
51
+ "ExitCodes",
52
+ "HostsSSHConfigs",
53
+ "ParallelCallExceptionsError",
54
+ "ParallelCallProcessError",
55
+ "SSHAuth",
56
+ "SSHClient",
57
+ "SSHConfig",
58
+ "Subprocess",
59
+ "async_api",
60
+ "mask_command",
64
61
  )
65
62
 
66
63
  _deprecated: dict[str, str] = ...
67
64
 
68
- def __getattr__(name: str) -> typing.Any: ...
65
+ def __getattr__(name: str) -> typing.Any: ... # pylint: disable=unused-argument
69
66
 
70
67
  __author__: str = ...
71
68
  __author_email__: str = ...
@@ -12,10 +12,10 @@ if typing.TYPE_CHECKING:
12
12
 
13
13
 
14
14
  def string_bytes_bytearray_as_bytes(src: str | bytes | bytearray) -> bytes:
15
- """Get bytes string from string/bytes/bytearray union.
15
+ """Get byte string from string/bytes/bytearray union.
16
16
 
17
- :param src: source string or bytes-like object
18
- :return: Byte string
17
+ :param src: Source string or bytes-like object.
18
+ :return: Byte string.
19
19
  :rtype: bytes
20
20
  :raises TypeError: unexpected source type.
21
21
  """
@@ -31,11 +31,11 @@ def string_bytes_bytearray_as_bytes(src: str | bytes | bytearray) -> bytes:
31
31
  def _mask_command(text: str, rules: str | re.Pattern[str]) -> str:
32
32
  """Mask part of text using rules.
33
33
 
34
- :param text: source text
34
+ :param text: Source text.
35
35
  :type text: str
36
- :param rules: regex rules to mask.
36
+ :param rules: Regex rules to mask.
37
37
  :type rules: str | re.Pattern
38
- :return: source with all MATCHED groups replaced by '<*masked*>'
38
+ :return: Source with all MATCHED groups replaced by '<*masked*>'.
39
39
  :rtype: str
40
40
  """
41
41
  masked: list[str] = []
@@ -55,11 +55,11 @@ def _mask_command(text: str, rules: str | re.Pattern[str]) -> str:
55
55
  def mask_command(text: str, *rules: str | re.Pattern[str] | None) -> str:
56
56
  """Apply all rules to command.
57
57
 
58
- :param text: source text
58
+ :param text: Source text.
59
59
  :type text: str
60
- :param rules: regex rules to mask.
60
+ :param rules: Regex rules to mask.
61
61
  :type rules: str | re.Pattern[str] | None
62
- :return: source with all MATCHED groups replaced by '<*masked*>'
62
+ :return: Source with all MATCHED groups replaced by '<*masked*>'.
63
63
  :rtype: str
64
64
  """
65
65
  return functools.reduce(_mask_command, (rule for rule in rules if rule is not None), text)
@@ -68,9 +68,9 @@ def mask_command(text: str, *rules: str | re.Pattern[str] | None) -> str:
68
68
  def cmd_to_string(command: str | Iterable[str]) -> str:
69
69
  """Convert command to string for usage with shell.
70
70
 
71
- :param command: original command.
71
+ :param command: Original command.
72
72
  :type command: str | Iterable[str]
73
- :return: command as single string
73
+ :return: Command as single string.
74
74
  :rtype: str
75
75
  """
76
76
  if isinstance(command, str):
@@ -78,18 +78,20 @@ def cmd_to_string(command: str | Iterable[str]) -> str:
78
78
  return shlex.join(command)
79
79
 
80
80
 
81
- def chroot_command(command: str, chroot_path: str | None = None) -> str:
81
+ def chroot_command(command: str, chroot_path: str | None = None, chroot_exe: str = "chroot") -> str:
82
82
  """Prepare command for chroot execution.
83
83
 
84
- :param command: original command.
84
+ :param command: Original command.
85
85
  :type command: str
86
- :param chroot_path: chroot path
86
+ :param chroot_path: chroot path.
87
87
  :type chroot_path: str | None
88
- :return: command to be executed with chroot rules if applicable
88
+ :param chroot_exe: chroot executable.
89
+ :type chroot_exe: str
90
+ :return: Command to be executed with chroot rules if applicable.
89
91
  :rtype: str
90
92
  """
91
93
  if chroot_path and chroot_path != "/":
92
94
  chroot_dst: str = shlex.quote(chroot_path.strip())
93
95
  quoted_command = shlex.quote(command)
94
- return f'chroot {chroot_dst} sh -c {shlex.quote(f"eval {quoted_command}")}'
96
+ return f'{chroot_exe} {chroot_dst} sh -c {shlex.quote(f"eval {quoted_command}")}'
95
97
  return command