From 5b1c3b4c6070a592742ade2dc4ae347b3c167b22 Mon Sep 17 00:00:00 2001 From: Andrew Melton Date: Tue, 26 Feb 2013 17:15:53 -0500 Subject: [PATCH] Adding received filter on exists api call --- stacktach/dbapi.py | 88 +++++++++++++++++++++---------- tests/unit/test_dbapi.py | 110 ++++++++++++++++++++++++++++++++++++--- 2 files changed, 164 insertions(+), 34 deletions(-) diff --git a/stacktach/dbapi.py b/stacktach/dbapi.py index 8d22b82..e2cb6b1 100644 --- a/stacktach/dbapi.py +++ b/stacktach/dbapi.py @@ -74,21 +74,44 @@ def get_usage_delete(request, delete_id): return {'delete': _get_model_by_id(models.InstanceDeletes, delete_id)} +def _exists_extra_values(exist): + values = {'received': str(dt.dt_from_decimal(exist.raw.when))} + return values + + @api_call def list_usage_exists(request): - objects = get_db_objects(models.InstanceExists, request, 'id') - dicts = _convert_model_list(objects) + try: + custom_filters = {} + if 'received_min' in request.GET: + received_min = request.GET['received_min'] + custom_filters['received_min'] = {} + custom_filters['received_min']['raw__when__gte'] = \ + utils.str_time_to_unix(received_min) + if 'received_max' in request.GET: + received_max = request.GET['received_max'] + custom_filters['received_max'] = {} + custom_filters['received_max']['raw__when__lte'] = \ + utils.str_time_to_unix(received_max) + except AttributeError: + msg = "Range filters must be dates." + raise BadRequestException(message=msg) + + objects = get_db_objects(models.InstanceExists, request, 'id', + custom_filters=custom_filters) + dicts = _convert_model_list(objects, _exists_extra_values) return {'exists': dicts} @api_call def get_usage_exist(request, exist_id): - return {'exist': _get_model_by_id(models.InstanceExists, exist_id)} + return {'exist': _get_model_by_id(models.InstanceExists, exist_id, + _exists_extra_values)} -def _get_model_by_id(klass, model_id): +def _get_model_by_id(klass, model_id, extra_values_func=None): model = get_object_or_404(klass, id=model_id) - model_dict = _convert_model(model) + model_dict = _convert_model(model, extra_values_func) return model_dict @@ -100,7 +123,7 @@ def _check_has_field(klass, field_name): raise BadRequestException(msg) -def _get_filter_args(klass, request): +def _get_filter_args(klass, request, custom_filters=None): filter_args = {} if 'instance' in request.GET: uuid = request.GET['instance'] @@ -110,29 +133,36 @@ def _get_filter_args(klass, request): raise BadRequestException(msg) for (key, value) in request.GET.items(): - - if key.endswith('_min'): - k = key[0:-4] - _check_has_field(klass, k) - try: - filter_args['%s__gte' % k] = utils.str_time_to_unix(value) - except AttributeError: - msg = "Range filters must be dates." - raise BadRequestException(message=msg) - elif key.endswith('_max'): - k = key[0:-4] - _check_has_field(klass, k) - try: - filter_args['%s__lte' % k] = utils.str_time_to_unix(value) - except AttributeError: - msg = "Range filters must be dates." - raise BadRequestException(message=msg) + if not custom_filters or key not in custom_filters: + if key.endswith('_min'): + k = key[0:-4] + _check_has_field(klass, k) + try: + filter_args['%s__gte' % k] = \ + utils.str_time_to_unix(value) + except AttributeError: + msg = "Range filters must be dates." + raise BadRequestException(message=msg) + elif key.endswith('_max'): + k = key[0:-4] + _check_has_field(klass, k) + try: + filter_args['%s__lte' % k] = \ + utils.str_time_to_unix(value) + except AttributeError: + msg = "Range filters must be dates." + raise BadRequestException(message=msg) return filter_args -def get_db_objects(klass, request, default_order_by, direction='asc'): - filter_args = _get_filter_args(klass, request) +def get_db_objects(klass, request, default_order_by, direction='asc', + custom_filters=None): + filter_args = _get_filter_args(klass, request, + custom_filters=custom_filters) + if custom_filters: + for key in custom_filters: + filter_args.update(custom_filters[key]) if len(filter_args) > 0: objects = klass.objects.filter(**filter_args) @@ -160,17 +190,19 @@ def get_db_objects(klass, request, default_order_by, direction='asc'): return objects.order_by(order_by)[start:end] -def _convert_model(model): +def _convert_model(model, extra_values_func=None): model_dict = model_to_dict(model) for key in model_dict: if isinstance(model_dict[key], decimal.Decimal): model_dict[key] = str(dt.dt_from_decimal(model_dict[key])) + if extra_values_func: + model_dict.update(extra_values_func(model)) return model_dict -def _convert_model_list(model_list): +def _convert_model_list(model_list, extra_values_func=None): converted = [] for item in model_list: - converted.append(_convert_model(item)) + converted.append(_convert_model(item, extra_values_func)) return converted diff --git a/tests/unit/test_dbapi.py b/tests/unit/test_dbapi.py index 5c891cf..5a1e78a 100644 --- a/tests/unit/test_dbapi.py +++ b/tests/unit/test_dbapi.py @@ -5,6 +5,8 @@ from django.db.models import FieldDoesNotExist import mox from stacktach import dbapi +from stacktach import models +from stacktach import utils as stacktach_utils import utils from utils import INSTANCE_ID_1 @@ -101,7 +103,8 @@ class DBAPITestCase(unittest.TestCase): fake_request = self.mox.CreateMockAnything() fake_request.GET = {} self.mox.StubOutWithMock(dbapi, '_get_filter_args') - dbapi._get_filter_args(fake_model, fake_request).AndReturn({}) + dbapi._get_filter_args(fake_model, fake_request, + custom_filters=None).AndReturn({}) self.mox.StubOutWithMock(dbapi, '_check_has_field') dbapi._check_has_field(fake_model, 'id') result = self.mox.CreateMockAnything() @@ -120,7 +123,8 @@ class DBAPITestCase(unittest.TestCase): fake_request = self.mox.CreateMockAnything() fake_request.GET = {'direction': 'desc'} self.mox.StubOutWithMock(dbapi, '_get_filter_args') - dbapi._get_filter_args(fake_model, fake_request).AndReturn({}) + dbapi._get_filter_args(fake_model, fake_request, + custom_filters=None).AndReturn({}) self.mox.StubOutWithMock(dbapi, '_check_has_field') dbapi._check_has_field(fake_model, 'id') result = self.mox.CreateMockAnything() @@ -139,7 +143,8 @@ class DBAPITestCase(unittest.TestCase): fake_request = self.mox.CreateMockAnything() fake_request.GET = {'limit': 1} self.mox.StubOutWithMock(dbapi, '_get_filter_args') - dbapi._get_filter_args(fake_model, fake_request).AndReturn({}) + dbapi._get_filter_args(fake_model, fake_request, + custom_filters=None).AndReturn({}) self.mox.StubOutWithMock(dbapi, '_check_has_field') dbapi._check_has_field(fake_model, 'id') result = self.mox.CreateMockAnything() @@ -158,7 +163,8 @@ class DBAPITestCase(unittest.TestCase): fake_request = self.mox.CreateMockAnything() fake_request.GET = {'offset': 1} self.mox.StubOutWithMock(dbapi, '_get_filter_args') - dbapi._get_filter_args(fake_model, fake_request).AndReturn({}) + dbapi._get_filter_args(fake_model, fake_request, + custom_filters=None).AndReturn({}) self.mox.StubOutWithMock(dbapi, '_check_has_field') dbapi._check_has_field(fake_model, 'id') result = self.mox.CreateMockAnything() @@ -177,7 +183,8 @@ class DBAPITestCase(unittest.TestCase): fake_request = self.mox.CreateMockAnything() fake_request.GET = {'offset': 2, 'limit': 2} self.mox.StubOutWithMock(dbapi, '_get_filter_args') - dbapi._get_filter_args(fake_model, fake_request).AndReturn({}) + dbapi._get_filter_args(fake_model, fake_request, + custom_filters=None).AndReturn({}) self.mox.StubOutWithMock(dbapi, '_check_has_field') dbapi._check_has_field(fake_model, 'id') result = self.mox.CreateMockAnything() @@ -197,7 +204,8 @@ class DBAPITestCase(unittest.TestCase): filters = {'instance': INSTANCE_ID_1} fake_request.GET = filters self.mox.StubOutWithMock(dbapi, '_get_filter_args') - dbapi._get_filter_args(fake_model, fake_request).AndReturn(filters) + dbapi._get_filter_args(fake_model, fake_request, + custom_filters=None).AndReturn(filters) self.mox.StubOutWithMock(dbapi, '_check_has_field') dbapi._check_has_field(fake_model, 'id') result = self.mox.CreateMockAnything() @@ -210,3 +218,93 @@ class DBAPITestCase(unittest.TestCase): self.assertEquals(query_result, result) self.mox.VerifyAll() + + def test_get_db_objects_with_custom_filter(self): + fake_model = self.make_fake_model() + fake_request = self.mox.CreateMockAnything() + filters = {'instance': INSTANCE_ID_1} + custom_filters = {'raw': {'raw__id': 1}} + fake_request.GET = filters + self.mox.StubOutWithMock(dbapi, '_get_filter_args') + dbapi._get_filter_args(fake_model, fake_request, + custom_filters=custom_filters).AndReturn(filters) + self.mox.StubOutWithMock(dbapi, '_check_has_field') + dbapi._check_has_field(fake_model, 'id') + result = self.mox.CreateMockAnything() + all_filters = {} + all_filters.update(filters) + all_filters.update(custom_filters['raw']) + fake_model.objects.filter(**all_filters).AndReturn(result) + result.order_by('id').AndReturn(result) + result.__getitem__(slice(None, None, None)).AndReturn(result) + self.mox.ReplayAll() + + query_result = dbapi.get_db_objects(fake_model, fake_request, 'id', + custom_filters=custom_filters) + self.assertEquals(query_result, result) + + self.mox.VerifyAll() + + def test_list_usage_exists_no_custom_filters(self): + fake_request = self.mox.CreateMockAnything() + fake_request.GET = {} + self.mox.StubOutWithMock(dbapi, 'get_db_objects') + objects = self.mox.CreateMockAnything() + dbapi.get_db_objects(models.InstanceExists, fake_request, 'id', + custom_filters={}).AndReturn(objects) + self.mox.StubOutWithMock(dbapi, '_convert_model_list') + dbapi._convert_model_list(objects, dbapi._exists_extra_values) + self.mox.ReplayAll() + resp = dbapi.list_usage_exists(fake_request) + self.assertEqual(resp.status_code, 200) + self.mox.VerifyAll() + + def test_list_usage_exists_with_received_min(self): + fake_request = self.mox.CreateMockAnything() + date = str(datetime.datetime.utcnow()) + fake_request.GET = {'received_min': date} + self.mox.StubOutWithMock(dbapi, 'get_db_objects') + unix_date = stacktach_utils.str_time_to_unix(date) + custom_filters = {'received_min': {'raw__when__gte': unix_date}} + objects = self.mox.CreateMockAnything() + dbapi.get_db_objects(models.InstanceExists, fake_request, 'id', + custom_filters=custom_filters).AndReturn(objects) + self.mox.StubOutWithMock(dbapi, '_convert_model_list') + dbapi._convert_model_list(objects, dbapi._exists_extra_values) + self.mox.ReplayAll() + resp = dbapi.list_usage_exists(fake_request) + self.assertEqual(resp.status_code, 200) + self.mox.VerifyAll() + + def test_list_usage_exists_with_received_max(self): + fake_request = self.mox.CreateMockAnything() + date = str(datetime.datetime.utcnow()) + fake_request.GET = {'received_max': date} + self.mox.StubOutWithMock(dbapi, 'get_db_objects') + unix_date = stacktach_utils.str_time_to_unix(date) + custom_filters = {'received_max': {'raw__when__lte': unix_date}} + objects = self.mox.CreateMockAnything() + dbapi.get_db_objects(models.InstanceExists, fake_request, 'id', + custom_filters=custom_filters).AndReturn(objects) + self.mox.StubOutWithMock(dbapi, '_convert_model_list') + dbapi._convert_model_list(objects, dbapi._exists_extra_values) + self.mox.ReplayAll() + resp = dbapi.list_usage_exists(fake_request) + self.assertEqual(resp.status_code, 200) + self.mox.VerifyAll() + + def test_list_usage_exists_with_bad_received_min(self): + fake_request = self.mox.CreateMockAnything() + fake_request.GET = {'received_min': 'obviouslybaddate'} + self.mox.ReplayAll() + resp = dbapi.list_usage_exists(fake_request) + self.assertEqual(resp.status_code, 400) + self.mox.VerifyAll() + + def test_list_usage_exists_with_bad_received_max(self): + fake_request = self.mox.CreateMockAnything() + fake_request.GET = {'received_max': 'obviouslybaddate'} + self.mox.ReplayAll() + resp = dbapi.list_usage_exists(fake_request) + self.assertEqual(resp.status_code, 400) + self.mox.VerifyAll() \ No newline at end of file