59 lines
1.8 KiB
Python
59 lines
1.8 KiB
Python
try:
|
|
from datetime import datetime
|
|
except ImportError:
|
|
datetime = None
|
|
import logging
|
|
import re
|
|
from subprocess import PIPE, Popen
|
|
from pickle import dumps
|
|
|
|
log = logging.getLogger(__name__)
|
|
PUBLIC_DIR_RE = re.compile(r'.*?/usr/lib/python(\d(?:.\d+)?)/(site|dist)-packages')
|
|
|
|
|
|
class memoize:
|
|
def __init__(self, func):
|
|
self.func = func
|
|
self.cache = {}
|
|
|
|
def __call__(self, *args, **kwargs):
|
|
key = dumps((args, kwargs))
|
|
if key not in self.cache:
|
|
self.cache[key] = self.func(*args, **kwargs)
|
|
return self.cache[key]
|
|
|
|
|
|
def execute(command, cwd=None, env=None, log_output=None):
|
|
"""Execute external commad.
|
|
|
|
:param cdw: currennt working directory
|
|
:param env: environment
|
|
:param log_output:
|
|
* opened log file or path to this file, or
|
|
* None if output should be included in the returned dict, or
|
|
* False if output should be redirectored to stdout/stderr
|
|
"""
|
|
args = {'shell': False, 'cwd': cwd, 'env': env}
|
|
close = False
|
|
if log_output is False:
|
|
pass
|
|
elif log_output is None:
|
|
args.update(stdout=PIPE, stderr=PIPE)
|
|
elif log_output:
|
|
if isinstance(log_output, str):
|
|
close = True
|
|
log_output = open(log_output, 'a')
|
|
if datetime:
|
|
log_output.write('\n# command executed on {}'.format(datetime.now().isoformat()))
|
|
log_output.write('\n$ {}\n'.format(repr(command)))
|
|
log_output.flush()
|
|
args.update(stdout=log_output, stderr=log_output)
|
|
|
|
log.debug('invoking: %r', command)
|
|
with Popen(command, **args) as process:
|
|
stdout, stderr = process.communicate()
|
|
close and log_output.close()
|
|
return dict(returncode=process.returncode,
|
|
stdout=stdout and str(stdout, 'utf-8'),
|
|
stderr=stderr and str(stderr, 'utf-8'))
|