Skip to content

Commit 07d74fe

Browse files
committed
Backport updates
Update docs: expected is not optional (cherry picked from commit 31c6a01) (cherry picked from commit df8a438) (cherry picked from commit f4908a5) On subprocess kill write exit code to result to prevent changes (#120) * fix missed docstring (cherry picked from commit fb0ef72) Add timestamp of command start to execute_async for future processing (cherry picked from commit b3dc162) More info in result: start timestamp (#124) (cherry picked from commit 8b7a8e7) Always set timestamp on kill, provide spent time in str() (cherry picked from commit 06f1650)
1 parent 1f1f0e1 commit 07d74fe

18 files changed

+306
-140
lines changed

README.rst

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,15 +37,15 @@ Pros:
3737
* Open Source: https://github.com/python-useful-helpers/exec-helpers
3838
* PyPI packaged: https://pypi.python.org/pypi/exec-helpers
3939
* Self-documented code: docstrings with types in comments
40-
* Tested: see bages on top
40+
* Tested: see badges on top
4141
* Support multiple Python versions:
4242

4343
::
4444

4545
Python 2.7
4646
PyPy
4747

48-
.. note:: Update to version 2.0+ for usage with python 3.4+. This version is for legacy python and no new features are planned.
48+
.. note:: Pythons: For Python 3.4 use versions 2.x.x, python 3.5+ use versions 3.x.x, python 3.6+ use versions 4+
4949

5050
This package includes:
5151

@@ -96,7 +96,7 @@ Creation from scratch:
9696
)
9797
9898
Key is a main connection key (always tried first) and keys are alternate keys.
99-
Key filename is afilename or list of filenames with keys, which should be loaded.
99+
Key filename is a filename or list of filenames with keys, which should be loaded.
100100
Passphrase is an alternate password for keys, if it differs from main password.
101101
If main key now correct for username - alternate keys tried, if correct key found - it became main.
102102
If no working key - password is used and None is set as main key.
@@ -217,7 +217,7 @@ Possible to call commands in parallel on multiple hosts if it's not produce huge
217217
remotes, # type: typing.Iterable[SSHClient]
218218
command, # type: str
219219
timeout=1 * 60 * 60, # type: type: typing.Union[int, float, None]
220-
expected=None, # type: typing.Optional[typing.Iterable[int]]
220+
expected=(0,), # type: typing.Iterable[typing.Union[int, ExitCodes]]
221221
raise_on_err=True # type: bool
222222
)
223223
results # type: typing.Dict[typing.Tuple[str, int], exec_result.ExecResult]

appveyor.yml

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,19 +21,11 @@ environment:
2121
PYTHON_ARCH: "64"
2222

2323
- PYTHON: "C:\\Python35"
24-
PYTHON_VERSION: "3.5.x" # currently 3.5.1
24+
PYTHON_VERSION: "3.5.x"
2525
PYTHON_ARCH: "32"
2626

2727
- PYTHON: "C:\\Python35-x64"
28-
PYTHON_VERSION: "3.5.x" # currently 3.5.1
29-
PYTHON_ARCH: "64"
30-
31-
- PYTHON: "C:\\Python36"
32-
PYTHON_VERSION: "3.6.x" # currently 3.6.0
33-
PYTHON_ARCH: "32"
34-
35-
- PYTHON: "C:\\Python36-x64"
36-
PYTHON_VERSION: "3.6.x" # currently 3.6.0
28+
PYTHON_VERSION: "3.5.x"
3729
PYTHON_ARCH: "64"
3830

3931
install:

doc/source/ExecResult.rst

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ API: ExecResult
1010
1111
Command execution result.
1212

13-
.. py:method:: __init__(cmd, stdin=None, stdout=None, stderr=None, exit_code=ExitCodes.EX_INVALID)
13+
.. py:method:: __init__(cmd, stdin=None, stdout=None, stderr=None, exit_code=0xDEADBEEF, *, started=None)
1414
1515
:param cmd: command
1616
:type cmd: ``str``
@@ -22,6 +22,8 @@ API: ExecResult
2222
:type stderr: ``typing.Optional[typing.Iterable[bytes]]``
2323
:param exit_code: Exit code. If integer - try to convert to BASH enum.
2424
:type exit_code: typing.Union[int, ExitCodes]
25+
:param started: Timestamp of command start
26+
:type started: typing.Optional[datetime.datetime]
2527

