Source code for jsontas.data_structures.filter

# Copyright 2020 Axis Communications AB.
#
# For a full list of individual contributors, please see the commit history.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Filter datastructure."""
from copy import deepcopy
from .datastructure import DataStructure


[docs]class Filter(DataStructure): """Filter datastructure. Example:: { "data": { "$filter": { "items": [ { "status": "success", "value": "1" }, { "status": "failure", "value": "2" }, { "status": "success", "value": "3" } ], "filters": [ { "key": "status", "operator": "$eq", "value": "success" } ] } } } # {"data": [{"status": "success", "value": "1"}, {"status": "success", "value": "3"}]} """
[docs] def filter(self, item): """Execute the filtering list against item. The filtering list is the list of key,operator,value dictionaries following the format of :obj:`jsontas.data_structures.operator.Operator` (in fact, the :obj:`jsontas.data_structures.operator.Operator` datastructure is used in this method to validate the filters) Note that when running the filter, the dataset is appended with an "item" which is a single item from the "items" filter list (can be seen above). The dataset could then be this:: { **current_dataset, "item": { "status": "success", "value": "1"} } With the filter being:: { "key": "status", "operator": "$eq", "value": "success" } And the filter would be True (the status of the item is 'success'). Note that this method will only ever run on the "item". If there is not "$item" in the "key", the method will add it. That is why it's possible to write:: {"key": "status"} instead of:: {"key": "$item.status"} But it would also mean that if one were to write:: {"key": "$anotherkey.something.else"} it would become:: {"key": "$item.$anotherkey.something.else"} which would fail. This is a design choice. The filter shall not utilize any data aside from the 'item' key in the dataset. :param item: Item to filter. :type item: dict :return: Whether or not all items in filter evaluates to True. :rtype: bool """ self.dataset.add("item", item) filters = deepcopy(self.data.get("filters")) for _filter in filters: key = _filter.get("key") if not key.startswith("$item."): key = "$item.{}".format(key) _, _filter["key"] = self.dataset.lookup(key, {}) _, value = self.dataset.lookup("$operator", _filter) if not value: return False return True
[docs] def execute(self): """Execute the filter datastructure. :return: Key and the value(s) found. :rtype: tuple """ value = [] if not isinstance(self.data.get("items"), (list, tuple, set)): return None, value for item in self.data.get("items", []): if self.filter(item): value.append(item) return None, value