From b09835f0851969ed15f76b0ea1210c7418d3e66c Mon Sep 17 00:00:00 2001 From: Daniel Kraus Date: Mon, 29 Aug 2016 18:04:35 +0800 Subject: [PATCH] Bugfix when building `not` filter multiple times Make a copy of `filter` otherwise the `field` value (a :class:`Filter`) of the `not` filter will be replaced with a `dict` and on next call of `build_filter` with the same filter_obj variable will fail. --- pydruid/utils/filters.py | 1 + tests/utils/test_filters.py | 7 +++++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/pydruid/utils/filters.py b/pydruid/utils/filters.py index a7ae3c22..76254a00 100644 --- a/pydruid/utils/filters.py +++ b/pydruid/utils/filters.py @@ -81,6 +81,7 @@ def build_filter(filter_obj): filter = filter.copy() # make a copy so we don't overwrite `fields` filter['fields'] = [Filter.build_filter(f) for f in filter['fields']] elif filter['type'] in ['not']: + filter = filter.copy() filter['field'] = Filter.build_filter(filter['field']) return filter diff --git a/tests/utils/test_filters.py b/tests/utils/test_filters.py index b66142da..21863909 100644 --- a/tests/utils/test_filters.py +++ b/tests/utils/test_filters.py @@ -125,8 +125,11 @@ def test_or_filter_multiple(self): assert actual == expected def test_not_filter(self): - f = filters.Filter(dimension='dim', value='val') - actual = filters.Filter.build_filter(~f) + f = ~filters.Filter(dimension='dim', value='val') + actual = filters.Filter.build_filter(f) + # Call `build_filter` twice to make sure it does not + # change the passed filter object argument `f`. + actual = filters.Filter.build_filter(f) expected = { 'type': 'not', 'field': {'type': 'selector', 'dimension': 'dim', 'value': 'val'}