|
|
@ -1,6 +1,6 @@
|
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
|
|
|
|
|
|
|
|
# Copyright 2018 Mike Fährmann
|
|
|
|
# Copyright 2018-2019 Mike Fährmann
|
|
|
|
#
|
|
|
|
#
|
|
|
|
# This program is free software; you can redistribute it and/or modify
|
|
|
|
# This program is free software; you can redistribute it and/or modify
|
|
|
|
# it under the terms of the GNU General Public License version 2 as
|
|
|
|
# it under the terms of the GNU General Public License version 2 as
|
|
|
@ -9,7 +9,9 @@
|
|
|
|
"""Execute processes"""
|
|
|
|
"""Execute processes"""
|
|
|
|
|
|
|
|
|
|
|
|
from .common import PostProcessor
|
|
|
|
from .common import PostProcessor
|
|
|
|
|
|
|
|
from .. import util
|
|
|
|
import subprocess
|
|
|
|
import subprocess
|
|
|
|
|
|
|
|
import shlex
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class ExecPP(PostProcessor):
|
|
|
|
class ExecPP(PostProcessor):
|
|
|
@ -17,27 +19,60 @@ class ExecPP(PostProcessor):
|
|
|
|
def __init__(self, pathfmt, options):
|
|
|
|
def __init__(self, pathfmt, options):
|
|
|
|
PostProcessor.__init__(self)
|
|
|
|
PostProcessor.__init__(self)
|
|
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
args = options["command"]
|
|
|
|
self.args = options["command"]
|
|
|
|
|
|
|
|
self.args[0] # test if 'args' is subscriptable
|
|
|
|
if isinstance(args, str):
|
|
|
|
except (KeyError, IndexError, TypeError):
|
|
|
|
self.args = util.Formatter(args.replace("{}", "{_temppath}"))
|
|
|
|
raise TypeError("option 'command' must be a non-empty list")
|
|
|
|
self.shell = True
|
|
|
|
|
|
|
|
self._format = self._format_args_string
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
|
|
|
for i, arg in enumerate(args):
|
|
|
|
|
|
|
|
if "{}" in arg:
|
|
|
|
|
|
|
|
args[i] = arg.replace("{}", "{_temppath}")
|
|
|
|
|
|
|
|
self.args = [util.Formatter(arg) for arg in args]
|
|
|
|
|
|
|
|
self.shell = False
|
|
|
|
|
|
|
|
self._format = self._format_args_list
|
|
|
|
|
|
|
|
|
|
|
|
if options.get("async", False):
|
|
|
|
if options.get("async", False):
|
|
|
|
self._exec = subprocess.Popen
|
|
|
|
self._exec = self._exec_async
|
|
|
|
|
|
|
|
|
|
|
|
def run(self, pathfmt):
|
|
|
|
def run(self, pathfmt):
|
|
|
|
self._exec([
|
|
|
|
kwdict = pathfmt.kwdict
|
|
|
|
arg.format_map(pathfmt.keywords)
|
|
|
|
kwdict["_directory"] = pathfmt.realdirectory
|
|
|
|
for arg in self.args
|
|
|
|
kwdict["_filename"] = pathfmt.filename
|
|
|
|
])
|
|
|
|
kwdict["_temppath"] = pathfmt.temppath
|
|
|
|
|
|
|
|
kwdict["_path"] = pathfmt.realpath
|
|
|
|
|
|
|
|
self._exec(self._format(kwdict))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _format_args_list(self, kwdict):
|
|
|
|
|
|
|
|
return [arg.format_map(kwdict) for arg in self.args]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _format_args_string(self, kwdict):
|
|
|
|
|
|
|
|
return self.args.format_map(_quote(kwdict))
|
|
|
|
|
|
|
|
|
|
|
|
def _exec(self, args):
|
|
|
|
def _exec(self, args):
|
|
|
|
retcode = subprocess.Popen(args).wait()
|
|
|
|
retcode = subprocess.Popen(args, shell=self.shell).wait()
|
|
|
|
if retcode:
|
|
|
|
if retcode:
|
|
|
|
self.log.warning(
|
|
|
|
self.log.warning(
|
|
|
|
"executing '%s' returned non-zero exit status %d",
|
|
|
|
"executing '%s' returned with non-zero exit status (%d)",
|
|
|
|
" ".join(args), retcode)
|
|
|
|
" ".join(args) if isinstance(args, list) else args, retcode)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _exec_async(self, args):
|
|
|
|
|
|
|
|
subprocess.Popen(args, shell=self.shell)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _quote(kwdict):
|
|
|
|
|
|
|
|
"""Create a copy of 'kwdict' and apply shlex.quote to its string values"""
|
|
|
|
|
|
|
|
kwdict = kwdict.copy()
|
|
|
|
|
|
|
|
for key, value in kwdict.items():
|
|
|
|
|
|
|
|
cls = value.__class__
|
|
|
|
|
|
|
|
if cls is str:
|
|
|
|
|
|
|
|
kwdict[key] = shlex.quote(value)
|
|
|
|
|
|
|
|
elif cls is list:
|
|
|
|
|
|
|
|
kwdict[key] = shlex.quote(", ".join(value))
|
|
|
|
|
|
|
|
elif cls is dict:
|
|
|
|
|
|
|
|
kwdict[key] = _quote(value)
|
|
|
|
|
|
|
|
return kwdict
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
__postprocessor__ = ExecPP
|
|
|
|
__postprocessor__ = ExecPP
|
|
|
|