More work towards filling out the client...

git-svn-id: https://bucket.mit.edu/svn/nilm/nilmdb@10624 ddd99763-3ecb-0310-9145-efcb8ce7c51f
This commit is contained in:
Jim Paris 2012-03-20 22:21:16 +00:00
parent 795d2ac7cf
commit a235c94c02
5 changed files with 58 additions and 61 deletions

View File

@ -1,5 +1,5 @@
from nilmdb import NilmDB, StreamError
from server import Server
from client import Client, ClientError
from client import Client, ClientError, ServerError
from layout import *
from serializer import WrapObject

View File

@ -10,16 +10,30 @@ import re
import os
import json
import urlparse
import urllib
import urllib2
from urllib2 import urlopen, HTTPError
import pycurl
class ClientError(Exception):
def __init__(self, code, message):
class NilmCommError(Exception):
"""Base exception for both ClientError and ServerError responses"""
def __init__(self, code, message, body = None):
Exception.__init__(self, message)
self.code = code
self.body = body
def __str__(self):
return sprintf("[%03d] %s", self.code, self.message)
def __repr__(self):
s = self.__str__()
if self.body:
s += "\n" + self.body
return s
class ClientError(NilmCommError):
pass
class ServerError(NilmCommError):
pass
class MyCurl(object):
def __init__(self, baseurl = ""):
@ -37,6 +51,15 @@ class MyCurl(object):
url = urlparse.urljoin(url, "?" + urllib.urlencode(params, True))
self.curl.setopt(pycurl.URL, url)
return url
def _check_error(self, body = None):
code = self.curl.getinfo(pycurl.RESPONSE_CODE)
if code >= 400 and code <= 499:
raise ClientError(code, "HTTP client error", body)
elif code >= 500 and code <= 599:
raise ServerError(code, "HTTP server error", body)
elif code != 200:
raise NilmCommError(code, "Unknown error", body)
def getjson(self, url, params = None):
"""Simple GET that returns JSON string"""
@ -48,10 +71,8 @@ class MyCurl(object):
try:
self.curl.perform()
except pycurl.error as e:
raise ClientError(500, e[1])
code = self.curl.getinfo(pycurl.RESPONSE_CODE)
if code != 200:
raise ClientError(code, "HTTP error")
raise ServerError(500, e[1])
self._check_error(self._body)
return json.loads(self._body)
class Client(object):
@ -81,59 +102,17 @@ class Client(object):
def stream_update_metadata(self):
raise NotImplementedError
def stream_create(self):
raise NotImplementedError
def stream_create(self, path, layout, index = None):
params = { "path": path,
"layout" : layout }
if index is not None:
params["index"] = index
return self.curl.getjson("stream/create", params)
def stream_insert(self, path):
params = { "path": path }
return self.curl.getjson("stream/insert", params)
# eq_(db.stream_list(), [])
# # Bad path
# with assert_raises(ValueError):
# db.stream_create("foo/bar/baz", "PrepData")
# with assert_raises(ValueError):
# db.stream_create("/foo", "PrepData")
# # Bad layout type
# with assert_raises(KeyError):
# db.stream_create("/newton/prep", "NoSuchLayout")
# # Bad index columns
# with assert_raises(KeyError):
# db.stream_create("/newton/prep", "PrepData", ["nonexistant"])
# db.stream_create("/newton/prep", "PrepData")
# db.stream_create("/newton/raw", "RawData")
# db.stream_create("/newton/zzz/rawnotch", "RawNotchedData")
# # Verify we got 3 streams
# eq_(db.stream_list(), [ ("/newton/prep", "PrepData"),
# ("/newton/raw", "RawData"),
# ("/newton/zzz/rawnotch", "RawNotchedData")
# ])
# # Match just one type
# eq_(db.stream_list(layout="RawData"), [ ("/newton/raw", "RawData") ])
# # Verify that columns were made right
# eq_(len(db.h5file.getNode("/newton/prep").cols), 9)
# eq_(len(db.h5file.getNode("/newton/raw").cols), 7)
# eq_(len(db.h5file.getNode("/newton/zzz/rawnotch").cols), 10)
# assert(db.h5file.getNode("/newton/prep").colindexed["timestamp"])
# assert(not db.h5file.getNode("/newton/prep").colindexed["p1"])
# # Set / get metadata
# eq_(db.stream_get_metadata("/newton/prep"), {})
# eq_(db.stream_get_metadata("/newton/raw"), {})
# meta1 = { "description": "The Data",
# "v_scale": "1.234" }
# meta2 = { "description": "The Data" }
# meta3 = { "v_scale": "1.234" }
# db.stream_set_metadata("/newton/prep", meta1)
# db.stream_update_metadata("/newton/prep", {})
# db.stream_update_metadata("/newton/raw", meta2)
# db.stream_update_metadata("/newton/raw", meta3)
# eq_(db.stream_get_metadata("/newton/prep"), meta1)
# eq_(db.stream_get_metadata("/newton/raw"), meta1)
# streams = getjson("/stream/list")

View File

@ -181,7 +181,7 @@ class NilmDB(object):
if index is None and "timestamp" in table.colnames:
index = [ "timestamp" ]
for ind in index:
table.cols._f_col(ind).createIndex()
table.cols._f_col(str(ind)).createIndex()
except KeyError as e:
# Remove this table if we got an error
self.h5file.removeNode(group, node)

View File

@ -67,6 +67,26 @@ class Stream(NilmApp):
or layout"""
return self.db.stream_list(path, layout)
# /stream/create?path=/newton/prep&layout=PrepData
@cherrypy.expose
@cherrypy.tools.json_out()
def create(self, path, layout, index = None):
"""Create a new stream in the database. Provide path
and one of the nilmdb.layout.layouts keys.
index: layout columns listed here are marked as PyTables indices.
If index = none, the 'timestamp' column is indexed if it exists.
Pass an empty list to prevent indexing.
"""
try:
return self.db.stream_create(path, layout, index)
except ValueError as e:
raise cherrypy.HTTPError("400 Bad Request",
"ValueError: " + e.message)
except KeyError as e:
raise cherrypy.HTTPError("400 Bad Request",
"KeyError: " + e.message)
# /stream/get_metadata?path=/newton/prep
# /stream/get_metadata?path=/newton/prep?key=foo&key=bar
@cherrypy.expose

View File

@ -1,7 +1,7 @@
import nilmdb
from nilmdb.printf import *
from nilmdb.client import ClientError
from nilmdb.client import ClientError, ServerError
from nose.tools import *
from nose.tools import assert_raises
@ -51,15 +51,13 @@ class TestClient(object):
def test_client_basic(self):
# Test a fake host
client = nilmdb.Client(url = "http://localhost:1/")
with assert_raises(nilmdb.ClientError) as e:
with assert_raises(nilmdb.ServerError):
client.version()
eq_(e.exception.code, 500)
# Then a fake URL on a real host
client = nilmdb.Client(url = "http://localhost:12380/fake/")
with assert_raises(nilmdb.ClientError) as e:
with assert_raises(nilmdb.ClientError):
client.version()
eq_(e.exception.code, 404)
# Now use the real URL
client = nilmdb.Client(url = "http://localhost:12380/")