home · contact · privacy
Restructure BrickDesign attributes parsing.
authorPlom Heller <plom@plomlompom.com>
Mon, 10 Aug 2026 19:12:20 +0000 (21:12 +0200)
committerPlom Heller <plom@plomlompom.com>
Mon, 10 Aug 2026 19:12:20 +0000 (21:12 +0200)
src/bricksplom/misc.py

index 39e22e91627e8141e81c9614cc86c668bc8a5936..ad06b03a3ee6d192bca48832542d5abf2007970f 100644 (file)
@@ -14,8 +14,7 @@ CHAR_COMMENT = '#'
 CHAR_DESIGN_ALT = '='
 CHAR_ATTR_EQ = '='
 CHAR_TEXTCONTAINS = ':'
-SEP_DESIGN_DESC = ' #'
-SEP_DESIGN_ATTR = '|'
+SEP_DESIGN_DESC = '#'
 CHAR_COLL_INDENT = ' '
 CHAR_SEP_LDRAW_MODES = ','
 CHAR_COLL_IN = '+'
@@ -293,6 +292,31 @@ class BrickDesignData:
         'Is knowledge of attribute certain (to owerpower ldraw guesses)?'
         return attr_key in self._secured
 
+    @classmethod
+    def from_text(
+            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)
+        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)
+            assert a_key in attributables
+            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:
+                assert a_val_str.isdigit(), a_val_str
+                setattr(attrs, a_key, int(a_val_str))
+            else:
+                setattr(attrs, a_key, a_val_str)
+        return attrs
+
 
 class BrickDesign(Textfiled, WithDb, Lookupable):
     'Shape and texture configurations with descriptions and equalities.'
@@ -432,23 +456,8 @@ class BrickDesign(Textfiled, WithDb, Lookupable):
                 alts[alt_id].add(design_id)
                 collected[design_id] = cls(design_id, db=db)
             else:
-                assert SEP_DESIGN_DESC in body
-                metadata, desc = body.split(SEP_DESIGN_DESC, maxsplit=1)
-                attrs = BrickDesignData(description=desc)
-                annos = BrickDesignData.__annotations__
-                for attr in metadata.split(SEP_DESIGN_ATTR):
-                    assert CHAR_ATTR_EQ in attr
-                    a_key, a_val_str = attr.split(CHAR_ATTR_EQ, maxsplit=1)
-                    if a_val_str[:1] == CHAR_ATTR_EQ:
-                        a_val_str = a_val_str[1:]
-                        attrs.secure((a_key))
-                    assert a_key in annos
-                    if annos[a_key] is int:
-                        assert a_val_str.isdigit(), a_val_str
-                        setattr(attrs, a_key, int(a_val_str))
-                    else:
-                        setattr(attrs, a_key, a_val_str)
-                collected[design_id] = cls(design_id, attrs, db=db)
+                collected[design_id] = cls(
+                    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: