Browse Source

More work towards filling out the client...

git-svn-id: https://bucket.mit.edu/svn/nilm/nilmdb@10624 ddd99763-3ecb-0310-9145-efcb8ce7c51f
tags/bxinterval-last
Jim Paris 12 years ago
parent
commit
a235c94c02
5 changed files with 58 additions and 61 deletions
  1. +1
    -1
      nilmdb/__init__.py
  2. +33
    -54
      nilmdb/client.py
  3. +1
    -1
      nilmdb/nilmdb.py
  4. +20
    -0
      nilmdb/server.py
  5. +3
    -5
      tests/test_client.py

+ 1
- 1
nilmdb/__init__.py 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

+ 33
- 54
nilmdb/client.py 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")



+ 1
- 1
nilmdb/nilmdb.py 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)


+ 20
- 0
nilmdb/server.py 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


+ 3
- 5
tests/test_client.py 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/")


Loading…
Cancel
Save