Skip to content

Commit

Permalink
use numpy-style selection
Browse files Browse the repository at this point in the history
  • Loading branch information
jreadey committed Jan 23, 2015
1 parent 23e1a8c commit f869b2e
Show file tree
Hide file tree
Showing 2 changed files with 106 additions and 24 deletions.
89 changes: 76 additions & 13 deletions server/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -709,37 +709,100 @@ def delete(self):


class ValueHandler(RequestHandler):


"""
Helper method - return slice for dim based on query params
Query arg should be in the form: [<dim1>, <dim2>, ... , <dimn>]
brackets are optional for one dimensional arrays.
Each dimension, valid formats are:
single integer: n
start and end: n:m
start, end, and stride: n:m:s
"""

def getSliceQueryParam(self, dim, extent):
log = logging.getLogger("h5serv")
# Get optional query parameters for given dim
dimQuery = 'dim' + str(dim + 1)
try:
start = int(self.get_query_argument(dimQuery + '_start', 0))
stop = int(self.get_query_argument(dimQuery + '_stop', extent))
step = int(self.get_query_argument(dimQuery + '_step', 1))
except ValueError:
msg ="Bad Request: invalid selection parameter (can't convert to int)"
log.info("getSliceQueryParam: " + str(dim) + ", " + str(extent))
query = self.get_query_argument("select", default='ALL')
if query == 'ALL':
# just return a slice for the entire dimension
log.info("getSliceQueryParam: return default")
return slice(0, extent)

log.info("select query value: [" + query + "]");

if not query.startswith('['):
msg = "Bad Request: selection query missing start bracket"
log.info(msg)
raise HTTPError(400, reason=msg)
if not query.endswith(']'):
msg = "Bad Request: selection query missing end bracket"
log.info(msg)
raise HTTPError(400, reason=msg)

# now strip out brackets
query = query[1:-1]

query_array = query.split(',')
if dim > len(query_array):
msg = "Not enough dimensions supplied to query argument"
log.info(msg)
raise HTTPError(400, reason=msg)
dim_query = query_array[dim].strip()
start = 0
stop = extent
step = 1
if dim_query.find(':') < 0:
# just a number - return start = stop for this value
try:
start = int(dim_query)
except ValueError:
msg ="Bad Request: invalid selection parameter (can't convert to int) for dimension: " + str(dim)
log.info(msg)
raise HTTPError(400, reason=msg)
stop = start
elif dim_query == ':':
# select everything
pass
else:
fields = dim_query.split(":")
if len(fields) > 3:
msg ="Bad Request: Too many ':' seperators for dimension: " + str(dim)
log.info(msg)
raise HTTPError(400, reason=msg)
try:
if fields[0]:
start = int(fields[0])
if fields[1]:
stop = int(fields[1])
if len(fields) > 2 and fields[2]:
step = int(fields[2])
except ValueError:
msg ="Bad Request: invalid selection parameter (can't convert to int) for dimension: " + str(dim)
log.info(msg)
raise HTTPError(400, reason=msg)

if start < 0 or start > extent:
msg = "Bad Request: Invalid selection start parameter for dimension: " + dimQuery
msg = "Bad Request: Invalid selection start parameter for dimension: " + str(dim)
log.info(msg)
raise HTTPError(400, reason=msg)
if stop > extent:
msg = "Bad Request: Invalid selection stop parameter for dimension: " + dimQuery
msg = "Bad Request: Invalid selection stop parameter for dimension: " + str(dim)
log.info(msg)
raise HTTPError(400, reason=msg)
if step == 0:
msg = "Bad Request: invalid selection step parameter for dimension: " + dimQuery
if step <= 0:
msg = "Bad Request: invalid selection step parameter for dimension: " + str(dim)
log.info(msg)
raise HTTPError(400, reason=msg)
s = slice(start, stop, step)
log.info(dimQuery + " start: " + str(start) + " stop: " + str(stop) + " step: " +
str(step))
log.info("dim query[" + str(dim) + "] returning: start: " + str(start) + " stop: " +
str(stop) + " step: " + str(step))
return s



