From f9e8d6d4785f763df582f62b0dce9856eeb7e857 Mon Sep 17 00:00:00 2001 From: Andrej730 Date: Mon, 12 Aug 2024 16:58:35 +0500 Subject: [PATCH] bcf - fix issues with unexpected reloads from zip It wasn't considering that self._topics could be an empty dict because there are no topics and it would also reload it. Now we have None value to distinguish when it actually wasn't loaded before. Same for viewpoints, reference files and document references. I've also imade mplementations identical/more similar between v2 and v3. --- src/bcf/bcf/v2/bcfxml.py | 16 ++++++++-------- src/bcf/bcf/v2/topic.py | 32 +++++++++++++++++++++----------- src/bcf/bcf/v3/bcfxml.py | 14 +++++++++----- src/bcf/bcf/v3/topic.py | 16 ++++++++-------- 4 files changed, 46 insertions(+), 32 deletions(-) diff --git a/src/bcf/bcf/v2/bcfxml.py b/src/bcf/bcf/v2/bcfxml.py index fe1d482d61..c8782ac9ba 100644 --- a/src/bcf/bcf/v2/bcfxml.py +++ b/src/bcf/bcf/v2/bcfxml.py @@ -24,7 +24,7 @@ class BcfXml: self._xml_handler = xml_handler or XmlParserSerializer() self._version: Optional[mdl.Version] = None self._project_info: Optional[mdl.ProjectExtension] = None - self._topics: dict[str, TopicHandler] = {} + self._topics: Optional[dict[str, TopicHandler]] = None self._extension_schema: Optional[bytes] = None self._zip_file = self._load_zip_file() @@ -88,21 +88,21 @@ class BcfXml: @property def topics(self) -> dict[str, TopicHandler]: """BCF topics.""" - if not self._topics and self._zip_file: - self._topics = self._load_topics(self._zip_file, self._xml_handler) + if self._topics is None: + self._topics = self._load_topics() return self._topics - def _load_topics( - self, zip_file: zipfile.ZipFile, xml_handler: AbstractXmlParserSerializer - ) -> dict[str, TopicHandler]: + def _load_topics(self) -> dict[str, TopicHandler]: topics = {} - for topic_dir in zipfile.Path(zip_file).iterdir(): + if self._zip_file is None: + return topics + for topic_dir in zipfile.Path(self._zip_file).iterdir(): if not topic_dir.is_dir(): continue markup_path = topic_dir.joinpath("markup.bcf") if not markup_path.exists(): continue - topics[topic_dir.name] = TopicHandler(topic_dir, xml_handler) + topics[topic_dir.name] = TopicHandler(topic_dir, self._xml_handler) return topics @classmethod diff --git a/src/bcf/bcf/v2/topic.py b/src/bcf/bcf/v2/topic.py index 4d016449e2..4bcfaa7043 100644 --- a/src/bcf/bcf/v2/topic.py +++ b/src/bcf/bcf/v2/topic.py @@ -27,9 +27,9 @@ class TopicHandler: xml_handler: Optional[AbstractXmlParserSerializer] = None, ) -> None: self._markup: Optional[mdl.Markup] = None - self._viewpoints: dict[str, VisualizationInfoHandler] = {} - self._reference_files: dict[str, bytes] = {} - self._document_references: dict[str, bytes] = {} + self._viewpoints: Optional[dict[str, VisualizationInfoHandler]] = None + self._reference_files: Optional[dict[str, bytes]] = None + self._document_references: Optional[dict[str, bytes]] = None self._bim_snippet: Optional[bytes] = None self._xml_handler = xml_handler or XmlParserSerializer() self._topic_dir = topic_dir @@ -80,14 +80,24 @@ class TopicHandler: @property def viewpoints(self) -> dict[str, VisualizationInfoHandler]: - if not self._viewpoints and self._topic_dir: + if self._viewpoints is None: self._viewpoints = self._load_viewpoints() return self._viewpoints + def _load_viewpoints(self) -> dict[str, VisualizationInfoHandler]: + if self._topic_dir and self.markup and (viewpoints := self.markup.viewpoints): + return VisualizationInfoHandler.from_topic_viewpoints(self._topic_dir, viewpoints) + return {} + @property def reference_files(self) -> dict[str, bytes]: - if self._reference_files or not self.header: + if self._reference_files is not None: return self._reference_files + + self._reference_files = {} + if not self.header: + return self._reference_files + for ref in self.header.file: if ref.is_external: continue @@ -99,8 +109,13 @@ class TopicHandler: @property def document_references(self) -> dict[str, bytes]: - if self._document_references or not self.topic: + if self._document_references is not None: return self._document_references + + self._document_references = {} + if not self.topic: + return self._document_references + for doc in self.topic.document_reference: if doc.is_external or not doc.referenced_document: continue @@ -118,11 +133,6 @@ class TopicHandler: return bim_snippet_path.read_bytes() return None - def _load_viewpoints(self) -> dict[str, VisualizationInfoHandler]: - if self.markup and (viewpoints := self.markup.viewpoints): - return VisualizationInfoHandler.from_topic_viewpoints(self._topic_dir, viewpoints) - return {} - @classmethod def create_new( cls, diff --git a/src/bcf/bcf/v3/bcfxml.py b/src/bcf/bcf/v3/bcfxml.py index 3318264670..16d920737a 100644 --- a/src/bcf/bcf/v3/bcfxml.py +++ b/src/bcf/bcf/v3/bcfxml.py @@ -26,7 +26,7 @@ class BcfXml: self._version: Optional[mdl.Version] = None self._project_info: Optional[mdl.ProjectInfo] = None self._extensions: Optional[mdl.Extensions] = None - self._topics: dict[str, TopicHandler] = {} + self._topics: Optional[dict[str, TopicHandler]] = None self._documents: Optional[DocumentsHandler] = None self._zip_file = self._load_zip_file() @@ -91,18 +91,22 @@ class BcfXml: @property def topics(self) -> dict[str, TopicHandler]: """BCF topics.""" - if not self._topics and self._zip_file: - self._load_topics() + if self._topics is None: + self._topics = self._load_topics() return self._topics - def _load_topics(self) -> None: + def _load_topics(self) -> dict[str, TopicHandler]: + topics = {} + if self._zip_file is None: + return topics for topic_dir in zipfile.Path(self._zip_file).iterdir(): if not topic_dir.is_dir(): continue markup_path = topic_dir.joinpath("markup.bcf") if not markup_path.exists(): continue - self._topics[topic_dir.name] = TopicHandler(topic_dir, self._xml_handler) + topics[topic_dir.name] = TopicHandler(topic_dir, self._xml_handler) + return topics @property def documents(self) -> Optional[DocumentsHandler]: diff --git a/src/bcf/bcf/v3/topic.py b/src/bcf/bcf/v3/topic.py index 2fd8db6fe4..b2f2bf4e22 100644 --- a/src/bcf/bcf/v3/topic.py +++ b/src/bcf/bcf/v3/topic.py @@ -26,7 +26,7 @@ class TopicHandler: xml_handler: Optional[AbstractXmlParserSerializer] = None, ) -> None: self._markup: Optional[mdl.Markup] = None - self._viewpoints: dict[str, VisualizationInfoHandler] = {} + self._viewpoints: Optional[dict[str, VisualizationInfoHandler]] = None self._bim_snippet: Optional[bytes] = None self._xml_handler = xml_handler or XmlParserSerializer() self._topic_dir = topic_dir @@ -77,15 +77,15 @@ class TopicHandler: @property def viewpoints(self) -> dict[str, "VisualizationInfoHandler"]: - if ( - not self._viewpoints - and self._topic_dir - and self.topic.viewpoints - and (viewpoints := self.topic.viewpoints.view_point) - ): - self._viewpoints = VisualizationInfoHandler.from_topic_viewpoints(self._topic_dir, viewpoints) + if self._viewpoints is None: + self._viewpoints = self._load_viewpoints() return self._viewpoints + def _load_viewpoints(self) -> dict[str, "VisualizationInfoHandler"]: + if self._topic_dir and self.topic.viewpoints and (viewpoints := self.topic.viewpoints.view_point): + return VisualizationInfoHandler.from_topic_viewpoints(self._topic_dir, viewpoints) + return {} + def _load_bim_snippet(self) -> Optional[bytes]: bim_snippet_obj = self.topic.bim_snippet if bim_snippet_obj and not bim_snippet_obj.is_external and self._topic_dir: