mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-10 09:48:32 +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] == model[122] == model["2XQ$n5SLP5MBLyL442paFx"]) # True
|
||||
"""
|
||||
|
||||
path = Path(path)
|
||||
if not path.exists():
|
||||
raise FileNotFoundError(f"Path does not exist: '{path}'.")
|
||||
@@ -205,7 +206,33 @@ def open(
|
||||
f = ifcopenshell_wrapper.open(str(path.absolute()), mmap=mmap)
|
||||
else:
|
||||
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:
|
||||
|
||||
@@ -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_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 = (
|
||||
"%(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 re
|
||||
import numbers
|
||||
import time
|
||||
import zipfile
|
||||
import functools
|
||||
import ifcopenshell
|
||||
import weakref
|
||||
import types
|
||||
from pathlib import Path
|
||||
from typing import Any, Optional, TYPE_CHECKING, Union, overload, Literal, TypedDict
|
||||
@@ -414,13 +412,13 @@ class rocksdb_file_storage:
|
||||
self._prefix = prefix
|
||||
|
||||
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():
|
||||
yield it.key(), it.value()
|
||||
it.next()
|
||||
|
||||
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):
|
||||
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]))
|
||||
|
||||
|
||||
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:
|
||||
"""Base class for containing IFC files.
|
||||
|
||||
@@ -611,7 +590,7 @@ class file_mixin:
|
||||
# @todo we should probably check that values for
|
||||
# attributes are not passed as duplicates using
|
||||
# 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
|
||||
|
||||
if len(attrs) > len(e):
|
||||
@@ -799,11 +778,11 @@ class file_mixin:
|
||||
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.get_inverse(inst.wrapped_data)]
|
||||
inverses = self.get_inverse(inst)
|
||||
|
||||
if allow_duplicate:
|
||||
if with_attribute_indices:
|
||||
idxs = self.get_inverse_indices(inst.wrapped_data)
|
||||
idxs = self.get_inverse_indices(inst)
|
||||
# TODO: include in typing.
|
||||
return list(zip(inverses, idxs))
|
||||
else:
|
||||
@@ -811,17 +790,6 @@ class file_mixin:
|
||||
|
||||
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:
|
||||
"""Deletes an IFC object in the file.
|
||||
|
||||
@@ -833,7 +801,7 @@ class file_mixin:
|
||||
"""
|
||||
if self.transaction:
|
||||
self.transaction.store_delete(inst)
|
||||
return self.remove(inst.wrapped_data)
|
||||
return self.remove(inst)
|
||||
|
||||
def batch(self):
|
||||
"""Low-level mechanism to speed up deletion of large subgraphs"""
|
||||
@@ -904,16 +872,6 @@ class file_mixin:
|
||||
def to_string(self) -> str:
|
||||
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
|
||||
def storage(self) -> Optional[rocksdb_file_storage]:
|
||||
"""
|
||||
|
||||
@@ -23,8 +23,7 @@ import sys
|
||||
import operator
|
||||
|
||||
from .. import open, ifcopenshell_wrapper
|
||||
from ..file import file
|
||||
from ..entity_instance import entity_instance
|
||||
from ifcopenshell import file, entity_instance
|
||||
|
||||
from . import has_occ
|
||||
|
||||
@@ -305,7 +304,7 @@ class iterator(ifcopenshell_wrapper.Iterator):
|
||||
self.settings = settings
|
||||
if isinstance(file_or_filename, file):
|
||||
self.file = file
|
||||
file_or_filename = file_or_filename.wrapped_data
|
||||
file_or_filename = file_or_filename
|
||||
else:
|
||||
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):
|
||||
args = [self]
|
||||
if file is not None:
|
||||
args.append(file.wrapped_data)
|
||||
args.append(file)
|
||||
if settings is not None:
|
||||
args.append(settings)
|
||||
ifcopenshell_wrapper.tree.__init__(*args)
|
||||
|
||||
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:
|
||||
ifcopenshell_wrapper.tree.add_file(self, iterator)
|
||||
@@ -387,7 +386,7 @@ class tree(ifcopenshell_wrapper.tree):
|
||||
) -> list[entity_instance]:
|
||||
def unwrap(value):
|
||||
if isinstance(value, entity_instance):
|
||||
return value.wrapped_data
|
||||
return value
|
||||
elif all(map(lambda v: hasattr(value, v), "XYZ")):
|
||||
return value.X(), value.Y(), value.Z()
|
||||
return value
|
||||
@@ -406,12 +405,12 @@ class tree(ifcopenshell_wrapper.tree):
|
||||
args.append(kwargs.get("completely_within", False))
|
||||
if "extend" in kwargs:
|
||||
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 unwrap(value):
|
||||
if isinstance(value, entity_instance):
|
||||
return value.wrapped_data
|
||||
return value
|
||||
elif hasattr(value, "Get"):
|
||||
return value.Get()[:3], value.Get()[3:]
|
||||
return value
|
||||
@@ -421,7 +420,7 @@ class tree(ifcopenshell_wrapper.tree):
|
||||
args.append(kwargs.get("completely_within", False))
|
||||
if "extend" in kwargs:
|
||||
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(
|
||||
self,
|
||||
@@ -430,13 +429,13 @@ class tree(ifcopenshell_wrapper.tree):
|
||||
tolerance: float = 0.002,
|
||||
check_all: bool = True,
|
||||
) -> 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)
|
||||
|
||||
def clash_collision_many(
|
||||
self, set_a: Iterable[entity_instance], set_b: Iterable[entity_instance], allow_touching=False
|
||||
) -> 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)
|
||||
|
||||
def clash_clearance_many(
|
||||
@@ -446,7 +445,7 @@ class tree(ifcopenshell_wrapper.tree):
|
||||
clearance: float = 0.05,
|
||||
check_all: bool = False,
|
||||
) -> 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)
|
||||
|
||||
@staticmethod
|
||||
@@ -509,7 +508,7 @@ def create_shape(
|
||||
return wrap_shape_creation(
|
||||
settings,
|
||||
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
|
||||
(0.0, 0.0, 0.0)
|
||||
"""
|
||||
return ifcopenshell_wrapper.map_shape(settings, inst.wrapped_data)
|
||||
return ifcopenshell_wrapper.map_shape(settings, inst)
|
||||
|
||||
|
||||
@overload
|
||||
@@ -618,20 +617,17 @@ def iterate(
|
||||
|
||||
|
||||
def make_shape_function(fn):
|
||||
def entity_instance_or_none(e):
|
||||
return None if e is None else entity_instance(e)
|
||||
|
||||
if has_occ:
|
||||
|
||||
def _(schema, string_or_shape, *args):
|
||||
if isinstance(string_or_shape, TopoDS.TopoDS_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:
|
||||
|
||||
def _(schema, string, *args):
|
||||
return entity_instance_or_none(fn(schema, string, *args))
|
||||
return fn(schema, string, *args)
|
||||
|
||||
return _
|
||||
|
||||
|
||||
Reference in New Issue
Block a user