|
@@ -11,6 +11,7 @@ import sys |
|
|
import time |
|
|
import time |
|
|
import os |
|
|
import os |
|
|
import simplejson as json |
|
|
import simplejson as json |
|
|
|
|
|
import functools |
|
|
|
|
|
|
|
|
try: |
|
|
try: |
|
|
import cherrypy |
|
|
import cherrypy |
|
@@ -39,7 +40,6 @@ def workaround_cp_bug_1200(func): # pragma: no cover (just a workaround) |
|
|
# Even if chunked responses are disabled, you may still miss miss |
|
|
# Even if chunked responses are disabled, you may still miss miss |
|
|
# LookupError, or UnicodeError exceptions due to CherryPy bug |
|
|
# LookupError, or UnicodeError exceptions due to CherryPy bug |
|
|
# #1200. This throws them as generic Exceptions insteads. |
|
|
# #1200. This throws them as generic Exceptions insteads. |
|
|
import functools |
|
|
|
|
|
import traceback |
|
|
import traceback |
|
|
@functools.wraps(func) |
|
|
@functools.wraps(func) |
|
|
def wrapper(*args, **kwargs): |
|
|
def wrapper(*args, **kwargs): |
|
@@ -51,6 +51,20 @@ def workaround_cp_bug_1200(func): # pragma: no cover (just a workaround) |
|
|
traceback.format_exc()) |
|
|
traceback.format_exc()) |
|
|
return wrapper |
|
|
return wrapper |
|
|
|
|
|
|
|
|
|
|
|
def exception_to_httperror(response = "400 Bad Request"): |
|
|
|
|
|
"""Return a decorator that catches Exception and throws |
|
|
|
|
|
a HTTPError describing it instead""" |
|
|
|
|
|
def decorator(func): |
|
|
|
|
|
@functools.wraps(func) |
|
|
|
|
|
def wrapper(*args, **kwargs): |
|
|
|
|
|
try: |
|
|
|
|
|
return func(*args, **kwargs) |
|
|
|
|
|
except Exception as e: |
|
|
|
|
|
message = sprintf("%s: %s", type(e).__name__, str(e)) |
|
|
|
|
|
raise cherrypy.HTTPError(response, message) |
|
|
|
|
|
return wrapper |
|
|
|
|
|
return decorator |
|
|
|
|
|
|
|
|
# CherryPy apps |
|
|
# CherryPy apps |
|
|
class Root(NilmApp): |
|
|
class Root(NilmApp): |
|
|
"""Root application for NILM database""" |
|
|
"""Root application for NILM database""" |
|
@@ -104,26 +118,20 @@ class Stream(NilmApp): |
|
|
# /stream/create?path=/newton/prep&layout=PrepData |
|
|
# /stream/create?path=/newton/prep&layout=PrepData |
|
|
@cherrypy.expose |
|
|
@cherrypy.expose |
|
|
@cherrypy.tools.json_out() |
|
|
@cherrypy.tools.json_out() |
|
|
|
|
|
@exception_to_httperror() |
|
|
def create(self, path, layout): |
|
|
def create(self, path, layout): |
|
|
"""Create a new stream in the database. Provide path |
|
|
"""Create a new stream in the database. Provide path |
|
|
and one of the nilmdb.layout.layouts keys. |
|
|
and one of the nilmdb.layout.layouts keys. |
|
|
""" |
|
|
""" |
|
|
try: |
|
|
|
|
|
return self.db.stream_create(path, layout) |
|
|
|
|
|
except Exception as e: |
|
|
|
|
|
message = sprintf("%s: %s", type(e).__name__, e.message) |
|
|
|
|
|
raise cherrypy.HTTPError("400 Bad Request", message) |
|
|
|
|
|
|
|
|
return self.db.stream_create(path, layout) |
|
|
|
|
|
|
|
|
# /stream/destroy?path=/newton/prep |
|
|
# /stream/destroy?path=/newton/prep |
|
|
@cherrypy.expose |
|
|
@cherrypy.expose |
|
|
@cherrypy.tools.json_out() |
|
|
@cherrypy.tools.json_out() |
|
|
|
|
|
@exception_to_httperror() |
|
|
def destroy(self, path): |
|
|
def destroy(self, path): |
|
|
"""Delete a stream and its associated data.""" |
|
|
"""Delete a stream and its associated data.""" |
|
|
try: |
|
|
|
|
|
return self.db.stream_destroy(path) |
|
|
|
|
|
except Exception as e: |
|
|
|
|
|
message = sprintf("%s: %s", type(e).__name__, e.message) |
|
|
|
|
|
raise cherrypy.HTTPError("400 Bad Request", message) |
|
|
|
|
|
|
|
|
return self.db.stream_destroy(path) |
|
|
|
|
|
|
|
|
# /stream/get_metadata?path=/newton/prep |
|
|
# /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 |
|
@@ -152,30 +160,24 @@ class Stream(NilmApp): |
|
|
# /stream/set_metadata?path=/newton/prep&data=<json> |
|
|
# /stream/set_metadata?path=/newton/prep&data=<json> |
|
|
@cherrypy.expose |
|
|
@cherrypy.expose |
|
|
@cherrypy.tools.json_out() |
|
|
@cherrypy.tools.json_out() |
|
|
|
|
|
@exception_to_httperror() |
|
|
def set_metadata(self, path, data): |
|
|
def set_metadata(self, path, data): |
|
|
"""Set metadata for the named stream, replacing any |
|
|
"""Set metadata for the named stream, replacing any |
|
|
existing metadata. Data should be a json-encoded |
|
|
existing metadata. Data should be a json-encoded |
|
|
dictionary""" |
|
|
dictionary""" |
|
|
try: |
|
|
|
|
|
data_dict = json.loads(data) |
|
|
|
|
|
self.db.stream_set_metadata(path, data_dict) |
|
|
|
|
|
except Exception as e: |
|
|
|
|
|
message = sprintf("%s: %s", type(e).__name__, e.message) |
|
|
|
|
|
raise cherrypy.HTTPError("400 Bad Request", message) |
|
|
|
|
|
|
|
|
data_dict = json.loads(data) |
|
|
|
|
|
self.db.stream_set_metadata(path, data_dict) |
|
|
return "ok" |
|
|
return "ok" |
|
|
|
|
|
|
|
|
# /stream/update_metadata?path=/newton/prep&data=<json> |
|
|
# /stream/update_metadata?path=/newton/prep&data=<json> |
|
|
@cherrypy.expose |
|
|
@cherrypy.expose |
|
|
@cherrypy.tools.json_out() |
|
|
@cherrypy.tools.json_out() |
|
|
|
|
|
@exception_to_httperror() |
|
|
def update_metadata(self, path, data): |
|
|
def update_metadata(self, path, data): |
|
|
"""Update metadata for the named stream. Data |
|
|
"""Update metadata for the named stream. Data |
|
|
should be a json-encoded dictionary""" |
|
|
should be a json-encoded dictionary""" |
|
|
try: |
|
|
|
|
|
data_dict = json.loads(data) |
|
|
|
|
|
self.db.stream_update_metadata(path, data_dict) |
|
|
|
|
|
except Exception as e: |
|
|
|
|
|
message = sprintf("%s: %s", type(e).__name__, e.message) |
|
|
|
|
|
raise cherrypy.HTTPError("400 Bad Request", message) |
|
|
|
|
|
|
|
|
data_dict = json.loads(data) |
|
|
|
|
|
self.db.stream_update_metadata(path, data_dict) |
|
|
return "ok" |
|
|
return "ok" |
|
|
|
|
|
|
|
|
# /stream/insert?path=/newton/prep |
|
|
# /stream/insert?path=/newton/prep |
|
|