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>
Adds the IFC-library primitives the ifcpatch Migrate recipe needs for a
defensive IFC4 / IFC4X3 -> IFC2X3 downgrade without each caller
reinventing the wheel.
In ifcopenshell.util.schema:
- Migrator(fallback_element_to_proxy=False) opt-in: when True, IFC4-only
IfcElement subclasses (IfcLamp, IfcPipeSegment, IfcGeographicElement,
...) migrate to IfcBuildingElementProxy instead of raising. Default
preserves the strict failure-on-unmappable contract for existing
callers (classification API, etc.).
- geometry_classes_introduced_after(target, source) derives the
IfcRepresentationItem subclasses present in `source` but absent in
`target` directly from the loaded schemas. Cached per pair. Replaces
hand-curated class lists that drift with each IFC update.
ifc4_only_geometry_classes() retained as an alias.
- generate_default_value synthesises a unit IfcAxis2Placement2D /
IfcAxis2Placement3D when downgrading entities whose Position became
required in the target schema (IfcIShapeProfileDef and friends in
IFC2X3).
- Enum-mismatch detection upgraded from string-matched RuntimeError to a
structural check via ifcopenshell.util.attribute.get_enum_items so
upgrade paths still surface real bugs loudly.
In ifcopenshell.util.shape_builder:
- polygonal_face_set_to_faceted_brep converts IfcPolygonalFaceSet /
IfcTriangulatedFaceSet (IFC4-only) directly to IfcFacetedBrep,
preserving topology including IfcIndexedPolygonalFaceWithVoids inner
bounds. Validates inputs at the boundary.
- arc_to_polyline_points approximates a circular arc through three
points with a chord polyline of configurable subdivisions. Tolerates
floating-point noise on planar Z. Raises on non-planar or invalid
inputs.
Test coverage: 47 unit tests across schema + shape_builder lanes
covering each helper directly (no transitive-only coverage), including
regression pins for the IFC4X3-prefix ordering invariant in
get_fallback_schema and the strict-default Migrator contract.
Generated with the assistance of an AI coding tool.
ShapeBuilder gains module-level NP_X / NP_Y / NP_Z / NP_XY / NP_XZ /
NP_YZ / NP_YX axis-index constants. Downstream geometry builders had
been redefining local copies for indexing np.ndarray vectors of shape
(3,) or (N, 3); centralising removes the duplication.
mep_transition_length and mep_transition_calculate verbose default
flipped from True to False. The prints are diagnostic-only output;
True-by-default spammed the console on every transition computation,
which fires per-fitting on IFC load.
Generated with the assistance of an AI coding tool.
* shape_builder: complete docstrings and return type annotations
* shape_builder: warn about mixed item types in get_representation
* shape_builder: fix half_space_solid agreement_flag docstring
Generated with the assistance of an AI coding tool.
After ba2456a if main IFC project had an offset and linked object had more than 333 faces, then it was imported at it's original location instead, missing an offset.
Also processing occurrences should be now more optimized, since we reuse the same verts buffer instead of recreating it 10 times.