Browse Source

More work on client tests

git-svn-id: https://bucket.mit.edu/svn/nilm/nilmdb@10625 ddd99763-3ecb-0310-9145-efcb8ce7c51f
tags/bxinterval-last
Jim Paris 10 years ago
parent
commit
22ef82b59c
6 changed files with 90 additions and 40 deletions
  1. +35
    -18
      nilmdb/client.py
  2. +3
    -2
      nilmdb/nilmdb.py
  3. +31
    -1
      nilmdb/server.py
  4. +1
    -1
      setup.cfg
  5. +15
    -13
      tests/test_client.py
  6. +5
    -5
      tests/test_nilmdb.py

+ 35
- 18
nilmdb/client.py View File

@@ -17,15 +17,16 @@ import pycurl

class NilmCommError(Exception):
"""Base exception for both ClientError and ServerError responses"""
def __init__(self, code, message, body = None):
# Whether to include the body in the __str__ expansion
show_body = 1
def __init__(self, code, message, body = None, url = "no URL"):
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:
self.url = url
def __str__(self): # pragma: no cover
s = sprintf("[%03d] %s (%s)", self.code, self.message, self.url)
if self.body and self.show_body:
s += "\n" + self.body
return s

@@ -40,6 +41,7 @@ class MyCurl(object):
"""If baseurl is supplied, all other functions that take
a URL can be given a relative URL instead."""
self.baseurl = baseurl
self.url = baseurl
self.curl = pycurl.Curl()
self.curl.setopt(pycurl.SSL_VERIFYHOST, 2)
self.curl.setopt(pycurl.FOLLOWLOCATION, 1)
@@ -50,16 +52,16 @@ class MyCurl(object):
if params:
url = urlparse.urljoin(url, "?" + urllib.urlencode(params, True))
self.curl.setopt(pycurl.URL, url)
return url
self.url = 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)
raise ClientError(code, "HTTP client error", body, self.url)
elif code >= 500 and code <= 599: # pragma: no cover
raise ServerError(code, "HTTP server error", body, self.url)
elif code != 200: # pragma: no cover
raise NilmCommError(code, "Unknown error", body, self.url)
def getjson(self, url, params = None):
"""Simple GET that returns JSON string"""
@@ -71,7 +73,7 @@ class MyCurl(object):
try:
self.curl.perform()
except pycurl.error as e:
raise ServerError(500, e[1])
raise ServerError(500, e[1], self.url)
self._check_error(self._body)
return json.loads(self._body)

@@ -79,6 +81,10 @@ class Client(object):
def __init__(self, url):
self.curl = MyCurl(url)

def _json_param(self, data):
"""Return compact json-encoded version of parameter"""
return json.dumps(data, separators=(',',':'))

def version(self):
return self.curl.getjson("version")

@@ -96,11 +102,22 @@ class Client(object):
params["key"] = keys
return self.curl.getjson("stream/get_metadata", params)

def stream_set_metadata(self):
raise NotImplementedError

def stream_update_metadata(self):
raise NotImplementedError
def stream_set_metadata(self, path, data):
"""Set stream metadata from a dictionary, replacing all existing
metadata."""
params = {
"path": path,
"data": self._json_param(data)
}
return self.curl.getjson("stream/set_metadata", params)

def stream_update_metadata(self, path, data):
"""Update stream metadata from a dictionary"""
params = {
"path": path,
"data": self._json_param(data)
}
return self.curl.getjson("stream/update_metadata", params)

