ExtractPropertiesToSQLite - add typing for created columns

This commit is contained in:
Andrej730
2026-03-04 17:57:34 +05:00
parent adaf33b74f
commit ecc82a52f5
2 changed files with 65 additions and 30 deletions
@@ -2287,6 +2287,11 @@ class QueryLinkedElement(bpy.types.Operator):
region_2d_to_origin_3d,
region_2d_to_vector_3d,
)
from ifcpatch.recipes.ExtractPropertiesToSQLite import (
ElementRow,
PropertyRow,
RelationshipRow,
)
LinksData.linked_data = {}
props = tool.Project.get_project_props()
@@ -2352,7 +2357,7 @@ class QueryLinkedElement(bpy.types.Operator):
self.c = self.db.cursor()
self.c.execute(f"SELECT * FROM elements WHERE global_id = '{guid}' LIMIT 1")
element = self.c.fetchone()
element = ElementRow(*self.c.fetchone())
attributes: dict[str, Any] = {}
for i, attr in enumerate(["GlobalId", "IFC Class", "Predefined Type", "Name", "Description"]):
@@ -2360,14 +2365,14 @@ class QueryLinkedElement(bpy.types.Operator):
attributes[attr] = element[i + 1]
self.c.execute("SELECT * FROM properties WHERE element_id = ?", (element[0],))
rows = self.c.fetchall()
rows = [PropertyRow(*row) for row in self.c.fetchall()]
properties = {}
properties: defaultdict[str, dict[str, str]] = defaultdict(dict)
for row in rows:
properties.setdefault(row[1], {})[row[2]] = row[3]
properties[row.pset_name][row.name] = row.value
self.c.execute("SELECT * FROM relationships WHERE from_id = ?", (element[0],))
relationships = self.c.fetchall()
relationships = [RelationshipRow(*row) for row in self.c.fetchall()]
relating_type_id = None
@@ -2375,12 +2380,12 @@ class QueryLinkedElement(bpy.types.Operator):
if relationship[1] == "IfcRelDefinesByType":
relating_type_id = relationship[2]
type_properties = {}
type_properties: defaultdict[str, dict[str, str]] = defaultdict(dict)
if relating_type_id is not None:
self.c.execute("SELECT * FROM properties WHERE element_id = ?", (relating_type_id,))
rows = self.c.fetchall()
rows = [PropertyRow(*row) for row in self.c.fetchall()]
for row in rows:
type_properties.setdefault(row[1], {})[row[2]] = row[3]
type_properties[row.pset_name][row.name] = row.value
LinksData.linked_data = {
"attributes": attributes,
@@ -19,17 +19,40 @@
import logging
import tempfile
from typing import NamedTuple
import ifcopenshell.util.element
import ifcpatch
try:
import sqlite3
import sqlite3 # noqa: F401
except:
print("No SQLite support")
class ElementRow(NamedTuple):
element_id: int
guid: str
class_: str
predefined_type: str | None
name: str | None
description: str | None
class PropertyRow(NamedTuple):
element_id: int
pset_name: str
name: str
value: str
class RelationshipRow(NamedTuple):
element_id: int
rel_ifc_class: str
to_id: int
class Patcher(ifcpatch.BasePatcher):
def __init__(
self,
@@ -94,20 +117,21 @@ class Patcher(ifcpatch.BasePatcher):
elements = self.file.by_type("IfcObjectDefinition")
rows = []
properties = []
relationships = []
rows: list[ElementRow] = []
properties: list[PropertyRow] = []
relationships: list[RelationshipRow] = []
id_map = {e.id(): i for i, e in enumerate(elements)}
for i, element in enumerate(elements):
rows.append(
[
ElementRow(
i,
element[0], # IfcRoot.GlobalId
element.is_a(),
ifcopenshell.util.element.get_predefined_type(element),
element[2], # IfcRoot.Name
element[3], # IfcRoot.Description
]
)
)
psets = ifcopenshell.util.element.get_psets(element, should_inherit=False)
for pset_name, pset_data in psets.items():
@@ -118,49 +142,55 @@ class Patcher(ifcpatch.BasePatcher):
value = "True" if value else "False"
elif not isinstance(value, str):
value = str(value)
properties.append([i, pset_name, prop_name, value])
properties.append(PropertyRow(i, pset_name, prop_name, value))
material = ifcopenshell.util.element.get_material(element, should_skip_usage=True)
if material:
name = getattr(material, "Name", getattr(material, "LayerSetName", None)) or "Unnamed"
properties.append([i, "IFC Material", "Name", name])
properties.append([i, "IFC Material", "Class", material.is_a()])
properties.append(PropertyRow(i, "IFC Material", "Name", name))
properties.append(PropertyRow(i, "IFC Material", "Class", material.is_a()))
if material.is_a("IfcMaterial"):
materials = []
elif material.is_a("IfcMaterialLayerSet"):
for idx, item in enumerate(material.MaterialLayers or []):
material = item.Material
properties.append([i, "IFC Material", f"Layer {idx + 1} Name", getattr(item, "Name", None)])
properties.append([i, "IFC Material", f"Layer {idx + 1} Material", material.Name])
properties.append(
PropertyRow(i, "IFC Material", f"Layer {idx + 1} Name", getattr(item, "Name", None))
)
properties.append(PropertyRow(i, "IFC Material", f"Layer {idx + 1} Material", material.Name))
if category := getattr(material, "Category", None):
properties.append([i, "IFC Material", f"Layer {idx + 1} Category", category])
properties.append(PropertyRow(i, "IFC Material", f"Layer {idx + 1} Category", category))
elif material.is_a("IfcMaterialProfileSet"):
for idx, item in enumerate(material.MaterialProfiles or []):
material = item.Material
properties.append([i, "IFC Material", f"Profile {idx + 1} Name", item.Name])
properties.append([i, "IFC Material", f"Profile {idx + 1} Material", material.Name])
properties.append(PropertyRow(i, "IFC Material", f"Profile {idx + 1} Name", item.Name))
properties.append(PropertyRow(i, "IFC Material", f"Profile {idx + 1} Material", material.Name))
if category := getattr(material, "Category", None):
properties.append([i, "IFC Material", f"Profile {idx + 1} Category", category])
properties.append(PropertyRow(i, "IFC Material", f"Profile {idx + 1} Category", category))
elif material.is_a("IfcMaterialConstituentSet"):
for idx, item in enumerate(material.MaterialConstituents or []):
material = item.Material
properties.append([i, "IFC Material", f"Constituent {idx + 1} Name", item.Name])
properties.append([i, "IFC Material", f"Constituent {idx + 1} Material", material.Name])
properties.append(PropertyRow(i, "IFC Material", f"Constituent {idx + 1} Name", item.Name))
properties.append(
PropertyRow(i, "IFC Material", f"Constituent {idx + 1} Material", material.Name)
)
if category := getattr(material, "Category", None):
properties.append([i, "IFC Material", f"Constituent {idx + 1} Category", category])
properties.append(
PropertyRow(i, "IFC Material", f"Constituent {idx + 1} Category", category)
)
elif material.is_a("IfcMaterialList"):
for idx, material in enumerate(material.Materials):
properties.append([i, "IFC Material", f"Material {idx + 1} Name", material.Name])
properties.append(PropertyRow(i, "IFC Material", f"Material {idx + 1} Name", material.Name))
if category := getattr(material, "Category", None):
properties.append([i, "IFC Material", f"Material {idx + 1} Category", category])
properties.append(PropertyRow(i, "IFC Material", f"Material {idx + 1} Category", category))
layers = ifcopenshell.util.element.get_layers(self.file, element)
for idx, layer in enumerate(layers):
properties.append([i, "IFC Presentation Layer Assignment", f"Layer {idx + 1}", layer.Name])
properties.append(PropertyRow(i, "IFC Presentation Layer Assignment", f"Layer {idx + 1}", layer.Name))
relating_type = ifcopenshell.util.element.get_type(element)
if relating_type and relating_type != element:
relationships.append([i, "IfcRelDefinesByType", id_map[relating_type.id()]])
relationships.append(RelationshipRow(i, "IfcRelDefinesByType", id_map[relating_type.id()]))
self.c.executemany("INSERT INTO elements VALUES (?, ?, ?, ?, ?, ?);", rows)
self.c.executemany("INSERT INTO properties VALUES (?, ?, ?, ?);", properties)