Files
IfcOpenShell/src/ifcopenshell-python/ifcopenshell/express
Dion Moult 38e0e0e297 Compare entity instances in one file by identity again
entity_instance.file is a property backed by a fresh SWIG wrapper on every
access, and ifcopenshell::file had no __eq__, so `self.file != other.file`
in entity_instance.__eq__ compared two throwaway wrappers and was always
true - even for an instance against itself. Every entity comparison
therefore took the deep get_info() branch, making distinct but structurally
identical instances compare equal and leaving the final `return False`
unreachable. Bonsai's TestAddRepresentationItemToShapeAspect showed this as
two separate IfcShapeAspects being treated as one, so the stale aspect was
never removed.

Restore the file_pointer() pair that was commented out on both
ifcopenshell::file and express::Base - IfcParseWrapper.i already described
it as the way to "trace file ownership of instances on the python side" -
and give file the __eq__/__hash__ it was missing. The express::Base one
needs $self->file() now that file_ lives on instance_data. This also
repairs rocksdb_lazy_instance.__eq__, which already called file_pointer().

EXPRESS `=` is value comparison and `:=:` is instance comparison, but
rule_compiler emits `==` for both (see the @todo on process_rel_op), and
derived attributes build their operands in the shared global file, so rules
compare same-file instances and need value semantics. Restore those for the
duration of rule execution with settings.compare_instances_by_value,
alongside the existing unpack_non_aggregate_inverses.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-06 10:20:03 +10:00
..
2024-08-27 18:25:29 +05:00
2026-07-26 18:03:09 +10:00
2026-07-26 18:03:09 +10:00
2026-07-26 18:03:09 +10:00
2022-08-27 15:34:16 +02:00
2021-01-23 12:02:41 +11:00
2021-01-23 12:02:41 +11:00
2021-01-23 12:02:41 +11:00
2026-07-26 18:03:09 +10:00
2026-07-26 18:03:09 +10:00
2026-07-26 18:03:09 +10:00
2026-07-26 18:03:09 +10:00
2026-07-26 18:03:09 +10:00
2026-07-26 18:03:09 +10:00
2026-07-26 18:03:09 +10:00

IfcOpenShell express schema parser and code generator

This folder contains Python code to generate C++ type information based on an Express schema. In particular is has only been tested using recent version of the IFC schema and will most likely fail on any other Express schema.

The code can be invoked in the following way and results in several code outputs named according to the schema name in the Express file. A python 3 interpreter with the pyparsing (pip install pyparsing) library is required.

note: Keep in mind that Express is not very suitable for this kind of usage. In the end, (as far as I can tell) no tool is able to read your model, because it doesn't understand the schema as it has no notion of the core part vs the addition.

Command line usage for code generation

The usage for C++ project.

# bootstrap.py express.bnf in ifcopenshell-python.ifcopenshell.express.
>>> python3 bootstrap.py express.bnf > express_parser.py
>>> python3 express_parser.py IFC2X3_TC1.exp header implementation schema_class definitions

The usage for python project.

# code rule generation
# generating 'ifcopenshell.express.rules.IFC2X3_TC1' in ifcopenshell-python.ifcopenshell.express.rules.
# rule_compiler in ifcopenshell-python.ifcopenshell.express.
>>> python -m rule_compiler IFC2X3_TC1.exp

Programmatic usage

import ifcopenshell
import ifcopenshell.express
schema = ifcopenshell.express.parse('IFC.exp')
ifcopenshell.register_schema(schema)
f = ifcopenshell.file(schema=schema.schema.name())
f.createIfcProject(ifcopenshell.guid.new())