aboutsummaryrefslogtreecommitdiffstats
path: root/bsfs
diff options
context:
space:
mode:
authorMatthias Baumgartner <dev@igsor.net>2023-02-08 20:47:18 +0100
committerMatthias Baumgartner <dev@igsor.net>2023-02-08 20:47:18 +0100
commit64f3ac76a2f8d6b51380c06233accfcc19dca228 (patch)
tree785819f986e56eabb723309dacd74d6b7353f604 /bsfs
parentcb819b8c268908b5f6cc680173db86e172847c46 (diff)
downloadbsfs-64f3ac76a2f8d6b51380c06233accfcc19dca228.tar.gz
bsfs-64f3ac76a2f8d6b51380c06233accfcc19dca228.tar.bz2
bsfs-64f3ac76a2f8d6b51380c06233accfcc19dca228.zip
filter query convenience functions
Diffstat (limited to 'bsfs')
-rw-r--r--bsfs/query/ast/filter_.py58
1 files changed, 53 insertions, 5 deletions
diff --git a/bsfs/query/ast/filter_.py b/bsfs/query/ast/filter_.py
index 798d37f..44490fc 100644
--- a/bsfs/query/ast/filter_.py
+++ b/bsfs/query/ast/filter_.py
@@ -31,10 +31,7 @@ from collections import abc
import typing
# bsfs imports
-from bsfs.utils import URI, typename, normalize_args
-
-# inner-module imports
-#from . import utils
+from bsfs.utils import URI, errors, typename, normalize_args
# exports
__all__ : typing.Sequence[str] = (
@@ -460,10 +457,61 @@ class OneOf(PredicateExpression, abc.Collection):
def IsIn(*values): # pylint: disable=invalid-name # explicitly mimics an expression
"""Match any of the given URIs."""
- return Or(Is(value) for value in normalize_args(*values))
+ args = normalize_args(*values)
+ if len(args) == 0:
+ raise AttributeError('expected at least one value, found none')
+ if len(args) == 1:
+ return Is(args[0])
+ return Or(Is(value) for value in args)
def IsNotIn(*values): # pylint: disable=invalid-name # explicitly mimics an expression
"""Match none of the given URIs."""
return Not(IsIn(*values))
+
+def Between(
+ lo: float = float('-inf'),
+ hi: float = float('inf'),
+ lo_strict: bool = True,
+ hi_strict: bool = True,
+ ):
+ """Match numerical values between *lo* and *hi*. Include bounds if strict is False."""
+ if abs(lo) == hi == float('inf'):
+ raise ValueError('range cannot be INF on both sides')
+ if lo > hi:
+ raise ValueError(f'lower bound ({lo}) cannot be less than upper bound ({hi})')
+ if lo == hi and not lo_strict and not hi_strict:
+ return Equals(lo)
+ if lo == hi: # either bound is strict
+ raise ValueError(f'bounds cannot be equal when either is strict')
+ if lo != float('-inf') and hi != float('inf'):
+ return And(GreaterThan(lo, lo_strict), LessThan(hi, hi_strict))
+ if lo != float('-inf'):
+ return GreaterThan(lo, lo_strict)
+ # hi != float('inf'):
+ return LessThan(hi, hi_strict)
+
+
+def Includes(*values, approx: bool = False):
+ """Match any of the given *values*. Uses `Substring` if *approx* is set."""
+ args = normalize_args(*values)
+ cls = Substring if approx else Equals
+ if len(args) == 0:
+ raise AttributeError('expected at least one value, found none')
+ if len(args) == 1:
+ return cls(args[0])
+ return Or(cls(v) for v in args)
+
+
+def Excludes(*values, approx: bool = False):
+ """Match none of the given *values*. Uses `Substring` if *approx* is set."""
+ args = normalize_args(*values)
+ cls = Substring if approx else Equals
+ if len(args) == 0:
+ raise AttributeError('expected at least one value, found none')
+ if len(args) == 1:
+ return Not(cls(args[0]))
+ return Not(Or(cls(v) for v in args))
+
+
## EOF ##