x264 source for verification 2026-05-22
This commit is contained in:
149
tools/digress/cli.py
Normal file
149
tools/digress/cli.py
Normal file
@@ -0,0 +1,149 @@
|
||||
"""
|
||||
Digress's CLI interface.
|
||||
"""
|
||||
|
||||
import inspect
|
||||
import sys
|
||||
from optparse import OptionParser
|
||||
|
||||
import textwrap
|
||||
|
||||
from types import MethodType
|
||||
|
||||
from digress import __version__ as version
|
||||
|
||||
def dispatchable(func):
|
||||
"""
|
||||
Mark a method as dispatchable.
|
||||
"""
|
||||
func.digress_dispatchable = True
|
||||
return func
|
||||
|
||||
class Dispatcher(object):
|
||||
"""
|
||||
Dispatcher for CLI commands.
|
||||
"""
|
||||
def __init__(self, fixture):
|
||||
self.fixture = fixture
|
||||
fixture.dispatcher = self
|
||||
|
||||
def _monkey_print_help(self, optparse, *args, **kwargs):
|
||||
# monkey patches OptionParser._print_help
|
||||
OptionParser.print_help(optparse, *args, **kwargs)
|
||||
|
||||
print >>sys.stderr, "\nAvailable commands:"
|
||||
|
||||
maxlen = max([ len(command_name) for command_name in self.commands ])
|
||||
|
||||
descwidth = 80 - maxlen - 4
|
||||
|
||||
for command_name, command_meth in self.commands.iteritems():
|
||||
print >>sys.stderr, " %s %s\n" % (
|
||||
command_name.ljust(maxlen + 1),
|
||||
("\n" + (maxlen + 4) * " ").join(
|
||||
textwrap.wrap(" ".join(filter(
|
||||
None,
|
||||
command_meth.__doc__.strip().replace("\n", " ").split(" ")
|
||||
)),
|
||||
descwidth
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
def _enable_flush(self):
|
||||
self.fixture.flush_before = True
|
||||
|
||||
def _populate_parser(self):
|
||||
self.commands = self._get_commands()
|
||||
|
||||
self.optparse = OptionParser(
|
||||
usage = "usage: %prog [options] command [args]",
|
||||
description = "Digress CLI frontend for %s." % self.fixture.__class__.__name__,
|
||||
version = "Digress %s" % version
|
||||
)
|
||||
|
||||
self.optparse.print_help = MethodType(self._monkey_print_help, self.optparse, OptionParser)
|
||||
|
||||
self.optparse.add_option(
|
||||
"-f",
|
||||
"--flush",
|
||||
action="callback",
|
||||
callback=lambda option, opt, value, parser: self._enable_flush(),
|
||||
help="flush existing data for a revision before testing"
|
||||
)
|
||||
|
||||
self.optparse.add_option(
|
||||
"-c",
|
||||
"--cases",
|
||||
metavar="FOO,BAR",
|
||||
action="callback",
|
||||
dest="cases",
|
||||
type=str,
|
||||
callback=lambda option, opt, value, parser: self._select_cases(*value.split(",")),
|
||||
help="test cases to run, run with command list to see full list"
|
||||
)
|
||||
|
||||
def _select_cases(self, *cases):
|
||||
self.fixture.cases = filter(lambda case: case.__name__ in cases, self.fixture.cases)
|
||||
|
||||
def _get_commands(self):
|
||||
commands = {}
|
||||
|
||||
for name, member in inspect.getmembers(self.fixture):
|
||||
if hasattr(member, "digress_dispatchable"):
|
||||
commands[name] = member
|
||||
|
||||
return commands
|
||||
|
||||
def _run_command(self, name, *args):
|
||||
if name not in self.commands:
|
||||
print >>sys.stderr, "error: %s is not a valid command\n" % name
|
||||
self.optparse.print_help()
|
||||
return
|
||||
|
||||
command = self.commands[name]
|
||||
|
||||
argspec = inspect.getargspec(command)
|
||||
|
||||
max_arg_len = len(argspec.args) - 1
|
||||
min_arg_len = max_arg_len - ((argspec.defaults is not None) and len(argspec.defaults) or 0)
|
||||
|
||||
if len(args) < min_arg_len:
|
||||
print >>sys.stderr, "error: %s takes at least %d arguments\n" % (
|
||||
name,
|
||||
min_arg_len
|
||||
)
|
||||
print >>sys.stderr, "%s\n" % command.__doc__
|
||||
self.optparse.print_help()
|
||||
return
|
||||
|
||||
if len(args) > max_arg_len:
|
||||
print >>sys.stderr, "error: %s takes at most %d arguments\n" % (
|
||||
name,
|
||||
max_arg_len
|
||||
)
|
||||
print >>sys.stderr, "%s\n" % command.__doc__
|
||||
self.optparse.print_help()
|
||||
return
|
||||
|
||||
command(*args)
|
||||
|
||||
def pre_dispatch(self):
|
||||
pass
|
||||
|
||||
def dispatch(self):
|
||||
self._populate_parser()
|
||||
|
||||
self.optparse.parse_args()
|
||||
self.pre_dispatch()
|
||||
args = self.optparse.parse_args()[1] # arguments may require reparsing after pre_dispatch; see test_x264.py
|
||||
|
||||
if len(args) == 0:
|
||||
print >>sys.stderr, "error: no command specified\n"
|
||||
self.optparse.print_help()
|
||||
return
|
||||
|
||||
command = args[0]
|
||||
addenda = args[1:]
|
||||
|
||||
self._run_command(command, *addenda)
|
||||
Reference in New Issue
Block a user