2628
.. py:attribute:: stdout_lock
2729
@@ -42,6 +44,14 @@ API: ExecResult
4244
``typing.Optional(datetime.datetime)``
4345
Timestamp
4446

47+
.. py:method:: set_timestamp()
48+
49+
Set timestamp if empty.
50+
51+
This will block future object changes.
52+
53+
.. versionadded:: 2.11.0
54+
4555
.. py:attribute:: cmd
4656
4757
``str``
@@ -98,6 +108,13 @@ API: ExecResult
98108

99109
:rtype: typing.Union[int, ExitCodes]
100110

111+
.. py:attribute:: started
112+
113+
``datetime.datetime``
114+
Timestamp of command start.
115+
116+
.. versionadded:: 2.11.0
117+
101118
.. py:attribute:: stdout_json
102119
103120
JSON from stdout.

doc/source/SSHClient.rst

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ API: SSHClient and SSHAuth.
175175

176176
.. versionadded:: 1.9.7
177177

178-
.. py:method:: check_call(command, verbose=False, timeout=1*60*60, error_info=None, expected=None, raise_on_err=True, **kwargs)
178+
.. py:method:: check_call(command, verbose=False, timeout=1*60*60, error_info=None, expected=(0,), raise_on_err=True, **kwargs)
179179
180180
Execute command and check for return code.
181181

@@ -188,14 +188,16 @@ API: SSHClient and SSHAuth.
188188
:param error_info: Text for error details, if fail happens
189189
:type error_info: ``typing.Optional[str]``
190190
:param expected: expected return codes (0 by default)
191-
:type expected: ``typing.Optional[typing.Iterable[int]]``
191+
:type expected: typing.Iterable[typing.Union[int, ExitCodes]]
192192
:param raise_on_err: Raise exception on unexpected return code
193193
:type raise_on_err: ``bool``
194194
:rtype: ExecResult
195195
:raises ExecHelperTimeoutError: Timeout exceeded
196196
:raises CalledProcessError: Unexpected exit code
197197

198198
.. versionchanged:: 1.2.0 default timeout 1 hour
199+
.. versionchanged:: 1.10.0 Exception class can be substituted
200+
.. versionchanged:: 1.11.0 Expected is not optional, defaults os dependent
199201

200202
.. py:method:: check_stderr(command, verbose=False, timeout=1*60*60, error_info=None, raise_on_err=True, **kwargs)
201203
@@ -240,8 +242,9 @@ API: SSHClient and SSHAuth.
240242
:raises ExecHelperTimeoutError: Timeout exceeded
241243

242244
.. versionchanged:: 1.2.0 default timeout 1 hour
245+
.. versionchanged:: 1.10.0 Exception class can be substituted
243246

244-
.. py:classmethod:: execute_together(remotes, command, timeout=1*60*60, expected=None, raise_on_err=True, **kwargs)
247+
.. py:classmethod:: execute_together(remotes, command, timeout=1*60*60, expected=(0,), raise_on_err=True, **kwargs)
245248
246249
Execute command on multiple remotes in async mode.
247250

@@ -252,7 +255,7 @@ API: SSHClient and SSHAuth.
252255
:param timeout: Timeout for command execution.
253256
:type timeout: ``typing.Union[int, float, None]``
254257
:param expected: expected return codes (0 by default)
255-
:type expected: ``typing.Optional[typing.Iterable[]]``
258+
:type expected: typing.Iterable[typing.Union[int, ExitCodes]]
256259
:param raise_on_err: Raise exception on unexpected return code
257260
:type raise_on_err: ``bool``
258261
:return: dictionary {(hostname, port): result}
@@ -261,6 +264,8 @@ API: SSHClient and SSHAuth.
261264
:raises ParallelCallExceptions: At lest one exception raised during execution (including timeout)
262265

