ty: detect unresolved references

This commit is contained in:
Andrej730
2026-07-18 20:35:10 +05:00
parent f744753726
commit b35f99e63f
99 changed files with 401 additions and 84 deletions
@@ -159,8 +159,10 @@ def _add_segment_to_curve(
else:
assert False
end_point = ...
for mapped_segment in mapped_segments:
if mapped_segment:
end_point = _add_curve_segment_to_composite_curve(file, layout_segment, mapped_segment, curve)
assert end_point is not ...
return end_point
@@ -308,5 +308,7 @@ def _get_segment_start_point_label(prev_segment: entity_instance, segment: entit
label = _cant_callback(prev_segment, segment)
else:
label = _cant_label(prev_segment, segment)
else:
assert False, s.DesignParameters
return label
@@ -46,6 +46,7 @@ def _create_layout(file: ifcopenshell.file, alignment: entity_instance, points:
ifcopenshell.api.nest.assign_object(file, related_objects=alignment_layouts, relating_object=alignment)
start_dist_along = 0.0
gradient = None
for p1, p2 in zip(points, points[1:]):
x1, y1, z1 = p1.Coordinates
x2, y2, z2 = p2.Coordinates
@@ -100,6 +101,7 @@ def _create_layout(file: ifcopenshell.file, alignment: entity_instance, points:
ifcopenshell.api.nest.assign_object(file, related_objects=[hsegment], relating_object=alignment_layouts[0])
if include_vertical:
assert gradient is not None
vsegment = file.createIfcAlignmentSegment(
ifcopenshell.guid.new(),
DesignParameters=file.createIfcAlignmentVerticalSegment(
@@ -57,6 +57,7 @@ def create_from_csv(file: ifcopenshell.file, filepath: str) -> entity_instance:
:param filepath: path the to CSV file
:return: IfcAlignment
"""
alignment = None
with open(filepath, newline="") as csvfile:
reader = csv.reader(csvfile)
row_count = 0
@@ -89,9 +90,14 @@ def create_from_csv(file: ifcopenshell.file, filepath: str) -> entity_instance:
)
else:
# add all subsequent vertical alignments
assert alignment is not None
vertical_layout = ifcopenshell.api.alignment.add_vertical_layout(file, alignment)
ifcopenshell.api.alignment.layout_vertical_alignment_by_pi_method(
file, vertical_layout, coordinates, radii
)
if row_count == 0:
raise ValueError(f"CSV file '{filepath}' is empty; expected at least one row for the horizontal alignment.")
assert alignment is not None
return alignment
@@ -182,6 +182,8 @@ class Usecase:
if not reference:
migrator = ifcopenshell.util.schema.Migrator()
old_referenced_source = ...
existing_classification = None
if self.settings["is_lightweight"]:
old_referenced_source = self.settings["reference"].ReferencedSource
self.settings["reference"].ReferencedSource = None
@@ -194,6 +196,7 @@ class Usecase:
reference = migrator.migrate(self.settings["reference"], self.file)
if self.settings["is_lightweight"]:
assert old_referenced_source is not ...
reference.ReferencedSource = self.settings["classification"]
self.settings["reference"].ReferencedSource = old_referenced_source
elif existing_classification:
@@ -88,6 +88,8 @@ def bearing2dd(bearing: str) -> float:
elif cY == "S" and cX == "W":
angle = 270.0
sign = -1.0
else:
assert False, (cY, cX)
try:
dms = ifcopenshell.util.geolocation.dms2dd(d, m, s, ms)
@@ -116,6 +116,8 @@ def add_feature(
return ifcopenshell.api.aggregate.assign_object(file, [feature], element)
rels = feature.AdheresToElement
ifc_class = "IfcRelAdheresToElement"
else:
assert False, feature
if rels:
if rels[0][4] == element:
@@ -54,6 +54,8 @@ def remove_feature(file: ifcopenshell.file, feature: ifcopenshell.entity_instanc
rels = []
else:
rels = feature.ProjectsElements
else:
assert False, feature
for rel in rels:
history = rel.OwnerHistory
file.remove(rel)
@@ -436,6 +436,7 @@ class Usecase:
def create_curve_bounded_planes(self, is_2d: bool = False) -> list[ifcopenshell.entity_instance]:
items = []
points = None
if self.file.schema != "IFC2X3":
points = self.create_cartesian_point_list_from_vertices(self.settings["geometry"].vertices, is_2d=False)
for polygon in self.settings["geometry"].polygons:
@@ -443,6 +444,7 @@ class Usecase:
if self.file.schema == "IFC2X3":
curve = self.create_curve_from_polygon_ifc2x3(polygon, is_2d=False)
else:
assert points is not None
curve = self.create_curve_from_polygon(points, polygon, is_2d=False)
items.append(self.file.createIfcCurveBoundedPlane(BasisSurface=plane, OuterBoundary=curve))
return items
@@ -457,12 +459,14 @@ class Usecase:
def create_annotation_fill_areas(self, is_2d: bool = False) -> list[ifcopenshell.entity_instance]:
items = []
points = None
if self.file.schema != "IFC2X3":
points = self.create_cartesian_point_list_from_vertices(self.settings["geometry"].vertices, is_2d=is_2d)
for polygon in self.settings["geometry"].polygons:
if self.file.schema == "IFC2X3":
curve = self.create_curve_from_polygon_ifc2x3(polygon, is_2d=is_2d)
else:
assert points is not None
curve = self.create_curve_from_polygon(points, polygon, is_2d=is_2d)
items.append(self.file.createIfcAnnotationFillArea(OuterBoundary=curve))
return items
@@ -813,17 +817,20 @@ class Usecase:
def create_triangulated_face_set(self) -> ifcopenshell.entity_instance:
ifc_raw_items = [None] * self.settings["total_items"]
ifc_raw_uv_items = None
if self.settings["should_generate_uvs"]:
ifc_raw_uv_items = [None] * self.settings["total_items"]
for i, value in enumerate(ifc_raw_items):
ifc_raw_items[i] = []
if self.settings["should_generate_uvs"]:
assert ifc_raw_uv_items is not None
ifc_raw_uv_items[i] = []
for polygon in self.settings["geometry"].polygons:
ifc_raw_items[polygon.material_index % self.settings["total_items"]].append(
[v + 1 for v in polygon.vertices]
)
if self.settings["should_generate_uvs"]:
assert ifc_raw_uv_items is not None
ifc_raw_uv_items[polygon.material_index % self.settings["total_items"]].append(
[uv + 1 for uv in polygon.loop_indices]
)
@@ -831,6 +838,7 @@ class Usecase:
coordinates = self.create_cartesian_point_list_from_vertices(self.settings["geometry"].vertices)
if self.settings["should_generate_uvs"]:
assert ifc_raw_uv_items is not None
# Blender supports multiple UV layers. We don't. Too bad.
tex_coords = self.file.createIfcTextureVertexList(
[tuple(x.uv) for x in self.settings["geometry"].uv_layers[0].data]
@@ -50,6 +50,12 @@ def disconnect_path(
for r in relating_element.ConnectedTo
if r.is_a("IfcRelConnectsPathElements") and r.RelatedElement == related_element
]
else:
raise ValueError(
"Either provide `element` and `connection_type`, or provide `relating_element` and `related_element`. "
f"Got: element={element}, connection_type={connection_type}, "
f"relating_element={relating_element}, related_element={related_element}."
)
for connection in set(connections):
history = connection.OwnerHistory
@@ -52,6 +52,7 @@ def edit_true_north(file: ifcopenshell.file, true_north: Optional[Union[tuple[fl
# This unsets true north
ifcopenshell.api.georeference.edit_true_north(model, true_north=None)
"""
x, y = None, None
if isinstance(true_north, (float, int)):
x, y = ifcopenshell.util.geolocation.angle2yaxis(true_north)
elif true_north is not None:
@@ -73,4 +74,5 @@ def edit_true_north(file: ifcopenshell.file, true_north: Optional[Union[tuple[fl
context.TrueNorth = file.create_entity("IfcDirection")
else:
context.TrueNorth = file.create_entity("IfcDirection")
assert x is not None and y is not None
context.TrueNorth.DirectionRatios = (x, y)
@@ -90,6 +90,8 @@ def edit_wcs(
point,
file.createIfcDirection((xaxis_x, xaxis_y)),
)
else:
assert False, context
context.WorldCoordinateSystem = placement
if file.get_total_inverses(old_wcs) == 0:
ifcopenshell.util.element.remove_deep2(file, old_wcs)
@@ -61,6 +61,8 @@ def add_structural_boundary_condition(
boundary_class = "IfcBoundaryEdgeCondition"
elif related_connection.is_a("IfcStructuralSurfaceConnection"):
boundary_class = "IfcBoundaryFaceCondition"
else:
assert False, related_connection
condition = file.create_entity(boundary_class, Name=name)
connection.AppliedCondition = condition
@@ -126,6 +126,7 @@ class Usecase:
use_style_assignment = self.file.schema == "IFC2X3" or self.settings["should_use_presentation_style_assignment"]
replace_previous_same_type_style = self.settings["replace_previous_same_type_style"]
style: ifcopenshell.entity_instance | None = None
for element in self.file.traverse(self.settings["shape_representation"]):
if not element.is_a("IfcShapeModel"):
continue
@@ -137,6 +138,7 @@ class Usecase:
if self.settings["styles"]:
# If there are more items than styles, fallback to using the last style
style = self.settings["styles"].pop(0)
assert style is not None
name = style.Name
current_style_type = style.is_a()
@@ -51,7 +51,8 @@ def assign_system(
# This duct is part of the system
ifcopenshell.api.system.assign_system(model, products=[duct], system=system)
"""
if not all(ifcopenshell.util.system.is_assignable(failed_product := product, system) for product in products):
raise TypeError(f"You cannot assign an {failed_product.is_a()} to an {system.is_a()}")
for product in products:
if not ifcopenshell.util.system.is_assignable(product, system):
raise TypeError(f"You cannot assign an {product.is_a()} to an {system.is_a()}")
return ifcopenshell.api.group.assign_group(file, products=products, group=system)
@@ -144,6 +144,8 @@ class Usecase:
elif unit_type == "volume":
dimensional_exponents = self.file.createIfcDimensionalExponents(3, 0, 0, 0, 0, 0, 0)
name_prefix = "cubic"
else:
assert False, unit_type
si_unit = self.file.createIfcSIUnit(
None,
@@ -159,6 +161,8 @@ class Usecase:
name = "{}mile".format(name_prefix + " " if name_prefix else "")
elif data["raw"] == "THOU":
name = "{}thou".format(name_prefix + " " if name_prefix else "")
else:
assert False, data
value_component = self.file.create_entity(
"IfcReal", **{"wrappedValue": ifcopenshell.util.unit.si_conversions[name]}
)