aboutsummaryrefslogtreecommitdiffstats
path: root/fuzzycat/utils.py
diff options
context:
space:
mode:
authorMartin Czygan <martin.czygan@gmail.com>2021-02-02 01:22:15 +0100
committerMartin Czygan <martin.czygan@gmail.com>2021-02-02 01:22:15 +0100
commit7588029a6a4d85cf88efa2350ecb6f8be32d105a (patch)
treeccfed22c3119019f0447eb279d819e3e1390a273 /fuzzycat/utils.py
parentea167dc34094ede319db8853270e5bfb6d229184 (diff)
downloadfuzzycat-7588029a6a4d85cf88efa2350ecb6f8be32d105a.tar.gz
fuzzycat-7588029a6a4d85cf88efa2350ecb6f8be32d105a.zip
add shellout helper
Diffstat (limited to 'fuzzycat/utils.py')
-rw-r--r--fuzzycat/utils.py54
1 files changed, 54 insertions, 0 deletions
diff --git a/fuzzycat/utils.py b/fuzzycat/utils.py
index 55729a1..b43cbcf 100644
--- a/fuzzycat/utils.py
+++ b/fuzzycat/utils.py
@@ -5,6 +5,8 @@ import os
import random
import re
import string
+import subprocess
+import tempfile
import requests
from glom import PathAccessError, glom
@@ -200,3 +202,55 @@ def zstdlines(filename):
line = prev_line + line
yield line
prev_line = lines[-1]
+
+
+def shellout(template,
+ preserve_whitespace=False,
+ executable='/bin/bash',
+ ignoremap=None,
+ encoding=None,
+ pipefail=True,
+ **kwargs):
+ """
+ Takes a shell command template and executes it. The template must use the
+ new (2.6+) format mini language. `kwargs` must contain any defined
+ placeholder, only `output` is optional and will be autofilled with a
+ temporary file if it used, but not specified explicitly.
+
+ If `pipefail` is `False` no subshell environment will be spawned, where a
+ failed pipe will cause an error as well. If `preserve_whitespace` is `True`,
+ no whitespace normalization is performed. A custom shell executable name can
+ be passed in `executable` and defaults to `/bin/bash`.
+
+ Raises RuntimeError on nonzero exit codes. To ignore certain errors, pass a
+ dictionary in `ignoremap`, with the error code to ignore as key and a string
+ message as value.
+
+ Simple template:
+
+ wc -l < {input} > {output}
+
+ Quoted curly braces:
+
+ ps ax|awk '{{print $1}}' > {output}
+
+ """
+ if not 'output' in kwargs:
+ kwargs.update({'output': tempfile.mkstemp(prefix='gluish-')[1]})
+ if ignoremap is None:
+ ignoremap = {}
+ if encoding:
+ command = template.decode(encoding).format(**kwargs)
+ else:
+ command = template.format(**kwargs)
+ if not preserve_whitespace:
+ command = re.sub('[ \t\n]+', ' ', command)
+ if pipefail:
+ command = '(set -o pipefail && %s)' % command
+ code = subprocess.call([command], shell=True, executable=executable)
+ if not code == 0:
+ if code not in ignoremap:
+ error = RuntimeError('%s exitcode: %s' % (command, code))
+ error.code = code
+ raise error
+ return kwargs.get('output')