Skip to content

Commit 0b3ec41

Browse files
committed
Mass backport from 3.4
* type hints Signed-off-by: Aleksei Stepanov <penguinolog@gmail.com>
1 parent 07d74fe commit 0b3ec41

File tree

9 files changed

+65
-60
lines changed

9 files changed

+65
-60
lines changed

.travis.yml

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,13 @@ install:
1010
_python:
1111
- &python27
1212
name: "Python 2.7"
13-
python: 2.7
13+
python: "2.7"
1414
- &pypy
1515
name: "PyPy"
16-
python: pypy
16+
python: "pypy"
1717
- &python37
1818
name: "Python 3.7"
19-
python: 3.7
19+
python: "3.7"
2020
dist: xenial
2121
sudo: true
2222

@@ -41,7 +41,6 @@ after_success:
4141
- coveralls
4242

4343
jobs:
44-
fast_finish: true
4544
include:
4645
- <<: *static_analysis
4746
name: "PyLint"

exec_helpers/_ssh_client_base.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ def __init__(
6767
super(RetryOnExceptions, self).__init__(lambda e: isinstance(e, retry_on) and not isinstance(e, reraise))
6868

6969

70+
# noinspection PyTypeHints
7071
class SshExecuteAsyncResult(api.ExecuteAsyncResult):
7172
"""Override original NamedTuple with proper typing."""
7273

exec_helpers/_subprocess_helpers.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,15 +51,15 @@ def safe_stop(proc, kill=False): # type: (psutil.Process, bool) -> None
5151
pass
5252

5353
parent = psutil.Process(pid)
54-
children = parent.children(recursive=True)
54+
children = parent.children(recursive=True) # type: typing.List[psutil.Process]
5555
for child in children: # type: psutil.Process
5656
safe_stop(child) # SIGTERM to allow cleanup
57-
_, alive = psutil.wait_procs(children, timeout=5)
58-
for child in alive: # type: psutil.Process
57+
_, alive = psutil.wait_procs(children, timeout=1)
58+
for child in alive:
5959
safe_stop(child, kill=True) # 2nd shot: SIGKILL
6060
if including_parent:
6161
safe_stop(parent) # SIGTERM to allow cleanup
62-
_, alive = psutil.wait_procs((parent,), timeout=5)
62+
_, alive = psutil.wait_procs((parent,), timeout=1)
6363
if alive:
6464
safe_stop(parent, kill=True) # 2nd shot: SIGKILL
6565
parent.wait(5)

exec_helpers/api.py

Lines changed: 23 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -115,32 +115,32 @@ def _mask_command(
115115
def mask(text, rules): # type: (str, typing.Text) -> str
116116
"""Mask part of text using rules."""
117117
indexes = [0] # Start of the line
118+
masked = ""
118119

119120
# places to exclude
120121
for match in re.finditer(rules, text):
121122
for idx, _ in enumerate(match.groups()):
122123
indexes.extend(match.span(idx + 1))
123124
indexes.append(len(text)) # End
124125

125-
masked = ""
126-
127126
# Replace inserts
128127
for idx in range(0, len(indexes) - 2, 2):
129128
start = indexes[idx]
130129
end = indexes[idx + 1]
131130
masked += text[start:end] + "<*masked*>"
132131

132+
# noinspection PyPep8
133133
masked += text[indexes[-2] : indexes[-1]] # final part
134134
return masked
135135

136-
cmd = cmd.rstrip()
136+
result = cmd.rstrip() # type: str
137137

138-
if self.log_mask_re:
139-
cmd = mask(cmd, self.log_mask_re)
140-
if log_mask_re:
141-
cmd = mask(cmd, log_mask_re)
138+
if self.log_mask_re is not None:
139+
result = mask(result, self.log_mask_re)
140+
if log_mask_re is not None:
141+
result = mask(result, log_mask_re)
142142

143-
return cmd
143+
return result
144144

145145
@abc.abstractmethod
146146
def execute_async(
@@ -249,7 +249,7 @@ def execute(
249249

250250
result = self._exec_command(
251251
command=command, async_result=async_result, timeout=timeout, verbose=verbose, **kwargs
252-
)
252+
) # type: exec_result.ExecResult
253253
message = "Command {result.cmd!r} exit code: {result.exit_code!s}".format(result=result)
254254
self.logger.log(level=logging.INFO if verbose else logging.DEBUG, msg=message) # type: ignore
255255
return result
@@ -315,18 +315,21 @@ def check_call(
315315
.. versionchanged:: 1.10.0 Expected is not optional, defaults os dependent
316316
"""
317317
expected_codes = proc_enums.exit_codes_to_enums(expected)
318-
ret = self.execute(command, verbose, timeout, **kwargs)
319-
if ret.exit_code not in expected_codes:
318+
result = self.execute(command, verbose, timeout, **kwargs) # type: exec_result.ExecResult
319+
if result.exit_code not in expected_codes:
320320
message = (
321321
"{append}Command {result.cmd!r} returned exit code "
322322
"{result.exit_code!s} while expected {expected!s}".format(
323-
append=error_info + "\n" if error_info else "", result=ret, expected=expected_codes
323+
append=error_info + "\n" if error_info else "", result=result, expected=expected_codes
324324
)
325325
)
326326
self.logger.error(msg=message)
327327
if raise_on_err:
328-
raise kwargs.get("exception_class", exceptions.CalledProcessError)(result=ret, expected=expected_codes)
329-
return ret
328+
raise kwargs.get("exception_class", exceptions.CalledProcessError)(
329+
result=result,
330+
expected=expected_codes
331+
)
332+
return result
330333

331334
def check_stderr(
332335
self,
@@ -358,20 +361,21 @@ def check_stderr(
358361
359362
.. versionchanged:: 1.2.0 default timeout 1 hour
360363
"""
361-
ret = self.check_call(
364+
result = self.check_call(
362365
command, verbose, timeout=timeout, error_info=error_info, raise_on_err=raise_on_err, **kwargs
363366
)
364-
if ret.stderr:
367+
append = error_info + "\n" if error_info else "" # type: str
368+
if result.stderr:
365369
message = (
366370
"{append}Command {result.cmd!r} output contains STDERR while not expected\n"
367-
"\texit code: {result.exit_code!s}".format(append=error_info + "\n" if error_info else "", result=ret)
371+
"\texit code: {result.exit_code!s}".format(append=append, result=result)
368372
)
369373
self.logger.error(msg=message)
370374
if raise_on_err:
371375
raise kwargs.get("exception_class", exceptions.CalledProcessError)(
372-
result=ret, expected=kwargs.get("expected")
376+
result=result, expected=kwargs.get("expected")
373377
)
374-
return ret
378+
return result
375379

376380
@staticmethod
377381
def _string_bytes_bytearray_as_bytes(src): # type: (typing.Union[six.text_type, bytes, bytearray]) -> bytes

exec_helpers/exec_result.py

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -85,10 +85,11 @@ def __init__(
8585

8686
self.__cmd = cmd
8787
if isinstance(stdin, six.binary_type):
88-
stdin = self._get_str_from_bin(bytearray(stdin))
88+
self.__stdin = self._get_str_from_bin(bytearray(stdin)) # type: typing.Optional[typing.Text]
8989
elif isinstance(stdin, bytearray):
90-
stdin = self._get_str_from_bin(stdin)
91-
self.__stdin = stdin # type: typing.Optional[typing.Text]
90+
self.__stdin = self._get_str_from_bin(stdin)
91+
else:
92+
self.__stdin = stdin
9293

9394
if stdout is not None:
9495
self._stdout = tuple(stdout) # type: typing.Tuple[bytes, ...]
@@ -107,10 +108,10 @@ def __init__(
107108
self.__started = started # type: typing.Optional[datetime.datetime]
108109

109110
# By default is none:
110-
self._stdout_str = None
111-
self._stderr_str = None
112-
self._stdout_brief = None
113-
self._stderr_brief = None
111+
self._stdout_str = None # type: typing.Optional[typing.Text]
112+
self._stderr_str = None # type: typing.Optional[typing.Text]
113+
self._stdout_brief = None # type: typing.Optional[typing.Text]
114+
self._stderr_brief = None # type: typing.Optional[typing.Text]
114115

115116
@property
116117
def stdout_lock(self): # type: () -> threading.RLock
@@ -176,7 +177,7 @@ def _get_str_from_bin(src): # type: (bytearray) -> typing.Text
176177
return src.strip().decode(encoding="utf-8", errors="backslashreplace")
177178

178179
@classmethod
179-
def _get_brief(cls, data): # type: (typing.Tuple[bytes]) -> typing.Text
180+
def _get_brief(cls, data): # type: (typing.Tuple[bytes, ...]) -> typing.Text
180181
"""Get brief output: 7 lines maximum (3 first + ... + 3 last).
181182
182183
:param data: source to process
@@ -228,7 +229,7 @@ def _poll_stream(
228229
log=None, # type: typing.Optional[logging.Logger]
229230
verbose=False, # type: bool
230231
): # type: (...) -> typing.List[bytes]
231-
dst = []
232+
dst = [] # type: typing.List[bytes]
232233
try:
233234
for line in src:
234235
dst.append(line)
@@ -323,8 +324,8 @@ def stdout_str(self): # type: () -> typing.Text
323324
"""
324325
with self.stdout_lock:
325326
if self._stdout_str is None:
326-
self._stdout_str = self._get_str_from_bin(self.stdout_bin) # type: ignore
327-
return self._stdout_str # type: ignore
327+
self._stdout_str = self._get_str_from_bin(self.stdout_bin)
328+
return self._stdout_str
328329

329330
@property
330331
def stderr_str(self): # type: () -> typing.Text
@@ -334,8 +335,8 @@ def stderr_str(self): # type: () -> typing.Text
334335
"""
335336
with self.stderr_lock:
336337
if self._stderr_str is None:
337-
self._stderr_str = self._get_str_from_bin(self.stderr_bin) # type: ignore
338-
return self._stderr_str # type: ignore
338+
self._stderr_str = self._get_str_from_bin(self.stderr_bin)
339+
return self._stderr_str
339340

340341
@property
341342
def stdout_brief(self): # type: () -> typing.Text
@@ -345,8 +346,8 @@ def stdout_brief(self): # type: () -> typing.Text
345346
"""
346347
with self.stdout_lock:
347348
if self._stdout_brief is None:
348-
self._stdout_brief = self._get_brief(self.stdout) # type: ignore
349-
return self._stdout_brief # type: ignore
349+
self._stdout_brief = self._get_brief(self.stdout)
350+
return self._stdout_brief
350351

351352
@property
352353
def stderr_brief(self): # type: () -> typing.Text
@@ -356,8 +357,8 @@ def stderr_brief(self): # type: () -> typing.Text
356357
"""
357358
with self.stderr_lock:
358359
if self._stderr_brief is None:
359-
self._stderr_brief = self._get_brief(self.stderr) # type: ignore
360-
return self._stderr_brief # type: ignore
360+
self._stderr_brief = self._get_brief(self.stderr)
361+
return self._stderr_brief
361362

362363
@property
363364
def exit_code(self): # type: () -> typing.Union[int, proc_enums.ExitCodes]
@@ -382,7 +383,7 @@ def exit_code(self, new_val): # type: (typing.Union[int, proc_enums.ExitCodes])
382383
if self.timestamp:
383384
raise RuntimeError("Exit code is already received.")
384385
if not isinstance(new_val, (six.integer_types, proc_enums.ExitCodes)):
385-
raise TypeError("Exit code is strictly int, got {!r}".format(new_val))
386+
raise TypeError("Exit code is strictly int, received: {code!r}".format(code=new_val))
386387
with self.stdout_lock, self.stderr_lock:
387388
self.__exit_code = proc_enums.exit_code_to_enum(new_val)
388389
if self.__exit_code != proc_enums.INVALID:

exec_helpers/proc_enums.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -193,16 +193,17 @@ def __str__(self): # type: () -> str
193193
def exit_code_to_enum(code): # type: (typing.Union[int, ExitCodes]) -> typing.Union[int, ExitCodes] # pragma: no cover
194194
"""Convert exit code to enum if possible."""
195195
if "win32" == sys.platform:
196-
return float(code)
197-
if isinstance(code, int) and code in ExitCodes.__members__.values():
196+
return digit_type(code)
197+
if isinstance(code, six.integer_types) and code in ExitCodes.__members__.values():
198198
return ExitCodes(code)
199199
return code
200200

201201

202202
def exit_codes_to_enums(
203203
codes=None # type: typing.Optional[typing.Iterable[typing.Union[int, ExitCodes]]]
204-
): # type: (...) -> typing.Iterable[typing.Union[int, ExitCodes]]
204+
): # type: (...) -> typing.Tuple[typing.Union[int, ExitCodes], ...]
205205
"""Convert integer exit codes to enums."""
206206
if codes is None:
207+
# noinspection PyRedundantParentheses
207208
return (EXPECTED,)
208209
return tuple(exit_code_to_enum(code) for code in codes)

exec_helpers/ssh_auth.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ def __init__(
7272
self.__username = username
7373
self.__password = password
7474
self.__key = key
75-
self.__keys = [None]
75+
self.__keys = [None] # type: typing.List[typing.Union[None, paramiko.RSAKey]]
7676
if key is not None:
7777
# noinspection PyTypeChecker
7878
self.__keys.append(key)
@@ -161,7 +161,7 @@ def connect(
161161
if self.__passphrase is not None:
162162
kwargs["passphrase"] = self.__passphrase
163163

164-
keys = [self.__key]
164+
keys = [self.__key] # type: typing.List[typing.Union[None, paramiko.RSAKey]]
165165
keys.extend([k for k in self.__keys if k != self.__key])
166166

167167
for key in keys:
@@ -170,7 +170,7 @@ def connect(
170170
client.connect(**kwargs)
171171
if self.__key != key:
172172
self.__key = key
173-
logger.debug("Main key has been updated, public key is: \n{}".format(self.public_key))
173+
logger.debug("Main key has been updated, public key is: \n%s", self.public_key)
174174
return
175175
except paramiko.PasswordRequiredException:
176176
if self.__password is None:

setup.py

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -151,12 +151,11 @@ def get_simple_vars_from_src(src):
151151
]
152152

153153
setup_args = dict(
154-
name='exec-helpers',
155-
author=variables['__author__'],
156-
author_email=variables['__author_email__'],
157-
maintainer=', '.join(
158-
'{name} <{email}>'.format(name=name, email=email)
159-
for name, email in variables['__maintainers__'].items()
154+
name="exec-helpers",
155+
author=variables["__author__"],
156+
author_email=variables["__author_email__"],
157+
maintainer=", ".join(
158+
"{name} <{email}>".format(name=name, email=email) for name, email in variables["__maintainers__"].items()
160159
),
161160
url=variables["__url__"],
162161
license=variables["__license__"],

test/test_ssh_client_init_special.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ def test_001_require_key(paramiko_ssh_client, auto_add_policy, ssh_auth_logger):
101101
auto_add_policy.assert_called_once()
102102

103103
ssh_auth_logger.debug.assert_called_once_with(
104-
"Main key has been updated, public key is: \n" "{}".format(ssh.auth.public_key)
104+
"Main key has been updated, public key is: \n%s", ssh.auth.public_key
105105
)
106106

107107
pkey = private_keys[0]
@@ -138,7 +138,7 @@ def test_002_use_next_key(paramiko_ssh_client, auto_add_policy, ssh_auth_logger)
138138
auto_add_policy.assert_called_once()
139139

140140
ssh_auth_logger.debug.assert_called_once_with(
141-
"Main key has been updated, public key is: \n" "{}".format(ssh.auth.public_key)
141+
"Main key has been updated, public key is: \n%s", ssh.auth.public_key
142142
)
143143

144144
kwargs = dict(hostname=host, pkey=None, port=port, username=username, password=None)
@@ -261,7 +261,7 @@ def test_009_auth_pass_no_key(paramiko_ssh_client, auto_add_policy, ssh_auth_log
261261
# Test
262262
ssh = exec_helpers.SSHClient(host=host, auth=exec_helpers.SSHAuth(username=username, password=password, key=key))
263263

264-
ssh_auth_logger.assert_has_calls((mock.call.debug("Main key has been updated, public key is: \nNone"),))
264+
ssh_auth_logger.assert_has_calls((mock.call.debug("Main key has been updated, public key is: \n%s", None),))
265265

266266
assert ssh.auth == exec_helpers.SSHAuth(username=username, password=password, keys=[key])
267267

0 commit comments

Comments
 (0)