263266
.. versionchanged:: 1.2.0 default timeout 1 hour
267+
.. versionchanged:: 1.10.0 Exception class can be substituted
268+
.. versionchanged:: 1.11.0 Expected is not optional, defaults os dependent
264269

265270
.. py:method:: open(path, mode='r')
266271
@@ -425,3 +430,9 @@ API: SSHClient and SSHAuth.
425430
.. py:attribute:: stdout
426431
427432
``typing.Optional[paramiko.ChannelFile]``
433+
434+
.. py:attribute:: started
435+
436+
``datetime.datetime``
437+
438+
.. versionadded:: 2.11.0

doc/source/Subprocess.rst

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ API: Subprocess
9898
.. note:: stdin channel is closed after the input processing
9999
.. versionadded:: 1.9.7
100100

101-
.. py:method:: check_call(command, verbose=False, timeout=1*60*60, error_info=None, expected=None, raise_on_err=True, **kwargs)
101+
.. py:method:: check_call(command, verbose=False, timeout=1*60*60, error_info=None, expected=(0,), raise_on_err=True, **kwargs)
102102
103103
Execute command and check for return code.
104104

@@ -111,7 +111,7 @@ API: Subprocess
111111
:param error_info: Text for error details, if fail happens
112112
:type error_info: ``typing.Optional[str]``
113113
:param expected: expected return codes (0 by default)
114-
:type expected: ``typing.Optional[typing.Iterable[int]]``
114+
:type expected: typing.Iterable[typing.Union[int, ExitCodes]]
115115
:param raise_on_err: Raise exception on unexpected return code
116116
:type raise_on_err: ``bool``
117117
:rtype: ExecResult
@@ -120,6 +120,8 @@ API: Subprocess
120120

121121
.. versionchanged:: 1.1.0 make method
122122
.. versionchanged:: 1.2.0 default timeout 1 hour
123+
.. versionchanged:: 1.10.0 Exception class can be substituted
124+
.. versionchanged:: 1.11.0 Expected is not optional, defaults os dependent
123125

124126
.. py:method:: check_stderr(command, verbose=False, timeout=1*60*60, error_info=None, raise_on_err=True, **kwargs)
125127
@@ -143,6 +145,7 @@ API: Subprocess
143145

144146
.. versionchanged:: 1.1.0 make method
145147
.. versionchanged:: 1.2.0 default timeout 1 hour
148+
.. versionchanged:: 1.10.0 Exception class can be substituted
146149

147150

148151
.. py:class:: SubprocessExecuteAsyncResult
@@ -164,3 +167,9 @@ API: Subprocess
164167
.. py:attribute:: stdout
165168
166169
``typing.Optional[typing.IO]``
170+
171+
.. py:attribute:: started
172+
173+
``datetime.datetime``
174+
175+
.. versionadded:: 2.11.0

doc/source/exceptions.rst

Lines changed: 49 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -18,21 +18,11 @@ API: exceptions
1818
1919
Base class for process call errors.
2020

21-
.. py:exception:: ExecHelperTimeoutError(ExecCalledProcessError)
21+
class ExecHelperTimeoutProcessError(ExecCalledProcessError):
22+
23+
Timeout based errors.
2224

23-
Execution timeout.
24-
25-
.. versionchanged:: 1.3.0 provide full result and timeout inside.
26-
.. versionchanged:: 1.3.0 subclass ExecCalledProcessError
27-
28-
.. py:method:: __init__(self, result, timeout)
29-
30-
Exception for error on process calls.
31-
32-
:param result: execution result
33-
:type result: exec_result.ExecResult
34-
:param timeout: timeout for command
35-
:type timeout: typing.Union[int, float]
25+
.. versionadded:: 2.11.0
3626

3727
.. py:attribute:: timeout
3828
@@ -54,18 +44,54 @@ API: exceptions
5444
``typing.Text``
5545
stdout string or brief string
5646

