Codebase list python-procrunner / 8d40216
Disable calling with unnamed arguments and enable type checking pre-commit Markus Gerstel 2 years ago
4 changed file(s) with 32 addition(s) and 46 deletion(s). Raw diff Collapse all Expand all
4040 hooks:
4141 - id: flake8
4242 additional_dependencies: ['flake8-comprehensions==3.5.0']
43
44 # Type checking
45 - repo: https://github.com/pre-commit/mirrors-mypy
46 rev: v0.910
47 hooks:
48 - id: mypy
49 files: 'src/.*\.py$'
77 * The run() function now returns a subprocess.CompletedProcess object,
88 which no longer allows array access operations
99 (those were deprecated in `#60 <https://github.com/DiamondLightSource/python-procrunner/pull/60>`_)
10 * Calling the run() function with multiple unnamed arguments is no longer supported
11 (previously deprecated in `#62 <https://github.com/DiamondLightSource/python-procrunner/pull/62>`_)
1012
1113 2.3.1 (2021-10-25)
1214 ------------------
00 from __future__ import annotations
11
22 import codecs
3 import functools
43 import io
54 import logging
65 import os
1312 import warnings
1413 from multiprocessing import Pipe
1514 from threading import Thread
15 from typing import Callable, Optional
1616
1717 #
1818 # run() - A function to synchronously run an external process, supporting
299299 return command
300300
301301
302 def _deprecate_argument_calling(f):
303 @functools.wraps(f)
304 def wrapper(*args, **kwargs):
305 if len(args) > 1:
306 warnings.warn(
307 "Calling procrunner.run() with unnamed arguments (apart from "
308 "the command) is deprecated. Use keyword arguments instead.",
309 DeprecationWarning,
310 stacklevel=2,
311 )
312 return f(*args, **kwargs)
313
314 return wrapper
315
316
317 @_deprecate_argument_calling
318302 def run(
319303 command,
320 timeout=None,
304 *,
305 timeout: Optional[float] = None,
321306 debug=None,
322 stdin=None,
323 print_stdout=True,
324 print_stderr=True,
325 callback_stdout=None,
326 callback_stderr=None,
327 environment=None,
328 environment_override=None,
329 win32resolve=True,
330 working_directory=None,
331 raise_timeout_exception=False,
307 stdin: Optional[bytes] = None,
308 print_stdout: bool = True,
309 print_stderr: bool = True,
310 callback_stdout: Optional[Callable] = None,
311 callback_stderr: Optional[Callable] = None,
312 environment: Optional[dict[str, str]] = None,
313 environment_override: Optional[dict[str, str]] = None,
314 win32resolve: bool = True,
315 working_directory: Optional[str] = None,
316 raise_timeout_exception: bool = False,
332317 ) -> subprocess.CompletedProcess:
333318 """
334319 Run an external process.
436421 if stdin is not None:
437422 notifyee, notifier = Pipe(False)
438423 thread_pipe_pool.append(notifyee)
439 stdin = _NonBlockingStreamWriter(
424 _NonBlockingStreamWriter(
440425 p.stdin, data=stdin, debug=debug, notify=notifier.close
441426 )
442427
530515 "Process ended after %.1f seconds with exit code %d", runtime, p.returncode
531516 )
532517
533 stdout = stdout.get_output()
534 stderr = stderr.get_output()
535
536 if timeout_encountered and raise_timeout_exception:
518 output_stdout = stdout.get_output()
519 output_stderr = stderr.get_output()
520
521 if timeout is not None and timeout_encountered and raise_timeout_exception:
537522 raise subprocess.TimeoutExpired(
538 cmd=command, timeout=timeout, output=stdout, stderr=stderr
523 cmd=command, timeout=timeout, output=output_stdout, stderr=output_stderr
539524 )
540525
541526 return subprocess.CompletedProcess(
542 args=command, returncode=p.returncode, stdout=stdout, stderr=stderr
527 args=command,
528 returncode=p.returncode,
529 stdout=output_stdout,
530 stderr=output_stderr,
543531 )
119119 assert te.value.stderr == b""
120120 assert te.value.timeout == 0.1
121121 assert te.value.cmd == command
122
123
124 def test_argument_deprecation(tmp_path):
125 with pytest.warns(DeprecationWarning, match="keyword arguments"):
126 result = procrunner.run(
127 [sys.executable, "-V"],
128 None,
129 working_directory=tmp_path,
130 )
131 assert not result.returncode
132 assert result.stderr or result.stdout