mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-12 18:43:26 +00:00
Fix all ty diagnostics on ifcviewer-wgpu (ci-lint ty-ios + ty-bonsai)
This branch carried v0.8.0's strict `[tool.ty.rules] all = "error"` config but not the source fixes that were made upstream to satisfy it, so both ci-lint ty gates were failing: `poe ty-ios` reported 256 diagnostics and `poe ty-bonsai` 258. Both are now clean. Most fixes are ported from v0.8.0 and follow two idioms: initialise a name before a conditional that may not bind it (plus an `assert` where the invariant is real but not provable), and close an exhaustive `if`/`elif` chain with `else: assert False, <discriminant>`. The branch's own newer accessors are preserved throughout - `.file`, `.declaration`, `file.types()`, `get_max_id()` are kept rather than reverted to `wrapped_data.*`, and non-ty upstream changes (notably the in-progress geometry cache removal) are deliberately not pulled in. Notable fixes that are not straight ports: * ifcopenshell_wrapper.pyi: `entity_instance.file` was declared as `def file(self) -> file`, where the property name shadows the `class file` below it, so the annotation resolved to `Unknown`. Every `element.file` in the codebase was therefore unchecked. Qualifying it to `ifcopenshell.file` restores `.schema` to its Literal union and surfaces no new diagnostics. * model/wall.py: a duplicated merge fragment in the void-straddle path ran an always-true `if void_straddles:` that read `new_opening` from the mutually exclusive branch (stale value, or NameError on the first iteration), followed by an unreachable duplicate `elif`. Removing it makes the file match v0.8.0. * light/operator.py: upstream's own fix unpacks three targets from two values and raises ValueError unconditionally; corrected to `None, None, None`. * assign_system.py, validate.py, geom/main.py: walrus-in-genexp is valid at runtime (PEP 572 binds in the containing scope) but ty does not model it; rewritten as explicit loops, matching upstream. Verified: poe ty-ios, poe ty-bonsai, ruff check src/ nix/, black --check ., and compileall -W error at py3.10 (ifcopenshell-python) and py3.11 (bonsai). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -112,6 +112,8 @@ def sum_child_root_elements(root_element: ifcopenshell.entity_instance, category
|
||||
values = new_child_root_element.CostValues
|
||||
elif root_element.is_a("IfcConstructionResource"):
|
||||
values = child_root_element.BaseCosts
|
||||
else:
|
||||
assert False, root_element
|
||||
for child_cost_value in values or []:
|
||||
if category_filter and child_cost_value.Category != category_filter:
|
||||
continue
|
||||
|
||||
@@ -331,6 +331,8 @@ def get_quantity(
|
||||
data["properties"] = get_quantities(quantity.HasQuantities, verbose=verbose)
|
||||
del data["HasQuantities"]
|
||||
result = data
|
||||
else:
|
||||
assert False, quantity
|
||||
if verbose:
|
||||
result = {"id": quantity.id(), "class": quantity.is_a(), "value": result}
|
||||
return result
|
||||
@@ -387,6 +389,7 @@ def get_property(
|
||||
if prop.Name != name:
|
||||
continue
|
||||
is_single_value = False # For now we pass value type only for single values.
|
||||
result_type = None
|
||||
if prop.is_a("IfcPropertySingleValue"):
|
||||
# 2 IfcPropertySingleValue.NominalValue
|
||||
result = v.wrappedValue if (v := prop[2]) else None
|
||||
@@ -409,6 +412,8 @@ def get_property(
|
||||
data["properties"] = get_properties(prop.HasProperties, verbose=verbose)
|
||||
del data["HasProperties"]
|
||||
result = data
|
||||
else:
|
||||
assert False, prop
|
||||
if verbose:
|
||||
result = {"id": prop.id(), "class": prop.is_a(), "value": result}
|
||||
if is_single_value:
|
||||
|
||||
@@ -260,6 +260,8 @@ def get_helmert_transformation_parameters(ifc_file: ifcopenshell.file) -> Option
|
||||
xaa = 1.0
|
||||
xao = 0.0
|
||||
scale = factor_x = factor_y = factor_z = 1
|
||||
else:
|
||||
assert False, conversion
|
||||
|
||||
if not xaa and not xao:
|
||||
xaa = 1.0
|
||||
|
||||
@@ -18,18 +18,16 @@
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
try:
|
||||
from lark import Lark, Transformer
|
||||
from lark.exceptions import UnexpectedCharacters, UnexpectedEOF, UnexpectedToken
|
||||
|
||||
LARK_AVAILABLE = True
|
||||
except ImportError:
|
||||
LARK_AVAILABLE = False
|
||||
|
||||
import importlib.util
|
||||
import re
|
||||
from typing import Union
|
||||
|
||||
LARK_AVAILABLE = importlib.util.find_spec("lark") is not None
|
||||
|
||||
if LARK_AVAILABLE:
|
||||
from lark import Lark, Transformer
|
||||
from lark.exceptions import UnexpectedCharacters, UnexpectedEOF, UnexpectedToken
|
||||
|
||||
mvd_grammar = r"""
|
||||
start: entry+
|
||||
|
||||
@@ -92,9 +90,9 @@ if LARK_AVAILABLE:
|
||||
self.store_text_attribute(args, "options")
|
||||
|
||||
def dynamic_option(self, args):
|
||||
original_keyword = str(args[0])
|
||||
key = original_keyword.lower()
|
||||
try:
|
||||
original_keyword = str(args[0])
|
||||
key = original_keyword.lower()
|
||||
raw_text = args[1].children[0].value
|
||||
parsed_value = parse_semicolon_separated_kv(raw_text)
|
||||
self._dynamic[key] = (parsed_value, original_keyword)
|
||||
|
||||
@@ -89,6 +89,9 @@ def get_axis2placement(placement: ifcopenshell.entity_instance) -> MatrixType:
|
||||
x = np.array((1, 0, 0))
|
||||
o = placement.Location.Coordinates
|
||||
|
||||
else:
|
||||
assert False, placement
|
||||
|
||||
return a2p(o, z, x)
|
||||
|
||||
|
||||
|
||||
@@ -569,6 +569,7 @@ class Migrator:
|
||||
# NOTE: `attribute` is an attribute in new file schema
|
||||
# print("Migrating attribute", element, new_element, attribute.name())
|
||||
old_file = element.file
|
||||
value = ...
|
||||
if hasattr(element, attribute.name()):
|
||||
value = getattr(element, attribute.name())
|
||||
# print("Attribute names matched", value)
|
||||
@@ -607,9 +608,7 @@ class Migrator:
|
||||
except: # We tried our best
|
||||
return
|
||||
|
||||
try:
|
||||
value
|
||||
except UnboundLocalError:
|
||||
if value is ...:
|
||||
print(
|
||||
f"Couldn't match attribute {attribute.name()} by name to migrate from {element} "
|
||||
f"to {new_element} and there is no special mapping to handle migration "
|
||||
|
||||
@@ -1290,6 +1290,8 @@ class FacetTransformer(lark.Transformer):
|
||||
result = bool(value.match(element_value)) if element_value is not None else False
|
||||
elif value in (None, True, False):
|
||||
result = element_value is value
|
||||
else:
|
||||
assert False, value
|
||||
|
||||
if comparison.startswith("!"):
|
||||
return not result
|
||||
|
||||
@@ -210,6 +210,8 @@ def np_rotation_matrix(
|
||||
matrix = np.array([[cos_theta, 0, sin_theta], [0, 1, 0], [-sin_theta, 0, cos_theta]])
|
||||
elif axis == "Z":
|
||||
matrix = np.array([[cos_theta, -sin_theta, 0], [sin_theta, cos_theta, 0], [0, 0, 1]])
|
||||
else:
|
||||
assert False, axis
|
||||
else:
|
||||
# Assume axis is a vector.
|
||||
axis = axis / np.linalg.norm(axis)
|
||||
@@ -473,7 +475,6 @@ class ShapeBuilder:
|
||||
if arc_points and self.file.schema == "IFC2X3":
|
||||
raise Exception("Arcs are not supported for IFC2X3.")
|
||||
|
||||
points: np.ndarray
|
||||
points = np.array(points)
|
||||
if position_offset is not None:
|
||||
points = points + position_offset
|
||||
@@ -635,7 +636,6 @@ class ShapeBuilder:
|
||||
diff = (0.01, 0.01) * diff_sign
|
||||
middle_point = points[0] + diff
|
||||
|
||||
points: list[VectorType]
|
||||
points = [points[0], middle_point, points[1]]
|
||||
points = [ifc_safe_vector_type(p) for p in points]
|
||||
seg = self.file.createIfcArcIndex((1, 2, 3))
|
||||
|
||||
Reference in New Issue
Block a user