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:
parent
795d2ac7cf
commit
a235c94c02
|
@ -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
|
||||
|
|
|
@ -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")
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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/")
|
||||
|
|
Loading…
Reference in New Issue
Block a user