from bricksplom.constants import CHAR_NEWLINE, NUMBER_UNSET
from bricksplom.ldraw import LdrawDb, LdrawPathFailure, LdrawRefsTree, XYZ
-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 = ' '
+_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 = ' '
CHAR_SEP_LDRAW_MODES = ','
-CHAR_COLL_IN = '+'
-CHAR_COLL_OUT = '-'
-CHAR_COLL_INACTIVE = '#'
-CHAR_COLL_SEP_COLUMN = '-'
-CHAR_COLL_SEP_PAGE = '='
-CHAR_COL_SOLID = '+'
-CHAR_COL_TRANSPARENT = '-'
-BOX_PREFIX = 'box:'
+_CHAR_COLL_IN = '+'
+_CHAR_COLL_OUT = '-'
+_CHAR_COLL_INACTIVE = '#'
+_CHAR_COLL_SEP_COLUMN = '-'
+_CHAR_COLL_SEP_PAGE = '='
+_CHAR_COL_SOLID = '+'
+_CHAR_COL_TRANSPARENT = '-'
+_BOX_PREFIX = 'box:'
ARG_QMARK = '?'
-PARAM_Q_ID = f'id{CHAR_ATTR_EQ}'
-MATCH_OPERATORS = {
- CHAR_ATTR_EQ,
- CHAR_TEXTCONTAINS,
- CHAR_ATTR_LESS,
- CHAR_ATTR_MORE
+PARAM_Q_ID = f'id{_CHAR_ATTR_EQ}'
+_MATCH_OPERATORS = {
+ _CHAR_ATTR_EQ,
+ _CHAR_TEXTCONTAINS,
+ _CHAR_ATTR_LESS,
+ _CHAR_ATTR_MORE
}
-TOK_SORT_BOX = 'box'
-TOK_SORT_ID = 'id'
-
-LDRAW_MODE_FILL_N_STUDS = 'fill_n_studs'
-LDRAW_MODE_FILL_PATHS = 'fill_paths'
-LDRAW_MODE_FILL_SIZES = 'fill_sizes'
-LDRAW_MODE_VERIFY_N_STUDS = 'verify_n_studs'
-LDRAW_MODE_VERIFY_PATHS = 'verify_paths'
-LDRAW_MODES = {LDRAW_MODE_FILL_N_STUDS,
- LDRAW_MODE_FILL_PATHS,
- LDRAW_MODE_FILL_SIZES,
- LDRAW_MODE_VERIFY_N_STUDS,
- LDRAW_MODE_VERIFY_PATHS}
-
-BrickListing = tuple[int, str, str] # count, ID, comment
-PageColumn = tuple[BrickListing, ...]
-Page = tuple[PageColumn, ...]
-
-
-class Textfiled(ABC):
+_TOK_SORT_BOX = 'box'
+_TOK_SORT_ID = 'id'
+
+_LDRAW_MODE_FILL_N_STUDS = 'fill_n_studs'
+_LDRAW_MODE_FILL_PATHS = 'fill_paths'
+_LDRAW_MODE_FILL_SIZES = 'fill_sizes'
+_LDRAW_MODE_VERIFY_N_STUDS = 'verify_n_studs'
+_LDRAW_MODE_VERIFY_PATHS = 'verify_paths'
+LDRAW_MODES = {_LDRAW_MODE_FILL_N_STUDS,
+ _LDRAW_MODE_FILL_PATHS,
+ _LDRAW_MODE_FILL_SIZES,
+ _LDRAW_MODE_VERIFY_N_STUDS,
+ _LDRAW_MODE_VERIFY_PATHS}
+
+_BrickListing = tuple[int, str, str] # count, ID, comment
+_PageColumn = tuple[_BrickListing, ...]
+_Page = tuple[_PageColumn, ...]
+
+
+class _Textfiled(ABC):
'Table to be read from textfile, and compatible output in .raw().'
@staticmethod
return tuple(line.rstrip()
for line in joined_path.read_text(encoding='utf8'
).split(CHAR_NEWLINE)
- if line.strip() and not line.startswith(CHAR_COMMENT))
+ if line.strip() and not line.startswith(_CHAR_COMMENT))
@staticmethod
def tokify(
if len(collected) == len_expected - 1:
tok = body
else:
- assert CHAR_SEP_TOKEN in body, body
- tok, body = body.split(CHAR_SEP_TOKEN, maxsplit=1)
+ assert _CHAR_SEP_TOKEN in body, body
+ tok, body = body.split(_CHAR_SEP_TOKEN, maxsplit=1)
collected += [tok]
return tuple(collected)
return self.raw()
-class WithDb:
+class _WithDb:
'Add db:Optional[BricksDB] field to __init__, setting .db.'
def __init__(
super().__init__(**kwargs)
-class Lookupable:
+class _Lookupable:
'Provides methods for BricksDb.lookup and .id_ padding.'
_id_indent: int = 0
id_: str
'most commonly relevant infos',
lambda item: item.show())
}
- if issubclass(cls, Textfiled):
+ if issubclass(cls, _Textfiled):
formatters['raw'] = (
'in source-file format',
lambda item: item.raw())
) -> dict[str, tuple[str, dict[str, Callable[[Self, str], bool]]]]:
'Available lookup matchers.'
return {
- TOK_SORT_ID: (
+ _TOK_SORT_ID: (
'ID of individual item',
- {CHAR_ATTR_EQ: (
+ {_CHAR_ATTR_EQ: (
lambda item, val: item.id_ == val)}
),
'text': (
'text contained in item description',
- {CHAR_TEXTCONTAINS: (
+ {_CHAR_TEXTCONTAINS: (
lambda item, val: val.upper() in item.show().upper())}
),
}
tuple[Self, ...]]]]:
'Available sorters.'
return {
- TOK_SORT_ID: (
+ _TOK_SORT_ID: (
'by individual items\' IDs',
lambda _, pre_sorted:
tuple(sorted(pre_sorted,
}
-class BrickColor(Textfiled, Lookupable, WithDb):
+class _BrickColor(_Textfiled, _Lookupable, _WithDb):
'Color incl. solidness/transparency field.'
_id_indent = 3
for id_, desc in [cls.tokify(line, 2) for line in cls.lines_of(path)]:
assert id_ not in collected
assert len(desc) > 1
- assert desc[0] in {CHAR_COL_SOLID, CHAR_COL_TRANSPARENT}
- collected[id_] = cls(id_, desc[0] == CHAR_COL_SOLID, desc[1:],
+ assert desc[0] in {_CHAR_COL_SOLID, _CHAR_COL_TRANSPARENT}
+ collected[id_] = cls(id_, desc[0] == _CHAR_COL_SOLID, desc[1:],
db=db)
return collected
) -> dict[str, tuple[str,
Callable[['BricksDb', tuple[Self, ...]],
tuple[Self, ...]]]]:
- return super().sorters() | {TOK_SORT_BOX: cls._by_box_sorter('color')}
+ return super().sorters() | {_TOK_SORT_BOX: cls._by_box_sorter('color')}
def show(
self
) -> str:
def idx_in_sample_set(
- pages: tuple[Page, ...]
+ pages: tuple[_Page, ...]
) -> str:
for idx, page in enumerate(pages):
for jdx, column in enumerate(page):
self
) -> str:
return (f'{self.id_indented()} '
- + (CHAR_COL_SOLID if self.solid else CHAR_COL_TRANSPARENT)
+ + (_CHAR_COL_SOLID if self.solid else _CHAR_COL_TRANSPARENT)
+ self.wavelength)
@dataclass
-class BrickDesignData:
- 'Lookupables for BrickDesign besides .id.'
+class _BrickDesignData:
+ 'Lookupables for _BrickDesign besides .id.'
n_studs: int = dc_field(default=NUMBER_UNSET, metadata={
'usage': 'number of studs'})
description: str = dc_field(default='?', metadata={
cls,
text: str
) -> Self:
- 'Parse from format expected by BrickDesign.from_textfile.'
- assert SEP_DESIGN_DESC in text
- parts = text.split(SEP_DESIGN_DESC, maxsplit=1)
+ 'Parse from format expected by _BrickDesign.from_textfile.'
+ assert _SEP_DESIGN_DESC in text
+ parts = text.split(_SEP_DESIGN_DESC, maxsplit=1)
attributables = cls.sortables()
attrs = cls(description=parts[-1])
metadata = parts[0].rstrip() if len(parts) > 1 else ''
- for attr in [a for a in metadata.split(CHAR_SEP_TOKEN) if a]:
- assert CHAR_ATTR_EQ in attr, attr
- a_key, a_val_str = attr.split(CHAR_ATTR_EQ, maxsplit=1)
+ for attr in [a for a in metadata.split(_CHAR_SEP_TOKEN) if a]:
+ assert _CHAR_ATTR_EQ in attr, attr
+ a_key, a_val_str = attr.split(_CHAR_ATTR_EQ, maxsplit=1)
assert a_key in attributables
- if a_val_str[:1] == CHAR_ATTR_EQ:
+ if a_val_str[:1] == _CHAR_ATTR_EQ:
a_val_str = a_val_str[1:]
attrs.secure((a_key))
if attributables[a_key] is int:
return attrs
-class BrickDesign(Textfiled, WithDb, Lookupable):
+class _BrickDesign(_Textfiled, _WithDb, _Lookupable):
'Shape and texture configurations with descriptions and equalities.'
_id_indent = 6
alternate_to: Optional[Self] = None
def __init__(
self,
id_: str,
- attrs: Optional[BrickDesignData] = None,
+ attrs: Optional[_BrickDesignData] = None,
**kwargs
) -> None:
self.id_ = id_
super().__init__(**kwargs)
def __getattribute__(self, key: str):
- if key in BrickDesignData.__annotations__ or key == 'secured':
+ if key in _BrickDesignData.__annotations__ or key == 'secured':
if self.direct_attrs:
attrs = self.direct_attrs
else:
self,
attr_name: str
) -> bool:
- 'Compare current attribute value to BrickDesignData default.'
- return getattr(self, attr_name) == getattr(BrickDesignData, attr_name)
+ 'Compare current attribute value to _BrickDesignData default.'
+ return getattr(self, attr_name) == getattr(_BrickDesignData, attr_name)
@classmethod
def formatters(
) -> float:
assert q_body.isdigit()
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 '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}': attr_matcher(attr_name)
- for attr_name, attr_type in BrickDesignData.sortables().items()
+ for attr_name, attr_type in _BrickDesignData.sortables().items()
if attr_type in {int, float}}
@classmethod
) -> tuple[Self, ...]:
return tuple(sorted(pre_sorted,
key=lambda item: getattr(item, attr_name)))
- return 'by ' + BrickDesignData.usage(attr_name), f_sort
+ return 'by ' + _BrickDesignData.usage(attr_name), f_sort
return super().sorters()\
- | {TOK_SORT_BOX: cls._by_box_sorter('design')}\
+ | {_TOK_SORT_BOX: cls._by_box_sorter('design')}\
| {attr_name: attr_sorter(attr_name)
- for attr_name in BrickDesignData.sortables().keys()}
+ for attr_name in _BrickDesignData.sortables().keys()}
@classmethod
def from_textfile(
for line in cls.lines_of(path)]:
assert design_id not in collected, design_id
assert len(body) > 1
- if body[0] == CHAR_DESIGN_ALT:
+ if body[0] == _CHAR_DESIGN_ALT:
alt_id = body[1:]
alts[alt_id] = alts.get(alt_id, set())
alts[alt_id].add(design_id)
collected[design_id] = cls(design_id, db=db)
else:
collected[design_id] = cls(
- design_id, db=db, attrs=BrickDesignData.from_text(body))
+ design_id, db=db, attrs=_BrickDesignData.from_text(body))
for id_, alternate_ids in alts.items():
collected[id_].alternate_ids = alternate_ids
for alt_id in alternate_ids:
) -> str:
raw = f'{self.id_indented()} '
if self.alternate_to:
- return f'{raw}{CHAR_DESIGN_ALT}{self.alternate_to.id_}'
+ return f'{raw}{_CHAR_DESIGN_ALT}{self.alternate_to.id_}'
attrs = []
- for attr_key in [k for k in BrickDesignData.sortables()
+ for attr_key in [k for k in _BrickDesignData.sortables()
if k != 'description' and not self.at_default(k)]:
- operator = CHAR_ATTR_EQ * (1 + int(self.secured(attr_key)))
+ operator = _CHAR_ATTR_EQ * (1 + int(self.secured(attr_key)))
attrs += [f'{attr_key}{operator}{getattr(self, attr_key)}']
- attrs += [f'{SEP_DESIGN_DESC}{self.description}']
- return f'{raw}{CHAR_SEP_TOKEN.join(attrs)}'
+ attrs += [f'{_SEP_DESIGN_DESC}{self.description}']
+ return f'{raw}{_CHAR_SEP_TOKEN.join(attrs)}'
-class Brick(Textfiled, WithDb, Lookupable):
+class _Brick(_Textfiled, _WithDb, _Lookupable):
'Individual configuration of design and color.'
_id_indent = 7
cls
) -> dict[str, tuple[str, Callable[['BricksDb', tuple[Self, ...]],
tuple[Self, ...]]]]:
- return super().sorters() | {TOK_SORT_BOX: cls._by_box_sorter()}
+ return super().sorters() | {_TOK_SORT_BOX: cls._by_box_sorter()}
@classmethod
def from_textfile(
for toks in [cls.tokify(line, 3) for line in cls.lines_of(path)]:
brick_id, design_id = toks[:2]
assert brick_id not in collected, brick_id
- color_id, comment = (toks[-1].split(CHAR_SEP_TOKEN, maxsplit=1)
+ color_id, comment = (toks[-1].split(_CHAR_SEP_TOKEN, maxsplit=1)
+ [''])[:2]
collected[brick_id] = cls(brick_id, design_id, color_id, comment,
db=db)
self
) -> str:
return (f'{self.id_indented()} '
- f'{BrickDesign.indent_id(self.design_id)} '
- f'{BrickColor.indent_id(self.color_id)} {self.comment}'
+ f'{_BrickDesign.indent_id(self.design_id)} '
+ f'{_BrickColor.indent_id(self.color_id)} {self.comment}'
).rstrip()
def __str__(
color = str(self.db.colors[self.color_id]).strip()
comment = f' # {self.comment}' if self.comment else ''
return (f'{self.id_indented()} '
- f'{BrickDesign.indent_id(self.design_id)} '
+ f'{_BrickDesign.indent_id(self.design_id)} '
f'{design.description} ({color}){comment}')
-class BrickSet(Textfiled, WithDb, Lookupable):
+class BrickSet(_Textfiled, _WithDb, _Lookupable):
'Named collection of bricks in order of pages of columns of counts.'
def __init__(
id_: str,
is_in: Optional[bool],
description: str,
- brick_listings: tuple[Page, ...],
+ brick_listings: tuple[_Page, ...],
**kwargs
) -> None:
self.id_ = id_
) -> dict[str, Self]:
collected: dict[str, tuple[Optional[bool],
str,
- list[list[list[BrickListing]]]]]
+ list[list[list[_BrickListing]]]]]
collected = {}
- i_listings: list[list[list[BrickListing]]] = [[[]]]
+ i_listings: list[list[list[_BrickListing]]] = [[[]]]
for line in cls.lines_of(path):
- if not line.startswith(CHAR_COLL_INDENT):
+ if not line.startswith(_CHAR_COLL_INDENT):
id_, metadata = cls.tokify(line, 2)
assert metadata
- assert metadata[0] in {CHAR_COLL_IN,
- CHAR_COLL_OUT,
- CHAR_COLL_INACTIVE}
- is_in = (None if metadata[0] == CHAR_COLL_INACTIVE
- else metadata[0] == CHAR_COLL_IN)
+ assert metadata[0] in {_CHAR_COLL_IN,
+ _CHAR_COLL_OUT,
+ _CHAR_COLL_INACTIVE}
+ is_in = (None if metadata[0] == _CHAR_COLL_INACTIVE
+ else metadata[0] == _CHAR_COLL_IN)
i_listings = [[[]]]
collected[id_] = is_in, metadata[1:], i_listings
- elif line[1:2] == CHAR_COLL_SEP_COLUMN:
+ elif line[1:2] == _CHAR_COLL_SEP_COLUMN:
i_listings[-1] += [[]]
- elif line[1:2] == CHAR_COLL_SEP_PAGE:
+ elif line[1:2] == _CHAR_COLL_SEP_PAGE:
i_listings += [[[]]]
else:
count, remainder = cls.tokify(line, 2)
assert count.isdigit()
- id_, comment = (remainder.split(CHAR_SEP_TOKEN, maxsplit=1)
+ id_, comment = (remainder.split(_CHAR_SEP_TOKEN, maxsplit=1)
+ [''])[:2]
assert len(id_) > 0
i_listings[-1][-1] += [(int(count), id_, comment)]
def _is_in_str(
self
) -> str:
- return (CHAR_COLL_INACTIVE if self.is_in is None
- else (CHAR_COLL_IN if self.is_in else CHAR_COLL_OUT))
+ return (_CHAR_COLL_INACTIVE if self.is_in is None
+ else (_CHAR_COLL_IN if self.is_in else _CHAR_COLL_OUT))
def raw(
self
return (f'{self.id_indented()} '
f'{self._is_in_str}{self.description}{CHAR_NEWLINE}'
+ self._format_paginated(lambda count, p_id, comment:
- f' {count:4} {Brick.indent_id(p_id)}'
+ f' {count:4} {_Brick.indent_id(p_id)}'
+ (f' {comment}' if comment else '')))
def __str__(
lines += [format_line(count, brick_id, comment)]
return CHAR_NEWLINE.join(lines) + CHAR_NEWLINE
- def brick_listings_flat(self) -> tuple[BrickListing, ...]:
+ def brick_listings_flat(self) -> tuple[_BrickListing, ...]:
'Flattened variant of .brick_listings, no division into pages/cols.'
- collected: list[BrickListing] = []
+ collected: list[_BrickListing] = []
for page in self.brick_listings:
for column in page:
collected += list(column)
design_id = brick.design_id
tail_comment = f' # {comment}' if comment else ''
color = str(self.db.colors[self.db.bricks[brick_id].color_id]
- ).lstrip().split(CHAR_SEP_TOKEN, maxsplit=1)[1]
+ ).lstrip().split(_CHAR_SEP_TOKEN, maxsplit=1)[1]
if to_boxes:
- box: Optional[Box] = None
+ box: Optional[_Box] = None
for i_box in self.db.boxes.values():
for idx_in_box in [
idx for idx, d_to_ls
if box:
break
box_listing = ((box.id_indented() if box
- else Box.indent_id(''))
+ else _Box.indent_id(''))
+ ':' + (f'{idx_in_box:>2}' if box else '__'))
else:
box_listing = ''
return (
- f'{count:>2}× {Brick.indent_id(brick_id)}:'
- f'{BrickDesign.indent_id(design_id)} {box_listing} {color} '
+ f'{count:>2}× {_Brick.indent_id(brick_id)}:'
+ f'{_BrickDesign.indent_id(design_id)} {box_listing} {color} '
+ self.db.designs[design_id].description + tail_comment)
return f'{self}{CHAR_NEWLINE}{self._format_paginated(format_line)}'
}
-class Box(WithDb, Lookupable):
+class _Box(_WithDb, _Lookupable):
'Order of designs.'
_id_indent = 5
super().__init__(**kwargs)
self.id_ = id_
self._set = bricks_set
- designed_listings: list[tuple[BrickDesign, list[BrickListing]]] = []
+ designed_listings: list[tuple[_BrickDesign, list[_BrickListing]]] = []
for listing in self.brick_listings_flat():
design = self.db.designs[self.db.bricks[listing[1]].design_id]
design = design.alternate_to or design
def brick_listings_flat(
self
- ) -> tuple[BrickListing, ...]:
+ ) -> tuple[_BrickListing, ...]:
'Shortcut to BrickSet method of same name.'
return self._set.brick_listings_flat()
f'=== {" / ".join(design.all_ids)}: {design.description} ===']
for count, brick_id, comment in listings:
color = self.db.colors[self.db.bricks[brick_id].color_id]
- lines += [f'{count:>2}× {Brick.indent_id(brick_id)} / {color} '
- f'# {comment}']
+ lines += [
+ f'{count:>2}× {_Brick.indent_id(brick_id)} / {color} '
+ f'# {comment}']
return CHAR_NEWLINE.join(lines)
class BricksDb:
'Collection of all the tables enabling their combined processing.'
- lookupables: dict[str, type[Lookupable]] = {
- 'boxes': Box,
- 'bricks': Brick,
- 'colors': BrickColor,
- 'designs': BrickDesign,
+ lookupables: dict[str, type[_Lookupable]] = {
+ 'boxes': _Box,
+ 'bricks': _Brick,
+ 'colors': _BrickColor,
+ 'designs': _BrickDesign,
'sets': BrickSet
}
- bricks: dict[str, Brick]
- colors: dict[str, BrickColor]
- designs: dict[str, BrickDesign]
+ bricks: dict[str, _Brick]
+ colors: dict[str, _BrickColor]
+ designs: dict[str, _BrickDesign]
sets: dict[str, BrickSet]
def __init__(
) -> None:
self._name_set_colors = name_set_colors
for name, cls in [(name, cls) for name, cls in self.lookupables.items()
- if issubclass(cls, Textfiled)]:
- kwargs = {'db': self} if issubclass(cls, WithDb) else {}
+ if issubclass(cls, _Textfiled)]:
+ kwargs = {'db': self} if issubclass(cls, _WithDb) else {}
setattr(self, name, cls.from_textfile((path_tables, f'{name}.txt'),
**kwargs))
self.ldraw = LdrawDb(Path(path_ldraw))
self._ldraw_modes = ldraw_modes.split(CHAR_SEP_LDRAW_MODES)
- if LDRAW_MODE_FILL_PATHS in self._ldraw_modes:
+ if _LDRAW_MODE_FILL_PATHS in self._ldraw_modes:
for design in [design for design in self.designs.values()
if not (design.alternate_to or design.ldraw)]:
filename = f'{design.id_}.dat'
design.direct_attrs.ldraw = filename
self._check_consistencies()
for design in self._designs_ldrawed():
- if LDRAW_MODE_FILL_N_STUDS in self._ldraw_modes\
+ if _LDRAW_MODE_FILL_N_STUDS in self._ldraw_modes\
and design.at_default('n_studs'):
assert design.direct_attrs is not None
design.direct_attrs.n_studs\
= self.ldraw.count_studs(design.ldraw)
- if LDRAW_MODE_FILL_SIZES in self._ldraw_modes:
+ if _LDRAW_MODE_FILL_SIZES in self._ldraw_modes:
xyz_calc = XYZ()
for k in [k for k in ('x', 'y', 'z') if design.at_default(k)]:
if set(xyz_calc) == {NUMBER_UNSET}:
@property
def boxes(
self
- ) -> dict[str, Box]:
- 'Parsed from BOX_PREFIX-prefixed entries in .sets.'
+ ) -> dict[str, _Box]:
+ 'Parsed from _BOX_PREFIX-prefixed entries in .sets.'
collected = {}
for bricks_set in [c for c in self.sets.values()
- if c.id_.startswith(BOX_PREFIX)]:
- box_id = bricks_set.id_[len(BOX_PREFIX):]
- collected[box_id] = Box(box_id, bricks_set, db=self)
+ if c.id_.startswith(_BOX_PREFIX)]:
+ box_id = bricks_set.id_[len(_BOX_PREFIX):]
+ collected[box_id] = _Box(box_id, bricks_set, db=self)
return collected
def _designs_ldrawed(
self
- ) -> tuple[BrickDesign, ...]:
+ ) -> tuple[_BrickDesign, ...]:
return tuple(design for design in self.designs.values()
if (not design.alternate_to)
and design.ldraw and design.ldraw != '!')
for design in self._designs_ldrawed():
# hunt for dangling Design.ldraw references
- if LDRAW_MODE_VERIFY_PATHS in self._ldraw_modes:
+ if _LDRAW_MODE_VERIFY_PATHS in self._ldraw_modes:
if not self.ldraw.path(design.ldraw).exists():
fails += ['unresolved ldraw reference for design of ID: '
f'{design.id_} ({design.ldraw})']
continue
# compare n_studs calculations to explicit records
- if LDRAW_MODE_VERIFY_N_STUDS in self._ldraw_modes\
+ if _LDRAW_MODE_VERIFY_N_STUDS in self._ldraw_modes\
and design.n_studs > -1\
and not design.secured('n_studs'):
studs_counted = self.ldraw.count_studs(design.ldraw)
for instruction in match_by:
match_key = match_val = match_operator = ''
for idx, c in enumerate(instruction):
- if c in MATCH_OPERATORS:
+ if c in _MATCH_OPERATORS:
match_operator = c
match_val = instruction[idx+1:]
break