mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-23 19:16:24 +00:00
move IfcHeaderExtractor to util.file
edited pyproject.toml as `disableBytesTypePromotions` is disabled by default in non-strict mode and type checker intrerprets `bytes` as `bytes | memoryview | bytearray` which is deprecated in https://peps.python.org/pep-0688/#no-special-meaning-for-bytes
This commit is contained in:
@@ -3,3 +3,4 @@ line-length = 120
|
|||||||
|
|
||||||
[tool.pyright]
|
[tool.pyright]
|
||||||
reportInvalidTypeForm = false
|
reportInvalidTypeForm = false
|
||||||
|
disableBytesTypePromotions = true
|
||||||
|
|||||||
@@ -20,7 +20,6 @@
|
|||||||
import bpy
|
import bpy
|
||||||
import json
|
import json
|
||||||
import math
|
import math
|
||||||
import zipfile
|
|
||||||
import ifcopenshell
|
import ifcopenshell
|
||||||
import ifcopenshell.util.attribute
|
import ifcopenshell.util.attribute
|
||||||
import ifcopenshell.util.element
|
import ifcopenshell.util.element
|
||||||
@@ -322,50 +321,3 @@ def draw_filter(layout, filter_groups, data, module):
|
|||||||
op.group_index = i
|
op.group_index = i
|
||||||
op.index = j
|
op.index = j
|
||||||
op.module = module
|
op.module = module
|
||||||
|
|
||||||
|
|
||||||
# TODO this should move into ifcopenshell.util
|
|
||||||
|
|
||||||
|
|
||||||
class IfcHeaderExtractor:
|
|
||||||
def __init__(self, filepath: str):
|
|
||||||
self.filepath = filepath
|
|
||||||
|
|
||||||
def extract(self):
|
|
||||||
extension = self.filepath.split(".")[-1]
|
|
||||||
if extension.lower() == "ifc":
|
|
||||||
with open(self.filepath) as ifc_file:
|
|
||||||
return self.extract_ifc_spf(ifc_file)
|
|
||||||
elif extension.lower() == "ifczip":
|
|
||||||
return self.extract_ifc_zip()
|
|
||||||
elif extension.lower() == "ifcsqlite":
|
|
||||||
return {} # TODO
|
|
||||||
|
|
||||||
def extract_ifc_spf(self, ifc_file):
|
|
||||||
# https://www.steptools.com/stds/step/IS_final_p21e3.html#clause-8
|
|
||||||
data = {}
|
|
||||||
max_lines_to_parse = 50
|
|
||||||
for _ in range(max_lines_to_parse):
|
|
||||||
line = next(ifc_file)
|
|
||||||
if isinstance(line, bytes):
|
|
||||||
line = line.decode("utf-8")
|
|
||||||
if line.startswith("FILE_DESCRIPTION"):
|
|
||||||
for i, part in enumerate(line.split("'")):
|
|
||||||
if i == 1:
|
|
||||||
data["description"] = part
|
|
||||||
elif i == 3:
|
|
||||||
data["implementation_level"] = part
|
|
||||||
elif line.startswith("FILE_NAME"):
|
|
||||||
for i, part in enumerate(line.split("'")):
|
|
||||||
if i == 1:
|
|
||||||
data["name"] = part
|
|
||||||
elif i == 3:
|
|
||||||
data["time_stamp"] = part
|
|
||||||
elif line.startswith("FILE_SCHEMA"):
|
|
||||||
data["schema_name"] = line.split("'")[1]
|
|
||||||
break
|
|
||||||
return data
|
|
||||||
|
|
||||||
def extract_ifc_zip(self):
|
|
||||||
archive = zipfile.ZipFile(self.filepath, "r")
|
|
||||||
return self.extract_ifc_spf(archive.open(archive.filelist[0]))
|
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ from . import ifc
|
|||||||
from blenderbim import get_debug_info
|
from blenderbim import get_debug_info
|
||||||
import blenderbim.bim
|
import blenderbim.bim
|
||||||
import blenderbim.tool as tool
|
import blenderbim.tool as tool
|
||||||
from blenderbim.bim.helper import IfcHeaderExtractor
|
from ifcopenshell.util.file import IfcHeaderExtractor
|
||||||
from blenderbim.bim.prop import Attribute
|
from blenderbim.bim.prop import Attribute
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,113 @@
|
|||||||
|
# IfcOpenShell - IFC toolkit and geometry engine
|
||||||
|
# Copyright (C) 2021 Dion Moult <dion@thinkmoult.com>
|
||||||
|
#
|
||||||
|
# This file is part of IfcOpenShell.
|
||||||
|
#
|
||||||
|
# IfcOpenShell is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# IfcOpenShell is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU Lesser General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU Lesser General Public License
|
||||||
|
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import zipfile
|
||||||
|
from typing import IO, Union, TypedDict, NotRequired
|
||||||
|
|
||||||
|
|
||||||
|
class HeaderMetadata(TypedDict):
|
||||||
|
name: NotRequired[str]
|
||||||
|
description: NotRequired[str]
|
||||||
|
implementation_level: NotRequired[str]
|
||||||
|
time_stamp: NotRequired[str]
|
||||||
|
schema_name: NotRequired[str]
|
||||||
|
|
||||||
|
|
||||||
|
class IfcHeaderExtractor:
|
||||||
|
"""An utility class for extracting header information from IFC files.
|
||||||
|
|
||||||
|
This class provides functionality to extract key metadata from the header section of
|
||||||
|
IFC files without recreating the entire file as `ifcopenshell.file`.
|
||||||
|
For optimization, extractor will search only for the first 50 lines
|
||||||
|
of the IFC file for metadata.
|
||||||
|
|
||||||
|
Supported formats: .ifc, .ifczip.
|
||||||
|
|
||||||
|
Metadata available by the extraction is presented in the example below.
|
||||||
|
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
.. code:: python
|
||||||
|
|
||||||
|
from ifcopenshell.util.file import IfcHeaderExtractor
|
||||||
|
|
||||||
|
extractor = IfcHeaderExtractor("path/to/your/file.ifc")
|
||||||
|
# Get dictionary of the extracted metadata.
|
||||||
|
header_info = extractor.extract()
|
||||||
|
|
||||||
|
# Print the extracted information
|
||||||
|
|
||||||
|
# ViewDefinition[DesignTransferView]
|
||||||
|
print("File Description:", header_info.get("description"))
|
||||||
|
|
||||||
|
# 2;1
|
||||||
|
print("Implementation Level:", header_info.get("implementation_level"))
|
||||||
|
|
||||||
|
# file.ifc
|
||||||
|
print("File Name:", header_info.get("name"))
|
||||||
|
|
||||||
|
# 2024-06-25T15:48:10+05:00
|
||||||
|
print("Time Stamp:", header_info.get("time_stamp"))
|
||||||
|
|
||||||
|
# IFC4X3_ADD2
|
||||||
|
print("Schema Name:", header_info.get("schema_name"))
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, filepath: str):
|
||||||
|
self.filepath = filepath
|
||||||
|
|
||||||
|
def extract(self) -> HeaderMetadata:
|
||||||
|
extension = self.filepath.split(".")[-1]
|
||||||
|
if extension.lower() == "ifc":
|
||||||
|
with open(self.filepath) as ifc_file:
|
||||||
|
return self.extract_ifc_spf(ifc_file)
|
||||||
|
elif extension.lower() == "ifczip":
|
||||||
|
return self.extract_ifc_zip()
|
||||||
|
elif extension.lower() == "ifcsqlite":
|
||||||
|
return {} # TODO
|
||||||
|
raise ValueError(f"Unsupported file extension: '{extension}'.")
|
||||||
|
|
||||||
|
def extract_ifc_spf(self, ifc_file: Union[IO[bytes], IO[str]]) -> HeaderMetadata:
|
||||||
|
# https://www.steptools.com/stds/step/IS_final_p21e3.html#clause-8
|
||||||
|
data = HeaderMetadata()
|
||||||
|
max_lines_to_parse = 50
|
||||||
|
for _ in range(max_lines_to_parse):
|
||||||
|
line = next(ifc_file)
|
||||||
|
if isinstance(line, bytes):
|
||||||
|
line = line.decode("utf-8")
|
||||||
|
if line.startswith("FILE_DESCRIPTION"):
|
||||||
|
for i, part in enumerate(line.split("'")):
|
||||||
|
if i == 1:
|
||||||
|
data["description"] = part
|
||||||
|
elif i == 3:
|
||||||
|
data["implementation_level"] = part
|
||||||
|
elif line.startswith("FILE_NAME"):
|
||||||
|
for i, part in enumerate(line.split("'")):
|
||||||
|
if i == 1:
|
||||||
|
data["name"] = part
|
||||||
|
elif i == 3:
|
||||||
|
data["time_stamp"] = part
|
||||||
|
elif line.startswith("FILE_SCHEMA"):
|
||||||
|
data["schema_name"] = line.split("'")[1]
|
||||||
|
break
|
||||||
|
return data
|
||||||
|
|
||||||
|
def extract_ifc_zip(self) -> HeaderMetadata:
|
||||||
|
archive = zipfile.ZipFile(self.filepath, "r")
|
||||||
|
return self.extract_ifc_spf(archive.open(archive.filelist[0]))
|
||||||
Reference in New Issue
Block a user