From: Plom Heller Date: Mon, 1 Jun 2026 01:22:55 +0000 (+0200) Subject: Add --sort-by {id,box,studs}. X-Git-Url: https://plomlompom.com/repos/%7B%7B%20web_path%20%7D%7D/%7B%7Bdb.prefix%7D%7D/test.html?a=commitdiff_plain;h=b4703e7d42f705a2b36fb0b6db618e720b81988a;p=bricksplom Add --sort-by {id,box,studs}. --- diff --git a/bricksplom.py b/bricksplom.py index f8ae1f9..7f675e2 100755 --- a/bricksplom.py +++ b/bricksplom.py @@ -29,8 +29,11 @@ CHAR_Q_ID = '=' CHAR_Q_STUDS = 's' CHAR_Q_TEXT = '?' BOX_PREFIX = 'box:' +TOK_SORT_BOX = 'box' +TOK_SORT_ID = 'id' +TOK_SORT_STUDS = 'studs' -BrickListing = tuple[int, str, str] +BrickListing = tuple[int, str, str] # count, ID, comment PageColumn = tuple[BrickListing, ...] Page = tuple[PageColumn, ...] @@ -141,6 +144,41 @@ class Lookupable: assert query_char in self.matchers, query_char return self.matchers[query_char](query_body) + @classmethod + def _by_box_sorter( + cls, + to_id_of='' + ) -> Callable[['BricksDb', tuple[Self, ...]], tuple[Self, ...]]: + def by_box( + db: 'BricksDb', + pre_sorted: tuple[Self, ...] + ) -> tuple[Self, ...]: + remains = list(pre_sorted) + items: list[Self] = [] + for box in sorted(db.boxes().values(), + key=lambda box: box.id_indented()): + for item_id in [t[1] for t in box.brick_listings_flat()]: + if to_id_of: + item_id = getattr(db.bricks[item_id], f'{to_id_of}_id') + if item_id not in [item.id_ for item in items]: + to_move = [item for item in remains + if item.id_ == item_id][0] + items += [to_move] + remains.remove(to_move) + return tuple(items + remains) + return by_box + + @property + def sorters( + self + ) -> dict[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())) + } + class BrickColor(Textfiled, Lookupable): 'Color incl. solidness/transparency field.' @@ -170,6 +208,13 @@ class BrickColor(Textfiled, Lookupable): collected[id_] = cls(id_, desc[0] == CHAR_COL_SOLID, desc[1:]) return collected + @property + def sorters( + self + ) -> dict[str, Callable[['BricksDb', tuple[Self, ...]], + tuple[Self, ...]]]: + return super().sorters | {TOK_SORT_BOX: self._by_box_sorter('color')} + def raw( self ) -> str: @@ -221,11 +266,24 @@ class BrickDesign(Textfiled, Lookupable): def matchers( self ) -> dict[str, Callable[[str], bool]]: - def q_studs(q_body) -> bool: + def q_studs( + q_body + ) -> bool: assert q_body.isdigit() return self.n_studs == int(q_body) return super().matchers | {CHAR_Q_STUDS: q_studs} + @property + def sorters( + self + ) -> dict[str, Callable[['BricksDb', tuple[Self, ...]], + tuple[Self, ...]]]: + return super().sorters | { + TOK_SORT_BOX: self._by_box_sorter('design'), + TOK_SORT_STUDS: lambda _, pre_sorted: tuple( + sorted(pre_sorted, key=lambda item: item.n_studs)) + } + @classmethod def from_textfile( cls, @@ -282,6 +340,13 @@ class Brick(Textfiled, WithDb, Lookupable): self.comment = comment super().__init__(**kwargs) + @property + def sorters( + self + ) -> dict[str, Callable[['BricksDb', tuple[Self, ...]], + tuple[Self, ...]]]: + return super().sorters | {TOK_SORT_BOX: self._by_box_sorter()} + @classmethod def from_textfile( cls, @@ -486,7 +551,7 @@ class Box(WithDb, Lookupable): self.id_ = id_ self._set = bricks_set designed_listings: list[tuple[BrickDesign, list[BrickListing]]] = [] - for listing in self._set.brick_listings_flat(): + for listing in self.brick_listings_flat(): design = self._db.designs[self._db.bricks[listing[1]].design_id] design = design.alternate_to or design if not (designed_listings and designed_listings[-1][0] == design): @@ -503,6 +568,12 @@ class Box(WithDb, Lookupable): + ', '.join('/'.join(design.all_ids) for design, _ in self.designs_to_listings)) + def brick_listings_flat( + self + ) -> tuple[BrickListing, ...]: + 'Shortcut to BrickSet method of same name.' + return self._set.brick_listings_flat() + def show( self, ) -> str: @@ -598,7 +669,8 @@ class BricksDb: table_name: str, item_id: str, show_raw: bool, - filter_by: str + filter_by: str, + sort_by: str ) -> str: 'Return result of inquiry on table of table_name.' assert table_name in self.lookupable @@ -606,12 +678,16 @@ class BricksDb: table = maybe_dict if isinstance(maybe_dict, dict) else maybe_dict() if item_id: filter_by = CHAR_Q_ID + item_id - items = sorted(table.values(), key=lambda x: x.id_indented()) + items = tuple(table.values()) + if items and sort_by: + items = items[0].sorters[sort_by](self, items) if filter_by: - items = [item for item in items - if item.match(filter_by[0], filter_by[1:])] - return CHAR_NEWLINE.join([(item.raw() if show_raw else str(item)) - for item in items]) + items = tuple(item for item in items + if item.match(filter_by[0], filter_by[1:])) + return CHAR_NEWLINE.join( + [(item.raw() if isinstance(item, Textfiled) and show_raw + else str(item)) + for item in items]) def main( @@ -639,13 +715,15 @@ def main( parser.add_argument('item_id', nargs='?', metavar='ITEM_ID') parser.add_argument('-r', '--raw', action='store_true') parser.add_argument('-f', '--filter-by', action='store') + parser.add_argument('-s', '--sort-by', action='store', default=TOK_SORT_ID) args = parser.parse_args() print( db.lookup( table_name=args.table, item_id=args.item_id, show_raw=args.raw, - filter_by=args.filter_by + filter_by=args.filter_by, + sort_by=args.sort_by ).rstrip())