# IfcOpenShell - IFC toolkit and geometry engine # Copyright (C) 2021 Thomas Krijnen # # 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 . """The entry module for IfcOpenShell Typically used for opening an IFC via a filepath, or accessing one of the submodules. Example: .. code:: python import ifcopenshell print(ifcopenshell.version) # v0.7.0-1b1fd1e6 model = ifcopenshell.open("/path/to/model.ifc") """ from __future__ import absolute_import from __future__ import division from __future__ import print_function import os import sys import tempfile import zipfile from pathlib import Path import ifcopenshell.util.file if hasattr(os, "uname"): platform_system = os.uname()[0].lower() else: platform_system = "windows" if sys.maxsize == (1 << 31) - 1: platform_architecture = "32bit" else: platform_architecture = "64bit" python_version_tuple = tuple(sys.version.split(" ")[0].split(".")) python_distribution = os.path.join(platform_system, platform_architecture, "python%s.%s" % python_version_tuple[:2]) sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "lib", python_distribution))) try: from . import ifcopenshell_wrapper except Exception as e: if int(python_version_tuple[0]) == 2: # Only for py2, as py3 has exception chaining import traceback traceback.print_exc() print("-" * 64) raise ImportError("IfcOpenShell not built for '%s'" % python_distribution) from . import guid from .file import file from .entity_instance import entity_instance, register_schema_attributes READ_ERROR = ifcopenshell_wrapper.file_open_status.READ_ERROR NO_HEADER = ifcopenshell_wrapper.file_open_status.NO_HEADER UNSUPPORTED_SCHEMA = ifcopenshell_wrapper.file_open_status.UNSUPPORTED_SCHEMA class Error(Exception): """Error used when a generic problem occurs""" pass class SchemaError(Error): """Error used when an IFC schema related problem occurs""" pass def open(path: "os.PathLike | str", format: str = None) -> file: """Loads an IFC dataset from a filepath You can specify a file format. If no format is given, it is guessed from its extension. Currently supported specified format : .ifc | .ifcZIP | .ifcXML Examples: model = ifcopenshell.open("/path/to/model.ifc") model = ifcopenshell.open("/path/to/model.ifcXML") model = ifcopenshell.open("/path/to/model.any_extension", ".ifc") """ path = Path(path) if format is None: format = ifcopenshell.util.file.guess_format(path) if format == ".ifcXML": f = ifcopenshell_wrapper.parse_ifcxml(str(path.absolute())) if f: return file(f) raise IOError(f"Failed to parse .ifcXML file from {path}") if format == ".ifcZIP": with tempfile.TemporaryDirectory() as unzipped_path: with zipfile.ZipFile(path) as zf: for name in zf.namelist(): if Path(name).suffix.lower() in (".ifc", ".ifcxml"): return open(zf.extract(name, unzipped_path)) else: raise LookupError(f"No .ifc or .ifcXML file found in {path}") f = ifcopenshell_wrapper.open(str(path.absolute())) if f.good(): return file(f) else: exc, msg = { READ_ERROR: (IOError, "Unable to open file for reading"), NO_HEADER: (Error, "Unable to parse IFC SPF header"), UNSUPPORTED_SCHEMA: ( SchemaError, "Unsupported schema: %s" % ",".join(f.header.file_schema.schema_identifiers), ), }[f.good().value()] raise exc(msg) def create_entity(type, schema="IFC4", *args, **kwargs): """Creates a new IFC entity that does not belong to an IFC file object Note that it is more common to create entities within a existing file object. See :meth:`ifcopenshell.file.file.create_entity`. :param type: Case insensitive name of the IFC class :type type: string :param schema: The IFC schema identifier :type schema: string :param args: The positional arguments of the IFC class :param kwargs: The keyword arguments of the IFC class :returns: An entity instance :rtype: ifcopenshell.entity_instance.entity_instance Example: .. code:: python person = ifcopenshell.create_entity("IfcPerson") # #0=IfcPerson($,$,$,$,$,$,$,$) model = ifcopenshell.file() model.add(person) # #1=IfcPerson($,$,$,$,$,$,$,$) """ e = entity_instance((schema, type)) attrs = list(enumerate(args)) + [(e.wrapped_data.get_argument_index(name), arg) for name, arg in kwargs.items()] for idx, arg in attrs: e[idx] = arg return e def register_schema(schema): """Registers a custom IFC schema :param schema: A schema object :type schema: ifcopenshell.express.schema_class.SchemaClass Example: .. code:: python schema = ifcopenshell.express.parse("/path/to/ifc-custom.exp") ifcopenshell.register_schema(schema) ifcopenshell.file(schema="IFC_CUSTOM") """ schema.schema.this.disown() schema.disown() ifcopenshell_wrapper.register_schema(schema.schema) register_schema_attributes(schema.schema) from .main import *