From: Plom Heller Date: Fri, 14 Aug 2026 23:42:26 +0000 (+0200) Subject: For matching on numerical values, allow "<" and ">" comparisons. X-Git-Url: https://plomlompom.com/repos/%22https:/validator.w3.org/%7B%7Bdb.prefix%7D%7D/static/processes?a=commitdiff_plain;p=bricksplom For matching on numerical values, allow "<" and ">" comparisons. --- diff --git a/src/bricksplom/misc.py b/src/bricksplom/misc.py index e7d276d..7cce3cf 100644 --- a/src/bricksplom/misc.py +++ b/src/bricksplom/misc.py @@ -13,6 +13,8 @@ CHAR_SEP_TOKEN = ' ' CHAR_COMMENT = '#' CHAR_DESIGN_ALT = '=' CHAR_ATTR_EQ = '=' +CHAR_ATTR_LESS = '<' +CHAR_ATTR_MORE = '>' CHAR_TEXTCONTAINS = ':' SEP_DESIGN_DESC = '#' CHAR_COLL_INDENT = ' ' @@ -28,7 +30,12 @@ BOX_PREFIX = 'box:' ARG_QMARK = '?' PARAM_Q_ID = f'id{CHAR_ATTR_EQ}' -PARAM_Q_DELIMITERS = {CHAR_ATTR_EQ, CHAR_TEXTCONTAINS} +MATCH_OPERATORS = { + CHAR_ATTR_EQ, + CHAR_TEXTCONTAINS, + CHAR_ATTR_LESS, + CHAR_ATTR_MORE + } TOK_SORT_BOX = 'box' TOK_SORT_ID = 'id' @@ -154,24 +161,31 @@ class Lookupable: @classmethod def matchers( cls - ) -> dict[str, tuple[str, Callable[[Self, str], bool]]]: + ) -> dict[str, tuple[str, dict[str, Callable[[Self, str], bool]]]]: 'Available lookup matchers.' return { - PARAM_Q_ID: ( - 'by ID of individual item', - lambda item, q_body: item.id_ == q_body), - f'text{CHAR_TEXTCONTAINS}': ( + TOK_SORT_ID: ( + 'ID of individual item', + {CHAR_ATTR_EQ: ( + lambda item, val: item.id_ == val)} + ), + 'text': ( 'text contained in item description', - lambda item, q_body: q_body.upper() in item.show().upper()) + {CHAR_TEXTCONTAINS: ( + lambda item, val: val.upper() in item.show().upper())} + ), } def match( self, - query_char: str, - query_body: str + target: str, + operator: str, + val: str ) -> bool: 'Return if self matches query.' - return self.matchers()[query_char][1](self, query_body) + target_matchers = self.matchers()[target][1] + assert operator in target_matchers, (target, operator) + return target_matchers[operator](self, val) @classmethod def _by_box_sorter( @@ -426,19 +440,22 @@ class BrickDesign(Textfiled, WithDb, Lookupable): @classmethod def matchers( cls - ) -> dict[str, tuple[str, Callable[[Self, str], bool]]]: + ) -> dict[str, tuple[str, dict[str, Callable[[Self, str], bool]]]]: def attr_matcher( attr_name: str - ) -> tuple[str, Callable[[Self, str], bool]]: - def match( + ) -> tuple[str, dict[str, Callable[[Self, str], bool]]]: + def cmp( item: Self, q_body: str - ) -> bool: + ) -> float: assert q_body.isdigit() - return getattr(item, attr_name) == int(q_body) - return 'by ' + BrickDesignData.usage(attr_name), match + return int(q_body) - float(getattr(item, attr_name)) + return 'by ' + BrickDesignData.usage(attr_name), { + CHAR_ATTR_EQ: lambda item, v: 0 == cmp(item, v), + CHAR_ATTR_LESS: lambda item, v: 0 < cmp(item, v), + CHAR_ATTR_MORE: lambda item, v: 0 > cmp(item, v)} return super().matchers() | { - f'{attr_name}{CHAR_ATTR_EQ}': attr_matcher(attr_name) + f'{attr_name}': attr_matcher(attr_name) for attr_name, attr_type in BrickDesignData.sortables().items() if attr_type in {int, float}} @@ -922,18 +939,19 @@ class BricksDb: ) -> str: 'Return formatted result of inquiry on table of table_name.' assert table_name in self.lookupables - match_keys_vals = [] + matchers = [] for instruction in match_by: - match_key = match_val = '' + match_key = match_val = match_operator = '' for idx, c in enumerate(instruction): - match_key += c - if c in PARAM_Q_DELIMITERS: + if c in MATCH_OPERATORS: + match_operator = c match_val = instruction[idx+1:] break - match_keys_vals += [(match_key, match_val)] + match_key += c + matchers += [(match_key, match_operator, match_val)] cls = self.lookupables[table_name] for arg_keys, x_ers in [ - (arg, m()) for arg, m in ((tuple(t[0] for t in match_keys_vals), + (arg, m()) for arg, m in ((tuple(t[0] for t in matchers), cls.matchers), (sort_by, cls.sorters), ((formatter, ), cls.formatters))]: @@ -944,9 +962,8 @@ class BricksDb: for arg_key in arg_keys: assert (not arg_key) or arg_key in keys, (arg_key, keys) if (items := tuple(getattr(self, table_name).values())): - for match_key, match_val in match_keys_vals: - items = tuple(x for x in items - if x.match(match_key, match_val)) + for key, operator, val in matchers: + items = tuple(x for x in items if x.match(key, operator, val)) for sorter in sort_by: items = cls.sorters()[sorter][1](self, items) return CHAR_NEWLINE.join([cls.formatters()[formatter][1](item)