mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-10 01:41:57 +00:00
Work towards v1.0 data model with encapsulated weak_ptr as basis for instances
This commit is contained in:
@@ -88,12 +88,12 @@ except Exception:
|
||||
|
||||
# `_file`, `_stream` is used only for annotations inside this file,
|
||||
# see https://github.com/microsoft/pyright/discussions/9065.
|
||||
from .file import file as _file
|
||||
from .file import file
|
||||
from .ifcopenshell_wrapper import file as _file
|
||||
from .ifcopenshell_wrapper import file
|
||||
|
||||
from .file import rocksdb_lazy_instance
|
||||
from . import guid
|
||||
from .entity_instance import entity_instance, register_schema_attributes
|
||||
from .ifcopenshell_wrapper import entity_instance
|
||||
from .sql import sqlite, sqlite_entity
|
||||
|
||||
# explicitly specify available imported symbols
|
||||
@@ -251,7 +251,6 @@ def register_schema(schema: ifcopenshell.express.schema_class.SchemaClass) -> No
|
||||
schema.schema.this.disown()
|
||||
schema.disown()
|
||||
ifcopenshell_wrapper.register_schema(schema.schema)
|
||||
register_schema_attributes(schema.schema)
|
||||
|
||||
|
||||
def schema_by_name(
|
||||
|
||||
@@ -43,75 +43,7 @@ except ImportError:
|
||||
T = TypeVar("T")
|
||||
|
||||
|
||||
def set_derived_attribute(*args):
|
||||
raise TypeError("Unable to set derived attribute")
|
||||
|
||||
|
||||
def set_unsupported_attribute(*args):
|
||||
raise TypeError("This is an unsupported attribute type")
|
||||
|
||||
|
||||
# For every schema and its entities populate a list
|
||||
# of functions for every entity attribute (including
|
||||
# inherited attributes) to set that particular
|
||||
# attribute by index.
|
||||
# For example. IFC2X3.IfcWall with have a list of
|
||||
# 9 methods. The first will point at
|
||||
# ifcopenshell.ifcopenshell_wrapper.entity_instance.setArgumentAsString
|
||||
# because the first attribute GlobalId ultimately
|
||||
# is of type string.
|
||||
# Previously, resolving the appropriate function was
|
||||
# done for each invocation of __setitem__. Now this
|
||||
# mapping is built once during initialization of the
|
||||
# module.
|
||||
MethodList = list[Callable[[ifcopenshell_wrapper.entity_instance, int, Any], Union[None, NoReturn]]]
|
||||
"""List of setter methods for class attributes."""
|
||||
_method_dict: dict[str, MethodList] = {}
|
||||
"""Mapping of entity classes (e.g. 'IFC4.IfcWall') to MethodLists."""
|
||||
|
||||
|
||||
def register_schema_attributes(schema: ifcopenshell_wrapper.schema_definition) -> None:
|
||||
for decl in schema.declarations():
|
||||
if hasattr(decl, "argument_types"):
|
||||
fq_name = ".".join((schema.name(), decl.name()))
|
||||
|
||||
# get type strings as reported by IfcOpenShell C++
|
||||
type_strs = decl.argument_types()
|
||||
type_strs = cast(Sequence[str], type_strs)
|
||||
|
||||
# convert case for setter function
|
||||
type_strs = [x.title().replace(" ", "") for x in type_strs]
|
||||
|
||||
# binary and enumeration are passed from python as string as well
|
||||
type_strs = [x.replace("Binary", "String") for x in type_strs]
|
||||
type_strs = [x.replace("Enumeration", "String") for x in type_strs]
|
||||
|
||||
# prefix to get method names
|
||||
fn_names = ["setArgumentAs" + x for x in type_strs]
|
||||
|
||||
# resolve to actual functions in wrapper
|
||||
functions = [
|
||||
(
|
||||
set_derived_attribute
|
||||
if mname == "setArgumentAsDerived"
|
||||
else (
|
||||
set_unsupported_attribute
|
||||
if mname == "setArgumentAsUnknown"
|
||||
else getattr(ifcopenshell_wrapper.entity_instance, mname)
|
||||
)
|
||||
)
|
||||
for mname in fn_names
|
||||
]
|
||||
|
||||
_method_dict[fq_name] = functions
|
||||
|
||||
|
||||
for nm in ifcopenshell_wrapper.schema_names():
|
||||
schema = ifcopenshell_wrapper.schema_by_name(nm)
|
||||
register_schema_attributes(schema)
|
||||
|
||||
|
||||
class entity_instance:
|
||||
class entity_instance_mixin:
|
||||
"""Represents an entity (wall, slab, property, etc) of an IFC model
|
||||
|
||||
An IFC model consists of entities. Examples of entities include walls,
|
||||
@@ -155,67 +87,33 @@ class entity_instance:
|
||||
print(wall.__class__) # <class 'ifcopenshell.entity_instance'>
|
||||
"""
|
||||
|
||||
wrapped_data: ifcopenshell_wrapper.entity_instance
|
||||
method_list: Union[MethodList, None] = None
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
e: Union[ifcopenshell_wrapper.entity_instance, tuple[str, str]],
|
||||
file: Union[ifcopenshell.file, None] = None,
|
||||
):
|
||||
"""
|
||||
:param e: Wrapper's ``entity_instance`` or a tuple ``(schema_identifier, ifc_class)``.
|
||||
"""
|
||||
# Instances of this class will be created and removed very often,
|
||||
# so it's important to keep it very optimized.
|
||||
|
||||
if isinstance(e, tuple):
|
||||
e = ifcopenshell_wrapper.new_IfcBaseClass(*e)
|
||||
object.__setattr__(self, "wrapped_data", e)
|
||||
|
||||
# Make sure the file is not gc'ed while we have live instances
|
||||
e.file = file
|
||||
|
||||
def __del__(self):
|
||||
"""
|
||||
#2471 while the precise chain of action is unclear, creating
|
||||
instance references prevents file gc, even with all instance
|
||||
refs deleted. This is a work-around for that.
|
||||
"""
|
||||
# Avoid infinite recursion if entity is failed to initialize
|
||||
# and wrapped_data is unset. Hacky since we override
|
||||
# both __dict__ and __dir__.
|
||||
try:
|
||||
wrapped_data = object.__getattribute__(self, "wrapped_data")
|
||||
wrapped_data.file = None
|
||||
except AttributeError:
|
||||
return
|
||||
|
||||
@property
|
||||
def file(self):
|
||||
# ugh circular imports, name collisions
|
||||
from . import file
|
||||
|
||||
return file.from_pointer(self.wrapped_data.file_pointer())
|
||||
raise NotImplementedError
|
||||
|
||||
def __getattr__(self, name: str) -> Any:
|
||||
if name in ("this", "thisown") or name.startswith("_swig_"):
|
||||
return object.__getattr__(self, name)
|
||||
"""
|
||||
Any aggregate attributes (e.g. `SET`) are returns as Python tuples.
|
||||
|
||||
Inverse attributes are always returned as tuples, even it's not a set origially in IFC
|
||||
Inverse attributes are returned as tuples, even it's not a set origially in IFC
|
||||
(e.g. IfcFeatureElementSubtraction.VoidsElements)
|
||||
(unless settings.unpack_non_aggregate_inverses is used, which is necessary for express rule execution)
|
||||
"""
|
||||
INVALID, FORWARD, INVERSE = range(3)
|
||||
attr_cat = self.wrapped_data.get_attribute_category(name)
|
||||
if attr_cat == FORWARD:
|
||||
idx = self.wrapped_data.get_argument_index(name)
|
||||
if _method_dict[self.is_a(True)][idx] != set_derived_attribute:
|
||||
# A bit ugly, but we fall through to derived attribute handling below
|
||||
return entity_instance.wrap_value(self.wrapped_data.get_argument(idx), self.wrapped_data.file)
|
||||
INVALID, FORWARD, INVERSE, DERIVED = range(4)
|
||||
attr_cat = self.get_attribute_category(name)
|
||||
if attr_cat == INVALID:
|
||||
raise AttributeError(
|
||||
"entity instance of type '%s' has no attribute '%s'" % (self.is_a(True), name)
|
||||
)
|
||||
elif attr_cat == FORWARD:
|
||||
idx = self.get_argument_index(name)
|
||||
return self.get_argument(idx)
|
||||
elif attr_cat == INVERSE:
|
||||
vs = entity_instance.wrap_value(self.wrapped_data.get_inverse(name), self.wrapped_data.file)
|
||||
vs = self.get_inverse(name)
|
||||
if settings.unpack_non_aggregate_inverses:
|
||||
schema_name = self.wrapped_data.is_a(True).split(".")[0]
|
||||
schema_name = self.is_a(True).split(".")[0]
|
||||
ent: ifcopenshell_wrapper.entity
|
||||
ent = ifcopenshell_wrapper.schema_by_name(schema_name).declaration_by_name(self.is_a())
|
||||
inv = next(i for i in ent.all_inverse_attributes() if i.name() == name)
|
||||
@@ -225,44 +123,38 @@ class entity_instance:
|
||||
else:
|
||||
vs = None
|
||||
return vs
|
||||
elif attr_cat == DERIVED:
|
||||
schema_name = self.is_a(True).split(".")[0]
|
||||
try:
|
||||
rules = importlib.import_module(f"ifcopenshell.express.rules.{schema_name}")
|
||||
except:
|
||||
import os
|
||||
|
||||
# derived attribute perhaps?
|
||||
schema_name = self.wrapped_data.is_a(True).split(".")[0]
|
||||
try:
|
||||
rules = importlib.import_module(f"ifcopenshell.express.rules.{schema_name}")
|
||||
except:
|
||||
import os
|
||||
current_dir_files = {fn.lower(): fn for fn in os.listdir(".")}
|
||||
exp_filename = schema_name.lower() + ".exp"
|
||||
schema_path = current_dir_files.get(exp_filename)
|
||||
if schema_path is None:
|
||||
raise Exception(
|
||||
f"Couldn't find express file '{schema_name.lower()}.exp' in the current folder: '{os.getcwd()}'."
|
||||
)
|
||||
fn = schema_path[:-4] + ".py"
|
||||
if not os.path.exists(fn):
|
||||
subprocess.run(
|
||||
[sys.executable, "-m", "ifcopenshell.express.rule_compiler", schema_path, fn], check=True
|
||||
)
|
||||
time.sleep(1.0)
|
||||
rules = importlib.import_module(schema_name)
|
||||
|
||||
current_dir_files = {fn.lower(): fn for fn in os.listdir(".")}
|
||||
exp_filename = schema_name.lower() + ".exp"
|
||||
schema_path = current_dir_files.get(exp_filename)
|
||||
if schema_path is None:
|
||||
raise Exception(
|
||||
f"Couldn't find express file '{schema_name.lower()}.exp' in the current folder: '{os.getcwd()}'."
|
||||
)
|
||||
fn = schema_path[:-4] + ".py"
|
||||
if not os.path.exists(fn):
|
||||
subprocess.run(
|
||||
[sys.executable, "-m", "ifcopenshell.express.rule_compiler", schema_path, fn], check=True
|
||||
)
|
||||
time.sleep(1.0)
|
||||
rules = importlib.import_module(schema_name)
|
||||
def yield_supertypes():
|
||||
decl = ifcopenshell_wrapper.schema_by_name(schema_name).declaration_by_name(self.is_a())
|
||||
while decl:
|
||||
yield decl.name()
|
||||
decl = decl.supertype()
|
||||
|
||||
def yield_supertypes():
|
||||
decl = ifcopenshell_wrapper.schema_by_name(schema_name).declaration_by_name(self.is_a())
|
||||
while decl:
|
||||
yield decl.name()
|
||||
decl = decl.supertype()
|
||||
|
||||
for sty in yield_supertypes():
|
||||
fn = getattr(rules, f"calc_{sty}_{name}", None)
|
||||
if fn:
|
||||
return fn(self)
|
||||
|
||||
if attr_cat != FORWARD:
|
||||
raise AttributeError(
|
||||
"entity instance of type '%s' has no attribute '%s'" % (self.wrapped_data.is_a(True), name)
|
||||
)
|
||||
for sty in yield_supertypes():
|
||||
fn = getattr(rules, f"calc_{sty}_{name}", None)
|
||||
if fn:
|
||||
return fn(self)
|
||||
|
||||
@staticmethod
|
||||
def walk(f: Callable[[Any], bool], g: Callable[[Any], Any], value: Any) -> Any:
|
||||
@@ -295,180 +187,53 @@ class entity_instance:
|
||||
"""
|
||||
|
||||
if isinstance(value, (tuple, list)):
|
||||
return tuple(map(functools.partial(entity_instance.walk, f, g), value))
|
||||
return tuple(map(functools.partial(entity_instance_mixin.walk, f, g), value))
|
||||
elif f(value):
|
||||
return g(value)
|
||||
else:
|
||||
return value
|
||||
|
||||
@staticmethod
|
||||
def wrap_value(v, file: ifcopenshell.file):
|
||||
def wrap(e: ifcopenshell_wrapper.entity_instance) -> entity_instance:
|
||||
return entity_instance(e, file)
|
||||
|
||||
def is_instance(e: Any) -> bool:
|
||||
return isinstance(e, ifcopenshell_wrapper.entity_instance)
|
||||
|
||||
return entity_instance.walk(is_instance, wrap, v)
|
||||
|
||||
@staticmethod
|
||||
def unwrap_value(v):
|
||||
def unwrap(e):
|
||||
return e.wrapped_data
|
||||
|
||||
def is_instance(e):
|
||||
return isinstance(e, entity_instance)
|
||||
|
||||
return entity_instance.walk(is_instance, unwrap, v)
|
||||
|
||||
def attribute_type(self, attr: Union[int, str]) -> str:
|
||||
"""Return the data type of a positional attribute of the element
|
||||
|
||||
:param attr: The index or name of the attribute
|
||||
"""
|
||||
attr_idx = attr if isinstance(attr, numbers.Integral) else self.wrapped_data.get_argument_index(attr)
|
||||
return self.wrapped_data.get_argument_type(attr_idx)
|
||||
|
||||
def attribute_name(self, attr_idx: int) -> str:
|
||||
"""Return the name of a positional attribute of the element
|
||||
|
||||
:param attr_idx: The index of the attribute
|
||||
"""
|
||||
return self.wrapped_data.get_argument_name(attr_idx)
|
||||
|
||||
def __setattr__(self, key: str, value: Any) -> None:
|
||||
index = self.wrapped_data.get_argument_index(key)
|
||||
if key in ("this", "thisown") or key.startswith("_swig_"):
|
||||
return object.__setattr__(self, key, value)
|
||||
|
||||
index = self.get_argument_index(key)
|
||||
try:
|
||||
self[index] = value
|
||||
except IndexError as e:
|
||||
# get_argument_index returns 0xFFFFFFFF if attribute is not found
|
||||
if index == 0xFFFFFFFF:
|
||||
raise AttributeError(
|
||||
"entity instance of type '%s' has no attribute '%s'" % (self.wrapped_data.is_a(True), key)
|
||||
"entity instance of type '%s' has no attribute '%s'" % (self.is_a(True), key)
|
||||
)
|
||||
raise e
|
||||
|
||||
def __getitem__(self, key: int) -> Any:
|
||||
if key < 0 or key >= len(self):
|
||||
raise IndexError("Attribute index {} out of range for instance of type {}".format(key, self.is_a()))
|
||||
return entity_instance.wrap_value(self.wrapped_data.get_argument(key), self.wrapped_data.file)
|
||||
return self.get_argument(key)
|
||||
|
||||
def __setitem__(self, idx: int, value: T) -> T:
|
||||
if self.wrapped_data.file and self.wrapped_data.file.transaction:
|
||||
self.wrapped_data.file.transaction.store_edit(self, idx, value)
|
||||
|
||||
if self.method_list is None:
|
||||
super().__setattr__("method_list", _method_dict[self.is_a(True)])
|
||||
|
||||
method = self.method_list[idx]
|
||||
|
||||
if value is None:
|
||||
if method is not set_derived_attribute:
|
||||
try:
|
||||
self.wrapped_data.setArgumentAsNull(idx)
|
||||
except RuntimeError as e:
|
||||
if e.args == ("Attribute not set",):
|
||||
raise TypeError(
|
||||
"attribute '%s' is not optional for entity instance of type '%s'"
|
||||
% (self.wrapped_data.get_argument_name(idx), self.wrapped_data.is_a(True))
|
||||
)
|
||||
raise e
|
||||
else:
|
||||
try:
|
||||
self.method_list[idx](self.wrapped_data, idx, entity_instance.unwrap_value(value))
|
||||
except TypeError:
|
||||
raise TypeError(
|
||||
"attribute '%s' for entity '%s' is expecting value of type '%s', got '%s'."
|
||||
% (
|
||||
self.wrapped_data.get_argument_name(idx),
|
||||
self.wrapped_data.is_a(True),
|
||||
self.wrapped_data.get_argument_type(idx),
|
||||
type(value).__name__,
|
||||
)
|
||||
)
|
||||
if self.file and self.file.transaction:
|
||||
self.file.transaction.store_edit(self, idx, value)
|
||||
|
||||
self.set_attribute_value_py(idx, value)
|
||||
|
||||
return value
|
||||
|
||||
def __len__(self):
|
||||
return len(self.wrapped_data)
|
||||
|
||||
def __repr__(self):
|
||||
return repr(self.wrapped_data)
|
||||
|
||||
def to_string(self, valid_spf=True) -> str:
|
||||
"""Returns a string representation of the current entity instance.
|
||||
Equal to str(self) when valid_spf=False. When valid_spf is True
|
||||
returns a representation of the string that conforms to valid Step
|
||||
Physical File notation. The difference being entity names in upper
|
||||
case and string attribute values with unicode values encoded per
|
||||
the specific control directives.
|
||||
"""
|
||||
|
||||
return self.wrapped_data.to_string(valid_spf)
|
||||
|
||||
@overload
|
||||
def is_a(self) -> str: ...
|
||||
@overload
|
||||
def is_a(self, ifc_class: str) -> bool: ...
|
||||
@overload
|
||||
def is_a(self, with_schema: bool) -> str: ...
|
||||
def is_a(self, *args: Union[str, bool]) -> Union[str, bool]:
|
||||
"""Return the IFC class name of an instance, or checks if an instance belongs to a class.
|
||||
|
||||
The check will also return true if a parent class name is provided.
|
||||
|
||||
:param args: If specified, is a case insensitive IFC class name to check
|
||||
or if specified as a boolean then will define whether
|
||||
returned IFC class name should include schema name
|
||||
(e.g. "IFC4.IfcWall" if `True` and "IfcWall" if `False`).
|
||||
If omitted will act as `False`.
|
||||
:returns: Either the name of the class, or a boolean if it passes the check
|
||||
|
||||
Example:
|
||||
|
||||
.. code:: python
|
||||
|
||||
f = ifcopenshell.file()
|
||||
f.create_entity('IfcPerson')
|
||||
f.is_a()
|
||||
>>> 'IfcPerson'
|
||||
f.is_a('IfcPerson')
|
||||
>>> True
|
||||
"""
|
||||
return self.wrapped_data.is_a(*args)
|
||||
|
||||
def id(self) -> int:
|
||||
"""Return the STEP numerical identifier"""
|
||||
return self.wrapped_data.id()
|
||||
|
||||
def __eq__(self, other: entity_instance) -> bool:
|
||||
def __eq__(self, other: entity_instance_mixin) -> bool:
|
||||
if not isinstance(self, type(other)):
|
||||
return False
|
||||
elif None in (self.wrapped_data.file, other.wrapped_data.file):
|
||||
# when not added to a file, we can only compare attribute values
|
||||
# and we need this for where rule evaluation
|
||||
return self.get_info_2(recursive=True, include_identifier=False) == other.get_info_2(
|
||||
recursive=True, include_identifier=False
|
||||
)
|
||||
else:
|
||||
# Proper entity instances have a stable identity by means of the numeric
|
||||
# step id. Selected type instances (such as IfcPropertySingleValue.NominalValue
|
||||
# always have id=0, so we compare <type, value, file pointer>
|
||||
if self.id():
|
||||
return self.wrapped_data == other.wrapped_data
|
||||
else:
|
||||
return (self.is_a(), self[0], self.wrapped_data.file_pointer()) == (
|
||||
other.is_a(),
|
||||
other[0],
|
||||
other.wrapped_data.file_pointer(),
|
||||
)
|
||||
|
||||
raise NotImplementedError
|
||||
|
||||
def is_entity(self) -> bool:
|
||||
"""Tests whether the instance is an entity type as opposed to a simple data type.
|
||||
|
||||
:return: True if the instance is an entity
|
||||
"""
|
||||
schema_name = self.wrapped_data.is_a(True).split(".")[0]
|
||||
schema_name = self.is_a(True).split(".")[0]
|
||||
decl = ifcopenshell_wrapper.schema_by_name(schema_name).declaration_by_name(self.is_a())
|
||||
return isinstance(decl, ifcopenshell_wrapper.entity)
|
||||
|
||||
@@ -505,9 +270,9 @@ class entity_instance:
|
||||
:return: bool: The comparison predicate applied to self and other
|
||||
"""
|
||||
|
||||
if isinstance(other, entity_instance):
|
||||
if isinstance(other, entity_instance_mixin):
|
||||
a, b = map(tuple, (self, other))
|
||||
if any(map(entity_instance.is_entity, (self, other))):
|
||||
if any(map(entity_instance_mixin.is_entity, (self, other))):
|
||||
a = (self.is_a(),) + a
|
||||
b = (other.is_a(),) + b
|
||||
elif self.is_entity():
|
||||
@@ -540,17 +305,17 @@ class entity_instance:
|
||||
# step id. Selected type instances (such as IfcPropertySingleValue.NominalValue
|
||||
# always have id=0, so we hash <type, value, file pointer>
|
||||
if id_ := self.id():
|
||||
return hash((id_, self.wrapped_data.file_pointer()))
|
||||
return hash((id_, self.file_pointer()))
|
||||
else:
|
||||
return hash((self.is_a(), self[0], self.wrapped_data.file_pointer()))
|
||||
return hash((self.is_a(), self[0], self.file_pointer()))
|
||||
|
||||
def __dir__(self):
|
||||
return sorted(
|
||||
set(
|
||||
itertools.chain(
|
||||
dir(type(self)),
|
||||
map(str, self.wrapped_data.get_attribute_names()),
|
||||
map(str, self.wrapped_data.get_inverse_attribute_names()),
|
||||
map(str, self.get_attribute_names()),
|
||||
map(str, self.get_inverse_attribute_names()),
|
||||
)
|
||||
)
|
||||
)
|
||||
@@ -595,7 +360,7 @@ class entity_instance:
|
||||
logging.exception("unhandled exception while getting id / type info on {}".format(self))
|
||||
for i in range(len(self)):
|
||||
try:
|
||||
if self.wrapped_data.get_attribute_names()[i] in ignore:
|
||||
if self.get_attribute_names()[i] in ignore:
|
||||
continue
|
||||
attr_value = self[i]
|
||||
|
||||
@@ -604,10 +369,10 @@ class entity_instance:
|
||||
if recursive or scalar_only:
|
||||
|
||||
def is_instance(e):
|
||||
return isinstance(e, entity_instance)
|
||||
return isinstance(e, entity_instance_mixin)
|
||||
|
||||
def get_info_(inst):
|
||||
return entity_instance.get_info(
|
||||
return entity_instance_mixin.get_info(
|
||||
inst,
|
||||
include_identifier=include_identifier,
|
||||
recursive=recursive,
|
||||
@@ -619,7 +384,7 @@ class entity_instance:
|
||||
to_include["v"] = False
|
||||
return None
|
||||
|
||||
attr_value = entity_instance.walk(
|
||||
attr_value = entity_instance_mixin.walk(
|
||||
is_instance, get_info_ if recursive else do_ignore, attr_value
|
||||
)
|
||||
|
||||
@@ -651,4 +416,4 @@ class entity_instance:
|
||||
assert recursive
|
||||
assert return_type is dict
|
||||
assert len(ignore) == 0
|
||||
return ifcopenshell_wrapper.get_info_cpp(self.wrapped_data, include_identifier)
|
||||
return ifcopenshell_wrapper.get_info_cpp(self, include_identifier)
|
||||
|
||||
@@ -26,16 +26,14 @@ import documentation
|
||||
|
||||
from collections import defaultdict
|
||||
|
||||
USE_VIRTUAL_INHERITANCE = True
|
||||
|
||||
class Header(codegen.Base):
|
||||
def __init__(self, mapping):
|
||||
declarations = []
|
||||
|
||||
case_lookup = lambda nm: [k for k in mapping.schema.keys if k.lower() == nm.lower()][0]
|
||||
case_normalize = lambda nm: nm if nm.startswith("IfcUtil::") else case_lookup(nm)
|
||||
case_normalize = lambda nm: nm if nm.startswith("express::") else case_lookup(nm)
|
||||
create_supertype_statement = lambda nms: ", ".join(
|
||||
"public %s %s" % ("" if c.startswith("IfcUtil::") else "", c) for c in nms
|
||||
"public %s %s" % ("" if c.startswith("express::") else "", c) for c in nms
|
||||
)
|
||||
|
||||
write = lambda str, **kwargs: declarations.append(
|
||||
@@ -43,7 +41,7 @@ class Header(codegen.Base):
|
||||
% dict({"documentation": templates.multi_line_comment(documentation.description(kwargs["name"]))}, **kwargs)
|
||||
)
|
||||
|
||||
forward_names = list(mapping.schema.entities.keys()) + list(mapping.schema.simpletypes.keys())
|
||||
forward_names = list(mapping.schema.entities.keys()) + list(mapping.schema.simpletypes.keys()) + list(mapping.schema.selects.keys())
|
||||
forward_definitions = "".join(["class %s; " % n for n in forward_names])
|
||||
|
||||
select_super_types = defaultdict(list)
|
||||
@@ -51,7 +49,20 @@ class Header(codegen.Base):
|
||||
for name, type in mapping.schema.selects.items():
|
||||
for nm in type.values:
|
||||
select_super_types[str(nm).lower()].append(name)
|
||||
write(templates.select_virtual if USE_VIRTUAL_INHERITANCE else templates.select_plain, name=name)
|
||||
|
||||
# Previously we used (virtual) inheritance, now we use casts to go from Base to Select.
|
||||
# Casts only go one conversion step deep, so we need to explicitly all descendant selected leafs.
|
||||
def visit_select(s):
|
||||
for x in map(str, s.values):
|
||||
yield x
|
||||
if mapping.schema.is_select(x):
|
||||
yield from visit_select(mapping.schema.selects[x])
|
||||
|
||||
write(templates.select,
|
||||
name=name,
|
||||
template_items="\n".join(templates.select_list_item % {'item_name': nm} for nm in visit_select(type)),
|
||||
cast_functions="\n".join(templates.select_cast_function % {'name': name, 'item_name': nm} for nm in visit_select(type)),
|
||||
)
|
||||
|
||||
def get_select_super_types(nm, bases=[]):
|
||||
x = list(select_super_types[nm.lower()])
|
||||
@@ -82,13 +93,15 @@ class Header(codegen.Base):
|
||||
all_superclasses.append(superclass)
|
||||
superclass = mapping.simple_type_parent(superclass)
|
||||
else:
|
||||
superclasses.append("IfcUtil::IfcBaseType")
|
||||
superclasses.append("express::DeclaredType")
|
||||
|
||||
if USE_VIRTUAL_INHERITANCE:
|
||||
superclasses.extend(get_select_super_types(name, bases=all_superclasses))
|
||||
# This is no longer used, previously virtual inheritance was used, now
|
||||
# a variant-like approach is used instead, so the definition of selects
|
||||
# is on the other side again, as it is in Express.
|
||||
# superclasses.extend(get_select_super_types(name, bases=all_superclasses))
|
||||
|
||||
is_emitted = (
|
||||
lambda nm: nm == "IfcUtil::IfcBaseType"
|
||||
lambda nm: nm == "express::DeclaredType"
|
||||
or nm in mapping.schema.selects
|
||||
or nm.lower() in emitted_simpletypes
|
||||
)
|
||||
@@ -99,7 +112,9 @@ class Header(codegen.Base):
|
||||
|
||||
emitted_simpletypes.add(name.lower())
|
||||
|
||||
superclass_statement = create_supertype_statement(superclasses)
|
||||
# with the v1 data model we're back to exactly one supertype, no more virtual inheritance to handle selects
|
||||
assert len(superclasses) == 1
|
||||
superclass_statement = superclasses[0]
|
||||
|
||||
write(
|
||||
templates.simpletype, name=name, type=type_str, attr_type=attr_type, superclass=superclass_statement
|
||||
@@ -128,7 +143,11 @@ class Header(codegen.Base):
|
||||
type_str = mapping.get_parameter_type(attr)
|
||||
if mapping.make_argument_type(attr) != "IfcUtil::Argument_UNKNOWN":
|
||||
attr_lines.append("%s %s() const;" % (type_str, attr.name))
|
||||
attr_lines.append("void set%s(%s v);" % (attr.name, type_str))
|
||||
attr_lines.append("void set%s(const %s& v);" % (attr.name, type_str))
|
||||
if type_str == 'std::optional< std::string >':
|
||||
# because a 2-step char[] -> std::string -> optional<string> is not allowed
|
||||
# attr_lines.append("void set%s(const %s& v);" % (attr.name, 'std::string'))
|
||||
pass
|
||||
|
||||
[write_method(attr) for attr in type.attributes]
|
||||
|
||||
@@ -157,11 +176,11 @@ class Header(codegen.Base):
|
||||
all_supertypes.append(tt.supertypes[0])
|
||||
tt = mapping.schema.entities[tt.supertypes[0]]
|
||||
|
||||
supertypes = list(type.supertypes) if len(type.supertypes) else ["IfcUtil::IfcBaseEntity"]
|
||||
if USE_VIRTUAL_INHERITANCE:
|
||||
supertypes.extend(get_select_super_types(name, bases=all_supertypes))
|
||||
supertypes = list(type.supertypes) if len(type.supertypes) else ["express::Entity"]
|
||||
# supertypes.extend(get_select_super_types(name, bases=all_supertypes))
|
||||
supertypes = list(map(case_normalize, supertypes))
|
||||
superclass = create_supertype_statement(supertypes)
|
||||
assert len(supertypes) == 1
|
||||
superclass = supertypes[0]
|
||||
|
||||
argument_count = mapping.argument_count(type)
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ ENTITY file_name;
|
||||
organization : LIST [1:?] OF STRING (256);
|
||||
preprocessor_version : STRING (256);
|
||||
originating_system : STRING (256);
|
||||
authorisation : STRING (256);
|
||||
authorization : STRING (256);
|
||||
END_ENTITY;
|
||||
|
||||
ENTITY file_description;
|
||||
|
||||
@@ -22,8 +22,6 @@ import templates
|
||||
|
||||
from schema import OrderedCaseInsensitiveDict
|
||||
|
||||
from header import USE_VIRTUAL_INHERITANCE
|
||||
|
||||
|
||||
class Implementation(codegen.Base):
|
||||
def __init__(self, mapping):
|
||||
@@ -70,15 +68,14 @@ class Implementation(codegen.Base):
|
||||
),
|
||||
)
|
||||
|
||||
if USE_VIRTUAL_INHERITANCE:
|
||||
for name, enum in mapping.schema.selects.items():
|
||||
write(
|
||||
templates.select_function,
|
||||
name=name,
|
||||
schema_name=schema_name,
|
||||
schema_name_upper=schema_name_upper,
|
||||
index_in_schema=self.names.index(str(name)),
|
||||
)
|
||||
for name, enum in mapping.schema.selects.items():
|
||||
write(
|
||||
templates.select_function,
|
||||
name=name,
|
||||
schema_name=schema_name,
|
||||
schema_name_upper=schema_name_upper,
|
||||
index_in_schema=self.names.index(str(name)),
|
||||
)
|
||||
|
||||
write = lambda str, **kwargs: entity_implementations.append(str % kwargs)
|
||||
|
||||
@@ -101,7 +98,6 @@ class Implementation(codegen.Base):
|
||||
|
||||
def find_template(arg):
|
||||
simple = mapping.schema.is_simpletype(arg["list_instance_type"])
|
||||
select = arg["list_instance_type"] == "IfcUtil::IfcBaseClass"
|
||||
express = (
|
||||
mapping.flatten_type_string(arg["list_instance_type"]) in mapping.express_to_cpp_typemapping
|
||||
)
|
||||
@@ -109,9 +105,9 @@ class Implementation(codegen.Base):
|
||||
return templates.get_attr_stmt_enum
|
||||
elif arg["is_nested"] and arg["is_templated_list"]:
|
||||
return templates.get_attr_stmt_nested_array
|
||||
elif arg["is_templated_list"] and not (select or simple or express):
|
||||
elif arg["is_templated_list"] and not (simple or express):
|
||||
return templates.get_attr_stmt_array
|
||||
elif arg["non_optional_type"].endswith("*"):
|
||||
elif arg["argument_type_enum"] == 'IfcUtil::Argument_ENTITY_INSTANCE':
|
||||
return templates.get_attr_stmt_entity
|
||||
else:
|
||||
return templates.get_attr_stmt
|
||||
@@ -122,10 +118,10 @@ class Implementation(codegen.Base):
|
||||
"if(get_attribute_value(%d).isNull()) { return %%s; }"
|
||||
% (arg["index"] - 1,)
|
||||
)
|
||||
if "boost::optional" in arg["full_type"]:
|
||||
null_check = attr_check % "boost::none"
|
||||
if "std::optional" in arg["full_type"]:
|
||||
null_check = attr_check % "std::nullopt"
|
||||
else:
|
||||
null_check = attr_check % "nullptr"
|
||||
null_check = attr_check % (arg['full_type'] + "{}")
|
||||
|
||||
tmpl = find_template(arg)
|
||||
write_attr(
|
||||
@@ -151,13 +147,14 @@ class Implementation(codegen.Base):
|
||||
|
||||
def find_template(arg):
|
||||
simple = mapping.schema.is_simpletype(arg["list_instance_type"])
|
||||
select = arg["list_instance_type"] == "IfcUtil::IfcBaseClass"
|
||||
express = arg["list_instance_type"] in mapping.express_to_cpp_typemapping
|
||||
if arg["is_enum"]:
|
||||
return templates.set_attr_stmt_enum
|
||||
elif arg["is_templated_list"] and not (select or simple or express):
|
||||
elif arg["is_nested"] and arg["is_templated_list"]:
|
||||
return templates.set_attr_stmt_nested_array
|
||||
elif arg["is_templated_list"] and not (simple or express):
|
||||
return templates.set_attr_stmt_array
|
||||
elif arg["full_type"].endswith('*'):
|
||||
elif arg["argument_type_enum"] == 'IfcUtil::Argument_ENTITY_INSTANCE':
|
||||
return templates.set_attr_instance
|
||||
else:
|
||||
return templates.set_attr_stmt
|
||||
@@ -167,7 +164,7 @@ class Implementation(codegen.Base):
|
||||
templates.function,
|
||||
class_name=name,
|
||||
name="set%s" % arg["name"],
|
||||
arguments="%s v" % arg["full_type"],
|
||||
arguments="const %s& v" % arg["full_type"],
|
||||
return_type="void",
|
||||
schema_name=schema_name,
|
||||
schema_name_upper=schema_name_upper,
|
||||
@@ -176,10 +173,10 @@ class Implementation(codegen.Base):
|
||||
"index": arg["index"] - 1,
|
||||
"type": arg["full_type"].replace("::Value", ""),
|
||||
"non_optional_type": arg["non_optional_type"].replace("::Value", ""),
|
||||
"star_if_optional": "*" if "boost::optional" in arg["full_type"] else "",
|
||||
"check_optional_set_begin": "if (v) {" if "boost::optional" in arg["full_type"] else "",
|
||||
"check_optional_set_else": "} else {" if "boost::optional" in arg["full_type"] else "if constexpr (false)",
|
||||
"check_optional_set_end": "}" if "boost::optional" in arg["full_type"] else "",
|
||||
"star_if_optional": "*" if "std::optional" in arg["full_type"] else "",
|
||||
"check_optional_set_begin": "if (v) {" if "std::optional" in arg["full_type"] else "",
|
||||
"check_optional_set_else": "} else {" if "std::optional" in arg["full_type"] else "if constexpr (false)",
|
||||
"check_optional_set_end": "}" if "std::optional" in arg["full_type"] else "",
|
||||
},
|
||||
)
|
||||
|
||||
@@ -226,7 +223,7 @@ class Implementation(codegen.Base):
|
||||
"schema_name_upper": schema_name_upper,
|
||||
"name": i.name,
|
||||
"arguments": "",
|
||||
"return_type": "::%s::%s::list::ptr" % (schema_name, i.entity),
|
||||
"return_type": "std::vector<::%s::%s>" % (schema_name, i.entity),
|
||||
"body": templates.get_inverse
|
||||
% {
|
||||
"type": i.entity,
|
||||
@@ -240,15 +237,15 @@ class Implementation(codegen.Base):
|
||||
]
|
||||
|
||||
superclass = (
|
||||
"%s(std::move(e))" % type.supertypes[0]
|
||||
"%s(e)" % type.supertypes[0]
|
||||
if len(type.supertypes) == 1
|
||||
else "IfcUtil::IfcBaseEntity(std::move(e))"
|
||||
else "express::Entity(e)"
|
||||
)
|
||||
|
||||
superclass_num_attrs = (
|
||||
"%s(IfcEntityInstanceData(in_memory_attribute_storage(%%d)))" % type.supertypes[0]
|
||||
"%s(const std::weak_ptr<InstanceData>&(in_memory_attribute_storage(%%d)))" % type.supertypes[0]
|
||||
if len(type.supertypes) == 1
|
||||
else "IfcUtil::IfcBaseEntity(IfcEntityInstanceData(in_memory_attribute_storage(%d)))"
|
||||
else "express::Entity(const std::weak_ptr<InstanceData>&(in_memory_attribute_storage(%d)))"
|
||||
) % len(constructor_arguments)
|
||||
|
||||
write(
|
||||
@@ -313,7 +310,7 @@ class Implementation(codegen.Base):
|
||||
for class_name, type in mapping.schema.simpletypes.items():
|
||||
type_str = mapping.make_type_string(mapping.flatten_type_string(type))
|
||||
attr_type = mapping.make_argument_type(type)
|
||||
superclass = mapping.simple_type_parent(class_name) or "IfcUtil::IfcBaseType"
|
||||
superclass = mapping.simple_type_parent(class_name) or "express::DeclaredType"
|
||||
|
||||
simpletype_impl_is = (
|
||||
templates.simpletype_impl_is_with_supertype
|
||||
@@ -358,24 +355,24 @@ class Implementation(codegen.Base):
|
||||
(),
|
||||
templates.simpletype_impl_class,
|
||||
),
|
||||
(
|
||||
"",
|
||||
"declaration",
|
||||
templates.const_function,
|
||||
"const IfcParse::type_declaration&",
|
||||
(),
|
||||
templates.simpletype_impl_declaration,
|
||||
),
|
||||
(
|
||||
"std::move(e)",
|
||||
"",
|
||||
constructor,
|
||||
"",
|
||||
("IfcEntityInstanceData&& e",),
|
||||
"",
|
||||
),
|
||||
("", "", constructor, "", ("%s v" % type_str,), ("set_attribute_value(0, v%s);" % ("->generalize()" if mapping.is_templated_list(type) else ""))) if mapping.simple_type_parent(class_name) is None else \
|
||||
("v", "", constructor, "", ("%s v" % type_str,), ""),
|
||||
# (
|
||||
# "",
|
||||
# "declaration",
|
||||
# templates.const_function,
|
||||
# "const IfcParse::type_declaration&",
|
||||
# (),
|
||||
# templates.simpletype_impl_declaration,
|
||||
# ),
|
||||
# (
|
||||
# "e",
|
||||
# "",
|
||||
# constructor,
|
||||
# "",
|
||||
# ("const std::weak_ptr<InstanceData>& e",),
|
||||
# "",
|
||||
# ),
|
||||
# ("", "", constructor, "", ("%s v" % type_str,), ("set_attribute_value(0, v%s);" % ("->generalize()" if mapping.is_templated_list(type) else ""))) if mapping.simple_type_parent(class_name) is None else \
|
||||
# ("v", "", constructor, "", ("%s v" % type_str,), ""),
|
||||
("", "", templates.cast_function, type_str, (), simpletype_impl_cast),
|
||||
),
|
||||
),
|
||||
|
||||
@@ -23,8 +23,6 @@ import nodes
|
||||
import templates
|
||||
import schema
|
||||
|
||||
from header import USE_VIRTUAL_INHERITANCE
|
||||
|
||||
class Mapping:
|
||||
|
||||
express_to_cpp_typemapping = {
|
||||
@@ -177,15 +175,8 @@ class Mapping:
|
||||
elif isinstance(type_str, nodes.AggregationType):
|
||||
is_nested_list = isinstance(attr_type.type, nodes.AggregationType)
|
||||
ty = self.get_parameter_type(attr_type.type if is_nested_list else attr_type)
|
||||
# We do not use pointers in aggregate_of<T>. aggregate_of has member vector<T*>
|
||||
ty = ty.replace("*", "")
|
||||
|
||||
# https://github.com/IfcOpenShell/IfcOpenShell/issues/2805
|
||||
# We do support statically typed select types as aggregates when USE_VIRTUAL_INHERITANCE=True
|
||||
|
||||
if not USE_VIRTUAL_INHERITANCE and self.schema.is_select(attr_type.type):
|
||||
type_str = templates.untyped_list
|
||||
elif self.schema.is_simpletype(ty) or str(ty) in self.express_to_cpp_typemapping.values():
|
||||
if self.schema.is_simpletype(ty) or str(ty) in self.express_to_cpp_typemapping.values():
|
||||
tmpl = templates.nested_array_type if is_nested_list else templates.array_type
|
||||
bounds = (attr_type.bounds.lower, attr_type.bounds.upper) if attr_type.bounds else (-1, -1)
|
||||
type_str = tmpl % {"instance_type": ty, "lower": bounds[0], "upper": bounds[1]}
|
||||
@@ -193,11 +184,11 @@ class Mapping:
|
||||
tmpl = templates.list_list_type if is_nested_list else templates.list_type
|
||||
type_str = tmpl % {"instance_type": ty}
|
||||
elif self.schema.is_entity(type_str) or self.schema.is_select(type_str):
|
||||
type_str = "::%s::%s*" % (self.schema.name.capitalize(), attr_type)
|
||||
type_str = "::%s::%s" % (self.schema.name.capitalize(), attr_type)
|
||||
is_ptr = True
|
||||
if allow_optional and attr.optional and not is_ptr:
|
||||
# pointers are still handled with nullptr for the time being
|
||||
type_str = "boost::optional< %s >" % type_str
|
||||
type_str = "std::optional< %s >" % type_str
|
||||
return type_str
|
||||
|
||||
def argument_count(self, t):
|
||||
@@ -224,8 +215,6 @@ class Mapping:
|
||||
isinstance(v, nodes.SimpleType) and isinstance(v.type, nodes.StringType)
|
||||
):
|
||||
return "string"
|
||||
if not USE_VIRTUAL_INHERITANCE and self.schema.is_select(v):
|
||||
return "IfcUtil::IfcBaseClass"
|
||||
if str(v) in self.schema.types or str(v) in self.schema.entities:
|
||||
return "::%s::%s" % (self.schema.name.capitalize(), v)
|
||||
else:
|
||||
@@ -254,8 +243,8 @@ class Mapping:
|
||||
arr = self.is_array(attr_type)
|
||||
simple = self.schema.is_simpletype(ty)
|
||||
express = self.flatten_type_string(ty) in self.express_to_cpp_typemapping
|
||||
select = ty == "IfcUtil::IfcBaseClass"
|
||||
return arr and not simple and not express and not select
|
||||
# select = ty == "IfcUtil::IfcBaseClass"
|
||||
return arr and not simple and not express
|
||||
|
||||
def get_assignable_arguments(self, t, include_derived=False):
|
||||
count = self.argument_count(t)
|
||||
|
||||
@@ -738,7 +738,7 @@ class AttributeGetattrTransformer(ast.NodeTransformer):
|
||||
while n := getattr(n, "parent", 0):
|
||||
parents.append(n)
|
||||
|
||||
custom_funcs = "is_entity", "usedin", "express_len", "express_getitem", "typeof"
|
||||
custom_funcs = "is_entity", "usedin", "express_len", "express_getitem", "typeof", "express_getattr"
|
||||
function_defs = [p.name for p in parents if isinstance(p, ast.FunctionDef)]
|
||||
if any(fn in function_defs for fn in custom_funcs):
|
||||
return node
|
||||
@@ -755,7 +755,7 @@ class AttributeGetattrTransformer(ast.NodeTransformer):
|
||||
# Replace the Attribute node with a call to the built-in `getattr` function
|
||||
return ast.copy_location(
|
||||
ast.Call(
|
||||
func=ast.Name(id="getattr", ctx=ast.Load()),
|
||||
func=ast.Name(id="express_getattr", ctx=ast.Load()),
|
||||
args=[
|
||||
new_value,
|
||||
ast.Str(s=node.attr),
|
||||
@@ -772,7 +772,7 @@ class AttributeGetattrTransformer(ast.NodeTransformer):
|
||||
while n := getattr(n, "parent", 0):
|
||||
parents.append(n)
|
||||
|
||||
custom_funcs = "is_entity", "usedin", "express_len", "express_getitem", "typeof"
|
||||
custom_funcs = "is_entity", "usedin", "express_len", "express_getitem", "typeof", "express_getattr"
|
||||
function_defs = [p.name for p in parents if isinstance(p, ast.FunctionDef)]
|
||||
if any(fn in function_defs for fn in custom_funcs):
|
||||
return node
|
||||
@@ -937,6 +937,14 @@ def express_getitem(aggr, idx, default):
|
||||
except IndexError as e: return None
|
||||
|
||||
|
||||
def express_getattr(aggr, name, default):
|
||||
v = getattr(aggr, name, default)
|
||||
if v is None:
|
||||
return default
|
||||
else:
|
||||
return v
|
||||
|
||||
|
||||
EXPRESS_ONE_BASED_INDEXING = 1
|
||||
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ from codegen import indent
|
||||
|
||||
|
||||
def reverse_compile(s):
|
||||
return re.sub(
|
||||
return re.sub(r'\bself\b', 'SELF', re.sub(
|
||||
r"\s*\-\s*EXPRESS_ONE_BASED_INDEXING",
|
||||
"",
|
||||
re.sub(
|
||||
@@ -22,11 +22,11 @@ def reverse_compile(s):
|
||||
.replace("len(", "SIZEOF(")
|
||||
.replace("assert ", "")
|
||||
.replace(" is not False", "")
|
||||
.replace("getattr(", "")
|
||||
.replace("express_getattr(", "")
|
||||
.replace("express_getitem(", ""),
|
||||
)[::-1],
|
||||
)[::-1],
|
||||
)
|
||||
))
|
||||
|
||||
|
||||
@dataclass
|
||||
|
||||
@@ -2,173 +2,173 @@
|
||||
|
||||
:: python bootstrap.py express.bnf > express_parser.py
|
||||
|
||||
IF EXIST IFC2X3_TC1.exp (
|
||||
python express_parser.py IFC2X3_TC1.exp header implementation schema_class definitions
|
||||
|
||||
IF EXIST Ifc2x3-schema.cpp (
|
||||
:: v0.6.0
|
||||
python cat.py -o ..\..\..\ifcparse\Ifc2x3.cpp txt/header_ifc2x3.txt Ifc2x3.cpp
|
||||
python cat.py -o ..\..\..\ifcparse\Ifc2x3.h txt/header_ifc2x3.txt Ifc2x3.h
|
||||
python cat.py -o ..\..\..\ifcparse\Ifc2x3-schema.cpp txt/header_ifc2x3.txt Ifc2x3-schema.cpp
|
||||
python cat.py -o ..\..\..\ifcparse\Ifc2x3-definitions.h txt/header_ifc2x3.txt Ifc2x3-definitions.h
|
||||
) ELSE (
|
||||
:: v0.5.0
|
||||
python cat.py -o ..\..\..\ifcparse\Ifc2x3.cpp txt/header_ifc2x3.txt txt/ifndef_ifc4.txt Ifc2x3.cpp txt/endif.txt
|
||||
python cat.py -o ..\..\..\ifcparse\Ifc2x3.h txt/header_ifc2x3.txt Ifc2x3.h
|
||||
python cat.py -o ..\..\..\ifcparse\Ifc2x3enum.h txt/header_ifc2x3.txt Ifc2x3enum.h
|
||||
python cat.py -o ..\..\..\ifcparse\Ifc2x3-latebound.cpp txt/header_ifc2x3.txt txt/ifndef_ifc4.txt Ifc2x3-latebound.cpp txt/endif.txt
|
||||
python cat.py -o ..\..\..\ifcparse\Ifc2x3-latebound.h txt/header_ifc2x3.txt Ifc2x3-latebound.h
|
||||
)
|
||||
|
||||
del *.cpp *.h
|
||||
)
|
||||
|
||||
IF EXIST IFC4_ADD2TC1.exp (
|
||||
python express_parser.py IFC4_ADD2TC1.exp header implementation schema_class definitions
|
||||
|
||||
IF EXIST Ifc4-schema.cpp (
|
||||
:: v0.6.0
|
||||
python cat.py -o ..\..\..\ifcparse\Ifc4.cpp txt/header_ifc4.txt Ifc4.cpp
|
||||
python cat.py -o ..\..\..\ifcparse\Ifc4.h txt/header_ifc4.txt Ifc4.h
|
||||
python cat.py -o ..\..\..\ifcparse\Ifc4-schema.cpp txt/header_ifc4.txt Ifc4-schema.cpp
|
||||
python cat.py -o ..\..\..\ifcparse\Ifc4-definitions.h txt/header_ifc4.txt Ifc4-definitions.h
|
||||
) ELSE (
|
||||
:: v0.5.0
|
||||
python cat.py -o ..\..\..\ifcparse\Ifc4.cpp txt/header_ifc4.txt txt/ifdef_ifc4.txt Ifc4.cpp txt/endif.txt
|
||||
python cat.py -o ..\..\..\ifcparse\Ifc4.h txt/header_ifc4.txt Ifc4.h
|
||||
python cat.py -o ..\..\..\ifcparse\Ifc4enum.h txt/header_ifc4.txt Ifc4enum.h
|
||||
python cat.py -o ..\..\..\ifcparse\Ifc4-latebound.cpp txt/header_ifc4.txt txt/ifdef_ifc4.txt Ifc4-latebound.cpp txt/endif.txt
|
||||
python cat.py -o ..\..\..\ifcparse\Ifc4-latebound.h txt/header_ifc4.txt Ifc4-latebound.h
|
||||
)
|
||||
|
||||
del *.cpp *.h
|
||||
)
|
||||
|
||||
IF EXIST IFC4x1.exp (
|
||||
python express_parser.py IFC4x1.exp header implementation schema_class definitions
|
||||
|
||||
IF EXIST Ifc4x1-schema.cpp (
|
||||
:: v0.6.0
|
||||
python cat.py -o ..\..\..\ifcparse\Ifc4x1.cpp txt/header_ifc4x1.txt Ifc4x1.cpp
|
||||
python cat.py -o ..\..\..\ifcparse\Ifc4x1.h txt/header_ifc4x1.txt Ifc4x1.h
|
||||
python cat.py -o ..\..\..\ifcparse\Ifc4x1-schema.cpp txt/header_ifc4x1.txt Ifc4x1-schema.cpp
|
||||
python cat.py -o ..\..\..\ifcparse\Ifc4x1-definitions.h txt/header_ifc4x1.txt Ifc4x1-definitions.h
|
||||
)
|
||||
|
||||
del *.cpp *.h
|
||||
)
|
||||
|
||||
IF EXIST IFC4x2.exp (
|
||||
python express_parser.py IFC4x2.exp header implementation schema_class definitions
|
||||
|
||||
IF EXIST Ifc4x2-schema.cpp (
|
||||
:: v0.6.0
|
||||
python cat.py -o ..\..\..\ifcparse\Ifc4x2.cpp txt/header_ifc4x2.txt Ifc4x2.cpp
|
||||
python cat.py -o ..\..\..\ifcparse\Ifc4x2.h txt/header_ifc4x2.txt Ifc4x2.h
|
||||
python cat.py -o ..\..\..\ifcparse\Ifc4x2-schema.cpp txt/header_ifc4x2.txt Ifc4x2-schema.cpp
|
||||
python cat.py -o ..\..\..\ifcparse\Ifc4x2-definitions.h txt/header_ifc4x2.txt Ifc4x2-definitions.h
|
||||
)
|
||||
|
||||
del *.cpp *.h
|
||||
)
|
||||
|
||||
IF EXIST IFC4x3_RC1.exp (
|
||||
python express_parser.py IFC4x3_RC1.exp header implementation schema_class definitions
|
||||
|
||||
IF EXIST Ifc4x3_rc1-schema.cpp (
|
||||
:: v0.6.0
|
||||
python cat.py -o ..\..\..\ifcparse\Ifc4x3_rc1.cpp txt/header_ifc4x3_rc1.txt Ifc4x3_rc1.cpp
|
||||
python cat.py -o ..\..\..\ifcparse\Ifc4x3_rc1.h txt/header_ifc4x3_rc1.txt Ifc4x3_rc1.h
|
||||
python cat.py -o ..\..\..\ifcparse\Ifc4x3_rc1-schema.cpp txt/header_ifc4x3_rc1.txt Ifc4x3_rc1-schema.cpp
|
||||
python cat.py -o ..\..\..\ifcparse\Ifc4x3_rc1-definitions.h txt/header_ifc4x3_rc1.txt Ifc4x3_rc1-definitions.h
|
||||
)
|
||||
|
||||
del *.cpp *.h
|
||||
)
|
||||
|
||||
IF EXIST IFC4x3_RC2.exp (
|
||||
python express_parser.py IFC4x3_RC2.exp header implementation schema_class definitions
|
||||
|
||||
IF EXIST Ifc4x3_rc2-schema.cpp (
|
||||
:: v0.6.0
|
||||
python cat.py -o ..\..\..\ifcparse\Ifc4x3_rc2.cpp txt/header_ifc4x3_rc2.txt Ifc4x3_rc2.cpp
|
||||
python cat.py -o ..\..\..\ifcparse\Ifc4x3_rc2.h txt/header_ifc4x3_rc2.txt Ifc4x3_rc2.h
|
||||
python cat.py -o ..\..\..\ifcparse\Ifc4x3_rc2-schema.cpp txt/header_ifc4x3_rc2.txt Ifc4x3_rc2-schema.cpp
|
||||
python cat.py -o ..\..\..\ifcparse\Ifc4x3_rc2-definitions.h txt/header_ifc4x3_rc2.txt Ifc4x3_rc2-definitions.h
|
||||
)
|
||||
|
||||
del *.cpp *.h
|
||||
)
|
||||
|
||||
IF EXIST IFC4x3_RC3.exp (
|
||||
python express_parser.py IFC4x3_RC3.exp header implementation schema_class definitions
|
||||
|
||||
IF EXIST Ifc4x3_rc3-schema.cpp (
|
||||
:: v0.6.0
|
||||
python cat.py -o ..\..\..\ifcparse\Ifc4x3_rc3.cpp txt/header_ifc4x3_rc2.txt Ifc4x3_rc3.cpp
|
||||
python cat.py -o ..\..\..\ifcparse\Ifc4x3_rc3.h txt/header_ifc4x3_rc2.txt Ifc4x3_rc3.h
|
||||
python cat.py -o ..\..\..\ifcparse\Ifc4x3_rc3-schema.cpp txt/header_ifc4x3_rc2.txt Ifc4x3_rc3-schema.cpp
|
||||
python cat.py -o ..\..\..\ifcparse\Ifc4x3_rc3-definitions.h txt/header_ifc4x3_rc2.txt Ifc4x3_rc3-definitions.h
|
||||
)
|
||||
|
||||
del *.cpp *.h
|
||||
)
|
||||
|
||||
IF EXIST IFC4x3_RC4.exp (
|
||||
python express_parser.py IFC4x3_RC4.exp header implementation schema_class definitions
|
||||
|
||||
IF EXIST Ifc4x3_rc4-schema.cpp (
|
||||
:: v0.6.0
|
||||
python cat.py -o ..\..\..\ifcparse\Ifc4x3_rc4.cpp txt/header_ifc4x3_rc2.txt Ifc4x3_rc4.cpp
|
||||
python cat.py -o ..\..\..\ifcparse\Ifc4x3_rc4.h txt/header_ifc4x3_rc2.txt Ifc4x3_rc4.h
|
||||
python cat.py -o ..\..\..\ifcparse\Ifc4x3_rc4-schema.cpp txt/header_ifc4x3_rc2.txt Ifc4x3_rc4-schema.cpp
|
||||
python cat.py -o ..\..\..\ifcparse\Ifc4x3_rc4-definitions.h txt/header_ifc4x3_rc2.txt Ifc4x3_rc4-definitions.h
|
||||
)
|
||||
|
||||
del *.cpp *.h
|
||||
)
|
||||
|
||||
IF EXIST IFC4X3.exp (
|
||||
python express_parser.py IFC4X3.exp header implementation schema_class definitions
|
||||
|
||||
IF EXIST Ifc4x3-schema.cpp (
|
||||
:: v0.6.0
|
||||
python cat.py -o ..\..\..\ifcparse\Ifc4x3.cpp txt/header_ifc4x3_rc2.txt Ifc4x3.cpp
|
||||
python cat.py -o ..\..\..\ifcparse\Ifc4x3.h txt/header_ifc4x3_rc2.txt Ifc4x3.h
|
||||
python cat.py -o ..\..\..\ifcparse\Ifc4x3-schema.cpp txt/header_ifc4x3_rc2.txt Ifc4x3-schema.cpp
|
||||
python cat.py -o ..\..\..\ifcparse\Ifc4x3-definitions.h txt/header_ifc4x3_rc2.txt Ifc4x3-definitions.h
|
||||
)
|
||||
|
||||
del *.cpp *.h
|
||||
)
|
||||
|
||||
IF EXIST IFC4X3_TC1.exp (
|
||||
python express_parser.py IFC4X3_TC1.exp header implementation schema_class definitions
|
||||
|
||||
IF EXIST Ifc4x3_tc1-schema.cpp (
|
||||
:: v0.6.0
|
||||
python cat.py -o ..\..\..\ifcparse\Ifc4x3_tc1.cpp txt/header_ifc4x3_tc1.txt Ifc4x3_tc1.cpp
|
||||
python cat.py -o ..\..\..\ifcparse\Ifc4x3_tc1.h txt/header_ifc4x3_tc1.txt Ifc4x3_tc1.h
|
||||
python cat.py -o ..\..\..\ifcparse\Ifc4x3_tc1-schema.cpp txt/header_ifc4x3_tc1.txt Ifc4x3_tc1-schema.cpp
|
||||
python cat.py -o ..\..\..\ifcparse\Ifc4x3_tc1-definitions.h txt/header_ifc4x3_tc1.txt Ifc4x3_tc1-definitions.h
|
||||
)
|
||||
|
||||
del *.cpp *.h
|
||||
)
|
||||
|
||||
IF EXIST IFC4X3_ADD1.exp (
|
||||
python express_parser.py IFC4X3_ADD1.exp header implementation schema_class definitions
|
||||
|
||||
IF EXIST Ifc4x3_add1-schema.cpp (
|
||||
:: v0.6.0
|
||||
python cat.py -o ..\..\..\ifcparse\Ifc4x3_add1.cpp txt/header_ifc4x3_add1.txt Ifc4x3_add1.cpp
|
||||
python cat.py -o ..\..\..\ifcparse\Ifc4x3_add1.h txt/header_ifc4x3_add1.txt Ifc4x3_add1.h
|
||||
python cat.py -o ..\..\..\ifcparse\Ifc4x3_add1-schema.cpp txt/header_ifc4x3_add1.txt Ifc4x3_add1-schema.cpp
|
||||
python cat.py -o ..\..\..\ifcparse\Ifc4x3_add1-definitions.h txt/header_ifc4x3_add1.txt Ifc4x3_add1-definitions.h
|
||||
)
|
||||
|
||||
del *.cpp *.h
|
||||
)
|
||||
:: IF EXIST IFC2X3_TC1.exp (
|
||||
:: python express_parser.py IFC2X3_TC1.exp header implementation schema_class definitions
|
||||
::
|
||||
:: IF EXIST Ifc2x3-schema.cpp (
|
||||
:: :: v0.6.0
|
||||
:: python cat.py -o ..\..\..\ifcparse\Ifc2x3.cpp txt/header_ifc2x3.txt Ifc2x3.cpp
|
||||
:: python cat.py -o ..\..\..\ifcparse\Ifc2x3.h txt/header_ifc2x3.txt Ifc2x3.h
|
||||
:: python cat.py -o ..\..\..\ifcparse\Ifc2x3-schema.cpp txt/header_ifc2x3.txt Ifc2x3-schema.cpp
|
||||
:: python cat.py -o ..\..\..\ifcparse\Ifc2x3-definitions.h txt/header_ifc2x3.txt Ifc2x3-definitions.h
|
||||
:: ) ELSE (
|
||||
:: :: v0.5.0
|
||||
:: python cat.py -o ..\..\..\ifcparse\Ifc2x3.cpp txt/header_ifc2x3.txt txt/ifndef_ifc4.txt Ifc2x3.cpp txt/endif.txt
|
||||
:: python cat.py -o ..\..\..\ifcparse\Ifc2x3.h txt/header_ifc2x3.txt Ifc2x3.h
|
||||
:: python cat.py -o ..\..\..\ifcparse\Ifc2x3enum.h txt/header_ifc2x3.txt Ifc2x3enum.h
|
||||
:: python cat.py -o ..\..\..\ifcparse\Ifc2x3-latebound.cpp txt/header_ifc2x3.txt txt/ifndef_ifc4.txt Ifc2x3-latebound.cpp txt/endif.txt
|
||||
:: python cat.py -o ..\..\..\ifcparse\Ifc2x3-latebound.h txt/header_ifc2x3.txt Ifc2x3-latebound.h
|
||||
:: )
|
||||
::
|
||||
:: del *.cpp *.h
|
||||
:: )
|
||||
::
|
||||
:: IF EXIST IFC4_ADD2TC1.exp (
|
||||
:: python express_parser.py IFC4_ADD2TC1.exp header implementation schema_class definitions
|
||||
::
|
||||
:: IF EXIST Ifc4-schema.cpp (
|
||||
:: :: v0.6.0
|
||||
:: python cat.py -o ..\..\..\ifcparse\Ifc4.cpp txt/header_ifc4.txt Ifc4.cpp
|
||||
:: python cat.py -o ..\..\..\ifcparse\Ifc4.h txt/header_ifc4.txt Ifc4.h
|
||||
:: python cat.py -o ..\..\..\ifcparse\Ifc4-schema.cpp txt/header_ifc4.txt Ifc4-schema.cpp
|
||||
:: python cat.py -o ..\..\..\ifcparse\Ifc4-definitions.h txt/header_ifc4.txt Ifc4-definitions.h
|
||||
:: ) ELSE (
|
||||
:: :: v0.5.0
|
||||
:: python cat.py -o ..\..\..\ifcparse\Ifc4.cpp txt/header_ifc4.txt txt/ifdef_ifc4.txt Ifc4.cpp txt/endif.txt
|
||||
:: python cat.py -o ..\..\..\ifcparse\Ifc4.h txt/header_ifc4.txt Ifc4.h
|
||||
:: python cat.py -o ..\..\..\ifcparse\Ifc4enum.h txt/header_ifc4.txt Ifc4enum.h
|
||||
:: python cat.py -o ..\..\..\ifcparse\Ifc4-latebound.cpp txt/header_ifc4.txt txt/ifdef_ifc4.txt Ifc4-latebound.cpp txt/endif.txt
|
||||
:: python cat.py -o ..\..\..\ifcparse\Ifc4-latebound.h txt/header_ifc4.txt Ifc4-latebound.h
|
||||
:: )
|
||||
::
|
||||
:: del *.cpp *.h
|
||||
:: )
|
||||
::
|
||||
:: IF EXIST IFC4x1.exp (
|
||||
:: python express_parser.py IFC4x1.exp header implementation schema_class definitions
|
||||
::
|
||||
:: IF EXIST Ifc4x1-schema.cpp (
|
||||
:: :: v0.6.0
|
||||
:: python cat.py -o ..\..\..\ifcparse\Ifc4x1.cpp txt/header_ifc4x1.txt Ifc4x1.cpp
|
||||
:: python cat.py -o ..\..\..\ifcparse\Ifc4x1.h txt/header_ifc4x1.txt Ifc4x1.h
|
||||
:: python cat.py -o ..\..\..\ifcparse\Ifc4x1-schema.cpp txt/header_ifc4x1.txt Ifc4x1-schema.cpp
|
||||
:: python cat.py -o ..\..\..\ifcparse\Ifc4x1-definitions.h txt/header_ifc4x1.txt Ifc4x1-definitions.h
|
||||
:: )
|
||||
::
|
||||
:: del *.cpp *.h
|
||||
:: )
|
||||
::
|
||||
:: IF EXIST IFC4x2.exp (
|
||||
:: python express_parser.py IFC4x2.exp header implementation schema_class definitions
|
||||
::
|
||||
:: IF EXIST Ifc4x2-schema.cpp (
|
||||
:: :: v0.6.0
|
||||
:: python cat.py -o ..\..\..\ifcparse\Ifc4x2.cpp txt/header_ifc4x2.txt Ifc4x2.cpp
|
||||
:: python cat.py -o ..\..\..\ifcparse\Ifc4x2.h txt/header_ifc4x2.txt Ifc4x2.h
|
||||
:: python cat.py -o ..\..\..\ifcparse\Ifc4x2-schema.cpp txt/header_ifc4x2.txt Ifc4x2-schema.cpp
|
||||
:: python cat.py -o ..\..\..\ifcparse\Ifc4x2-definitions.h txt/header_ifc4x2.txt Ifc4x2-definitions.h
|
||||
:: )
|
||||
::
|
||||
:: del *.cpp *.h
|
||||
:: )
|
||||
::
|
||||
:: IF EXIST IFC4x3_RC1.exp (
|
||||
:: python express_parser.py IFC4x3_RC1.exp header implementation schema_class definitions
|
||||
::
|
||||
:: IF EXIST Ifc4x3_rc1-schema.cpp (
|
||||
:: :: v0.6.0
|
||||
:: python cat.py -o ..\..\..\ifcparse\Ifc4x3_rc1.cpp txt/header_ifc4x3_rc1.txt Ifc4x3_rc1.cpp
|
||||
:: python cat.py -o ..\..\..\ifcparse\Ifc4x3_rc1.h txt/header_ifc4x3_rc1.txt Ifc4x3_rc1.h
|
||||
:: python cat.py -o ..\..\..\ifcparse\Ifc4x3_rc1-schema.cpp txt/header_ifc4x3_rc1.txt Ifc4x3_rc1-schema.cpp
|
||||
:: python cat.py -o ..\..\..\ifcparse\Ifc4x3_rc1-definitions.h txt/header_ifc4x3_rc1.txt Ifc4x3_rc1-definitions.h
|
||||
:: )
|
||||
::
|
||||
:: del *.cpp *.h
|
||||
:: )
|
||||
::
|
||||
:: IF EXIST IFC4x3_RC2.exp (
|
||||
:: python express_parser.py IFC4x3_RC2.exp header implementation schema_class definitions
|
||||
::
|
||||
:: IF EXIST Ifc4x3_rc2-schema.cpp (
|
||||
:: :: v0.6.0
|
||||
:: python cat.py -o ..\..\..\ifcparse\Ifc4x3_rc2.cpp txt/header_ifc4x3_rc2.txt Ifc4x3_rc2.cpp
|
||||
:: python cat.py -o ..\..\..\ifcparse\Ifc4x3_rc2.h txt/header_ifc4x3_rc2.txt Ifc4x3_rc2.h
|
||||
:: python cat.py -o ..\..\..\ifcparse\Ifc4x3_rc2-schema.cpp txt/header_ifc4x3_rc2.txt Ifc4x3_rc2-schema.cpp
|
||||
:: python cat.py -o ..\..\..\ifcparse\Ifc4x3_rc2-definitions.h txt/header_ifc4x3_rc2.txt Ifc4x3_rc2-definitions.h
|
||||
:: )
|
||||
::
|
||||
:: del *.cpp *.h
|
||||
:: )
|
||||
::
|
||||
:: IF EXIST IFC4x3_RC3.exp (
|
||||
:: python express_parser.py IFC4x3_RC3.exp header implementation schema_class definitions
|
||||
::
|
||||
:: IF EXIST Ifc4x3_rc3-schema.cpp (
|
||||
:: :: v0.6.0
|
||||
:: python cat.py -o ..\..\..\ifcparse\Ifc4x3_rc3.cpp txt/header_ifc4x3_rc2.txt Ifc4x3_rc3.cpp
|
||||
:: python cat.py -o ..\..\..\ifcparse\Ifc4x3_rc3.h txt/header_ifc4x3_rc2.txt Ifc4x3_rc3.h
|
||||
:: python cat.py -o ..\..\..\ifcparse\Ifc4x3_rc3-schema.cpp txt/header_ifc4x3_rc2.txt Ifc4x3_rc3-schema.cpp
|
||||
:: python cat.py -o ..\..\..\ifcparse\Ifc4x3_rc3-definitions.h txt/header_ifc4x3_rc2.txt Ifc4x3_rc3-definitions.h
|
||||
:: )
|
||||
::
|
||||
:: del *.cpp *.h
|
||||
:: )
|
||||
::
|
||||
:: IF EXIST IFC4x3_RC4.exp (
|
||||
:: python express_parser.py IFC4x3_RC4.exp header implementation schema_class definitions
|
||||
::
|
||||
:: IF EXIST Ifc4x3_rc4-schema.cpp (
|
||||
:: :: v0.6.0
|
||||
:: python cat.py -o ..\..\..\ifcparse\Ifc4x3_rc4.cpp txt/header_ifc4x3_rc2.txt Ifc4x3_rc4.cpp
|
||||
:: python cat.py -o ..\..\..\ifcparse\Ifc4x3_rc4.h txt/header_ifc4x3_rc2.txt Ifc4x3_rc4.h
|
||||
:: python cat.py -o ..\..\..\ifcparse\Ifc4x3_rc4-schema.cpp txt/header_ifc4x3_rc2.txt Ifc4x3_rc4-schema.cpp
|
||||
:: python cat.py -o ..\..\..\ifcparse\Ifc4x3_rc4-definitions.h txt/header_ifc4x3_rc2.txt Ifc4x3_rc4-definitions.h
|
||||
:: )
|
||||
::
|
||||
:: del *.cpp *.h
|
||||
:: )
|
||||
::
|
||||
:: IF EXIST IFC4X3.exp (
|
||||
:: python express_parser.py IFC4X3.exp header implementation schema_class definitions
|
||||
::
|
||||
:: IF EXIST Ifc4x3-schema.cpp (
|
||||
:: :: v0.6.0
|
||||
:: python cat.py -o ..\..\..\ifcparse\Ifc4x3.cpp txt/header_ifc4x3_rc2.txt Ifc4x3.cpp
|
||||
:: python cat.py -o ..\..\..\ifcparse\Ifc4x3.h txt/header_ifc4x3_rc2.txt Ifc4x3.h
|
||||
:: python cat.py -o ..\..\..\ifcparse\Ifc4x3-schema.cpp txt/header_ifc4x3_rc2.txt Ifc4x3-schema.cpp
|
||||
:: python cat.py -o ..\..\..\ifcparse\Ifc4x3-definitions.h txt/header_ifc4x3_rc2.txt Ifc4x3-definitions.h
|
||||
:: )
|
||||
::
|
||||
:: del *.cpp *.h
|
||||
:: )
|
||||
::
|
||||
:: IF EXIST IFC4X3_TC1.exp (
|
||||
:: python express_parser.py IFC4X3_TC1.exp header implementation schema_class definitions
|
||||
::
|
||||
:: IF EXIST Ifc4x3_tc1-schema.cpp (
|
||||
:: :: v0.6.0
|
||||
:: python cat.py -o ..\..\..\ifcparse\Ifc4x3_tc1.cpp txt/header_ifc4x3_tc1.txt Ifc4x3_tc1.cpp
|
||||
:: python cat.py -o ..\..\..\ifcparse\Ifc4x3_tc1.h txt/header_ifc4x3_tc1.txt Ifc4x3_tc1.h
|
||||
:: python cat.py -o ..\..\..\ifcparse\Ifc4x3_tc1-schema.cpp txt/header_ifc4x3_tc1.txt Ifc4x3_tc1-schema.cpp
|
||||
:: python cat.py -o ..\..\..\ifcparse\Ifc4x3_tc1-definitions.h txt/header_ifc4x3_tc1.txt Ifc4x3_tc1-definitions.h
|
||||
:: )
|
||||
::
|
||||
:: del *.cpp *.h
|
||||
:: )
|
||||
::
|
||||
:: IF EXIST IFC4X3_ADD1.exp (
|
||||
:: python express_parser.py IFC4X3_ADD1.exp header implementation schema_class definitions
|
||||
::
|
||||
:: IF EXIST Ifc4x3_add1-schema.cpp (
|
||||
:: :: v0.6.0
|
||||
:: python cat.py -o ..\..\..\ifcparse\Ifc4x3_add1.cpp txt/header_ifc4x3_add1.txt Ifc4x3_add1.cpp
|
||||
:: python cat.py -o ..\..\..\ifcparse\Ifc4x3_add1.h txt/header_ifc4x3_add1.txt Ifc4x3_add1.h
|
||||
:: python cat.py -o ..\..\..\ifcparse\Ifc4x3_add1-schema.cpp txt/header_ifc4x3_add1.txt Ifc4x3_add1-schema.cpp
|
||||
:: python cat.py -o ..\..\..\ifcparse\Ifc4x3_add1-definitions.h txt/header_ifc4x3_add1.txt Ifc4x3_add1-definitions.h
|
||||
:: )
|
||||
::
|
||||
:: del *.cpp *.h
|
||||
:: )
|
||||
|
||||
IF EXIST IFC4X3_ADD2.exp (
|
||||
python express_parser.py IFC4X3_ADD2.exp header implementation schema_class definitions
|
||||
@@ -183,3 +183,17 @@ IF EXIST IFC4X3_ADD2.exp (
|
||||
|
||||
del *.cpp *.h
|
||||
)
|
||||
|
||||
IF EXIST header_schema.exp (
|
||||
python express_parser.py header_schema.exp header implementation schema_class definitions
|
||||
|
||||
IF EXIST Header_section_schema-schema.cpp (
|
||||
:: v0.6.0
|
||||
python cat.py -o ..\..\..\ifcparse\Header_section_schema.cpp Header_section_schema.cpp
|
||||
python cat.py -o ..\..\..\ifcparse\Header_section_schema.h Header_section_schema.h
|
||||
python cat.py -o ..\..\..\ifcparse\Header_section_schema-schema.cpp Header_section_schema-schema.cpp
|
||||
python cat.py -o ..\..\..\ifcparse\Header_section_schema-definitions.h Header_section_schema-definitions.h
|
||||
)
|
||||
|
||||
del *.cpp *.h
|
||||
)
|
||||
@@ -178,7 +178,7 @@ class EarlyBoundCodeWriter:
|
||||
num_names = len(self.names)
|
||||
self.statements.append("declaration* %(schema_name)s_types[%(num_names)d] = {nullptr};" % locals())
|
||||
|
||||
self.statements.append("{factory_placeholder}")
|
||||
# self.statements.append("{factory_placeholder}")
|
||||
|
||||
# self.statements.append(
|
||||
# """
|
||||
@@ -285,7 +285,7 @@ class EarlyBoundCodeWriter:
|
||||
declarations = ",".join(_())
|
||||
schema_name_ref = self.strings.append(schema_name)
|
||||
self.statements.append(
|
||||
' return new schema_definition(%(schema_name_ref)s, {%(declarations)s}, new %(schema_name)s_instance_factory());'
|
||||
' return new schema_definition(%(schema_name_ref)s, {%(declarations)s});'
|
||||
% locals()
|
||||
)
|
||||
self.statements.append("}");
|
||||
@@ -340,16 +340,17 @@ class EarlyBoundCodeWriter:
|
||||
)
|
||||
)
|
||||
|
||||
self.statements[self.statements.index("{factory_placeholder}")] = (
|
||||
"""
|
||||
class %(schema_name)s_instance_factory : public IfcParse::instance_factory {
|
||||
virtual IfcUtil::IfcBaseClass* operator()(const IfcParse::declaration* decl, IfcEntityInstanceData&& data) const {
|
||||
%(instance_mapping)s
|
||||
}
|
||||
};
|
||||
"""
|
||||
% locals()
|
||||
)
|
||||
# Factor no longer exists because we don't have virtual methods anymore.
|
||||
# self.statements[self.statements.index("{factory_placeholder}")] = (
|
||||
# """
|
||||
# class %(schema_name)s_instance_factory : public IfcParse::instance_factory {
|
||||
# virtual IfcUtil::IfcBaseClass* operator()(const IfcParse::declaration* decl, const std::weak_ptr<InstanceData>& data) const {
|
||||
# %(instance_mapping)s
|
||||
# }
|
||||
# };
|
||||
# """
|
||||
# % locals()
|
||||
# )
|
||||
|
||||
""
|
||||
self.statements[self.statements.index("{string_pool_placeholder}")] = (
|
||||
|
||||
@@ -23,17 +23,20 @@ header = """
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <boost/optional.hpp>
|
||||
#include <optional>
|
||||
|
||||
#include "../ifcparse/ifc_parse_api.h"
|
||||
|
||||
#include "../ifcparse/aggregate_of_instance.h"
|
||||
#include "../ifcparse/IfcBaseClass.h"
|
||||
#include "../ifcparse/express.h"
|
||||
#include "../ifcparse/IfcSchema.h"
|
||||
#include "../ifcparse/IfcException.h"
|
||||
#include "../ifcparse/Argument.h"
|
||||
|
||||
namespace IfcParse {
|
||||
class IfcFile;
|
||||
class IfcSpfHeader;
|
||||
} // namespace IfcParse
|
||||
|
||||
struct %(schema_name)s {
|
||||
|
||||
IFC_PARSE_API static const IfcParse::schema_definition& get_schema();
|
||||
@@ -60,7 +63,7 @@ enum_header = """
|
||||
#include "../ifcparse/ifc_parse_api.h"
|
||||
|
||||
#include <string>
|
||||
#include <boost/optional.hpp>
|
||||
#include <optional>
|
||||
|
||||
#endif
|
||||
"""
|
||||
@@ -108,12 +111,14 @@ derived_field_statement = " {std::set<int> idxs; %(statements)sderived_map[Ty
|
||||
derived_field_statement_attrs = "idxs.insert(%d); "
|
||||
|
||||
simpletype = """%(documentation)s
|
||||
class IFC_PARSE_API %(name)s : %(superclass)s {
|
||||
class IFC_PARSE_API %(name)s : public %(superclass)s {
|
||||
public:
|
||||
virtual const IfcParse::type_declaration& declaration() const;
|
||||
%(name)s() {}
|
||||
explicit %(name)s (const std::weak_ptr<InstanceData>& data) : %(superclass)s(data) {}
|
||||
|
||||
// virtual const IfcParse::type_declaration& declaration() const;
|
||||
static const IfcParse::type_declaration& Class();
|
||||
explicit %(name)s (IfcEntityInstanceData&& e);
|
||||
%(name)s (%(type)s v);
|
||||
// %(name)s (%(type)s v);
|
||||
operator %(type)s() const;
|
||||
};
|
||||
"""
|
||||
@@ -127,51 +132,60 @@ simpletype_impl_type = "return *((IfcParse::type_declaration*)%(schema_name_uppe
|
||||
simpletype_impl_class = "return *((IfcParse::type_declaration*)%(schema_name_upper)s_types[%(index_in_schema)d]);"
|
||||
simpletype_impl_explicit_constructor = "data_ = e;"
|
||||
simpletype_impl_constructor = (
|
||||
"data_ = new IfcEntityInstanceData(%(schema_name_upper)s_types[%(index_in_schema)d]); set_attribute_value(0, v);"
|
||||
"data_ = new const std::weak_ptr<InstanceData>&(%(schema_name_upper)s_types[%(index_in_schema)d]); set_attribute_value(0, v);"
|
||||
)
|
||||
simpletype_impl_constructor_templated = "data_ = new IfcEntityInstanceData(%(schema_name_upper)s_types[%(index_in_schema)d]); set_attribute_value(0, v->generalize());"
|
||||
simpletype_impl_constructor_templated = "data_ = new const std::weak_ptr<InstanceData>&(%(schema_name_upper)s_types[%(index_in_schema)d]); set_attribute_value(0, v->generalize());"
|
||||
simpletype_impl_cast = "return get_attribute_value(0);"
|
||||
simpletype_impl_cast_templated = (
|
||||
"aggregate_of_instance::ptr es = get_attribute_value(0); return es->as< %(underlying_type)s >();"
|
||||
)
|
||||
simpletype_impl_cast_templated = "std::vector<express::Base> es = get_attribute_value(0); return cast_vector<%(underlying_type)s>(es);"
|
||||
|
||||
simpletype_impl_declaration = "return *((IfcParse::type_declaration*)%(schema_name_upper)s_types[%(index_in_schema)d]);"
|
||||
|
||||
select_virtual = """%(documentation)s
|
||||
class IFC_PARSE_API %(name)s : public virtual IfcUtil::IfcBaseInterface {
|
||||
select = """%(documentation)s
|
||||
class IFC_PARSE_API %(name)s : public express::Select {
|
||||
public:
|
||||
%(name)s() {}
|
||||
explicit %(name)s(const express::Base& c) : express::Select(c) {}
|
||||
|
||||
static const IfcParse::select_type& Class();
|
||||
typedef aggregate_of< %(name)s > list;
|
||||
%(template_items)s
|
||||
%(cast_functions)s
|
||||
};
|
||||
"""
|
||||
|
||||
select_plain = """%(documentation)s
|
||||
typedef IfcUtil::IfcBaseClass %(name)s;
|
||||
select_list_item = """ template<class T, std::enable_if_t<std::is_same_v<T, %(item_name)s>, int> = 0>
|
||||
%(item_name)s as() const { return express::Base::as<%(item_name)s>(); }
|
||||
"""
|
||||
|
||||
enumeration = """class IFC_PARSE_API %(name)s : public IfcUtil::IfcBaseType {
|
||||
%(documentation)s
|
||||
select_cast_function = """ %(name)s(const %(item_name)s& c) : express::Select(c) {};
|
||||
"""
|
||||
|
||||
enumeration = """%(documentation)s
|
||||
class IFC_PARSE_API %(name)s : public express::DeclaredType {
|
||||
public:
|
||||
%(name)s() {}
|
||||
explicit %(name)s (const std::weak_ptr<InstanceData>& data) : express::DeclaredType(data) {}
|
||||
|
||||
typedef enum {%(values)s} Value;
|
||||
static const char* ToString(Value v);
|
||||
static Value FromString(const std::string& s);
|
||||
|
||||
virtual const IfcParse::enumeration_type& declaration() const;
|
||||
// virtual const IfcParse::enumeration_type& declaration() const;
|
||||
static const IfcParse::enumeration_type& Class();
|
||||
%(name)s (IfcEntityInstanceData&& e);
|
||||
%(name)s (Value v);
|
||||
%(name)s (const std::string& v);
|
||||
// %(name)s (Value v);
|
||||
// %(name)s (const std::string& v);
|
||||
operator Value() const;
|
||||
};
|
||||
"""
|
||||
|
||||
entity = """%(documentation)s
|
||||
class IFC_PARSE_API %(name)s : %(superclass)s {
|
||||
class IFC_PARSE_API %(name)s : public %(superclass)s {
|
||||
public:
|
||||
%(attributes)s %(inverse)s virtual const IfcParse::entity& declaration() const;
|
||||
%(name)s() {}
|
||||
explicit %(name)s (const std::weak_ptr<InstanceData>& data) : %(superclass)s(data) {}
|
||||
|
||||
%(attributes)s %(inverse)s // virtual const IfcParse::entity& declaration() const;
|
||||
static const IfcParse::entity& Class();
|
||||
%(name)s (IfcEntityInstanceData&& e);
|
||||
%(name)s (%(constructor_arguments)s);
|
||||
typedef aggregate_of< %(name)s > list;
|
||||
// %(name)s (%(constructor_arguments)s);
|
||||
};
|
||||
"""
|
||||
|
||||
@@ -180,20 +194,22 @@ const IfcParse::select_type& %(schema_name)s::%(name)s::Class() { return *((IfcP
|
||||
"""
|
||||
|
||||
enumeration_function = """
|
||||
const IfcParse::enumeration_type& %(schema_name)s::%(name)s::declaration() const { return *((IfcParse::enumeration_type*)%(schema_name_upper)s_types[%(index_in_schema)d]); }
|
||||
// const IfcParse::enumeration_type& %(schema_name)s::%(name)s::declaration() const { return *((IfcParse::enumeration_type*)%(schema_name_upper)s_types[%(index_in_schema)d]); }
|
||||
const IfcParse::enumeration_type& %(schema_name)s::%(name)s::Class() { return *((IfcParse::enumeration_type*)%(schema_name_upper)s_types[%(index_in_schema)d]); }
|
||||
|
||||
%(schema_name)s::%(name)s::%(name)s(IfcEntityInstanceData&& e)
|
||||
: IfcBaseType(std::move(e))
|
||||
/*
|
||||
%(schema_name)s::%(name)s::%(name)s(const std::weak_ptr<InstanceData>& e)
|
||||
: express::DeclaredType(e)
|
||||
{}
|
||||
|
||||
%(schema_name)s::%(name)s::%(name)s(Value v) {
|
||||
set_attribute_value(0, EnumerationReference(&declaration(), static_cast<size_t>(v)));
|
||||
set_attribute_value(0, EnumerationReference(&Class(), static_cast<size_t>(v)));
|
||||
}
|
||||
|
||||
%(schema_name)s::%(name)s::%(name)s(const std::string& v) {
|
||||
set_attribute_value(0, EnumerationReference(&declaration(), declaration().lookup_enum_offset(v)));
|
||||
set_attribute_value(0, EnumerationReference(&Class(), Class().lookup_enum_offset(v)));
|
||||
}
|
||||
*/
|
||||
|
||||
const char* %(schema_name)s::%(name)s::ToString(Value v) {
|
||||
return %(schema_name)s::%(name)s::%(name)s::Class().lookup_enum_value((size_t)v);
|
||||
@@ -211,14 +227,14 @@ const char* %(schema_name)s::%(name)s::ToString(Value v) {
|
||||
entity_implementation = """// Function implementations for %(name)s
|
||||
%(attributes)s
|
||||
%(inverse)s
|
||||
const IfcParse::entity& %(schema_name)s::%(name)s::declaration() const { return *((IfcParse::entity*)%(schema_name_upper)s_types[%(index_in_schema)d]); }
|
||||
// const IfcParse::entity& %(schema_name)s::%(name)s::declaration() const { return *((IfcParse::entity*)%(schema_name_upper)s_types[%(index_in_schema)d]); }
|
||||
const IfcParse::entity& %(schema_name)s::%(name)s::Class() { return *((IfcParse::entity*)%(schema_name_upper)s_types[%(index_in_schema)d]); }
|
||||
%(schema_name)s::%(name)s::%(name)s(IfcEntityInstanceData&& e) : %(superclass)s { }
|
||||
%(schema_name)s::%(name)s::%(name)s(%(constructor_arguments)s) : %(superclass_num_attrs)s { %(constructor_implementation)s; populate_derived(); }
|
||||
// %(schema_name)s::%(name)s::%(name)s(const std::weak_ptr<InstanceData>& e) : %(superclass)s { }
|
||||
// %(schema_name)s::%(name)s::%(name)s(%(constructor_arguments)s) : %(superclass_num_attrs)s { %(constructor_implementation)s; populate_derived(); }
|
||||
"""
|
||||
|
||||
# data_ = e;
|
||||
# data_ = new IfcEntityInstanceData(%(schema_name_upper)s_types[%(index_in_schema)d]);
|
||||
# data_ = new const std::weak_ptr<InstanceData>&(%(schema_name_upper)s_types[%(index_in_schema)d]);
|
||||
|
||||
optional_attribute_description = "/// Whether the optional attribute %s is defined for this %s"
|
||||
|
||||
@@ -232,10 +248,10 @@ cast_function = "%(schema_name)s::%(class_name)s::operator %(return_type)s() con
|
||||
|
||||
array_type = "std::vector< %(instance_type)s > /*[%(lower)s:%(upper)s]*/"
|
||||
nested_array_type = "std::vector< std::vector< %(instance_type)s > >"
|
||||
list_type = "aggregate_of< %(instance_type)s >::ptr"
|
||||
list_list_type = "aggregate_of_aggregate_of< %(instance_type)s >::ptr"
|
||||
list_type = "std::vector< %(instance_type)s >"
|
||||
list_list_type = "std::vector< std::vector< %(instance_type)s > >"
|
||||
untyped_list = "aggregate_of_instance::ptr"
|
||||
inverse_attr = "aggregate_of< %(entity)s >::ptr %(name)s() const; // INVERSE %(entity)s::%(attribute)s"
|
||||
inverse_attr = "std::vector< %(entity)s > %(name)s() const; // INVERSE %(entity)s::%(attribute)s"
|
||||
|
||||
enum_from_string_stmt = ' if (s == "%(value)s") return ::%(schema_name)s::%(name)s::%(short_name)s_%(value)s;'
|
||||
|
||||
@@ -249,21 +265,24 @@ optional_attr_stmt = "return !get_attribute_value(%(index)d).isNull();"
|
||||
|
||||
get_attr_stmt = "%(null_check)s %(non_optional_type)s v = get_attribute_value(%(index)d); return v;"
|
||||
get_attr_stmt_enum = "%(null_check)s return %(non_optional_type)s::FromString(get_attribute_value(%(index)d));"
|
||||
get_attr_stmt_entity = "%(null_check)s return ((IfcUtil::IfcBaseClass*)(get_attribute_value(%(index)d)))->as<%(non_optional_type_no_pointer)s>(true);"
|
||||
get_attr_stmt_array = "%(null_check)s aggregate_of_instance::ptr es = get_attribute_value(%(index)d); return es->as< %(list_instance_type)s >();"
|
||||
get_attr_stmt_nested_array = "%(null_check)s aggregate_of_aggregate_of_instance::ptr es = get_attribute_value(%(index)d); return es->as< %(list_instance_type)s >();"
|
||||
get_attr_stmt_entity = "%(null_check)s return ((express::Base)(get_attribute_value(%(index)d))).as<%(non_optional_type_no_pointer)s>();"
|
||||
get_attr_stmt_array = "%(null_check)s std::vector<express::Base> es = get_attribute_value(%(index)d); return cast_vector<%(list_instance_type)s>(es);"
|
||||
get_attr_stmt_nested_array = "%(null_check)s std::vector<std::vector<express::Base>> es = get_attribute_value(%(index)d); return cast_vector_vector<%(list_instance_type)s>(es);"
|
||||
|
||||
get_inverse = "if (!file_) { return nullptr; } return file_->getInverse(id_, %(schema_name_upper)s_types[%(type_index)d], %(index)d)->as<%(type)s>();"
|
||||
get_inverse = "return cast_vector<%(type)s>(data()->file()->getInverse(data()->id(), %(schema_name_upper)s_types[%(type_index)d], %(index)d));"
|
||||
|
||||
set_attr_stmt = (
|
||||
"%(check_optional_set_begin)sset_attribute_value(%(index)d, %(star_if_optional)sv);%(check_optional_set_else)sunset_attribute_value(%(index)d);%(check_optional_set_end)s"
|
||||
)
|
||||
set_attr_instance = (
|
||||
"%(check_optional_set_begin)sset_attribute_value(%(index)d, v->as<IfcUtil::IfcBaseClass>());%(check_optional_set_else)sunset_attribute_value(%(index)d);%(check_optional_set_end)s"
|
||||
"%(check_optional_set_begin)sset_attribute_value(%(index)d, v);%(check_optional_set_else)sunset_attribute_value(%(index)d);%(check_optional_set_end)s"
|
||||
)
|
||||
set_attr_stmt_enum = "%(check_optional_set_begin)sset_attribute_value(%(index)d, EnumerationReference(&%(non_optional_type)s::Class(), (size_t) %(star_if_optional)sv));%(check_optional_set_else)sunset_attribute_value(%(index)d);%(check_optional_set_end)s"
|
||||
set_attr_stmt_array = (
|
||||
"%(check_optional_set_begin)sset_attribute_value(%(index)d, (%(star_if_optional)sv)->generalize());%(check_optional_set_else)sunset_attribute_value(%(index)d);%(check_optional_set_end)s"
|
||||
"%(check_optional_set_begin)sset_attribute_value(%(index)d, cast_vector<express::Base>(%(star_if_optional)sv));%(check_optional_set_else)sunset_attribute_value(%(index)d);%(check_optional_set_end)s"
|
||||
)
|
||||
set_attr_stmt_nested_array = (
|
||||
"%(check_optional_set_begin)sset_attribute_value(%(index)d, cast_vector_vector<express::Base>(%(star_if_optional)sv));%(check_optional_set_else)sunset_attribute_value(%(index)d);%(check_optional_set_end)s"
|
||||
)
|
||||
|
||||
constructor_stmt = (
|
||||
@@ -289,3 +308,5 @@ inverse_implementation = ' inverse_map[Type::%(type)s].insert(std::make_pair(
|
||||
|
||||
def multi_line_comment(li):
|
||||
return ("/// %s" % ("\n/// ".join(li))) if len(li) else ""
|
||||
|
||||
|
||||
|
||||
@@ -31,9 +31,6 @@ from typing import Any, Optional, TYPE_CHECKING, Union, overload, Literal, Typed
|
||||
from collections.abc import Callable, Generator
|
||||
from typing_extensions import assert_never
|
||||
|
||||
from . import ifcopenshell_wrapper
|
||||
from .entity_instance import entity_instance
|
||||
|
||||
from ifcopenshell.util.mvd_info import MvdInfo, LARK_AVAILABLE
|
||||
|
||||
if TYPE_CHECKING:
|
||||
@@ -108,7 +105,7 @@ class Transaction:
|
||||
|
||||
def serialise_value(self, element, value) -> Any:
|
||||
return element.walk(
|
||||
lambda v: isinstance(v, entity_instance),
|
||||
lambda v: isinstance(v, ifcopenshell.entity_instance),
|
||||
lambda v: {"id": v.id()} if v.id() else {"type": v.is_a(), "value": v.wrappedValue},
|
||||
value,
|
||||
)
|
||||
@@ -237,28 +234,8 @@ class Transaction:
|
||||
else:
|
||||
assert_never(operation["action"])
|
||||
|
||||
|
||||
file_dict: dict[int, tuple[weakref.ReferenceType[file], int]] = {}
|
||||
"""Mapping of internal IfcFile pointer address to existing ``ifcopenshell.file``
|
||||
and the timestamp when it was created.
|
||||
|
||||
Needed only to quickly access related from ``entity_instance`` it's ``file``.
|
||||
"""
|
||||
|
||||
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
|
||||
INVALID_SYNTAX = ifcopenshell_wrapper.file_open_status.INVALID_SYNTAX
|
||||
|
||||
# TODO: Workaround for old builds, remove after build stabilizes.
|
||||
try:
|
||||
UNKNOWN = ifcopenshell_wrapper.file_open_status.UNKNOWN
|
||||
except:
|
||||
UNKNOWN = 5 # Workaround
|
||||
|
||||
import struct
|
||||
|
||||
|
||||
def consume_buffer(val, inner):
|
||||
while val:
|
||||
s = struct.unpack("@q", val[:8])[0]
|
||||
@@ -508,20 +485,21 @@ class file_header:
|
||||
self.file = file
|
||||
self.header_data = header_data
|
||||
|
||||
# @todo these are probably no longer necessary now as we no longer depend on decoration of file
|
||||
@property
|
||||
def file_description(self) -> entity_instance:
|
||||
return entity_instance.wrap_value(self.header_data.file_description_py(), file=self.file)
|
||||
def file_description(self) -> ifcopenshell.entity_instance:
|
||||
return self.header_data.file_description_py()
|
||||
|
||||
@property
|
||||
def file_name(self) -> entity_instance:
|
||||
return entity_instance.wrap_value(self.header_data.file_name_py(), file=self.file)
|
||||
def file_name(self) -> ifcopenshell.entity_instance:
|
||||
return self.header_data.file_name_py()
|
||||
|
||||
@property
|
||||
def file_schema(self) -> entity_instance:
|
||||
return entity_instance.wrap_value(self.header_data.file_schema_py(), file=self.file)
|
||||
def file_schema(self) -> ifcopenshell.entity_instance:
|
||||
return self.header_data.file_schema_py()
|
||||
|
||||
|
||||
class file:
|
||||
class file_mixin:
|
||||
"""Base class for containing IFC files.
|
||||
|
||||
Class has instance methods for filtering by element Id, Type, etc.
|
||||
@@ -537,8 +515,7 @@ class file:
|
||||
print(products[0] == model[122] == model["2XQ$n5SLP5MBLyL442paFx"]) # True
|
||||
"""
|
||||
|
||||
wrapped_data: ifcopenshell_wrapper.file
|
||||
units: dict[str, entity_instance] = {}
|
||||
units: dict[str, ifcopenshell.entity_instance] = {}
|
||||
history_size: int = 64
|
||||
history: list[Transaction]
|
||||
"""Chronological order - from oldest to newest."""
|
||||
@@ -548,104 +525,13 @@ class file:
|
||||
to_delete: Union[set[ifcopenshell.entity_instance], None] = None
|
||||
"""Entities for batch removal."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
f: Optional[ifcopenshell_wrapper.file] = None,
|
||||
schema: Optional[ifcopenshell.util.schema.IFC_SCHEMA] = None,
|
||||
schema_version: Optional[tuple[int, int, int, int]] = None,
|
||||
):
|
||||
"""Create a new blank IFC model
|
||||
|
||||
|
||||
This IFC model does not have any entities in it yet. See the
|
||||
``create_entity`` function for how to create new entities. All data is
|
||||
stored in memory. If you wish to write the IFC model to disk, see the
|
||||
``write`` function.
|
||||
|
||||
:param f: The underlying IfcOpenShell file object to be wrapped. This
|
||||
is an internal implementation detail and should generally be left
|
||||
as None by users.
|
||||
:param schema: Which IFC schema to use, chosen from "IFC2X3", "IFC4",
|
||||
or "IFC4X3". These refer to the ISO approved versions of IFC.
|
||||
Defaults to "IFC4" if not specified, which is currently recommended
|
||||
for all new projects.
|
||||
:param schema_version: If you want to specify an exact version of IFC
|
||||
that may not be an ISO approved version, use this argument instead
|
||||
of ``schema``. IFC versions on technical.buildingsmart.org are
|
||||
described using 4 integers representing the major, minor, addendum,
|
||||
and corrigendum number. For example, (4, 0, 2, 1) refers to IFC4
|
||||
ADD2 TC1, which is the official version approved by ISO when people
|
||||
refer to "IFC4". Generally you should not use this argument unless
|
||||
you are testing non-ISO IFC releases.
|
||||
|
||||
Example:
|
||||
|
||||
.. code:: python
|
||||
|
||||
# Create a new IFC4 model, create a wall, then save it to an IFC-SPF file.
|
||||
model = ifcopenshell.file()
|
||||
model.create_entity("IfcWall")
|
||||
model.write("/path/to/model.ifc")
|
||||
|
||||
# Create a new IFC4X3 model
|
||||
model = ifcopenshell.file(schema="IFC4X3")
|
||||
|
||||
# A poweruser testing out a particular version of IFC4X3
|
||||
model = ifcopenshell.file(schema_version=(4, 3, 0, 1))
|
||||
"""
|
||||
if schema_version:
|
||||
prefixes = ("IFC", "X", "_ADD", "_TC")
|
||||
schema = "".join("".join(map(str, t)) if t[1] else "" for t in zip(prefixes, schema_version))
|
||||
else:
|
||||
schema = {"IFC4X3": "IFC4X3_ADD2"}.get(schema, schema)
|
||||
if f is not None:
|
||||
self.wrapped_data = f
|
||||
if not f.good():
|
||||
from . import Error, SchemaError
|
||||
|
||||
exc, msg = {
|
||||
READ_ERROR: lambda: (IOError, "Unable to open file for reading"),
|
||||
NO_HEADER: lambda: (Error, "Unable to parse IFC SPF header"),
|
||||
UNSUPPORTED_SCHEMA: lambda: (
|
||||
SchemaError,
|
||||
"Unsupported schema: %s" % ",".join(self.header.file_schema.schema_identifiers),
|
||||
),
|
||||
INVALID_SYNTAX: lambda: (Error, "Syntax error during parse, check logs"),
|
||||
# This is the case when passing uninitialized_tag
|
||||
UNKNOWN: lambda: (None, None),
|
||||
}[f.good().value()]()
|
||||
if exc is not None:
|
||||
raise exc(msg)
|
||||
else:
|
||||
args = filter(None, [schema])
|
||||
args = map(ifcopenshell_wrapper.schema_by_name, args)
|
||||
self.wrapped_data = ifcopenshell_wrapper.file(*args)
|
||||
def post_init(self):
|
||||
self.history = []
|
||||
self.future = []
|
||||
self.transaction: Optional[Transaction] = None
|
||||
|
||||
# we store a tuple of C++ file pointer address and creation time stamp so that
|
||||
# when memory addresses get recycled we do not run into collisions when the
|
||||
# address is used as a cache key.
|
||||
file_dict[self.wrapped_data.file_pointer()] = (weakref.ref(self), time.monotonic_ns())
|
||||
|
||||
@property
|
||||
def identifier(self) -> tuple[int, int]:
|
||||
"""Pair of C++ file pointer address and creation time stamp to uniquely identify a file
|
||||
over the life time of ifcopenshell module that should be mostly safe except in pathological
|
||||
cases
|
||||
|
||||
Returns:
|
||||
tuple[int, int]: Pair of C++ file pointer address and creation time stamp
|
||||
"""
|
||||
return (self.wrapped_data.file_pointer(), file_dict[self.wrapped_data.file_pointer()][1])
|
||||
|
||||
def __del__(self) -> None:
|
||||
# Avoid infinite recursion if file is failed to initialize
|
||||
# and wrapped_data is unset.
|
||||
if "wrapped_data" not in dir(self):
|
||||
return
|
||||
del file_dict[self.file_pointer()]
|
||||
|
||||
def set_history_size(self, size: int) -> None:
|
||||
self.history_size = size
|
||||
while len(self.history) > self.history_size:
|
||||
@@ -716,7 +602,7 @@ class file:
|
||||
"""
|
||||
eid = kwargs.pop("id", -1)
|
||||
|
||||
e = entity_instance((self.schema_identifier, type), self)
|
||||
e = self.create(type)
|
||||
|
||||
# Create pairs of {attribute index, attribute value}.
|
||||
# Keyword arguments are mapped to their corresponding
|
||||
@@ -758,15 +644,6 @@ class file:
|
||||
if attrs:
|
||||
self.transaction = transaction
|
||||
|
||||
# Once the values are populated add the instance
|
||||
# to the file.
|
||||
self.wrapped_data.add(e.wrapped_data, eid)
|
||||
|
||||
# The file container now handles the lifetime of
|
||||
# this instance. Tell SWIG that it is no longer
|
||||
# the owner.
|
||||
e.wrapped_data.this.disown()
|
||||
|
||||
if self.transaction:
|
||||
self.transaction.store_create(e)
|
||||
|
||||
@@ -777,7 +654,7 @@ class file:
|
||||
"""General IFC schema version: IFC2X3, IFC4, IFC4X3."""
|
||||
prefixes = ("IFC", "X", "_ADD", "_TC")
|
||||
reg = "".join(f"(?P<{s}>{s}\\d+)?" for s in prefixes)
|
||||
match = re.match(reg, self.wrapped_data.schema)
|
||||
match = re.match(reg, self.schema)
|
||||
version_tuple = tuple(
|
||||
map(
|
||||
lambda pp: int(pp[1][len(pp[0]) :]) if pp[1] else None,
|
||||
@@ -789,7 +666,7 @@ class file:
|
||||
@property
|
||||
def schema_identifier(self) -> str:
|
||||
"""Full IFC schema version: IFC2X3_TC1, IFC4_ADD2, IFC4X3_ADD2, etc."""
|
||||
return self.wrapped_data.schema
|
||||
return self.schema
|
||||
|
||||
@property
|
||||
def schema_version(self) -> tuple[int, int, int, int]:
|
||||
@@ -797,7 +674,7 @@ class file:
|
||||
|
||||
E.g. IFC4X3_ADD2 is represented as (4, 3, 2, 0).
|
||||
"""
|
||||
schema = self.wrapped_data.schema
|
||||
schema = self.schema
|
||||
version = []
|
||||
for prefix in ("IFC", "X", "_ADD", "_TC"):
|
||||
number = re.search(prefix + r"(\d)", schema)
|
||||
@@ -814,35 +691,16 @@ class file:
|
||||
if attr[0:6] == "create":
|
||||
return functools.partial(self.create_entity, attr[6:])
|
||||
else:
|
||||
return getattr(self.wrapped_data, attr)
|
||||
return getattr(self, attr)
|
||||
|
||||
def __getitem__(self, key: Union[numbers.Integral, str, bytes]) -> entity_instance:
|
||||
if isinstance(key, numbers.Integral):
|
||||
return entity_instance(self.wrapped_data.by_id(key), self)
|
||||
return self.by_id(key)
|
||||
elif isinstance(key, (str, bytes)):
|
||||
return entity_instance(self.wrapped_data.by_guid(str(key)), self)
|
||||
return self.by_guid(str(key))
|
||||
else:
|
||||
raise TypeError("Indexing into file requires either an integral number or compressed guid string")
|
||||
|
||||
def by_id(self, id: int) -> ifcopenshell.entity_instance:
|
||||
"""Return an IFC entity instance filtered by IFC ID.
|
||||
|
||||
:param id: STEP numerical identifier
|
||||
|
||||
:raises RuntimeError: If `id` is not found.
|
||||
|
||||
:returns: An ifcopenshell.entity_instance
|
||||
"""
|
||||
return self[id]
|
||||
|
||||
def by_guid(self, guid: str) -> ifcopenshell.entity_instance:
|
||||
"""Return an IFC entity instance filtered by IFC GUID.
|
||||
|
||||
:param guid: GlobalId value in 22-character encoded form
|
||||
|
||||
:raises RuntimeError: If `guid` is not found.
|
||||
|
||||
:returns: An ifcopenshell.entity_instance
|
||||
"""
|
||||
return self[guid]
|
||||
|
||||
def add(self, inst: ifcopenshell.entity_instance, _id: int = None) -> ifcopenshell.entity_instance:
|
||||
"""Adds an entity including any dependent entities to an IFC file.
|
||||
@@ -853,9 +711,10 @@ class file:
|
||||
"""
|
||||
|
||||
if self.transaction:
|
||||
max_id = self.wrapped_data.getMaxId()
|
||||
inst.wrapped_data.this.disown()
|
||||
result = entity_instance(self.wrapped_data.add(inst.wrapped_data, -1 if _id is None else _id), self)
|
||||
max_id = self.getMaxId()
|
||||
|
||||
result = self._add(inst, -1 if _id is None else _id)
|
||||
|
||||
if self.transaction:
|
||||
added_elements = [e for e in self.traverse(result) if e.id() > max_id]
|
||||
[self.transaction.store_create(e) for e in reversed(added_elements)]
|
||||
@@ -874,8 +733,8 @@ class file:
|
||||
:returns: A list of ifcopenshell.entity_instance objects
|
||||
"""
|
||||
if include_subtypes:
|
||||
return [entity_instance(e, self) for e in self.wrapped_data.by_type(type)]
|
||||
return [entity_instance(e, self) for e in self.wrapped_data.by_type_excl_subtypes(type)]
|
||||
return self._by_type(type)
|
||||
return self._by_type_excl_subtypes(type)
|
||||
|
||||
def traverse(
|
||||
self, inst: ifcopenshell.entity_instance, max_levels: Optional[int] = None, breadth_first: bool = False
|
||||
@@ -891,11 +750,11 @@ class file:
|
||||
max_levels = -1
|
||||
|
||||
if breadth_first:
|
||||
fn = self.wrapped_data.traverse_breadth_first
|
||||
fn = self.traverse_breadth_first
|
||||
else:
|
||||
fn = self.wrapped_data.traverse
|
||||
fn = self.traverse
|
||||
|
||||
return [entity_instance(e, self) for e in fn(inst.wrapped_data, max_levels)]
|
||||
return fn(inst, max_levels)
|
||||
|
||||
@overload
|
||||
def get_inverse(
|
||||
@@ -940,11 +799,11 @@ class file:
|
||||
if with_attribute_indices and not allow_duplicate:
|
||||
raise ValueError("with_attribute_indices requires allow_duplicate to be True")
|
||||
|
||||
inverses = [entity_instance(e, self) for e in self.wrapped_data.get_inverse(inst.wrapped_data)]
|
||||
inverses = [entity_instance(e, self) for e in self.get_inverse(inst.wrapped_data)]
|
||||
|
||||
if allow_duplicate:
|
||||
if with_attribute_indices:
|
||||
idxs = self.wrapped_data.get_inverse_indices(inst.wrapped_data)
|
||||
idxs = self.get_inverse_indices(inst.wrapped_data)
|
||||
# TODO: include in typing.
|
||||
return list(zip(inverses, idxs))
|
||||
else:
|
||||
@@ -961,7 +820,7 @@ class file:
|
||||
:param inst: The entity instance to get inverse relationships
|
||||
:returns: The total number of references
|
||||
"""
|
||||
return self.wrapped_data.get_total_inverses(inst.wrapped_data)
|
||||
return self.get_total_inverses(inst.wrapped_data)
|
||||
|
||||
def remove(self, inst: ifcopenshell.entity_instance) -> None:
|
||||
"""Deletes an IFC object in the file.
|
||||
@@ -974,22 +833,22 @@ class file:
|
||||
"""
|
||||
if self.transaction:
|
||||
self.transaction.store_delete(inst)
|
||||
return self.wrapped_data.remove(inst.wrapped_data)
|
||||
return self.remove(inst.wrapped_data)
|
||||
|
||||
def batch(self):
|
||||
"""Low-level mechanism to speed up deletion of large subgraphs"""
|
||||
if self.transaction:
|
||||
self.transaction.batch()
|
||||
return self.wrapped_data.batch()
|
||||
return self.batch()
|
||||
|
||||
def unbatch(self):
|
||||
"""Low-level mechanism to speed up deletion of large subgraphs"""
|
||||
if self.transaction:
|
||||
self.transaction.unbatch()
|
||||
return self.wrapped_data.unbatch()
|
||||
return self.unbatch()
|
||||
|
||||
def __iter__(self) -> Generator[ifcopenshell.entity_instance, None, None]:
|
||||
return iter(self[id] for id in self.wrapped_data.entity_names())
|
||||
return iter(self[id] for id in self.entity_names())
|
||||
|
||||
def assign_header_from(self, other: ifcopenshell.file) -> None:
|
||||
for k, vs in HEADER_FIELDS.items():
|
||||
@@ -1024,7 +883,7 @@ class file:
|
||||
raise NotImplementedError("Writing .ifcXML files is not supported")
|
||||
if format == ".ifcZIP":
|
||||
return self.write(path, ".ifc", zipped=True)
|
||||
self.wrapped_data.write(str(path))
|
||||
self.write(str(path))
|
||||
|
||||
if zipped:
|
||||
unzipped_path = path.with_suffix(format)
|
||||
@@ -1042,23 +901,18 @@ class file:
|
||||
def from_string(s: str) -> file:
|
||||
return file(ifcopenshell_wrapper.read(s))
|
||||
|
||||
@staticmethod
|
||||
def from_pointer(address: int) -> file:
|
||||
assert (f := file_dict[address][0]()) is not None
|
||||
return f
|
||||
|
||||
def to_string(self) -> str:
|
||||
return self.wrapped_data.to_string()
|
||||
return self.to_string()
|
||||
|
||||
@property
|
||||
def header(self) -> file_header:
|
||||
# TODO: Workaround for old builds, remove after build stabilizes.
|
||||
# TODO: No need for `wrapped_data.header` to be a method - should use `@property`?
|
||||
header = self.wrapped_data.header
|
||||
header = self.header
|
||||
if isinstance(header, types.MethodType):
|
||||
return file_header(self, self.wrapped_data.header())
|
||||
return file_header(self, self.header())
|
||||
else:
|
||||
return self.wrapped_data.header
|
||||
return self.header
|
||||
|
||||
@property
|
||||
def storage(self) -> Optional[rocksdb_file_storage]:
|
||||
@@ -1066,5 +920,5 @@ class file:
|
||||
Returns:
|
||||
Optional[rocksdb_file_storage]: underlying key-value store interface when opened as a RocksDB-backed file
|
||||
"""
|
||||
if self.wrapped_data.storage_mode() == 1:
|
||||
if self.storage_mode() == 1:
|
||||
return rocksdb_file_storage(self)
|
||||
|
||||
@@ -27,8 +27,8 @@ import ifcopenshell.util.schema
|
||||
from pathlib import Path
|
||||
from typing import Any, NoReturn, Union, Optional, TYPE_CHECKING, TypedDict
|
||||
from . import ifcopenshell_wrapper
|
||||
from .file import file
|
||||
from .entity_instance import entity_instance
|
||||
from . import file
|
||||
from . import entity_instance
|
||||
|
||||
if TYPE_CHECKING:
|
||||
import sqlite3
|
||||
|
||||
@@ -24,9 +24,9 @@ try:
|
||||
|
||||
import ifcopenshell.util.attribute
|
||||
import ifcopenshell.util.schema
|
||||
from .file import file
|
||||
from . import file
|
||||
from . import ifcopenshell_wrapper
|
||||
from .entity_instance import entity_instance
|
||||
from . import entity_instance
|
||||
|
||||
from lark import Lark, Transformer
|
||||
from typing import Any, NoReturn, Union, Optional
|
||||
|
||||
Reference in New Issue
Block a user