Compare commits
7 Commits
nilmdb-1.6
...
nilmdb-1.7
Author | SHA1 | Date | |
---|---|---|---|
b5df575c79 | |||
2768a5ad15 | |||
a105543c38 | |||
309f38d0ed | |||
9a27b6ef6a | |||
99532cf9e0 | |||
dfdd0e5c74 |
@@ -123,14 +123,36 @@ class HTTPClient(object):
|
|||||||
"""
|
"""
|
||||||
(response, isjson) = self._do_req(method, url, query, body,
|
(response, isjson) = self._do_req(method, url, query, body,
|
||||||
stream = True, headers = headers)
|
stream = True, headers = headers)
|
||||||
|
|
||||||
|
# Like the iter_lines function in Requests, but only splits on
|
||||||
|
# the specified line ending.
|
||||||
|
def lines(source, ending):
|
||||||
|
pending = None
|
||||||
|
for chunk in source:
|
||||||
|
if pending is not None:
|
||||||
|
chunk = pending + chunk
|
||||||
|
tmp = chunk.split(ending)
|
||||||
|
lines = tmp[:-1]
|
||||||
|
if chunk.endswith(ending):
|
||||||
|
pending = None
|
||||||
|
else:
|
||||||
|
pending = tmp[-1]
|
||||||
|
for line in lines:
|
||||||
|
yield line
|
||||||
|
if pending is not None: # pragma: no cover (missing newline)
|
||||||
|
yield pending
|
||||||
|
|
||||||
|
# Yield the chunks or lines as requested
|
||||||
if binary:
|
if binary:
|
||||||
for chunk in response.iter_content(chunk_size = 65536):
|
for chunk in response.iter_content(chunk_size = 65536):
|
||||||
yield chunk
|
yield chunk
|
||||||
elif isjson:
|
elif isjson:
|
||||||
for line in response.iter_lines():
|
for line in lines(response.iter_content(chunk_size = 1),
|
||||||
|
ending = '\r\n'):
|
||||||
yield json.loads(line)
|
yield json.loads(line)
|
||||||
else:
|
else:
|
||||||
for line in response.iter_lines():
|
for line in lines(response.iter_content(chunk_size = 65536),
|
||||||
|
ending = '\n'):
|
||||||
yield line
|
yield line
|
||||||
|
|
||||||
def get_gen(self, url, params = None, binary = False):
|
def get_gen(self, url, params = None, binary = False):
|
||||||
|
@@ -5,6 +5,9 @@
|
|||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define __STDC_FORMAT_MACROS
|
||||||
|
#include <inttypes.h>
|
||||||
|
|
||||||
/* Values missing from stdint.h */
|
/* Values missing from stdint.h */
|
||||||
#define UINT8_MIN 0
|
#define UINT8_MIN 0
|
||||||
#define UINT16_MIN 0
|
#define UINT16_MIN 0
|
||||||
@@ -19,13 +22,6 @@
|
|||||||
|
|
||||||
typedef int64_t timestamp_t;
|
typedef int64_t timestamp_t;
|
||||||
|
|
||||||
/* This code probably needs to be double-checked for the case where
|
|
||||||
sizeof(long) != 8, so enforce that here with something that will
|
|
||||||
fail at build time. We assume that the python integer type can
|
|
||||||
hold an int64_t. */
|
|
||||||
const static char __long_ok[1 - 2*!(sizeof(int64_t) ==
|
|
||||||
sizeof(long int))] = { 0 };
|
|
||||||
|
|
||||||
/* Somewhat arbitrary, just so we can use fixed sizes for strings
|
/* Somewhat arbitrary, just so we can use fixed sizes for strings
|
||||||
etc. */
|
etc. */
|
||||||
static const int MAX_LAYOUT_COUNT = 1024;
|
static const int MAX_LAYOUT_COUNT = 1024;
|
||||||
@@ -58,7 +54,7 @@ static PyObject *raise_str(int line, int col, int code, const char *string)
|
|||||||
static PyObject *raise_int(int line, int col, int code, int64_t num)
|
static PyObject *raise_int(int line, int col, int code, int64_t num)
|
||||||
{
|
{
|
||||||
PyObject *o;
|
PyObject *o;
|
||||||
o = Py_BuildValue("(iiil)", line, col, code, num);
|
o = Py_BuildValue("(iiiL)", line, col, code, (long long)num);
|
||||||
if (o != NULL) {
|
if (o != NULL) {
|
||||||
PyErr_SetObject(ParseError, o);
|
PyErr_SetObject(ParseError, o);
|
||||||
Py_DECREF(o);
|
Py_DECREF(o);
|
||||||
@@ -249,11 +245,11 @@ static PyObject *Rocket_get_file_size(Rocket *self)
|
|||||||
/****
|
/****
|
||||||
* Append from string
|
* Append from string
|
||||||
*/
|
*/
|
||||||
static inline long int strtol10(const char *nptr, char **endptr) {
|
static inline long int strtoll10(const char *nptr, char **endptr) {
|
||||||
return strtol(nptr, endptr, 10);
|
return strtoll(nptr, endptr, 10);
|
||||||
}
|
}
|
||||||
static inline long int strtoul10(const char *nptr, char **endptr) {
|
static inline long int strtoull10(const char *nptr, char **endptr) {
|
||||||
return strtoul(nptr, endptr, 10);
|
return strtoull(nptr, endptr, 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* .append_string(count, data, offset, linenum, start, end, last_timestamp) */
|
/* .append_string(count, data, offset, linenum, start, end, last_timestamp) */
|
||||||
@@ -264,6 +260,7 @@ static PyObject *Rocket_append_string(Rocket *self, PyObject *args)
|
|||||||
int offset;
|
int offset;
|
||||||
const char *linestart;
|
const char *linestart;
|
||||||
int linenum;
|
int linenum;
|
||||||
|
long long ll1, ll2, ll3;
|
||||||
timestamp_t start;
|
timestamp_t start;
|
||||||
timestamp_t end;
|
timestamp_t end;
|
||||||
timestamp_t last_timestamp;
|
timestamp_t last_timestamp;
|
||||||
@@ -280,10 +277,13 @@ static PyObject *Rocket_append_string(Rocket *self, PyObject *args)
|
|||||||
but we need the null termination for strto*. If we had
|
but we need the null termination for strto*. If we had
|
||||||
strnto* that took a length, we could use t# and not require
|
strnto* that took a length, we could use t# and not require
|
||||||
a copy. */
|
a copy. */
|
||||||
if (!PyArg_ParseTuple(args, "isiilll:append_string", &count,
|
if (!PyArg_ParseTuple(args, "isiiLLL:append_string", &count,
|
||||||
&data, &offset, &linenum,
|
&data, &offset, &linenum,
|
||||||
&start, &end, &last_timestamp))
|
&ll1, &ll2, &ll3))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
start = ll1;
|
||||||
|
end = ll2;
|
||||||
|
last_timestamp = ll3;
|
||||||
|
|
||||||
/* Skip spaces, but don't skip over a newline. */
|
/* Skip spaces, but don't skip over a newline. */
|
||||||
#define SKIP_BLANK(buf) do { \
|
#define SKIP_BLANK(buf) do { \
|
||||||
@@ -372,14 +372,14 @@ static PyObject *Rocket_append_string(Rocket *self, PyObject *args)
|
|||||||
goto extra_data_on_line; \
|
goto extra_data_on_line; \
|
||||||
break
|
break
|
||||||
|
|
||||||
CS(INT8, strtol10, t64.i, t8.i, t8.u, , 1);
|
CS(INT8, strtoll10, t64.i, t8.i, t8.u, , 1);
|
||||||
CS(UINT8, strtoul10, t64.u, t8.u, t8.u, , 1);
|
CS(UINT8, strtoull10, t64.u, t8.u, t8.u, , 1);
|
||||||
CS(INT16, strtol10, t64.i, t16.i, t16.u, le16toh, 2);
|
CS(INT16, strtoll10, t64.i, t16.i, t16.u, le16toh, 2);
|
||||||
CS(UINT16, strtoul10, t64.u, t16.u, t16.u, le16toh, 2);
|
CS(UINT16, strtoull10, t64.u, t16.u, t16.u, le16toh, 2);
|
||||||
CS(INT32, strtol10, t64.i, t32.i, t32.u, le32toh, 4);
|
CS(INT32, strtoll10, t64.i, t32.i, t32.u, le32toh, 4);
|
||||||
CS(UINT32, strtoul10, t64.u, t32.u, t32.u, le32toh, 4);
|
CS(UINT32, strtoull10, t64.u, t32.u, t32.u, le32toh, 4);
|
||||||
CS(INT64, strtol10, t64.i, t64.i, t64.u, le64toh, 8);
|
CS(INT64, strtoll10, t64.i, t64.i, t64.u, le64toh, 8);
|
||||||
CS(UINT64, strtoul10, t64.u, t64.u, t64.u, le64toh, 8);
|
CS(UINT64, strtoull10, t64.u, t64.u, t64.u, le64toh, 8);
|
||||||
CS(FLOAT32, strtod, t64.d, t32.f, t32.u, le32toh, 4);
|
CS(FLOAT32, strtod, t64.d, t32.f, t32.u, le32toh, 4);
|
||||||
CS(FLOAT64, strtod, t64.d, t64.d, t64.u, le64toh, 8);
|
CS(FLOAT64, strtod, t64.d, t64.d, t64.u, le64toh, 8);
|
||||||
#undef CS
|
#undef CS
|
||||||
@@ -397,7 +397,8 @@ static PyObject *Rocket_append_string(Rocket *self, PyObject *args)
|
|||||||
/* Build return value and return */
|
/* Build return value and return */
|
||||||
offset = buf - data;
|
offset = buf - data;
|
||||||
PyObject *o;
|
PyObject *o;
|
||||||
o = Py_BuildValue("(iili)", written, offset, last_timestamp, linenum);
|
o = Py_BuildValue("(iiLi)", written, offset,
|
||||||
|
(long long)last_timestamp, linenum);
|
||||||
return o;
|
return o;
|
||||||
err:
|
err:
|
||||||
PyErr_SetFromErrno(PyExc_OSError);
|
PyErr_SetFromErrno(PyExc_OSError);
|
||||||
@@ -431,14 +432,18 @@ static PyObject *Rocket_append_binary(Rocket *self, PyObject *args)
|
|||||||
int data_len;
|
int data_len;
|
||||||
int linenum;
|
int linenum;
|
||||||
int offset;
|
int offset;
|
||||||
|
long long ll1, ll2, ll3;
|
||||||
timestamp_t start;
|
timestamp_t start;
|
||||||
timestamp_t end;
|
timestamp_t end;
|
||||||
timestamp_t last_timestamp;
|
timestamp_t last_timestamp;
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, "it#iilll:append_binary",
|
if (!PyArg_ParseTuple(args, "it#iiLLL:append_binary",
|
||||||
&count, &data, &data_len, &offset,
|
&count, &data, &data_len, &offset,
|
||||||
&linenum, &start, &end, &last_timestamp))
|
&linenum, &ll1, &ll2, &ll3))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
start = ll1;
|
||||||
|
end = ll2;
|
||||||
|
last_timestamp = ll3;
|
||||||
|
|
||||||
/* Advance to offset */
|
/* Advance to offset */
|
||||||
if (offset > data_len)
|
if (offset > data_len)
|
||||||
@@ -476,8 +481,8 @@ static PyObject *Rocket_append_binary(Rocket *self, PyObject *args)
|
|||||||
|
|
||||||
/* Build return value and return */
|
/* Build return value and return */
|
||||||
PyObject *o;
|
PyObject *o;
|
||||||
o = Py_BuildValue("(iili)", rows, offset + rows * self->binary_size,
|
o = Py_BuildValue("(iiLi)", rows, offset + rows * self->binary_size,
|
||||||
last_timestamp, linenum);
|
(long long)last_timestamp, linenum);
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -534,7 +539,7 @@ static PyObject *Rocket_extract_string(Rocket *self, PyObject *args)
|
|||||||
if (fread(&t64.u, 8, 1, self->file) != 1)
|
if (fread(&t64.u, 8, 1, self->file) != 1)
|
||||||
goto err;
|
goto err;
|
||||||
t64.u = le64toh(t64.u);
|
t64.u = le64toh(t64.u);
|
||||||
ret = sprintf(&str[len], "%ld", t64.i);
|
ret = sprintf(&str[len], "%" PRId64, t64.i);
|
||||||
if (ret <= 0)
|
if (ret <= 0)
|
||||||
goto err;
|
goto err;
|
||||||
len += ret;
|
len += ret;
|
||||||
@@ -556,14 +561,14 @@ static PyObject *Rocket_extract_string(Rocket *self, PyObject *args)
|
|||||||
len += ret; \
|
len += ret; \
|
||||||
} \
|
} \
|
||||||
break
|
break
|
||||||
CASE(INT8, "%hhd", t8.i, t8.u, , 1);
|
CASE(INT8, "%" PRId8, t8.i, t8.u, , 1);
|
||||||
CASE(UINT8, "%hhu", t8.u, t8.u, , 1);
|
CASE(UINT8, "%" PRIu8, t8.u, t8.u, , 1);
|
||||||
CASE(INT16, "%hd", t16.i, t16.u, le16toh, 2);
|
CASE(INT16, "%" PRId16, t16.i, t16.u, le16toh, 2);
|
||||||
CASE(UINT16, "%hu", t16.u, t16.u, le16toh, 2);
|
CASE(UINT16, "%" PRIu16, t16.u, t16.u, le16toh, 2);
|
||||||
CASE(INT32, "%d", t32.i, t32.u, le32toh, 4);
|
CASE(INT32, "%" PRId32, t32.i, t32.u, le32toh, 4);
|
||||||
CASE(UINT32, "%u", t32.u, t32.u, le32toh, 4);
|
CASE(UINT32, "%" PRIu32, t32.u, t32.u, le32toh, 4);
|
||||||
CASE(INT64, "%ld", t64.i, t64.u, le64toh, 8);
|
CASE(INT64, "%" PRId64, t64.i, t64.u, le64toh, 8);
|
||||||
CASE(UINT64, "%lu", t64.u, t64.u, le64toh, 8);
|
CASE(UINT64, "%" PRIu64, t64.u, t64.u, le64toh, 8);
|
||||||
/* These next two are a bit debatable. floats
|
/* These next two are a bit debatable. floats
|
||||||
are 6-9 significant figures, so we print 7.
|
are 6-9 significant figures, so we print 7.
|
||||||
Doubles are 15-19, so we print 17. This is
|
Doubles are 15-19, so we print 17. This is
|
||||||
@@ -653,7 +658,7 @@ static PyObject *Rocket_extract_timestamp(Rocket *self, PyObject *args)
|
|||||||
|
|
||||||
/* Convert and return */
|
/* Convert and return */
|
||||||
t64.u = le64toh(t64.u);
|
t64.u = le64toh(t64.u);
|
||||||
return Py_BuildValue("l", t64.i);
|
return Py_BuildValue("L", (long long)t64.i);
|
||||||
}
|
}
|
||||||
|
|
||||||
/****
|
/****
|
||||||
|
@@ -147,7 +147,10 @@ class Root(NilmApp):
|
|||||||
# /
|
# /
|
||||||
@cherrypy.expose
|
@cherrypy.expose
|
||||||
def index(self):
|
def index(self):
|
||||||
raise cherrypy.NotFound()
|
cherrypy.response.headers['Content-Type'] = 'text/plain'
|
||||||
|
msg = sprintf("This is NilmDB version %s, running on host %s.\n",
|
||||||
|
nilmdb.__version__, socket.getfqdn())
|
||||||
|
return msg
|
||||||
|
|
||||||
# /favicon.ico
|
# /favicon.ico
|
||||||
@cherrypy.expose
|
@cherrypy.expose
|
||||||
|
8
tests/data/timestamped
Normal file
8
tests/data/timestamped
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
-10000000000 2.61246e+05 2.22735e+05 4.60340e+03 2.58221e+03 8.42804e+03 3.41890e+03 9.57898e+02 4.00585e+03
|
||||||
|
-100000000 2.61246e+05 2.22735e+05 4.60340e+03 2.58221e+03 8.42804e+03 3.41890e+03 9.57898e+02 4.00585e+03
|
||||||
|
-100000 2.61246e+05 2.22735e+05 4.60340e+03 2.58221e+03 8.42804e+03 3.41890e+03 9.57898e+02 4.00585e+03
|
||||||
|
-1000 2.61246e+05 2.22735e+05 4.60340e+03 2.58221e+03 8.42804e+03 3.41890e+03 9.57898e+02 4.00585e+03
|
||||||
|
1 2.61246e+05 2.22735e+05 4.60340e+03 2.58221e+03 8.42804e+03 3.41890e+03 9.57898e+02 4.00585e+03
|
||||||
|
1000 2.61246e+05 2.22735e+05 4.60340e+03 2.58221e+03 8.42804e+03 3.41890e+03 9.57898e+02 4.00585e+03
|
||||||
|
1000000 2.61246e+05 2.22735e+05 4.60340e+03 2.58221e+03 8.42804e+03 3.41890e+03 9.57898e+02 4.00585e+03
|
||||||
|
1000000000 2.61246e+05 2.22735e+05 4.60340e+03 2.58221e+03 8.42804e+03 3.41890e+03 9.57898e+02 4.00585e+03
|
@@ -475,6 +475,13 @@ class TestCmdline(object):
|
|||||||
# bad start time
|
# bad start time
|
||||||
self.fail("insert -t -r 120 --start 'whatever' /newton/prep /dev/null")
|
self.fail("insert -t -r 120 --start 'whatever' /newton/prep /dev/null")
|
||||||
|
|
||||||
|
# Test negative times
|
||||||
|
self.ok("insert --start @-10000000000 --end @1000000001 /newton/prep"
|
||||||
|
" tests/data/timestamped")
|
||||||
|
self.ok("extract -c /newton/prep --start min --end @1000000001")
|
||||||
|
self.match("8\n")
|
||||||
|
self.ok("remove /newton/prep --start min --end @1000000001")
|
||||||
|
|
||||||
def test_07_detail_extended(self):
|
def test_07_detail_extended(self):
|
||||||
# Just count the number of lines, it's probably fine
|
# Just count the number of lines, it's probably fine
|
||||||
self.ok("list --detail")
|
self.ok("list --detail")
|
||||||
|
@@ -157,11 +157,14 @@ class TestServer(object):
|
|||||||
|
|
||||||
def test_server(self):
|
def test_server(self):
|
||||||
# Make sure we can't force an exit, and test other 404 errors
|
# Make sure we can't force an exit, and test other 404 errors
|
||||||
for url in [ "/exit", "/", "/favicon.ico" ]:
|
for url in [ "/exit", "/favicon.ico" ]:
|
||||||
with assert_raises(HTTPError) as e:
|
with assert_raises(HTTPError) as e:
|
||||||
geturl(url)
|
geturl(url)
|
||||||
eq_(e.exception.code, 404)
|
eq_(e.exception.code, 404)
|
||||||
|
|
||||||
|
# Root page
|
||||||
|
in_("This is NilmDB", geturl("/"))
|
||||||
|
|
||||||
# Check version
|
# Check version
|
||||||
eq_(distutils.version.LooseVersion(getjson("/version")),
|
eq_(distutils.version.LooseVersion(getjson("/version")),
|
||||||
distutils.version.LooseVersion(nilmdb.__version__))
|
distutils.version.LooseVersion(nilmdb.__version__))
|
||||||
|
Reference in New Issue
Block a user