Command line errors cleaned up and made more consistent
This commit is contained in:
parent
f0c2a64ae3
commit
87b43e5d04
|
@ -24,10 +24,16 @@ subcmd_mods = {}
|
|||
for cmd in subcommands:
|
||||
subcmd_mods[cmd] = __import__("nilmdb.cmdline." + cmd, fromlist = [ cmd ])
|
||||
|
||||
class JimArgumentParser(argparse.ArgumentParser):
|
||||
def error(self, message):
|
||||
self.print_usage(sys.stderr)
|
||||
self.exit(2, sprintf("error: %s\n", message))
|
||||
|
||||
class Cmdline(object):
|
||||
|
||||
def __init__(self, argv):
|
||||
self.argv = argv
|
||||
self.client = None
|
||||
|
||||
def arg_time(self, toparse):
|
||||
"""Parse a time string argument"""
|
||||
|
@ -93,8 +99,8 @@ class Cmdline(object):
|
|||
version_string = sprintf("nilmtool %s, client library %s",
|
||||
version, nilmdb.Client.client_version)
|
||||
|
||||
self.parser = argparse.ArgumentParser(add_help = False,
|
||||
formatter_class = def_form)
|
||||
self.parser = JimArgumentParser(add_help = False,
|
||||
formatter_class = def_form)
|
||||
|
||||
group = self.parser.add_argument_group("General options")
|
||||
group.add_argument("-h", "--help", action='help',
|
||||
|
@ -119,7 +125,8 @@ class Cmdline(object):
|
|||
|
||||
def die(self, formatstr, *args):
|
||||
fprintf(sys.stderr, formatstr + "\n", *args)
|
||||
self.client.close()
|
||||
if self.client:
|
||||
self.client.close()
|
||||
sys.exit(-1)
|
||||
|
||||
def run(self):
|
||||
|
@ -141,7 +148,7 @@ class Cmdline(object):
|
|||
try:
|
||||
server_version = self.client.version()
|
||||
except nilmdb.client.Error as e:
|
||||
self.die("Error connecting to server: %s", str(e))
|
||||
self.die("error connecting to server: %s", str(e))
|
||||
|
||||
# Now dispatch client request to appropriate function. Parser
|
||||
# should have ensured that we don't have any unknown commands
|
||||
|
|
|
@ -24,4 +24,4 @@ def cmd_create(self):
|
|||
try:
|
||||
self.client.stream_create(self.args.path, self.args.layout)
|
||||
except nilmdb.client.ClientError as e:
|
||||
self.die("Error creating stream: %s", str(e))
|
||||
self.die("error creating stream: %s", str(e))
|
||||
|
|
|
@ -22,4 +22,4 @@ def cmd_destroy(self):
|
|||
try:
|
||||
self.client.stream_destroy(self.args.path)
|
||||
except nilmdb.client.ClientError as e:
|
||||
self.die("Error deleting stream: %s", str(e))
|
||||
self.die("error destroying stream: %s", str(e))
|
||||
|
|
|
@ -39,7 +39,7 @@ def cmd_extract_verify(self):
|
|||
def cmd_extract(self):
|
||||
streams = self.client.stream_list(self.args.path)
|
||||
if len(streams) != 1:
|
||||
self.die("Error getting stream info for path %s", self.args.path)
|
||||
self.die("error getting stream info for path %s", self.args.path)
|
||||
layout = streams[0][1]
|
||||
|
||||
if self.args.annotate:
|
||||
|
|
|
@ -51,12 +51,12 @@ def cmd_insert(self):
|
|||
# Find requested stream
|
||||
streams = self.client.stream_list(self.args.path)
|
||||
if len(streams) != 1:
|
||||
self.die("Error getting stream info for path %s", self.args.path)
|
||||
self.die("error getting stream info for path %s", self.args.path)
|
||||
|
||||
layout = streams[0][1]
|
||||
|
||||
if self.args.start and len(self.args.file) != 1:
|
||||
self.die("--start can only be used with one input file, for now")
|
||||
self.die("error: --start can only be used with one input file")
|
||||
|
||||
for filename in self.args.file:
|
||||
if filename == '-':
|
||||
|
@ -65,7 +65,7 @@ def cmd_insert(self):
|
|||
try:
|
||||
infile = open(filename, "r")
|
||||
except IOError:
|
||||
self.die("Error opening input file %s", filename)
|
||||
self.die("error opening input file %s", filename)
|
||||
|
||||
# Build a timestamper for this file
|
||||
if self.args.none:
|
||||
|
@ -77,11 +77,11 @@ def cmd_insert(self):
|
|||
try:
|
||||
start = self.parse_time(filename)
|
||||
except ValueError:
|
||||
self.die("Error extracting time from filename '%s'",
|
||||
self.die("error extracting time from filename '%s'",
|
||||
filename)
|
||||
|
||||
if not self.args.rate:
|
||||
self.die("Need to specify --rate")
|
||||
self.die("error: --rate is needed, but was not specified")
|
||||
rate = self.args.rate
|
||||
|
||||
ts = nilmdb.timestamper.TimestamperRate(infile, start, rate)
|
||||
|
@ -100,6 +100,6 @@ def cmd_insert(self):
|
|||
# ugly bracketed ranges of 16-digit numbers and a mangled URL.
|
||||
# Need to consider adding something like e.prettyprint()
|
||||
# that is smarter about the contents of the error.
|
||||
self.die("Error inserting data: %s", str(e))
|
||||
self.die("error inserting data: %s", str(e))
|
||||
|
||||
return
|
||||
|
|
|
@ -43,21 +43,21 @@ def cmd_metadata(self):
|
|||
for keyval in keyvals:
|
||||
kv = keyval.split('=')
|
||||
if len(kv) != 2 or kv[0] == "":
|
||||
self.die("Error parsing key=value argument '%s'", keyval)
|
||||
self.die("error parsing key=value argument '%s'", keyval)
|
||||
data[kv[0]] = kv[1]
|
||||
|
||||
# Make the call
|
||||
try:
|
||||
handler(self.args.path, data)
|
||||
except nilmdb.client.ClientError as e:
|
||||
self.die("Error setting/updating metadata: %s", str(e))
|
||||
self.die("error setting/updating metadata: %s", str(e))
|
||||
else:
|
||||
# Get (or unspecified)
|
||||
keys = self.args.get or None
|
||||
try:
|
||||
data = self.client.stream_get_metadata(self.args.path, keys)
|
||||
except nilmdb.client.ClientError as e:
|
||||
self.die("Error getting metadata: %s", str(e))
|
||||
self.die("error getting metadata: %s", str(e))
|
||||
for key, value in sorted(data.items()):
|
||||
# Omit nonexistant keys
|
||||
if value is None:
|
||||
|
|
|
@ -33,15 +33,11 @@ def cmd_remove_verify(self):
|
|||
self.parser.error("start is after end")
|
||||
|
||||
def cmd_remove(self):
|
||||
streams = self.client.stream_list(self.args.path)
|
||||
if len(streams) != 1:
|
||||
self.die("Error getting stream info for path %s", self.args.path)
|
||||
|
||||
try:
|
||||
count = self.client.stream_remove(self.args.path,
|
||||
self.args.start, self.args.end)
|
||||
except nilmdb.client.ClientError as e: # pragma: no cover (shouldn't happen)
|
||||
self.die("Error removing data: %s", str(e))
|
||||
except nilmdb.client.ClientError as e:
|
||||
self.die("error removing data: %s", str(e))
|
||||
|
||||
if self.args.count:
|
||||
printf("%d\n", count)
|
||||
|
|
|
@ -26,12 +26,19 @@ class Error(Exception):
|
|||
self.url = url # URL we were requesting
|
||||
self.traceback = traceback # server traceback, if available
|
||||
def __str__(self):
|
||||
s = sprintf("[%s]", self.status)
|
||||
if self.message:
|
||||
s += sprintf(" %s", self.message)
|
||||
if self.traceback: # pragma: no cover
|
||||
s += sprintf("\nServer traceback:\n%s", self.traceback)
|
||||
return s
|
||||
def __repr__(self): # pragma: no cover
|
||||
s = sprintf("[%s]", self.status)
|
||||
if self.message:
|
||||
s += sprintf(" %s", self.message)
|
||||
if self.url:
|
||||
s += sprintf(" (%s)", self.url)
|
||||
if self.traceback: # pragma: no cover
|
||||
if self.traceback:
|
||||
s += sprintf("\nServer traceback:\n%s", self.traceback)
|
||||
return s
|
||||
class ClientError(Error):
|
||||
|
|
|
@ -80,7 +80,7 @@ _sql_schema_updates = {
|
|||
class NilmDBError(Exception):
|
||||
"""Base exception for NilmDB errors"""
|
||||
def __init__(self, message = "Unspecified error"):
|
||||
Exception.__init__(self, self.__class__.__name__ + ": " + message)
|
||||
Exception.__init__(self, message)
|
||||
|
||||
class StreamError(NilmDBError):
|
||||
pass
|
||||
|
@ -484,8 +484,8 @@ class NilmDB(object):
|
|||
than actually fetching the data. It is not limited by
|
||||
max_results.
|
||||
"""
|
||||
table = self.data.getnode(path)
|
||||
stream_id = self._stream_id(path)
|
||||
table = self.data.getnode(path)
|
||||
intervals = self._get_intervals(stream_id)
|
||||
requested = Interval(start or 0, end or 1e12)
|
||||
result = []
|
||||
|
@ -530,8 +530,8 @@ class NilmDB(object):
|
|||
are truncated or split appropriately. Returns the number of
|
||||
data points removed.
|
||||
"""
|
||||
table = self.data.getnode(path)
|
||||
stream_id = self._stream_id(path)
|
||||
table = self.data.getnode(path)
|
||||
intervals = self._get_intervals(stream_id)
|
||||
to_remove = Interval(start or 0, end or 1e12)
|
||||
removed = 0
|
||||
|
|
|
@ -63,7 +63,7 @@ def exception_to_httperror(*expected):
|
|||
try:
|
||||
return func(*args, **kwargs)
|
||||
except expected as e:
|
||||
message = sprintf("%s: %s", type(e).__name__, str(e))
|
||||
message = sprintf("%s", str(e))
|
||||
raise cherrypy.HTTPError("400 Bad Request", message)
|
||||
return wrapper
|
||||
return decorator
|
||||
|
@ -213,7 +213,7 @@ class Stream(NilmApp):
|
|||
parser.parse(body)
|
||||
except nilmdb.layout.ParserError as e:
|
||||
raise cherrypy.HTTPError("400 Bad Request",
|
||||
"Error parsing input data: " +
|
||||
"error parsing input data: " +
|
||||
e.message)
|
||||
|
||||
if (not parser.min_timestamp or not parser.max_timestamp or
|
||||
|
|
|
@ -10,6 +10,7 @@ from nose.tools import assert_raises
|
|||
import itertools
|
||||
import datetime_tz
|
||||
import os
|
||||
import re
|
||||
import shutil
|
||||
import sys
|
||||
import threading
|
||||
|
@ -97,14 +98,24 @@ class TestCmdline(object):
|
|||
self.dump()
|
||||
eq_(self.exitcode, 0)
|
||||
|
||||
def fail(self, arg_string, infile = None, exitcode = None):
|
||||
def fail(self, arg_string, infile = None,
|
||||
exitcode = None, require_error = True):
|
||||
self.run(arg_string, infile)
|
||||
if exitcode is not None and self.exitcode != exitcode:
|
||||
# Wrong exit code
|
||||
self.dump()
|
||||
eq_(self.exitcode, exitcode)
|
||||
if self.exitcode == 0:
|
||||
# Success, when we wanted failure
|
||||
self.dump()
|
||||
ne_(self.exitcode, 0)
|
||||
# Make sure the output contains the word "error" at the
|
||||
# beginning of a line, but only if an exitcode wasn't
|
||||
# specified.
|
||||
if require_error and not re.search("^error",
|
||||
self.captured, re.MULTILINE):
|
||||
raise AssertionError("command failed, but output doesn't "
|
||||
"contain the string 'error'")
|
||||
|
||||
def contain(self, checkstring):
|
||||
in_(checkstring, self.captured)
|
||||
|
@ -339,13 +350,13 @@ class TestCmdline(object):
|
|||
self.ok("insert --help")
|
||||
|
||||
self.fail("insert /foo/bar baz qwer")
|
||||
self.contain("Error getting stream info")
|
||||
self.contain("error getting stream info")
|
||||
|
||||
self.fail("insert /newton/prep baz qwer")
|
||||
self.match("Error opening input file baz\n")
|
||||
self.match("error opening input file baz\n")
|
||||
|
||||
self.fail("insert /newton/prep")
|
||||
self.contain("Error extracting time")
|
||||
self.contain("error extracting time")
|
||||
|
||||
self.fail("insert --start 19801205 /newton/prep 1 2 3 4")
|
||||
self.contain("--start can only be used with one input file")
|
||||
|
@ -386,7 +397,7 @@ class TestCmdline(object):
|
|||
os.environ['TZ'] = "UTC"
|
||||
self.fail("insert --rate 120 /newton/raw "
|
||||
"tests/data/prep-20120323T1004")
|
||||
self.contain("Error parsing input data")
|
||||
self.contain("error parsing input data")
|
||||
|
||||
# empty data does nothing
|
||||
self.ok("insert --rate 120 --start '03/23/2012 06:05:00' /newton/prep "
|
||||
|
@ -432,7 +443,7 @@ class TestCmdline(object):
|
|||
def test_08_extract(self):
|
||||
# nonexistent stream
|
||||
self.fail("extract /no/such/foo --start 2000-01-01 --end 2020-01-01")
|
||||
self.contain("Error getting stream info")
|
||||
self.contain("error getting stream info")
|
||||
|
||||
# reversed range
|
||||
self.fail("extract -a /newton/prep --start 2020-01-01 --end 2000-01-01")
|
||||
|
@ -441,15 +452,18 @@ class TestCmdline(object):
|
|||
# empty ranges return error 2
|
||||
self.fail("extract -a /newton/prep " +
|
||||
"--start '23 Mar 2012 10:00:30' " +
|
||||
"--end '23 Mar 2012 10:00:30'", exitcode = 2)
|
||||
"--end '23 Mar 2012 10:00:30'",
|
||||
exitcode = 2, require_error = False)
|
||||
self.contain("no data")
|
||||
self.fail("extract -a /newton/prep " +
|
||||
"--start '23 Mar 2012 10:00:30.000001' " +
|
||||
"--end '23 Mar 2012 10:00:30.000001'", exitcode = 2)
|
||||
"--end '23 Mar 2012 10:00:30.000001'",
|
||||
exitcode = 2, require_error = False)
|
||||
self.contain("no data")
|
||||
self.fail("extract -a /newton/prep " +
|
||||
"--start '23 Mar 2022 10:00:30' " +
|
||||
"--end '23 Mar 2022 10:00:30'", exitcode = 2)
|
||||
"--end '23 Mar 2022 10:00:30'",
|
||||
exitcode = 2, require_error = False)
|
||||
self.contain("no data")
|
||||
|
||||
# but are ok if we're just counting results
|
||||
|
@ -502,7 +516,7 @@ class TestCmdline(object):
|
|||
|
||||
# Try nonexistent stream
|
||||
self.fail("remove /no/such/foo --start 2000-01-01 --end 2020-01-01")
|
||||
self.contain("Error getting stream info")
|
||||
self.contain("No stream at path")
|
||||
|
||||
self.fail("remove /newton/prep --start 2020-01-01 --end 2000-01-01")
|
||||
self.contain("start is after end")
|
||||
|
|
Loading…
Reference in New Issue
Block a user