"""
Get slices given lists of start, stop, step values
Expand Down
41 changes: 30 additions & 11 deletions test/integ/valuetest.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import helper
import unittest
import json


class ValueTest(unittest.TestCase):
def __init__(self, *args, **kwargs):
Expand Down Expand Up @@ -93,7 +94,7 @@ def testGetSelection(self):

# get values starting at index 2
req = helper.getEndpoint() + "/datasets/" + dset112UUID + "/value" + \
"?dim1_start=2"
"?select=[2:]"
rsp = requests.get(req, headers=headers)
self.failUnlessEqual(rsp.status_code, 200)
rspJson = json.loads(rsp.text)
Expand All @@ -103,7 +104,7 @@ def testGetSelection(self):

# get values starting at index 2 with stop of 10
req = helper.getEndpoint() + "/datasets/" + dset112UUID + "/value" + \
"?dim1_start=2&dim1_stop=10"
"?select=[2:10]"
rsp = requests.get(req, headers=headers)
self.failUnlessEqual(rsp.status_code, 200)
rspJson = json.loads(rsp.text)
Expand All @@ -113,7 +114,7 @@ def testGetSelection(self):

# get values starting at index 2 with stop of 10, and stride of 2
req = helper.getEndpoint() + "/datasets/" + dset112UUID + "/value" + \
"?dim1_start=2&dim1_stop=10&dim1_step=2"
"?select=[2:10:2]"
rsp = requests.get(req, headers=headers)
self.failUnlessEqual(rsp.status_code, 200)
rspJson = json.loads(rsp.text)
Expand All @@ -128,7 +129,7 @@ def testGetSelection(self):

# get rows 2, 3, 4, and 5
req = helper.getEndpoint() + "/datasets/" + dset111UUID + "/value" + \
"?dim2_start=2&dim2_stop=6"
"?select=[:,2:6]"
rsp = requests.get(req, headers=headers)
self.failUnlessEqual(rsp.status_code, 200)
rspJson = json.loads(rsp.text)
Expand All @@ -142,13 +143,13 @@ def testGetSelection(self):

# get 2d subregion with stride
req = helper.getEndpoint() + "/datasets/" + dset111UUID + "/value" + \
"?dim1_start=1&dim1_end=9&dim2_start=1&dim2_stop=9&dim2_step=2"
"?select=[1:9,1:9:2]"
rsp = requests.get(req, headers=headers)
self.failUnlessEqual(rsp.status_code, 200)
rspJson = json.loads(rsp.text)
data = rspJson['value']
self.assertEqual(len(data), 9)
for i in range(9):
self.assertEqual(len(data), 8)
for i in range(8):
arr = data[i]
self.assertEqual(len(arr), 4)
for j in range(4):
Expand All @@ -163,16 +164,34 @@ def testGetSelectionBadQuery(self):

# rank 1 dataset
dset112UUID = helper.getUUID(domain, g11UUID, 'dset1.1.2')

# pass in non-numeric start

# don't use bracket
req = helper.getEndpoint() + "/datasets/" + dset112UUID + "/value" + \
"?select=abc"
rsp = requests.get(req, headers=headers)
self.failUnlessEqual(rsp.status_code, 400)

# not a number
req = helper.getEndpoint() + "/datasets/" + dset112UUID + "/value" + \
"?select=[a:b:c]"
rsp = requests.get(req, headers=headers)
self.failUnlessEqual(rsp.status_code, 400)

# start is negative
req = helper.getEndpoint() + "/datasets/" + dset112UUID + "/value" + \
"?select=[-1:3]"
rsp = requests.get(req, headers=headers)
self.failUnlessEqual(rsp.status_code, 400)

# stop past extent
req = helper.getEndpoint() + "/datasets/" + dset112UUID + "/value" + \
"?dim1_start=abc"
"?select=[1:25]"
rsp = requests.get(req, headers=headers)
self.failUnlessEqual(rsp.status_code, 400)

# pass in 0 step
req = helper.getEndpoint() + "/datasets/" + dset112UUID + "/value" + \
"?dim1_start=2&dim1_step=0"
"?select=[1:2:0]"
rsp = requests.get(req, headers=headers)
self.failUnlessEqual(rsp.status_code, 400)

Expand Down

0 comments on commit f869b2e

Please sign in to comment.