def stream_create(self, path, layout, index = None):
params = { "path": path,


+ 3
- 2
nilmdb/nilmdb.py View File

@@ -117,7 +117,7 @@ class NilmDB(object):
cur.execute("PRAGMA user_version = {v:d}".format(v=version))

def stream_list(self, path = None, layout = None):
"""Return list of (path, layout) tuples of all streams
"""Return list of [path, layout] lists of all streams
in the database.

If path is specified, include only streams with a path that
@@ -136,7 +136,8 @@ class NilmDB(object):
params += (path,)
result = self.con.execute("SELECT path, layout " +
"FROM streams " + where, params).fetchall()
return sorted(result)
return sorted(list(x) for x in result)

def stream_create(self, path, layout_name, index = None):
"""Create a new table in the database.


+ 31
- 1
nilmdb/server.py View File

@@ -10,6 +10,7 @@ from nilmdb.printf import *
import cherrypy
import sys
import os
import json
import traceback

try:
@@ -88,7 +89,7 @@ class Stream(NilmApp):
"KeyError: " + e.message)

# /stream/get_metadata?path=/newton/prep
# /stream/get_metadata?path=/newton/prep?key=foo&key=bar
# /stream/get_metadata?path=/newton/prep&key=foo&key=bar
@cherrypy.expose
@cherrypy.tools.json_out()
def get_metadata(self, path, key=None):
@@ -111,6 +112,35 @@ class Stream(NilmApp):
result[k] = None
return result

# /stream/set_metadata?path=/newton/prep&data=<json>
@cherrypy.expose
@cherrypy.tools.json_out()
def set_metadata(self, path, data):
"""Set metadata for the named stream, replacing any
existing metadata. Data should be a json-encoded
dictionary"""
try:
data_dict = json.loads(data)
self.db.stream_set_metadata(path, data_dict)
except Exception as e:
raise cherrypy.HTTPError("400 Bad Request",
"Error: " + e.message)
return "ok"
# /stream/update_metadata?path=/newton/prep&data=<json>
@cherrypy.expose
@cherrypy.tools.json_out()
def update_metadata(self, path, data):
"""Update metadata for the named stream. Data
should be a json-encoded dictionary"""
try:
data_dict = json.loads(data)
self.db.stream_update_metadata(path, data_dict)
except Exception as e:
raise cherrypy.HTTPError("400 Bad Request",
"Error: " + e.message)
return "ok"

# /stream/upload?path=/newton/prep
@cherrypy.expose
@cherrypy.tools.json_out()


+ 1
- 1
setup.cfg View File

@@ -1,5 +1,6 @@
[nosetests]
nocapture=1
nologcapture=1 # remove this to see cherrypy logs on failure
with-coverage=1
cover-inclusive=1
cover-package=nilmdb
@@ -10,7 +11,6 @@ stop=1
verbosity=2
#tests=tests/test_nilmdb.py
#tests=tests/test_client.py

#with-profile=1
#profile-sort=time
#profile-restrict=10 # doesn't work right, treated as string or something

+ 15
- 13
tests/test_client.py View File

@@ -88,20 +88,13 @@ class TestClient(object):
client.stream_create("/newton/zzz/rawnotch", "RawNotchedData")

# Verify we got 3 streams
eq_(client.stream_list(), [ ("/newton/prep", "PrepData"),
("/newton/raw", "RawData"),
("/newton/zzz/rawnotch", "RawNotchedData")
])
eq_(client.stream_list(), [ ["/newton/prep", "PrepData"],
["/newton/raw", "RawData"],
["/newton/zzz/rawnotch", "RawNotchedData"]
])
# Match just one type or one path
eq_(client.stream_list(layout="RawData"), [ ("/newton/raw", "RawData") ])
eq_(client.stream_list(path="/newton/raw"), [ ("/newton/raw", "RawData") ])

# Verify that columns were made right
eq_(len(client.h5file.getNode("/newton/prep").cols), 9)
eq_(len(client.h5file.getNode("/newton/raw").cols), 7)
eq_(len(client.h5file.getNode("/newton/zzz/rawnotch").cols), 10)
assert(client.h5file.getNode("/newton/prep").colindexed["timestamp"])
assert(not client.h5file.getNode("/newton/prep").colindexed["p1"])
eq_(client.stream_list(layout="RawData"), [ ["/newton/raw", "RawData"] ])
eq_(client.stream_list(path="/newton/raw"), [ ["/newton/raw", "RawData"] ])

# Set / get metadata
eq_(client.stream_get_metadata("/newton/prep"), {})
@@ -116,4 +109,13 @@ class TestClient(object):
client.stream_update_metadata("/newton/raw", meta3)
eq_(client.stream_get_metadata("/newton/prep"), meta1)
eq_(client.stream_get_metadata("/newton/raw"), meta1)
eq_(client.stream_get_metadata("/newton/raw", [ "description" ] ), meta2)
eq_(client.stream_get_metadata("/newton/raw", [ "description",
"v_scale" ] ), meta1)

# test wrong types (list instead of dict)
with assert_raises(ClientError):
client.stream_set_metadata("/newton/prep", [1,2,3])
with assert_raises(ClientError):
client.stream_update_metadata("/newton/prep", [1,2,3])


+ 5
- 5
tests/test_nilmdb.py View File

@@ -59,13 +59,13 @@ class Test00Nilmdb(object): # named 00 so it runs first
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")
eq_(db.stream_list(), [ ["/newton/prep", "PrepData"],
["/newton/raw", "RawData"],
["/newton/zzz/rawnotch", "RawNotchedData"]
])
# Match just one type or one path
eq_(db.stream_list(layout="RawData"), [ ("/newton/raw", "RawData") ])
eq_(db.stream_list(path="/newton/raw"), [ ("/newton/raw", "RawData") ])
eq_(db.stream_list(layout="RawData"), [ ["/newton/raw", "RawData"] ])
eq_(db.stream_list(path="/newton/raw"), [ ["/newton/raw", "RawData"] ])

# Verify that columns were made right
eq_(len(db.h5file.getNode("/newton/prep").cols), 9)


Loading…
Cancel
Save