Skip to content

Commit

Permalink
Improve error reporting in smart
Browse files Browse the repository at this point in the history
Add code to check proper command line arguments for various
smart commands. Exit with error if erroneous/additional arguments
are given in the command line.

Signed-off-by: Bogdan Marinescu <[email protected]>
  • Loading branch information
Bogdan Marinescu authored and bluelightning committed Dec 13, 2013
1 parent 1227051 commit 406541f
Show file tree
Hide file tree
Showing 11 changed files with 106 additions and 2 deletions.
12 changes: 11 additions & 1 deletion smart/commands/channel.py
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,17 @@ def main(ctrl, opts):
opts.show is None and opts.yaml is None):
iface.warning(_("Can't edit channels information."))
raise Error, _("Configuration is in readonly mode.")


# Argument check
opts.check_args_of_option("set", -1)
opts.check_args_of_option("remove", -1)
opts.check_args_of_option("edit", 0)
opts.check_args_of_option("enable", -1)
opts.check_args_of_option("disable", -1)
opts.ensure_action("channel", ["add", "set", "remove", "remove-all",
"list", "show", "yaml", "enable", "disable"])
opts.check_remaining_args()

if opts.add is not None:
if not opts.add and opts.args == ["-"]:
newchannels = []
Expand Down
3 changes: 3 additions & 0 deletions smart/commands/check.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,9 @@ def parse_options(argv):

def main(ctrl, opts, reloadchannels=True):

# Argument check
opts.check_args_of_option("channels", 1)

if sysconf.get("auto-update"):
from smart.commands import update
updateopts = update.parse_options([])
Expand Down
6 changes: 6 additions & 0 deletions smart/commands/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,12 @@ def main(ctrl, opts):
globals["false"] = False
globals["no"] = False

# Check arguments
opts.check_args_of_option("set", -1)
opts.check_args_of_option("remove", -1)
opts.ensure_action("config", ["set", "show", "yaml", "remove"])
opts.check_remaining_args()

if opts.set:
for opt in opts.set:
m = SETRE.match(opt)
Expand Down
8 changes: 8 additions & 0 deletions smart/commands/download.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,14 @@ def parse_options(argv):

def main(ctrl, opts):

# Argument check
opts.check_args_of_option("target", 1)
opts.check_args_of_option("output", 1)
opts.check_args_of_option("from_urls", -1)
opts.check_args_of_option("from_metalink", -1)
if not opts.args and not opts.from_metalink and not opts.from_urls:
raise Error, _("no package(s) given")

packages = []
if opts.args:
if sysconf.get("auto-update"):
Expand Down
4 changes: 4 additions & 0 deletions smart/commands/info.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,10 @@ def parse_options(argv):

def main(ctrl, opts, reloadchannels=True):

# Argument check
if not opts.args:
raise Error, _("No package(s) given")

if sysconf.get("auto-update"):
from smart.commands import update
updateopts = update.parse_options([])
Expand Down
4 changes: 4 additions & 0 deletions smart/commands/install.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,10 @@ def parse_options(argv):

def main(ctrl, opts):

# Argument check
if not opts.args:
raise Error, _("no package(s) given")

if opts.explain:
sysconf.set("explain-changesets", True, soft=True)

Expand Down
6 changes: 5 additions & 1 deletion smart/commands/reinstall.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,11 @@ def parse_options(argv):
return opts

def main(ctrl, opts):


# Argument check
if not opts.args:
raise Error, _("no package(s) given")

if opts.explain:
sysconf.set("explain-changesets", True, soft=True)

Expand Down
4 changes: 4 additions & 0 deletions smart/commands/remove.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,10 @@ def parse_options(argv):

def main(ctrl, opts):

# Argument check
if not opts.args:
raise Error, _("no package(s) given")

if opts.explain:
sysconf.set("explain-changesets", True, soft=True)

Expand Down
2 changes: 2 additions & 0 deletions smart/commands/search.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ def option_parser():
def parse_options(argv):
opts = query.parse_options(argv, usage=USAGE, \
description=DESCRIPTION, examples=EXAMPLES)
if not argv:
raise Error, _("Search expression not specified")
opts.name = opts.args
opts.summary = opts.args
opts.description = opts.args
Expand Down
3 changes: 3 additions & 0 deletions smart/commands/upgrade.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,9 @@ def parse_options(argv):

def main(ctrl, opts):

# Argument check
opts.check_args_of_option("flag", 1)

if opts.explain:
sysconf.set("explain-changesets", True, soft=True)

Expand Down
56 changes: 56 additions & 0 deletions smart/util/optparse.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@
import types
import textwrap
from gettext import gettext as _
from smart import Error
import re

def _repr(self):
return "<%s at 0x%x: %s>" % (self.__class__.__name__, id(self), self)
Expand Down Expand Up @@ -708,6 +710,12 @@ def process(self, opt, value, values, parser):
self.action, self.dest, opt, value, values, parser)

def take_action(self, action, dest, opt, value, values, parser):
# Keep all the options in the command line in the '_given_opts' array
# This will be used later to validate the command line
given_opts = getattr(parser.values, "_given_opts", [])
user_opt = re.sub(r"^\-*", "", opt).replace("-", "_")
given_opts.append(user_opt)
setattr(parser.values, "_given_opts", given_opts)
if action == "store":
setattr(values, dest, value)
elif action == "store_const":
Expand Down Expand Up @@ -819,6 +827,54 @@ def ensure_value(self, attr, value):
setattr(self, attr, value)
return getattr(self, attr)

# Check if the given option has the specified number of arguments
# Raise an error if the option has an invalid number of arguments
# A negative number for 'nargs' means "at least |nargs| arguments are needed"
def check_args_of_option(self, opt, nargs, err=None):
given_opts = getattr(self, "_given_opts", [])
if not opt in given_opts:
return
values = getattr(self, opt, [])
if type(values) != type([]):
return
if nargs < 0:
nargs = -nargs
if len(values) >= nargs:
return
if not err:
if nargs == 1:
err = _("Option '%s' requires at least one argument") % opt
else:
err = _("Option '%s' requires at least %d arguments") % (opt, nargs)
raise Error, err
elif nargs == 0:
if len( values ) == 0:
return
raise Error, err
else:
if len(values) == nargs:
return
if not err:
if nargs == 1:
err = _("Option '%s' requires one argument") % opt
else:
err = _("Option '%s' requires %d arguments") % (opt, nargs)
raise Error, err

# Check that at least one of the options in 'actlist' was given as an argument
# to the command 'cmdname'
def ensure_action(self, cmdname, actlist):
given_opts = getattr(self, "_given_opts", [])
for action in actlist:
if action in given_opts:
return
raise Error, _("No action specified for command '%s'") % cmdname

# Check if there are any other arguments left after parsing the command line and
# raise an error if such arguments are found
def check_remaining_args(self):
if self.args:
raise Error, _("Invalid argument(s) '%s'" % str(self.args))

class OptionContainer:

Expand Down

0 comments on commit 406541f

Please sign in to comment.