[postprocessor:exec] improve; add command-line option (#421)

pull/448/head
Mike Fährmann 5 years ago
parent 5a54efa025
commit b06c372e4d
No known key found for this signature in database
GPG Key ID: 5680CA389D365A88

@ -27,6 +27,15 @@ class ConfigConstAction(argparse.Action):
namespace.options.append(((self.dest,), self.const)) namespace.options.append(((self.dest,), self.const))
class AppendCommandAction(argparse.Action):
def __call__(self, parser, namespace, values, option_string=None):
items = getattr(namespace, self.dest, None) or []
val = self.const.copy()
val["command"] = values
items.append(val)
setattr(namespace, self.dest, items)
class DeprecatedConfigConstAction(argparse.Action): class DeprecatedConfigConstAction(argparse.Action):
"""Set argparse const values as config values + deprecation warning""" """Set argparse const values as config values + deprecation warning"""
def __call__(self, parser, namespace, values, option_string=None): def __call__(self, parser, namespace, values, option_string=None):
@ -303,6 +312,12 @@ def build_parser():
action="append_const", const={"name": "zip"}, action="append_const", const={"name": "zip"},
help="Store downloaded files in a ZIP archive", help="Store downloaded files in a ZIP archive",
) )
postprocessor.add_argument(
"--exec",
dest="postprocessors", metavar="CMD",
action=AppendCommandAction, const={"name": "exec"},
help="Execute CMD for each downloaded file",
)
postprocessor.add_argument( postprocessor.add_argument(
"--ugoira-conv", "--ugoira-conv",
dest="postprocessors", dest="postprocessors",

@ -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

Loading…
Cancel
Save