From 902c313b4dfbfd19bf5825c0f44ef845f7d0f67b Mon Sep 17 00:00:00 2001 From: Brett Smith Date: Tue, 5 Jan 2021 16:46:42 -0500 Subject: [PATCH] cliutil: New function can_run. --- conservancy_beancount/cliutil.py | 18 ++++++++++++++++++ tests/test_cliutil.py | 12 ++++++++++++ 2 files changed, 30 insertions(+) diff --git a/conservancy_beancount/cliutil.py b/conservancy_beancount/cliutil.py index 89e5601..2e04695 100644 --- a/conservancy_beancount/cliutil.py +++ b/conservancy_beancount/cliutil.py @@ -20,6 +20,7 @@ import os import pkg_resources import re import signal +import subprocess import sys import traceback import types @@ -37,6 +38,7 @@ from typing import ( Any, BinaryIO, Callable, + Container, IO, Iterable, NamedTuple, @@ -279,6 +281,22 @@ def add_version_argument(parser: argparse.ArgumentParser) -> argparse.Action: help="Show program version and license information", ) +def can_run( + cmd: Sequence[str], + stdout: Optional[int]=subprocess.DEVNULL, + stderr: Optional[int]=None, + ok_returncodes: Container[int]=frozenset([0]), +) -> bool: + try: + with subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=stdout, stderr=stderr) as proc: + # Typing says this can be None, but I don't think that's true + # given that we passed stdin=PIPE. + proc.stdin.close() # type:ignore[union-attr] + except (OSError, subprocess.SubprocessError): + return False + else: + return proc.returncode in ok_returncodes + def date_arg(arg: str) -> datetime.date: return datetime.datetime.strptime(arg, '%Y-%m-%d').date() diff --git a/tests/test_cliutil.py b/tests/test_cliutil.py index f5ae44c..20ea61e 100644 --- a/tests/test_cliutil.py +++ b/tests/test_cliutil.py @@ -20,6 +20,8 @@ import pytest from pathlib import Path +from . import testutil + from conservancy_beancount import cliutil FILE_NAMES = ['-foobar', '-foo.bin'] @@ -227,3 +229,13 @@ def test_version_argument(argparser, capsys, arg): ]) def test_diff_year(date, diff, expected): assert cliutil.diff_year(date, diff) == expected + +@pytest.mark.parametrize('cmd,expected', [ + (['true'], True), + (['true', '--version'], True), + (['false'], False), + (['false', '--version'], False), + ([str(testutil.TESTS_DIR)], False), +]) +def test_can_run(cmd, expected): + assert cliutil.can_run(cmd) == expected