def test_find_nested_dotted_path_value(self): obj = {"a": {"b.c": 42}} obtained = find_nested_value(obj, "a.b.c") self.assertEqual(obtained, 42) obj = {"a.b": {"c.d": 42}} obtained = find_nested_value(obj, "a.b.c.d") self.assertEqual(obtained, 42) obj = {"a": {"b": {"a": {"b": 42}}}} obtained = find_nested_value(obj, "a.b.a.b") self.assertEqual(obtained, 42)
def test_find_nested_dotted_path_value(self): record = {"a": {"b.c": 42}} obtained = find_nested_value(record, "a.b.c") self.assertEqual(obtained, 42) record = {"a.b": {"c.d": 42}} obtained = find_nested_value(record, "a.b.c.d") self.assertEqual(obtained, 42) record = {"a": {"b": {"a": {"b": 42}}}} obtained = find_nested_value(record, "a.b.a.b") self.assertEqual(obtained, 42)
def test_find_disambiguated_dotted_path_values(self): # XXX: To be honest, this is a really scary use case. Probably a # limitation of the dotted path notation we may want to document. # At least this test acts as documentation for now. record = {"a": {"b": 0}, "a.b": 42} obtained = find_nested_value(record, "a.b") self.assertEqual(obtained, 42)
def _build_pagination_token(self, sorting, last_record, offset): """Build a pagination token. It is a base64 JSON object with the sorting fields values of the last_record. """ nonce = 'pagination-token-{}'.format(uuid4()) if self.request.method.lower() == 'delete': registry = self.request.registry validity = registry.settings['pagination_token_validity_seconds'] registry.cache.set(nonce, '', validity) token = { 'last_record': {}, 'offset': offset, 'nonce': nonce, } for field, _ in sorting: last_value = find_nested_value(last_record, field, MISSING) if last_value is not MISSING: token['last_record'][field] = last_value return encode64(json.dumps(token))
def test_find_disambiguated_dotted_path_values(self): # XXX: To be honest, this is a really scary use case. Probably a # limitation of the dotted path notation we may want to document. # At least this test acts as documentation for now. obj = {"a": {"b": 0}, "a.b": 42} obtained = find_nested_value(obj, "a.b") self.assertEqual(obtained, 42)
def _build_pagination_token(self, sorting, last_record, offset): """Build a pagination token. It is a base64 JSON object with the sorting fields values of the last_record. """ nonce = "pagination-token-{}".format(uuid4()) if self.request.method.lower() == "delete": registry = self.request.registry validity = registry.settings["pagination_token_validity_seconds"] registry.cache.set(nonce, "", validity) token = { 'last_record': {}, 'offset': offset, 'nonce': nonce, } for field, _ in sorting: last_value = find_nested_value(last_record, field) if last_value is not None: token['last_record'][field] = last_value return encode64(json.dumps(token))
def _build_pagination_token(self, sorting, last_record, offset): """Build a pagination token. It is a base64 JSON object with the sorting fields values of the last_record. """ token = {'last_record': {}, 'offset': offset} for field, _ in sorting: last_value = find_nested_value(last_record, field) if last_value is not None: token['last_record'][field] = last_value return encode64(json.dumps(token))
def apply_filters(records, filters): """Filter the specified records, using basic iteration. """ operators = { COMPARISON.LT: operator.lt, COMPARISON.MAX: operator.le, COMPARISON.EQ: operator.eq, COMPARISON.NOT: operator.ne, COMPARISON.MIN: operator.ge, COMPARISON.GT: operator.gt, COMPARISON.IN: operator.contains, COMPARISON.EXCLUDE: lambda x, y: not operator.contains(x, y), COMPARISON.LIKE: lambda x, y: re.search(y, x, re.IGNORECASE), } for record in records: matches = True for f in filters: right = f.value if f.field == DEFAULT_ID_FIELD: if isinstance(right, int): right = str(right) left = find_nested_value(record, f.field, MISSING) if f.operator in (COMPARISON.IN, COMPARISON.EXCLUDE): right, left = left, right elif f.operator == COMPARISON.LIKE: # Add implicit start/end wildchars if none is specified. if '*' not in right: right = '*{}*'.format(right) right = '^{}$'.format(right.replace('*', '.*')) elif f.operator != COMPARISON.HAS: left = schwartzian_transform(left) right = schwartzian_transform(right) if f.operator == COMPARISON.HAS: matches = left != MISSING if f.value else left == MISSING else: matches = matches and operators[f.operator](left, right) if matches: yield record
def _build_pagination_token(self, sorting, last_object, offset): """Build a pagination token. It is a base64 JSON object with the sorting fields values of the last_object. """ nonce = f"pagination-token-{uuid4()}" if self.request.method.lower() == "delete": registry = self.request.registry validity = registry.settings["pagination_token_validity_seconds"] registry.cache.set(nonce, "", validity) token = {"last_object": {}, "offset": offset, "nonce": nonce} for field, _ in sorting: last_value = find_nested_value(last_object, field, MISSING) if last_value is not MISSING: token["last_object"][field] = last_value return encode64(json.dumps(token))
def apply_filters(records, filters): """Filter the specified records, using basic iteration. """ operators = { COMPARISON.LT: operator.lt, COMPARISON.MAX: operator.le, COMPARISON.EQ: operator.eq, COMPARISON.NOT: operator.ne, COMPARISON.MIN: operator.ge, COMPARISON.GT: operator.gt, COMPARISON.IN: operator.contains, COMPARISON.EXCLUDE: lambda x, y: not operator.contains(x, y), COMPARISON.LIKE: lambda x, y: re.search(y, x, re.IGNORECASE), } for record in records: matches = True for f in filters: right = f.value if f.field == DEFAULT_ID_FIELD: if isinstance(right, int): right = str(right) left = find_nested_value(record, f.field) if f.operator in (COMPARISON.IN, COMPARISON.EXCLUDE): right, left = left, right else: if left is None: right_is_number = (isinstance(right, (int, float)) and right not in (True, False)) if right_is_number: # Python3 cannot compare None to a number. matches = False continue else: left = '' # To mimic what we do for postgresql. matches = matches and operators[f.operator](left, right) if matches: yield record
def apply_filters(records, filters): """Filter the specified records, using basic iteration. """ def contains_filtering(record_value, search_term): if record_value == MISSING: return False try: search_set = set([canonical_json(v) for v in search_term]) record_value_set = set([canonical_json(v) for v in record_value]) except TypeError: return False return record_value_set.intersection(search_set) == search_set def contains_any_filtering(record_value, search_term): if record_value == MISSING: return False try: search_set = set([canonical_json(v) for v in search_term]) record_value_set = set([canonical_json(v) for v in record_value]) except TypeError: return False return record_value_set.intersection(search_set) operators = { COMPARISON.LT: operator.lt, COMPARISON.MAX: operator.le, COMPARISON.EQ: operator.eq, COMPARISON.NOT: operator.ne, COMPARISON.MIN: operator.ge, COMPARISON.GT: operator.gt, COMPARISON.IN: operator.contains, COMPARISON.EXCLUDE: lambda x, y: not operator.contains(x, y), COMPARISON.LIKE: lambda x, y: re.search(y, x, re.IGNORECASE), COMPARISON.CONTAINS: contains_filtering, COMPARISON.CONTAINS_ANY: contains_any_filtering, } for record in records: matches = True for f in filters: right = f.value if f.field == DEFAULT_ID_FIELD: if isinstance(right, int): right = str(right) left = find_nested_value(record, f.field, MISSING) if f.operator in (COMPARISON.IN, COMPARISON.EXCLUDE): right, left = left, right elif f.operator == COMPARISON.LIKE: # Add implicit start/end wildchars if none is specified. if "*" not in right: right = f"*{right}*" right = f"^{right.replace('*', '.*')}$" elif f.operator in ( COMPARISON.LT, COMPARISON.MAX, COMPARISON.EQ, COMPARISON.NOT, COMPARISON.MIN, COMPARISON.GT, ): left = schwartzian_transform(left) right = schwartzian_transform(right) if f.operator == COMPARISON.HAS: matches = left != MISSING if f.value else left == MISSING else: matches = matches and operators[f.operator](left, right) if matches: yield record
def test_fallback_default_value(self): obj = {"a": {"c": 42}} self.assertEqual(find_nested_value(obj, "x", 1337), 1337) self.assertEqual(find_nested_value(obj, "a.b", 1337), 1337) self.assertEqual(find_nested_value(obj, "x.a", 1337), 1337) self.assertEqual(find_nested_value(obj, "a.c.d", 1337), 1337)
def test_unmatched_path_returns_none(self): obj = {"a": 42} self.assertIsNone(find_nested_value(obj, "x")) self.assertIsNone(find_nested_value(obj, "a.b")) self.assertIsNone(find_nested_value(obj, "x.a"))
def test_find_dotted_path_value(self): obj = {"a.b": 42} obtained = find_nested_value(obj, "a.b") self.assertEqual(obtained, 42)
def column(first, record, name): return find_nested_value(record, name, default=float('inf'))
def test_find_flat_value(self): obj = {"a": 42} obtained = find_nested_value(obj, "a") self.assertEqual(obtained, 42)
def test_unmatched_path_returns_none(self): record = {"a": 42} self.assertIsNone(find_nested_value(record, "x")) self.assertIsNone(find_nested_value(record, "a.b")) self.assertIsNone(find_nested_value(record, "x.a"))
def test_find_deeply_nested_value(self): record = {"a": {"b": {"c": 42}}} obtained = find_nested_value(record, "a.b.c") self.assertEqual(obtained, 42)
def test_find_flat_value(self): record = {"a": 42} obtained = find_nested_value(record, "a") self.assertEqual(obtained, 42)
def column(record, name): return schwartzian_transform(find_nested_value(record, name, default=MISSING))
def test_find_nested_value(self): record = {"a": {"b": 42}} obtained = find_nested_value(record, "a.b") self.assertEqual(obtained, 42)
def test_fallback_default_value(self): record = {"a": {"c": 42}} self.assertEqual(find_nested_value(record, "x", 1337), 1337) self.assertEqual(find_nested_value(record, "a.b", 1337), 1337) self.assertEqual(find_nested_value(record, "x.a", 1337), 1337) self.assertEqual(find_nested_value(record, "a.c.d", 1337), 1337)
def column(record, name): return schwartzian_transform( find_nested_value(record, name, default=MISSING))
def test_find_deeply_nested_value(self): obj = {"a": {"b": {"c": 42}}} obtained = find_nested_value(obj, "a.b.c") self.assertEqual(obtained, 42)
def apply_filters(records, filters): """Filter the specified records, using basic iteration. """ def contains_filtering(record_value, search_term): if record_value == MISSING: return False try: search_set = set([canonical_json(v) for v in search_term]) record_value_set = set([canonical_json(v) for v in record_value]) except TypeError: return False return record_value_set.intersection(search_set) == search_set def contains_any_filtering(record_value, search_term): if record_value == MISSING: return False try: search_set = set([canonical_json(v) for v in search_term]) record_value_set = set([canonical_json(v) for v in record_value]) except TypeError: return False return record_value_set.intersection(search_set) operators = { COMPARISON.LT: operator.lt, COMPARISON.MAX: operator.le, COMPARISON.EQ: operator.eq, COMPARISON.NOT: operator.ne, COMPARISON.MIN: operator.ge, COMPARISON.GT: operator.gt, COMPARISON.IN: operator.contains, COMPARISON.EXCLUDE: lambda x, y: not operator.contains(x, y), COMPARISON.LIKE: lambda x, y: re.search(y, x, re.IGNORECASE), COMPARISON.CONTAINS: contains_filtering, COMPARISON.CONTAINS_ANY: contains_any_filtering, } for record in records: matches = True for f in filters: right = f.value if f.field == DEFAULT_ID_FIELD: if isinstance(right, int): right = str(right) left = find_nested_value(record, f.field, MISSING) if f.operator in (COMPARISON.IN, COMPARISON.EXCLUDE): right, left = left, right elif f.operator == COMPARISON.LIKE: # Add implicit start/end wildchars if none is specified. if '*' not in right: right = '*{}*'.format(right) right = '^{}$'.format(right.replace('*', '.*')) elif f.operator in (COMPARISON.LT, COMPARISON.MAX, COMPARISON.EQ, COMPARISON.NOT, COMPARISON.MIN, COMPARISON.GT): left = schwartzian_transform(left) right = schwartzian_transform(right) if f.operator == COMPARISON.HAS: matches = left != MISSING if f.value else left == MISSING else: matches = matches and operators[f.operator](left, right) if matches: yield record
def test_find_dotted_path_value(self): record = {"a.b": 42} obtained = find_nested_value(record, "a.b") self.assertEqual(obtained, 42)