mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-22 23:12:34 +00:00
Fix running of test/tests.py
This commit is contained in:
@@ -169,6 +169,7 @@ def open(
|
|||||||
print(products[0].id(), products[0].GlobalId) # 122 2XQ$n5SLP5MBLyL442paFx
|
print(products[0].id(), products[0].GlobalId) # 122 2XQ$n5SLP5MBLyL442paFx
|
||||||
print(products[0] == model[122] == model["2XQ$n5SLP5MBLyL442paFx"]) # True
|
print(products[0] == model[122] == model["2XQ$n5SLP5MBLyL442paFx"]) # True
|
||||||
"""
|
"""
|
||||||
|
|
||||||
path = Path(path)
|
path = Path(path)
|
||||||
if not path.exists():
|
if not path.exists():
|
||||||
raise FileNotFoundError(f"Path does not exist: '{path}'.")
|
raise FileNotFoundError(f"Path does not exist: '{path}'.")
|
||||||
@@ -205,7 +206,33 @@ def open(
|
|||||||
f = ifcopenshell_wrapper.open(str(path.absolute()), mmap=mmap)
|
f = ifcopenshell_wrapper.open(str(path.absolute()), mmap=mmap)
|
||||||
else:
|
else:
|
||||||
f = ifcopenshell_wrapper.open(str(path.absolute()))
|
f = ifcopenshell_wrapper.open(str(path.absolute()))
|
||||||
return file(f)
|
|
||||||
|
f.post_init()
|
||||||
|
|
||||||
|
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
|
||||||
|
UNKNOWN = ifcopenshell_wrapper.file_open_status.UNKNOWN
|
||||||
|
|
||||||
|
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(f.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)
|
||||||
|
|
||||||
|
return f
|
||||||
|
|
||||||
|
|
||||||
def create_entity(type: str, schema: str = "IFC4", *args: Any, **kwargs: Any) -> entity_instance:
|
def create_entity(type: str, schema: str = "IFC4", *args: Any, **kwargs: Any) -> entity_instance:
|
||||||
|
|||||||
@@ -270,7 +270,7 @@ get_attr_stmt_entity = "%(null_check)s return ((express::Base)(get_attribute_val
|
|||||||
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_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_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 = "return cast_vector<%(type)s>(data()->file()->getInverse(data()->id(), %(schema_name_upper)s_types[%(type_index)d], %(index)d));"
|
get_inverse = "return cast_vector<%(type)s>(file()->getInverse(data()->id(), %(schema_name_upper)s_types[%(type_index)d], %(index)d));"
|
||||||
|
|
||||||
set_attr_stmt = (
|
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"
|
"%(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"
|
||||||
|
|||||||
@@ -20,11 +20,9 @@ from __future__ import annotations
|
|||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import numbers
|
import numbers
|
||||||
import time
|
|
||||||
import zipfile
|
import zipfile
|
||||||
import functools
|
import functools
|
||||||
import ifcopenshell
|
import ifcopenshell
|
||||||
import weakref
|
|
||||||
import types
|
import types
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Any, Optional, TYPE_CHECKING, Union, overload, Literal, TypedDict
|
from typing import Any, Optional, TYPE_CHECKING, Union, overload, Literal, TypedDict
|
||||||
@@ -414,13 +412,13 @@ class rocksdb_file_storage:
|
|||||||
self._prefix = prefix
|
self._prefix = prefix
|
||||||
|
|
||||||
def items(self):
|
def items(self):
|
||||||
it = self.file.wrapped_data.key_value_store_iter(self._prefix)
|
it = self.file.key_value_store_iter(self._prefix)
|
||||||
while it and it.valid():
|
while it and it.valid():
|
||||||
yield it.key(), it.value()
|
yield it.key(), it.value()
|
||||||
it.next()
|
it.next()
|
||||||
|
|
||||||
def read(self, key):
|
def read(self, key):
|
||||||
return self.file.wrapped_data.key_value_store_query(key)
|
return self.file.key_value_store_query(key)
|
||||||
|
|
||||||
def by_id(self, name):
|
def by_id(self, name):
|
||||||
if isinstance(name, tuple):
|
if isinstance(name, tuple):
|
||||||
@@ -480,25 +478,6 @@ class rocksdb_file_storage:
|
|||||||
return "".join("".join(map(str, t)) if t[1] else "" for t in zip(prefixes, version_tuple[0:2]))
|
return "".join("".join(map(str, t)) if t[1] else "" for t in zip(prefixes, version_tuple[0:2]))
|
||||||
|
|
||||||
|
|
||||||
class file_header:
|
|
||||||
def __init__(self, file, header_data):
|
|
||||||
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) -> ifcopenshell.entity_instance:
|
|
||||||
return self.header_data.file_description_py()
|
|
||||||
|
|
||||||
@property
|
|
||||||
def file_name(self) -> ifcopenshell.entity_instance:
|
|
||||||
return self.header_data.file_name_py()
|
|
||||||
|
|
||||||
@property
|
|
||||||
def file_schema(self) -> ifcopenshell.entity_instance:
|
|
||||||
return self.header_data.file_schema_py()
|
|
||||||
|
|
||||||
|
|
||||||
class file_mixin:
|
class file_mixin:
|
||||||
"""Base class for containing IFC files.
|
"""Base class for containing IFC files.
|
||||||
|
|
||||||
@@ -611,7 +590,7 @@ class file_mixin:
|
|||||||
# @todo we should probably check that values for
|
# @todo we should probably check that values for
|
||||||
# attributes are not passed as duplicates using
|
# attributes are not passed as duplicates using
|
||||||
# both regular arguments and keyword arguments.
|
# both regular arguments and keyword arguments.
|
||||||
kwargs_attrs = [(e.wrapped_data.get_argument_index(name), arg) for name, arg in kwargs.items()]
|
kwargs_attrs = [(e.get_argument_index(name), arg) for name, arg in kwargs.items()]
|
||||||
attrs = list(enumerate(args)) + kwargs_attrs
|
attrs = list(enumerate(args)) + kwargs_attrs
|
||||||
|
|
||||||
if len(attrs) > len(e):
|
if len(attrs) > len(e):
|
||||||
@@ -799,11 +778,11 @@ class file_mixin:
|
|||||||
if with_attribute_indices and not allow_duplicate:
|
if with_attribute_indices and not allow_duplicate:
|
||||||
raise ValueError("with_attribute_indices requires allow_duplicate to be True")
|
raise ValueError("with_attribute_indices requires allow_duplicate to be True")
|
||||||
|
|
||||||
inverses = [entity_instance(e, self) for e in self.get_inverse(inst.wrapped_data)]
|
inverses = self.get_inverse(inst)
|
||||||
|
|
||||||
if allow_duplicate:
|
if allow_duplicate:
|
||||||
if with_attribute_indices:
|
if with_attribute_indices:
|
||||||
idxs = self.get_inverse_indices(inst.wrapped_data)
|
idxs = self.get_inverse_indices(inst)
|
||||||
# TODO: include in typing.
|
# TODO: include in typing.
|
||||||
return list(zip(inverses, idxs))
|
return list(zip(inverses, idxs))
|
||||||
else:
|
else:
|
||||||
@@ -811,17 +790,6 @@ class file_mixin:
|
|||||||
|
|
||||||
return set(inverses)
|
return set(inverses)
|
||||||
|
|
||||||
def get_total_inverses(self, inst: ifcopenshell.entity_instance) -> int:
|
|
||||||
"""Returns the number of entities that reference this entity
|
|
||||||
|
|
||||||
This is equivalent to `len(model.get_inverse(element))`, but
|
|
||||||
significantly faster.
|
|
||||||
|
|
||||||
:param inst: The entity instance to get inverse relationships
|
|
||||||
:returns: The total number of references
|
|
||||||
"""
|
|
||||||
return self.get_total_inverses(inst.wrapped_data)
|
|
||||||
|
|
||||||
def remove(self, inst: ifcopenshell.entity_instance) -> None:
|
def remove(self, inst: ifcopenshell.entity_instance) -> None:
|
||||||
"""Deletes an IFC object in the file.
|
"""Deletes an IFC object in the file.
|
||||||
|
|
||||||
@@ -833,7 +801,7 @@ class file_mixin:
|
|||||||
"""
|
"""
|
||||||
if self.transaction:
|
if self.transaction:
|
||||||
self.transaction.store_delete(inst)
|
self.transaction.store_delete(inst)
|
||||||
return self.remove(inst.wrapped_data)
|
return self.remove(inst)
|
||||||
|
|
||||||
def batch(self):
|
def batch(self):
|
||||||
"""Low-level mechanism to speed up deletion of large subgraphs"""
|
"""Low-level mechanism to speed up deletion of large subgraphs"""
|
||||||
@@ -904,16 +872,6 @@ class file_mixin:
|
|||||||
def to_string(self) -> str:
|
def to_string(self) -> str:
|
||||||
return self.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.header
|
|
||||||
if isinstance(header, types.MethodType):
|
|
||||||
return file_header(self, self.header())
|
|
||||||
else:
|
|
||||||
return self.header
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def storage(self) -> Optional[rocksdb_file_storage]:
|
def storage(self) -> Optional[rocksdb_file_storage]:
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -23,8 +23,7 @@ import sys
|
|||||||
import operator
|
import operator
|
||||||
|
|
||||||
from .. import open, ifcopenshell_wrapper
|
from .. import open, ifcopenshell_wrapper
|
||||||
from ..file import file
|
from ifcopenshell import file, entity_instance
|
||||||
from ..entity_instance import entity_instance
|
|
||||||
|
|
||||||
from . import has_occ
|
from . import has_occ
|
||||||
|
|
||||||
@@ -305,7 +304,7 @@ class iterator(ifcopenshell_wrapper.Iterator):
|
|||||||
self.settings = settings
|
self.settings = settings
|
||||||
if isinstance(file_or_filename, file):
|
if isinstance(file_or_filename, file):
|
||||||
self.file = file
|
self.file = file
|
||||||
file_or_filename = file_or_filename.wrapped_data
|
file_or_filename = file_or_filename
|
||||||
else:
|
else:
|
||||||
file_or_filename = self.file = open(file_or_filename)
|
file_or_filename = self.file = open(file_or_filename)
|
||||||
|
|
||||||
@@ -367,13 +366,13 @@ class tree(ifcopenshell_wrapper.tree):
|
|||||||
def __init__(self, file: Optional[file] = None, settings: Optional[settings] = None):
|
def __init__(self, file: Optional[file] = None, settings: Optional[settings] = None):
|
||||||
args = [self]
|
args = [self]
|
||||||
if file is not None:
|
if file is not None:
|
||||||
args.append(file.wrapped_data)
|
args.append(file)
|
||||||
if settings is not None:
|
if settings is not None:
|
||||||
args.append(settings)
|
args.append(settings)
|
||||||
ifcopenshell_wrapper.tree.__init__(*args)
|
ifcopenshell_wrapper.tree.__init__(*args)
|
||||||
|
|
||||||
def add_file(self, file: file, settings: settings) -> None:
|
def add_file(self, file: file, settings: settings) -> None:
|
||||||
ifcopenshell_wrapper.tree.add_file(self, file.wrapped_data, settings)
|
ifcopenshell_wrapper.tree.add_file(self, file, settings)
|
||||||
|
|
||||||
def add_iterator(self, iterator: iterator) -> None:
|
def add_iterator(self, iterator: iterator) -> None:
|
||||||
ifcopenshell_wrapper.tree.add_file(self, iterator)
|
ifcopenshell_wrapper.tree.add_file(self, iterator)
|
||||||
@@ -387,7 +386,7 @@ class tree(ifcopenshell_wrapper.tree):
|
|||||||
) -> list[entity_instance]:
|
) -> list[entity_instance]:
|
||||||
def unwrap(value):
|
def unwrap(value):
|
||||||
if isinstance(value, entity_instance):
|
if isinstance(value, entity_instance):
|
||||||
return value.wrapped_data
|
return value
|
||||||
elif all(map(lambda v: hasattr(value, v), "XYZ")):
|
elif all(map(lambda v: hasattr(value, v), "XYZ")):
|
||||||
return value.X(), value.Y(), value.Z()
|
return value.X(), value.Y(), value.Z()
|
||||||
return value
|
return value
|
||||||
@@ -406,12 +405,12 @@ class tree(ifcopenshell_wrapper.tree):
|
|||||||
args.append(kwargs.get("completely_within", False))
|
args.append(kwargs.get("completely_within", False))
|
||||||
if "extend" in kwargs:
|
if "extend" in kwargs:
|
||||||
args.append(kwargs["extend"])
|
args.append(kwargs["extend"])
|
||||||
return [entity_instance(e) for e in ifcopenshell_wrapper.tree.select(*args)]
|
return ifcopenshell_wrapper.tree.select(*args)
|
||||||
|
|
||||||
def select_box(self, value, **kwargs) -> list[entity_instance]:
|
def select_box(self, value, **kwargs) -> list[entity_instance]:
|
||||||
def unwrap(value):
|
def unwrap(value):
|
||||||
if isinstance(value, entity_instance):
|
if isinstance(value, entity_instance):
|
||||||
return value.wrapped_data
|
return value
|
||||||
elif hasattr(value, "Get"):
|
elif hasattr(value, "Get"):
|
||||||
return value.Get()[:3], value.Get()[3:]
|
return value.Get()[:3], value.Get()[3:]
|
||||||
return value
|
return value
|
||||||
@@ -421,7 +420,7 @@ class tree(ifcopenshell_wrapper.tree):
|
|||||||
args.append(kwargs.get("completely_within", False))
|
args.append(kwargs.get("completely_within", False))
|
||||||
if "extend" in kwargs:
|
if "extend" in kwargs:
|
||||||
args.append(kwargs.get("extend", -1.0e-5))
|
args.append(kwargs.get("extend", -1.0e-5))
|
||||||
return [entity_instance(e) for e in ifcopenshell_wrapper.tree.select_box(*args)]
|
return ifcopenshell_wrapper.tree.select_box(*args)
|
||||||
|
|
||||||
def clash_intersection_many(
|
def clash_intersection_many(
|
||||||
self,
|
self,
|
||||||
@@ -430,13 +429,13 @@ class tree(ifcopenshell_wrapper.tree):
|
|||||||
tolerance: float = 0.002,
|
tolerance: float = 0.002,
|
||||||
check_all: bool = True,
|
check_all: bool = True,
|
||||||
) -> tuple[ifcopenshell_wrapper.clash, ...]:
|
) -> tuple[ifcopenshell_wrapper.clash, ...]:
|
||||||
args = [self, [e.wrapped_data for e in set_a], [e.wrapped_data for e in set_b], tolerance, check_all]
|
args = [self, set_a, set_b, tolerance, check_all]
|
||||||
return ifcopenshell_wrapper.tree.clash_intersection_many(*args)
|
return ifcopenshell_wrapper.tree.clash_intersection_many(*args)
|
||||||
|
|
||||||
def clash_collision_many(
|
def clash_collision_many(
|
||||||
self, set_a: Iterable[entity_instance], set_b: Iterable[entity_instance], allow_touching=False
|
self, set_a: Iterable[entity_instance], set_b: Iterable[entity_instance], allow_touching=False
|
||||||
) -> tuple[ifcopenshell_wrapper.clash, ...]:
|
) -> tuple[ifcopenshell_wrapper.clash, ...]:
|
||||||
args = [self, [e.wrapped_data for e in set_a], [e.wrapped_data for e in set_b], allow_touching]
|
args = [self, set_a, set_b, allow_touching]
|
||||||
return ifcopenshell_wrapper.tree.clash_collision_many(*args)
|
return ifcopenshell_wrapper.tree.clash_collision_many(*args)
|
||||||
|
|
||||||
def clash_clearance_many(
|
def clash_clearance_many(
|
||||||
@@ -446,7 +445,7 @@ class tree(ifcopenshell_wrapper.tree):
|
|||||||
clearance: float = 0.05,
|
clearance: float = 0.05,
|
||||||
check_all: bool = False,
|
check_all: bool = False,
|
||||||
) -> tuple[ifcopenshell_wrapper.clash, ...]:
|
) -> tuple[ifcopenshell_wrapper.clash, ...]:
|
||||||
args = [self, [e.wrapped_data for e in set_a], [e.wrapped_data for e in set_b], clearance, check_all]
|
args = [self, set_a, set_b, clearance, check_all]
|
||||||
return ifcopenshell_wrapper.tree.clash_clearance_many(*args)
|
return ifcopenshell_wrapper.tree.clash_clearance_many(*args)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
@@ -509,7 +508,7 @@ def create_shape(
|
|||||||
return wrap_shape_creation(
|
return wrap_shape_creation(
|
||||||
settings,
|
settings,
|
||||||
ifcopenshell_wrapper.create_shape(
|
ifcopenshell_wrapper.create_shape(
|
||||||
settings, inst.wrapped_data, repr.wrapped_data if repr is not None else None, geometry_library
|
settings, inst, repr if repr is not None else None, geometry_library
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -525,7 +524,7 @@ def map_shape(settings: settings, inst: entity_instance) -> ifcopenshell_wrapper
|
|||||||
>>> ifcopenshell.geom.map_shape(ifcopenshell.geom.settings(), point).components
|
>>> ifcopenshell.geom.map_shape(ifcopenshell.geom.settings(), point).components
|
||||||
(0.0, 0.0, 0.0)
|
(0.0, 0.0, 0.0)
|
||||||
"""
|
"""
|
||||||
return ifcopenshell_wrapper.map_shape(settings, inst.wrapped_data)
|
return ifcopenshell_wrapper.map_shape(settings, inst)
|
||||||
|
|
||||||
|
|
||||||
@overload
|
@overload
|
||||||
@@ -618,20 +617,17 @@ def iterate(
|
|||||||
|
|
||||||
|
|
||||||
def make_shape_function(fn):
|
def make_shape_function(fn):
|
||||||
def entity_instance_or_none(e):
|
|
||||||
return None if e is None else entity_instance(e)
|
|
||||||
|
|
||||||
if has_occ:
|
if has_occ:
|
||||||
|
|
||||||
def _(schema, string_or_shape, *args):
|
def _(schema, string_or_shape, *args):
|
||||||
if isinstance(string_or_shape, TopoDS.TopoDS_Shape):
|
if isinstance(string_or_shape, TopoDS.TopoDS_Shape):
|
||||||
string_or_shape = utils.serialize_shape(string_or_shape)
|
string_or_shape = utils.serialize_shape(string_or_shape)
|
||||||
return entity_instance_or_none(fn(schema, string_or_shape, *args))
|
return fn(schema, string_or_shape, *args)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
|
||||||
def _(schema, string, *args):
|
def _(schema, string, *args):
|
||||||
return entity_instance_or_none(fn(schema, string, *args))
|
return fn(schema, string, *args)
|
||||||
|
|
||||||
return _
|
return _
|
||||||
|
|
||||||
|
|||||||
@@ -774,8 +774,12 @@ express::Base IfcParse::impl::rocks_db_file_storage::create(const IfcParse::decl
|
|||||||
}
|
}
|
||||||
|
|
||||||
express::Base IfcParse::impl::in_memory_file_storage::create(const IfcParse::declaration* decl, int id) {
|
express::Base IfcParse::impl::in_memory_file_storage::create(const IfcParse::declaration* decl, int id) {
|
||||||
auto instance_name = id == -1 ? (int)file->FreshId() : id;
|
uint32_t instance_name;
|
||||||
if (decl->as_entity() == nullptr && decl->as_type_declaration() == nullptr) {
|
if (decl->as_entity() != nullptr) {
|
||||||
|
instance_name = id == -1 ? (int)file->FreshId() : id;
|
||||||
|
} else if (decl->as_type_declaration() != nullptr) {
|
||||||
|
instance_name = 0;
|
||||||
|
} else {
|
||||||
throw std::runtime_error("Requires and entity or type declaration");
|
throw std::runtime_error("Requires and entity or type declaration");
|
||||||
}
|
}
|
||||||
auto ptr = byid_.insert({instance_name, std::make_shared<InstanceData>(file, decl, instance_name, decl->as_entity() ? in_memory_attribute_storage(decl->as_entity()->attribute_count()) : in_memory_attribute_storage(1))}).first;
|
auto ptr = byid_.insert({instance_name, std::make_shared<InstanceData>(file, decl, instance_name, decl->as_entity() ? in_memory_attribute_storage(decl->as_entity()->attribute_count()) : in_memory_attribute_storage(1))}).first;
|
||||||
|
|||||||
@@ -1840,8 +1840,6 @@ express::Base IfcFile::addEntity(const express::Base& entity, int id) {
|
|||||||
return mit->second;
|
return mit->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
express::Base new_entity;
|
|
||||||
|
|
||||||
// Obtain all forward references by a depth-first
|
// Obtain all forward references by a depth-first
|
||||||
// traversal and add them to the file.
|
// traversal and add them to the file.
|
||||||
try {
|
try {
|
||||||
@@ -1862,7 +1860,7 @@ express::Base IfcFile::addEntity(const express::Base& entity, int id) {
|
|||||||
// container and entity is created. The attribute references
|
// container and entity is created. The attribute references
|
||||||
// need to be updated to point to instances in this file.
|
// need to be updated to point to instances in this file.
|
||||||
IfcFile* other_file = entity.file();
|
IfcFile* other_file = entity.file();
|
||||||
create(&entity.declaration(), id);
|
auto new_entity = create(&entity.declaration(), id);
|
||||||
auto* decl = &entity.declaration();
|
auto* decl = &entity.declaration();
|
||||||
|
|
||||||
auto num_attributes = (decl->as_entity() ? decl->as_entity()->attribute_count() : 1);
|
auto num_attributes = (decl->as_entity() ? decl->as_entity()->attribute_count() : 1);
|
||||||
|
|||||||
@@ -342,6 +342,7 @@ private:
|
|||||||
|
|
||||||
%pythoncode %{
|
%pythoncode %{
|
||||||
schema = property(schema_name)
|
schema = property(schema_name)
|
||||||
|
header = property(header)
|
||||||
|
|
||||||
old_init = __init__
|
old_init = __init__
|
||||||
def __init__(self, schema=None, schema_version=None):
|
def __init__(self, schema=None, schema_version=None):
|
||||||
@@ -519,7 +520,7 @@ private:
|
|||||||
return IfcUtil::ArgumentTypeToString(helper_fn_attribute_type($self, i));
|
return IfcUtil::ArgumentTypeToString(helper_fn_attribute_type($self, i));
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string& get_argument_name(unsigned int i) const {
|
const std::string& attribute_name(unsigned int i) const {
|
||||||
if ($self->declaration().as_entity()) {
|
if ($self->declaration().as_entity()) {
|
||||||
return $self->declaration().as_entity()->attribute_by_index(i)->name();
|
return $self->declaration().as_entity()->attribute_by_index(i)->name();
|
||||||
} else if (i == 0) {
|
} else if (i == 0) {
|
||||||
@@ -821,31 +822,9 @@ private:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Expose FileDescription and FileName header entities
|
|
||||||
// to make them readable even if they were not filled properly before.
|
|
||||||
// Though it is invalid IFC, technically.
|
|
||||||
// FileSchema is not exposed as IFC file won't load if it's invalid.
|
|
||||||
|
|
||||||
%extend IfcParse::FileDescription {
|
|
||||||
AttributeValue description() const { return $self->getArgument(0); }
|
|
||||||
AttributeValue implementation_level() const { return $self->getArgument(1); }
|
|
||||||
};
|
|
||||||
|
|
||||||
%extend IfcParse::FileName {
|
|
||||||
AttributeValue name() const { return $self->getArgument(0); }
|
|
||||||
AttributeValue time_stamp() const { return $self->getArgument(1); }
|
|
||||||
AttributeValue author() const { return $self->getArgument(2); }
|
|
||||||
AttributeValue organization() const { return $self->getArgument(3); }
|
|
||||||
AttributeValue preprocessor_version() const { return $self->getArgument(4); }
|
|
||||||
AttributeValue originating_system() const { return $self->getArgument(5); }
|
|
||||||
AttributeValue authorization() const { return $self->getArgument(6); }
|
|
||||||
};
|
|
||||||
|
|
||||||
%extend IfcParse::IfcSpfHeader {
|
%extend IfcParse::IfcSpfHeader {
|
||||||
// Cast to base class pointers for SWIG, because
|
// Upcast to header instances for SWIG, because
|
||||||
// it has no idea about the schema definitions.
|
// it has no idea about the schema definitions.
|
||||||
// The code to access these methods as attributes
|
|
||||||
// is in file.py
|
|
||||||
express::Base file_description_py() {
|
express::Base file_description_py() {
|
||||||
return $self->file_description();
|
return $self->file_description();
|
||||||
}
|
}
|
||||||
@@ -855,32 +834,11 @@ private:
|
|||||||
express::Base file_schema_py() {
|
express::Base file_schema_py() {
|
||||||
return $self->file_schema();
|
return $self->file_schema();
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
%extend IfcParse::FileDescription {
|
|
||||||
%pythoncode %{
|
%pythoncode %{
|
||||||
# Hide the getters with read-write property implementations
|
file_description = property(file_description_py)
|
||||||
description = property(description, description)
|
file_name = property(file_name_py)
|
||||||
implementation_level = property(implementation_level, implementation_level)
|
file_schema = property(file_schema_py)
|
||||||
%}
|
|
||||||
};
|
|
||||||
|
|
||||||
%extend IfcParse::FileName {
|
|
||||||
%pythoncode %{
|
|
||||||
name = property(name, name)
|
|
||||||
time_stamp = property(time_stamp, time_stamp)
|
|
||||||
author = property(author, author)
|
|
||||||
organization = property(organization, organization)
|
|
||||||
preprocessor_version = property(preprocessor_version, preprocessor_version)
|
|
||||||
originating_system = property(originating_system, originating_system)
|
|
||||||
authorization = property(authorization, authorization)
|
|
||||||
%}
|
|
||||||
};
|
|
||||||
|
|
||||||
%extend IfcParse::FileSchema {
|
|
||||||
%pythoncode %{
|
|
||||||
# Hide the getters with read-write property implementations
|
|
||||||
schema_identifiers = property(schema_identifiers, schema_identifiers)
|
|
||||||
%}
|
%}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -53,6 +53,8 @@ f2 = ifcopenshell.file(schema=f.schema)
|
|||||||
prop2 = f2.add(prop)
|
prop2 = f2.add(prop)
|
||||||
assert str(prop) == str(prop2).replace(str(prop2.id()), str(prop.id()))
|
assert str(prop) == str(prop2).replace(str(prop2.id()), str(prop.id()))
|
||||||
assert prop2.id() == 1
|
assert prop2.id() == 1
|
||||||
|
# Adding the same instance returns the previous copy
|
||||||
|
assert f2.add(prop) == prop2
|
||||||
|
|
||||||
# A recursively obtained python dictionary representation
|
# A recursively obtained python dictionary representation
|
||||||
# matches for copied instances as well
|
# matches for copied instances as well
|
||||||
|
|||||||
Reference in New Issue
Block a user