Source code for nxpy.command.option
# nxpy.command package -------------------------------------------------------
# Copyright Nicola Musatti 2010 - 2012
# Use, modification, and distribution are subject to the Boost Software
# License, Version 1.0. (See accompanying file LICENSE.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
# See http://sourceforge.net/nxpy for library home page. ---------------------
r"""
Function argument to command line option conversion.
Provides means to describe commands with complicated syntaxes, which often combine sub-commands,
options and arguments. Typical examples include subversion and ftp.
"""
import nxpy.core.sequence
[docs]class InvalidOptionError(Exception):
r"""Raised when an option is not supported."""
[docs]class Config(object):
r"""
Command option definitions.
Provides a single definition point for all the options supported by a command.
"""
def __init__(self, prefix="--", separator=" ", bool_opts=(), value_opts=(), iterable_opts=(),
format_opts={}, mapped_opts={}, opposite_opts={}):
r"""
Constructor. Its arguments are used to specify all the valid options.
Each option is prefixed by 'prefix'. When an option takes multiple arguments these are
separated by a 'separator'. 'bool_opts' must be specified on the command line when they
are 'True'. 'value_options' take a single argument; 'iterable_options' take multiple
arguments; 'format_options' have their syntax specified by means of a format string;
'mapped_options' require some form of translation, usually because they are not valid
Python identifiers; 'opposite_options' must be specified on the command line when they
are 'False'.
"""
self.prefix = prefix
self.separator = separator
self.bool_opts = bool_opts
self.value_opts = value_opts
self.iterable_opts = iterable_opts
self.format_opts = format_opts
self.mapped_opts = mapped_opts
self.opposite_opts = opposite_opts
self.opts = set(nxpy.core.sequence.make_tuple(bool_opts))
self.opts.update(nxpy.core.sequence.make_tuple(value_opts))
self.opts.update(nxpy.core.sequence.make_tuple(iterable_opts))
self.opts.update(format_opts.keys())
self.opts.difference_update(mapped_opts.keys())
[docs]class Parser(object):
r"""
Constructs a complex command line from the provided 'command' and its 'options' and
'arguments'. Uses a Config instance, 'config', to provide means to check conditions on the
supplied options.
"""
def __init__(self, config, command, arguments, options, **defaults):
invalid = set(options.keys()).difference(defaults.keys())
if len(invalid) > 0:
raise InvalidOptionError(", ".join(invalid) +
": invalid option(s)")
self.config = config
self.command = command
self.arguments = arguments
self.options = {}
self.options.update(defaults)
self.options.update(options)
self.cmd_line = []
def getCommandLine(self):
if not self.cmd_line:
self._applyOptions()
if self.arguments:
self.cmd_line.extend(self.arguments)
return " ".join(self.cmd_line)
def checkMandatoryOptions(self, *options):
if not all([ bool(self.options[o]) for o in options ]):
raise InvalidOptionError(", ".join(options) +
": mandatory options")
def checkExclusiveOptions(self, *options):
if sum([ bool(self.options[o]) for o in options ]) > 1:
raise InvalidOptionError(", ".join(options) +
": mutually exclusive options")
def checkExactlyOneOption(self, *options):
s = sum([ bool(self.options[o]) for o in options ])
if s != 1:
raise InvalidOptionError(", ".join(options) +
": only one among these options should be specified")
def checkNotBothOptsAndArgs(self, *options):
if any([ bool(self.options[o]) for o in options ]) and self.arguments:
raise InvalidOptionError(", ".join(options) +
": This/these option(s) is/are invalid when arguments are specified")
def checkOneBetweenOptsAndArgs(self, *options):
if ( any([ bool(self.options[o]) for o in options ]) +
bool(self.arguments) ) != 1:
raise InvalidOptionError(", ".join(options) +
": This/these option(s) is/are mutually exclusive with arguments")
def _applyOptions(self):
if self.command is not None:
self.cmd_line.append(self.command)
for opt in self.options.keys():
if self.options[opt]:
if opt in self.config.opts:
self.cmd_line.append(self.config.prefix + opt)
elif opt in self.config.mapped_opts:
self.cmd_line.append(self.config.mapped_opts[opt])
if opt in self.config.value_opts:
self.cmd_line.append(self.options[opt])
elif opt in self.config.iterable_opts:
self.cmd_line.append(self.config.separator.join(self.options[opt]))
elif opt in self.config.format_opts.keys():
self.cmd_line.append(
self.config.format_opts[opt] % self.options[opt])
elif opt in self.config.opposite_opts.keys():
self.cmd_line.append(self.config.opposite_opts[opt])