ARG_Q_MARK = '?'
PARAM_Q_ID = f'id{CHAR_ATTR_EQ}'
-PARAM_Q_TEXT = f'text{CHAR_TEXTCONTAINS}'
PARAM_Q_DELIMITERS = {CHAR_ATTR_EQ, CHAR_TEXTCONTAINS}
TOK_SORT_BOX = 'box'
TOK_SORT_ID = 'id'
LDRAW_MODE_VERIFY_PATHS,
LDRAW_MODE_VERIFY_N_STUDS}
+ATTR_DESCS: dict[str, str] = {
+ 'n_studs': 'number of studs',
+ 'description': 'guesstimate what this be',
+ 'ldraw': 'path of associated LDRAW file'
+}
+
BrickListing = tuple[int, str, str] # count, ID, comment
PageColumn = tuple[BrickListing, ...]
Page = tuple[PageColumn, ...]
@classmethod
def formatters(
cls
- ) -> dict[str, Callable[[Self], str]]:
+ ) -> dict[str, tuple[str, Callable[[Self], str]]]:
'Available per-item string formatters.'
formatters = {
- 'default': lambda item: item.show()
+ 'default': (
+ 'most commonly relevant infos',
+ lambda item: item.show())
}
if issubclass(cls, Textfiled):
- formatters['raw'] = lambda item: item.raw()
+ formatters['raw'] = (
+ 'in source-file format',
+ lambda item: item.raw())
return formatters
@classmethod
def matchers(
cls
- ) -> dict[str, Callable[[Self, str], bool]]:
+ ) -> dict[str, tuple[str, Callable[[Self, str], bool]]]:
'Available lookup matchers.'
return {
- PARAM_Q_ID: (lambda item, q_body:
- item.id_ == q_body),
- PARAM_Q_TEXT: (lambda item, q_body:
- q_body.upper() in str(item).upper())
+ PARAM_Q_ID: (
+ 'by ID of individual item',
+ lambda item, q_body: item.id_ == q_body),
+ f'text{CHAR_TEXTCONTAINS}': (
+ 'text contained in item description',
+ lambda item, q_body: q_body.upper() in item.show().upper())
}
def match(
query_body: str
) -> bool:
'Return if self matches query.'
- return self.matchers()[query_char](self, query_body)
+ return self.matchers()[query_char][1](self, query_body)
@classmethod
def _by_box_sorter(
cls,
to_id_of=''
- ) -> Callable[['BricksDb', tuple[Self, ...]], tuple[Self, ...]]:
+ ) -> tuple[str,
+ Callable[['BricksDb', tuple[Self, ...]],
+ tuple[Self, ...]]]:
def by_box(
db: 'BricksDb',
pre_sorted: tuple[Self, ...]
items += [to_move]
remains.remove(to_move)
return tuple(items + remains)
- return by_box
+ return 'by IDs of containing boxes', by_box
@classmethod
def sorters(
cls
- ) -> dict[str, Callable[['BricksDb', tuple[Self, ...]],
- tuple[Self, ...]]]:
+ ) -> dict[str, tuple[str, Callable[['BricksDb', tuple[Self, ...]],
+ tuple[Self, ...]]]]:
'Available sorters.'
return {
- TOK_SORT_ID: (lambda _, pre_sorted:
- tuple(sorted(pre_sorted,
- key=lambda item: item.id_indented())))
+ TOK_SORT_ID: (
+ 'by individual items\' IDs',
+ lambda _, pre_sorted:
+ tuple(sorted(pre_sorted,
+ key=lambda item: item.id_indented())))
}
@classmethod
def sorters(
cls
- ) -> dict[str, Callable[['BricksDb', tuple[Self, ...]],
- tuple[Self, ...]]]:
+ ) -> dict[str, tuple[str,
+ Callable[['BricksDb', tuple[Self, ...]],
+ tuple[Self, ...]]]]:
return super().sorters() | {TOK_SORT_BOX: cls._by_box_sorter('color')}
def raw(
@classmethod
def matchers(
cls
- ) -> dict[str, Callable[[Self, str], bool]]:
+ ) -> dict[str, tuple[str, Callable[[Self, str], bool]]]:
def attr_matcher(
attr_name: str
- ) -> Callable[[Self, str], bool]:
+ ) -> tuple[str, Callable[[Self, str], bool]]:
def match(
item: Self,
q_body: str
) -> bool:
assert q_body.isdigit()
return getattr(item, attr_name) == int(q_body)
- return match
+ return 'by ' + ATTR_DESCS[attr_name], match
return super().matchers() | {
f'{attr_name}{CHAR_ATTR_EQ}': attr_matcher(attr_name)
for attr_name, attr_type in BrickDesignData.__annotations__.items()
@classmethod
def sorters(
cls
- ) -> dict[str, Callable[['BricksDb', tuple[Self, ...]],
- tuple[Self, ...]]]:
+ ) -> dict[str, tuple[str,
+ Callable[['BricksDb', tuple[Self, ...]],
+ tuple[Self, ...]]]]:
def attr_sorter(
attr_name: str,
- ) -> Callable[[BricksDb, tuple[Self, ...]], tuple[Self, ...]]:
+ ) -> tuple[str, Callable[[BricksDb, tuple[Self, ...]],
+ tuple[Self, ...]]]:
def f_sort(
_: BricksDb,
pre_sorted: tuple[Self, ...]
) -> tuple[Self, ...]:
return tuple(sorted(pre_sorted,
key=lambda item: getattr(item, attr_name)))
- return f_sort
+ return 'by ' + ATTR_DESCS[attr_name], f_sort
return super().sorters()\
| {TOK_SORT_BOX: cls._by_box_sorter('design')}\
| {attr_name: attr_sorter(attr_name)
@classmethod
def sorters(
cls
- ) -> dict[str, Callable[['BricksDb', tuple[Self, ...]],
- tuple[Self, ...]]]:
+ ) -> dict[str, tuple[str, Callable[['BricksDb', tuple[Self, ...]],
+ tuple[Self, ...]]]]:
return super().sorters() | {TOK_SORT_BOX: cls._by_box_sorter()}
@classmethod
) -> str:
return f'{self.id_} {self._is_in_str} {self.description}'
- @classmethod
- def matchers(
- cls
- ) -> dict[str, Callable[[Self, str], bool]]:
- return super().matchers() | {
- PARAM_Q_TEXT: (lambda item, q_body:
- q_body.upper() in item.show().upper())
- }
-
def _format_paginated(
self,
format_line: Callable[[int, str, str], str]
match_val = match_by[idx+1:]
break
cls = self.lookupables[table_name]
- for arg_key, keys in [(arg, m().keys())
- for arg, m in ((match_key, cls.matchers),
- (sort_by, cls.sorters),
- (formatter, cls.formatters))]:
+ for arg_key, x_ers in [(arg, m())
+ for arg, m in ((match_key, cls.matchers),
+ (sort_by, cls.sorters),
+ (formatter, cls.formatters))]:
+ keys = x_ers.keys()
if arg_key == ARG_Q_MARK:
- return CHAR_NEWLINE.join(keys)
+ return CHAR_NEWLINE.join([f'{key} – {x_ers[key][0]}'
+ for key in sorted(keys)])
assert (not arg_key) or arg_key in keys, (arg_key, keys)
items = tuple(getattr(self, table_name).values())
if items and sort_by:
- items = cls.sorters()[sort_by](self, items)
+ items = cls.sorters()[sort_by][1](self, items)
if items and match_by:
items = tuple(x for x in items if x.match(match_key, match_val))
- return CHAR_NEWLINE.join([cls.formatters()[formatter](item)
+ return CHAR_NEWLINE.join([cls.formatters()[formatter][1](item)
for item in items])