47+
48+
.. py:exception:: ExecHelperNoKillError(ExecHelperTimeoutProcessError)
49+
50+
Impossible to kill process.
51+
52+
.. versionadded:: 2.11.0
53+
54+
.. py:method:: __init__(self, result, timeout)
55+
56+
Exception for error on process calls.
57+
58+
:param result: execution result
59+
:type result: ExecResult
60+
:param timeout: timeout for command
61+
:type timeout: typing.Union[int, float]
62+
63+
64+
.. py:exception:: ExecHelperTimeoutError(ExecHelperTimeoutProcessError)
65+
66+
Execution timeout.
67+
68+
.. versionchanged:: 1.3.0 provide full result and timeout inside.
69+
.. versionchanged:: 1.3.0 subclass ExecCalledProcessError
70+
71+
.. py:method:: __init__(self, result, timeout)
72+
73+
Exception for error on process calls.
74+
75+
:param result: execution result
76+
:type result: ExecResult
77+
:param timeout: timeout for command
78+
:type timeout: typing.Union[int, float]
79+
80+
5781
.. py:exception:: CalledProcessError(ExecCalledProcessError)
5882
5983
Exception for error on process calls.
6084

6185
.. versionchanged:: 1.1.1 - provide full result
6286

63-
.. py:method:: __init__(result, expected=None)
87+
.. py:method:: __init__(result, expected=(0,))
6488
6589
:param result: execution result
6690
:type result: ExecResult
67-
:param returncode: return code
68-
:type returncode: typing.Union[int, ExitCodes]
91+
:param expected: expected return codes
92+
:type expected: typing.Iterable[typing.Union[int, ExitCodes]]
93+
94+
.. versionchanged:: 2.11.0 Expected is not optional, defaults os dependent
6995

7096
.. py:attribute:: result
7197
@@ -104,7 +130,7 @@ API: exceptions
104130
105131
Exception during parallel execution.
106132

107-
.. py:method:: __init__(command, errors, results, expected=None, )
133+
.. py:method:: __init__(command, errors, results, expected=(0,), )
108134
109135
:param command: command
110136
:type command: ``str``
@@ -113,9 +139,10 @@ API: exceptions
113139
:param results: all results
114140
:type results: typing.Dict[typing.Tuple[str, int], ExecResult]
115141
:param expected: expected return codes
116-
:type expected: typing.Optional[typing.List[typing.List[typing.Union[int, ExitCodes]]]
142+
:type expected: typing.Iterable[typing.Union[int, ExitCodes]]
117143

118144
.. versionchanged:: 1.0 - fixed inheritance
145+
.. versionchanged:: 2.11.0 Expected is not optional, defaults os dependent
119146

120147
.. py:attribute:: cmd
121148
@@ -144,7 +171,7 @@ API: exceptions
144171
145172
Exception raised during parallel call as result of exceptions.
146173

147-
.. py:method:: __init__(command, exceptions, errors, results, expected=None, )
174+
.. py:method:: __init__(command, exceptions, errors, results, expected=(0,), )
148175
149176
:param command: command
150177
:type command: ``str``
@@ -155,9 +182,10 @@ API: exceptions
155182
:param results: all results
156183
:type results: typing.Dict[typing.Tuple[str, int], ExecResult]
157184
:param expected: expected return codes
158-
:type expected: typing.Optional[typing.List[typing.List[typing.Union[int, ExitCodes]]]
185+
:type expected: typing.Iterable[typing.Union[int, ExitCodes]]
159186

160187
.. versionchanged:: 1.0 - fixed inheritance
188+
.. versionchanged:: 2.11.0 Expected is not optional, defaults os dependent
161189

162190
.. py:attribute:: cmd
163191

exec_helpers/__init__.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,6 @@
1616

1717
from __future__ import absolute_import
1818

19-
import typing
20-
2119
import pkg_resources
2220

2321
from .proc_enums import ExitCodes
@@ -55,7 +53,7 @@
5553
"SubprocessExecuteAsyncResult",
5654
"ExitCodes",
5755
"ExecResult",
58-
) # type: typing.Tuple[str, ...]
56+
)
5957

6058
try: # pragma: no cover
6159
__version__ = pkg_resources.get_distribution(__name__).version

0 commit comments

Comments
 (0)