Files
IfcOpenShell/src/ifcopenshell-python/ifcopenshell/__init__.py
T

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

186 lines
5.9 KiB
Python
Raw Normal View History

# IfcOpenShell - IFC toolkit and geometry engine
# Copyright (C) 2021 Thomas Krijnen <thomas@aecgeeks.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/>.
"""The entry module for IfcOpenShell
Typically used for opening an IFC via a filepath, or accessing one of the
submodules.
Example::
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
2016-06-22 15:03:18 +02:00
from __future__ import print_function
import os
import sys
2022-11-21 01:27:03 +01:00
import tempfile
import zipfile
from pathlib import Path
2020-11-01 20:08:27 +07:00
if hasattr(os, "uname"):
platform_system = os.uname()[0].lower()
else:
2020-11-01 20:08:27 +07:00
platform_system = "windows"
2017-11-06 09:10:28 +01:00
if sys.maxsize == (1 << 31) - 1:
2020-11-01 20:08:27 +07:00
platform_architecture = "32bit"
else:
2020-11-01 20:08:27 +07:00
platform_architecture = "64bit"
2017-11-06 09:10:28 +01:00
2020-11-01 20:08:27 +07:00
python_version_tuple = tuple(sys.version.split(" ")[0].split("."))
2020-11-01 20:08:27 +07:00
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
2016-06-22 15:03:18 +02:00
except Exception as e:
if int(python_version_tuple[0]) == 2:
# Only for py2, as py3 has exception chaining
2016-06-22 15:03:18 +02:00
import traceback
2017-11-06 11:06:40 +01:00
2016-06-22 15:03:18 +02:00
traceback.print_exc()
2020-11-01 20:08:27 +07:00
print("-" * 64)
raise ImportError("IfcOpenShell not built for '%s'" % python_distribution)
2017-11-06 09:10:28 +01:00
2016-06-22 15:03:18 +02:00
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
2017-11-06 09:10:28 +01:00
2022-11-21 01:27:03 +01:00
def guess_format(path):
"""Try to guess format using file extension"""
if path.suffix.lower() in (".ifczip", ".zip"):
return ".ifcZIP"
if path.suffix.lower() in (".ifcxml", ".xml"):
return ".ifcXML"
2022-11-22 00:40:27 +01:00
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")
"""
2022-11-21 01:27:03 +01:00
path = Path(path)
if format is None:
format = 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"):
2022-11-22 00:40:27 +01:00
return open(zf.extract(name, unzipped_path))
2022-11-21 01:27:03 +01:00
else:
raise LookupError(f"No .ifc or .ifcXML file found in {path}")
f = ifcopenshell_wrapper.open(str(path.absolute()))
2018-01-01 11:22:12 +01:00
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,
2022-11-21 01:27:03 +01:00
"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::
person = ifcopenshell.create_entity("IfcPerson") # #0=IfcPerson($,$,$,$,$,$,$,$)
model = ifcopenshell.file()
model.add(person) # #1=IfcPerson($,$,$,$,$,$,$,$)
"""
e = entity_instance((schema, type))
2020-11-01 20:08:27 +07:00
attrs = list(enumerate(args)) + [(e.wrapped_data.get_argument_index(name), arg) for name, arg in kwargs.items()]
2017-11-06 09:10:28 +01:00
for idx, arg in attrs:
e[idx] = arg
return e
2020-11-01 20:08:27 +07:00
gcroot = []
2020-11-01 20:08:27 +07:00
def register_schema(schema):
"""Registers a custom IFC schema
:param schema: A schema object
:type schema: ifcopenshell.express.schema_class.SchemaClass
Example::
schema = ifcopenshell.express.parse("/path/to/ifc-custom.exp")
ifcopenshell.register_schema(schema)
ifcopenshell.file(schema="IFC_CUSTOM")
"""
gcroot.append(schema)
ifcopenshell_wrapper.register_schema(schema.schema)
register_schema_attributes(schema.schema)
2017-11-06 09:10:28 +01:00
2020-11-01 20:08:27 +07:00
2017-10-06 16:05:55 +02:00
from .main import *