mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-25 01:50:02 +00:00
#2471 work around file gc with instance refs
This commit is contained in:
@@ -107,20 +107,36 @@ class entity_instance(object):
|
|||||||
e = ifcopenshell_wrapper.new_IfcBaseClass(*e)
|
e = ifcopenshell_wrapper.new_IfcBaseClass(*e)
|
||||||
super(entity_instance, self).__setattr__("wrapped_data", e)
|
super(entity_instance, self).__setattr__("wrapped_data", e)
|
||||||
super(entity_instance, self).__setattr__("method_list", None)
|
super(entity_instance, self).__setattr__("method_list", None)
|
||||||
|
|
||||||
|
# Make sure the file is not gc'ed while we have live instances
|
||||||
self.wrapped_data.file = file
|
self.wrapped_data.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.
|
||||||
|
"""
|
||||||
|
self.wrapped_data.file = None
|
||||||
|
|
||||||
def __getattr__(self, name):
|
def __getattr__(self, name):
|
||||||
INVALID, FORWARD, INVERSE = range(3)
|
INVALID, FORWARD, INVERSE = range(3)
|
||||||
attr_cat = self.wrapped_data.get_attribute_category(name)
|
attr_cat = self.wrapped_data.get_attribute_category(name)
|
||||||
if attr_cat == FORWARD:
|
if attr_cat == FORWARD:
|
||||||
return entity_instance.wrap_value(
|
return entity_instance.wrap_value(
|
||||||
self.wrapped_data.get_argument(self.wrapped_data.get_argument_index(name)), self.wrapped_data.file
|
self.wrapped_data.get_argument(
|
||||||
|
self.wrapped_data.get_argument_index(name)
|
||||||
|
),
|
||||||
|
self.wrapped_data.file,
|
||||||
)
|
)
|
||||||
elif attr_cat == INVERSE:
|
elif attr_cat == INVERSE:
|
||||||
return entity_instance.wrap_value(self.wrapped_data.get_inverse(name), self.wrapped_data.file)
|
return entity_instance.wrap_value(
|
||||||
|
self.wrapped_data.get_inverse(name), self.wrapped_data.file
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
raise AttributeError(
|
raise AttributeError(
|
||||||
"entity instance of type '%s' has no attribute '%s'" % (self.wrapped_data.is_a(True), name)
|
"entity instance of type '%s' has no attribute '%s'"
|
||||||
|
% (self.wrapped_data.is_a(True), name)
|
||||||
)
|
)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
@@ -159,7 +175,11 @@ class entity_instance(object):
|
|||||||
:type attr: int
|
:type attr: int
|
||||||
:rtype: string
|
:rtype: string
|
||||||
"""
|
"""
|
||||||
attr_idx = attr if isinstance(attr, numbers.Integral) else self.wrapped_data.get_argument_index(attr)
|
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)
|
return self.wrapped_data.get_argument_type(attr_idx)
|
||||||
|
|
||||||
def attribute_name(self, attr_idx):
|
def attribute_name(self, attr_idx):
|
||||||
@@ -177,15 +197,23 @@ class entity_instance(object):
|
|||||||
|
|
||||||
def __getitem__(self, key):
|
def __getitem__(self, key):
|
||||||
if key < 0 or key >= len(self):
|
if key < 0 or key >= len(self):
|
||||||
raise IndexError("Attribute index {} out of range for instance of type {}".format(key, self.is_a()))
|
raise IndexError(
|
||||||
return entity_instance.wrap_value(self.wrapped_data.get_argument(key), self.wrapped_data.file)
|
"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
|
||||||
|
)
|
||||||
|
|
||||||
def __setitem__(self, idx, value):
|
def __setitem__(self, idx, value):
|
||||||
if self.wrapped_data.file and self.wrapped_data.file.transaction:
|
if self.wrapped_data.file and self.wrapped_data.file.transaction:
|
||||||
self.wrapped_data.file.transaction.store_edit(self, idx, value)
|
self.wrapped_data.file.transaction.store_edit(self, idx, value)
|
||||||
|
|
||||||
if self.method_list is None:
|
if self.method_list is None:
|
||||||
super(entity_instance, self).__setattr__("method_list", _method_dict[self.is_a(True)])
|
super(entity_instance, self).__setattr__(
|
||||||
|
"method_list", _method_dict[self.is_a(True)]
|
||||||
|
)
|
||||||
|
|
||||||
method = self.method_list[idx]
|
method = self.method_list[idx]
|
||||||
|
|
||||||
@@ -193,7 +221,9 @@ class entity_instance(object):
|
|||||||
if method is not set_derived_atribute:
|
if method is not set_derived_atribute:
|
||||||
self.wrapped_data.setArgumentAsNull(idx)
|
self.wrapped_data.setArgumentAsNull(idx)
|
||||||
else:
|
else:
|
||||||
self.method_list[idx](self.wrapped_data, idx, entity_instance.unwrap_value(value))
|
self.method_list[idx](
|
||||||
|
self.wrapped_data, idx, entity_instance.unwrap_value(value)
|
||||||
|
)
|
||||||
|
|
||||||
return value
|
return value
|
||||||
|
|
||||||
@@ -240,8 +270,11 @@ class entity_instance(object):
|
|||||||
if self.id():
|
if self.id():
|
||||||
return self.wrapped_data == other.wrapped_data
|
return self.wrapped_data == other.wrapped_data
|
||||||
else:
|
else:
|
||||||
return (self.is_a(), self[0], self.wrapped_data.file_pointer()) == \
|
return (self.is_a(), self[0], self.wrapped_data.file_pointer()) == (
|
||||||
(other.is_a(), other[0], other.wrapped_data.file_pointer())
|
other.is_a(),
|
||||||
|
other[0],
|
||||||
|
other.wrapped_data.file_pointer(),
|
||||||
|
)
|
||||||
|
|
||||||
def __hash__(self):
|
def __hash__(self):
|
||||||
# Proper entity instances have a stable identity by means of the numeric
|
# Proper entity instances have a stable identity by means of the numeric
|
||||||
@@ -263,7 +296,9 @@ class entity_instance(object):
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
def get_info(self, include_identifier=True, recursive=False, return_type=dict, ignore=()):
|
def get_info(
|
||||||
|
self, include_identifier=True, recursive=False, return_type=dict, ignore=()
|
||||||
|
):
|
||||||
"""Return a dictionary of the entity_instance's properties (Python and IFC) and their values.
|
"""Return a dictionary of the entity_instance's properties (Python and IFC) and their values.
|
||||||
|
|
||||||
:param include_identifier: Whether or not to include the STEP numerical identifier
|
:param include_identifier: Whether or not to include the STEP numerical identifier
|
||||||
@@ -293,7 +328,11 @@ class entity_instance(object):
|
|||||||
yield "id", self.id()
|
yield "id", self.id()
|
||||||
yield "type", self.is_a()
|
yield "type", self.is_a()
|
||||||
except BaseException:
|
except BaseException:
|
||||||
logging.exception("unhandled exception while getting id / type info on {}".format(self))
|
logging.exception(
|
||||||
|
"unhandled exception while getting id / type info on {}".format(
|
||||||
|
self
|
||||||
|
)
|
||||||
|
)
|
||||||
for i in range(len(self)):
|
for i in range(len(self)):
|
||||||
try:
|
try:
|
||||||
if self.wrapped_data.get_attribute_names()[i] in ignore:
|
if self.wrapped_data.get_attribute_names()[i] in ignore:
|
||||||
@@ -316,16 +355,24 @@ class entity_instance(object):
|
|||||||
ignore=ignore,
|
ignore=ignore,
|
||||||
)
|
)
|
||||||
|
|
||||||
attr_value = entity_instance.walk(is_instance, get_info_, attr_value)
|
attr_value = entity_instance.walk(
|
||||||
|
is_instance, get_info_, attr_value
|
||||||
|
)
|
||||||
yield self.attribute_name(i), attr_value
|
yield self.attribute_name(i), attr_value
|
||||||
except BaseException:
|
except BaseException:
|
||||||
logging.exception("unhandled exception occurred setting attribute name for {}".format(self))
|
logging.exception(
|
||||||
|
"unhandled exception occurred setting attribute name for {}".format(
|
||||||
|
self
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
return return_type(_())
|
return return_type(_())
|
||||||
|
|
||||||
__dict__ = property(get_info)
|
__dict__ = property(get_info)
|
||||||
|
|
||||||
def get_info_2(self, include_identifier=True, recursive=False, return_type=dict, ignore=()):
|
def get_info_2(
|
||||||
|
self, include_identifier=True, recursive=False, return_type=dict, ignore=()
|
||||||
|
):
|
||||||
assert include_identifier
|
assert include_identifier
|
||||||
assert recursive
|
assert recursive
|
||||||
assert return_type is dict
|
assert return_type is dict
|
||||||
|
|||||||
Reference in New Issue
Block a user