From c089c11cd68f817abe586588647b54540e3e1ad8 Mon Sep 17 00:00:00 2001 From: Thomas Krijnen Date: Thu, 15 Jan 2026 16:22:18 +0100 Subject: [PATCH] Hack a bit to make stream tests run --- .../ifcopenshell/stream.py | 32 ++++++++++++++++--- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/src/ifcopenshell-python/ifcopenshell/stream.py b/src/ifcopenshell-python/ifcopenshell/stream.py index 6fdae02c4c..a1ba5b25cd 100644 --- a/src/ifcopenshell-python/ifcopenshell/stream.py +++ b/src/ifcopenshell-python/ifcopenshell/stream.py @@ -88,6 +88,13 @@ try: class stream(file): def __init__(self, filepath: str): + # See ifcopenshell.file.file_mixin.post_init() + # history, future and transaction are stored in a list so that they + # can easily be shared among file instances that are the same C++ + # object but have different python identities. We just have to conform + # here to that storage assumption: + self.state = [[], [], None] + self.history_size = 64 self.history = [] self.future = [] @@ -178,10 +185,23 @@ try: for ifc_class in exclude_classes: declaration = self.ifc_schema.declaration_by_name(ifc_class) exclude.update([st.name().upper() for st in ifcopenshell.util.schema.get_subtypes(declaration)]) + + # For creating C++ instances so that some of the calls here work + self.shadow_file = ifcopenshell.file(schema_identifier=self.ifc_schema) + # But we only create them once per type because we basically only need access to 'semi-static' such as get_attribute_category() + self.instance_map = {} + offset += len(line) + newline_character self.preprocess_schema() + def _create_entity(self, type): + if inst := self.instance_map.get(type): + return inst + else: + inst = self.instance_map[type] = self.shadow_file.create_entity(type) + return inst + def preprocess_schema(self) -> None: self.ifc_class_names = {} self.ifc_class_subtypes = {} @@ -307,17 +327,16 @@ try: # The best option we've got for mimicing `file.schema_identifier`. return self._schema - class stream_entity(entity_instance): + class stream_entity: stream_wrapper: stream_wrapper def __init__(self, id: int, ifc_class: str, file: stream = None): if not ifc_class: print(id, ifc_class, file) assert False - e = ifcopenshell_wrapper.new_IfcBaseClass(file.schema, ifc_class) s = stream_wrapper(id, ifc_class, file) - super(entity_instance, self).__setattr__("wrapped_data", e) - super(entity_instance, self).__setattr__("stream_wrapper", s) + object.__setattr__(self, "wrapped_data", file._create_entity(ifc_class)) + object.__setattr__(self, "stream_wrapper", s) def id(self) -> int: return self.stream_wrapper.id @@ -330,6 +349,9 @@ try: def __del__(self) -> None: pass + def __bool__(self): + return True + def __getitem__(self, key: int) -> Any: return self.__getattr__(list(self.stream_wrapper.attributes.keys())[key]) @@ -339,7 +361,7 @@ try: def __getattr__(self, name: str) -> Any: INVALID, FORWARD, INVERSE = range(3) - attr_cat = self.get_attribute_category(name) + attr_cat = self.wrapped_data.get_attribute_category(name) if attr_cat == FORWARD: if self.stream_wrapper.attribute_cache: return self.stream_wrapper.attribute_cache[name]