home · contact · privacy
Wrap (some) LDraw code code in LdrawDb. master
authorPlom Heller <plom@plomlompom.com>
Mon, 3 Aug 2026 08:45:48 +0000 (10:45 +0200)
committerPlom Heller <plom@plomlompom.com>
Mon, 3 Aug 2026 08:45:48 +0000 (10:45 +0200)
src/bricksplom/ldraw.py
src/bricksplom/misc.py

index 7ada10d35e4ba5fcf9907cbc3c45011586cc3681..04572d998d89c87191c5a57e33870704d4b5e738 100644 (file)
@@ -18,36 +18,52 @@ LDRAW_STUDS = {
 }
 
 
-def ldraw_studs_count(
-        path_ldraw: Path,
-        filename: str
-        ) -> int:
-    'On item at {path_ldraw}/../p/{filename} count studs.'
-    path = path_ldraw.joinpath(filename)
-    if not path.exists():
-        path = path_ldraw.joinpath('..', 'p', filename)
+class LdrawDb:
+    'Connection to local LDRAW archive.'
+
+    def __init__(
+            self,
+            root: Path
+            ) -> None:
+        self._root = root
+
+    def path(
+            self,
+            filename
+            ) -> Path:
+        'Build {._root}/part/{filename}.'
+        return self._root.joinpath('parts', filename)
+
+    def count_studs(
+            self,
+            filename
+            ) -> int:
+        'On item at {._root}/p(art)/{filename} count studs.'
+        path = self.path(filename)
         if not path.exists():
-            raise Exception(f'invalid ldraw reference: {filename}')
-    studs_counted = 0
-    for line in path.read_text(encoding='utf8').split(CHAR_NEWLINE):
-        line = line.lstrip()
-        if not line.startswith('1'):
-            continue
-        toks = line.split(maxsplit=14)
-        target = toks[14].replace('\\', '/')
-        matrix = tuple(tuple(toks[n:n+3]) for n in (5, 8, 11))
-        do_ignore = False
-        for row in [[float(x) for x in row] for row in matrix]:
-            if do_ignore:
-                break
-            for idx in range(len(row)):  # pylint: disable=C0200
+            path = self._root.joinpath('p', filename)
+            if not path.exists():
+                raise Exception(f'invalid ldraw reference: {filename}')
+        studs_counted = 0
+        for line in path.read_text(encoding='utf8').split(CHAR_NEWLINE):
+            line = line.lstrip()
+            if not line.startswith('1'):
+                continue
+            toks = line.split(maxsplit=14)
+            target = toks[14].replace('\\', '/')
+            matrix = tuple(tuple(toks[n:n+3]) for n in (5, 8, 11))
+            do_ignore = False
+            for row in [[float(x) for x in row] for row in matrix]:
                 if do_ignore:
                     break
-                cell = row[idx]
-                if cell != 0 and [True for jdx in range(len(row))
-                                  if jdx != idx and row[jdx] != 0]:
-                    do_ignore = True
-                    break
-        studs_counted += (int((not do_ignore) and target in LDRAW_STUDS)
-                          or ldraw_studs_count(path_ldraw, target))
-    return studs_counted
+                for idx in range(len(row)):  # pylint: disable=C0200
+                    if do_ignore:
+                        break
+                    cell = row[idx]
+                    if cell != 0 and [True for jdx in range(len(row))
+                                      if jdx != idx and row[jdx] != 0]:
+                        do_ignore = True
+                        break
+            studs_counted += (int((not do_ignore) and target in LDRAW_STUDS)
+                              or self.count_studs(target))
+        return studs_counted
index f7cb6143c261d7b1d1c5ed6d5c1b4631871a6bce..76d8417a26a63227c7815ab86ebee8da5222f424 100644 (file)
@@ -7,7 +7,7 @@ from pathlib import Path
 from typing import Callable, Optional, Self
 # ourselves
 from bricksplom.constants import CHAR_NEWLINE
-from bricksplom.ldraw import ldraw_studs_count
+from bricksplom.ldraw import LdrawDb
 
 CHAR_SEP_TOKEN = ' '
 CHAR_COMMENT = '#'
@@ -681,13 +681,13 @@ class BricksDb:
             kwargs = {'db': self} if issubclass(cls, WithDb) else {}
             setattr(self, name, cls.from_textfile((path_tables, f'{name}.txt'),
                                                   **kwargs))
-        self._path_ldraw = Path(path_ldraw).joinpath('parts')
+        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:
             for design in [design for design in self.designs.values()
                            if not (design.alternate_to or design.ldraw)]:
                 filename = f'{design.id_}.dat'
-                if self._path_ldraw.joinpath(filename).exists():
+                if self._ldraw.path(filename).exists():
                     assert design.direct_attrs is not None
                     design.direct_attrs.ldraw = filename
         self._check_consistencies()
@@ -696,7 +696,7 @@ class BricksDb:
                            if d.n_studs != 1]:
                 assert design.direct_attrs is not None
                 design.direct_attrs.n_studs\
-                    = ldraw_studs_count(self._path_ldraw, design.ldraw)
+                    = self._ldraw.count_studs(design.ldraw)
 
     @property
     def boxes(
@@ -758,7 +758,7 @@ class BricksDb:
         for design in self._designs_ldrawed():
             # hunt for dangling Design.ldraw references
             if LDRAW_MODE_VERIFY_PATHS in self._ldraw_modes:
-                if not self._path_ldraw.joinpath(design.ldraw).exists():
+                if not self._ldraw.path(design.ldraw).exists():
                     fails += ['unresolved ldraw reference for design of ID: '
                               f'{design.id_} ({design.ldraw})']
                     continue
@@ -766,8 +766,7 @@ class BricksDb:
             if LDRAW_MODE_VERIFY_N_STUDS in self._ldraw_modes:
                 if design.n_studs <= -1:
                     continue
-                studs_counted = ldraw_studs_count(self._path_ldraw,
-                                                  design.ldraw)
+                studs_counted = self._ldraw.count_studs(design.ldraw)
                 if design.n_studs != studs_counted:
                     fails += ['n_studs count differs between record and ldraw '
                               f'calculation for design of ID: {design.id_} '