# standard libs
from abc import ABC, abstractmethod
-from dataclasses import dataclass, field as dc_field
+from dataclasses import dataclass, field as dc_field, fields as dc_fields
from pathlib import Path
from typing import Any, Callable, Optional, Self
# ourselves
LDRAW_MODE_VERIFY_N_STUDS,
LDRAW_MODE_VERIFY_PATHS}
-ATTR_DESCS: dict[str, str] = {
- 'n_studs': 'number of studs',
- 'description': 'guesstimate what this be',
- 'ldraw': 'path of associated LDRAW file',
- 'x': 'size over x-axis',
- 'y': 'size over y-axis',
- 'z': 'size over z-axis',
-}
-
BrickListing = tuple[int, str, str] # count, ID, comment
PageColumn = tuple[BrickListing, ...]
Page = tuple[PageColumn, ...]
@dataclass
class BrickDesignData:
'Lookupables for BrickDesign besides .id.'
- n_studs: int = NUMBER_UNSET
- description: str = '?'
- ldraw: str = ''
- x: float = NUMBER_UNSET
- y: float = NUMBER_UNSET
- z: float = NUMBER_UNSET
+ n_studs: int = dc_field(default=NUMBER_UNSET, metadata={
+ 'usage': 'number of studs'})
+ description: str = dc_field(default='?', metadata={
+ 'usage': 'guesstimate what this be'})
+ ldraw: str = dc_field(default='', metadata={
+ 'usage': 'path of associated LDRAW file'})
+ x: float = dc_field(default=NUMBER_UNSET, metadata={
+ 'usage': 'size over x-axis'})
+ y: float = dc_field(default=NUMBER_UNSET, metadata={
+ 'usage': 'size over y-axis'})
+ z: float = dc_field(default=NUMBER_UNSET, metadata={
+ 'usage': 'size over z-axis'})
_secured: set = dc_field(default_factory=set)
+ @classmethod
+ def usage(
+ cls,
+ field_name: str
+ ) -> str:
+ 'Return "usage" Field metadata if set for field_name.'
+ usages = {f.name: f.metadata['usage'] for f in dc_fields(cls)
+ if 'usage' in f.metadata}
+ assert field_name in usages
+ return usages[field_name]
+
@classmethod
def sortables(
cls
) -> bool:
assert q_body.isdigit()
return getattr(item, attr_name) == int(q_body)
- return 'by ' + ATTR_DESCS[attr_name], match
+ return 'by ' + BrickDesignData.usage(attr_name), match
return super().matchers() | {
f'{attr_name}{CHAR_ATTR_EQ}': attr_matcher(attr_name)
for attr_name, attr_type in BrickDesignData.sortables().items()
) -> tuple[Self, ...]:
return tuple(sorted(pre_sorted,
key=lambda item: getattr(item, attr_name)))
- return 'by ' + ATTR_DESCS[attr_name], f_sort
+ return 'by ' + BrickDesignData.usage(attr_name), f_sort
return super().sorters()\
| {TOK_SORT_BOX: cls._by_box_sorter('design')}\
| {attr_name: attr_sorter(attr_name)