2016-06-22 15:03:18 +02:00
|
|
|
###############################################################################
|
|
|
|
|
# #
|
|
|
|
|
# This file is part of IfcOpenShell. #
|
|
|
|
|
# #
|
|
|
|
|
# IfcOpenShell is free software: you can redistribute it and/or modify #
|
|
|
|
|
# it under the terms of the Lesser GNU General Public License as published by #
|
|
|
|
|
# the Free Software Foundation, either version 3.0 of the License, or #
|
|
|
|
|
# (at your option) any later version. #
|
|
|
|
|
# #
|
|
|
|
|
# IfcOpenShell is distributed in the hope that it will be useful, #
|
|
|
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
|
|
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
|
|
|
|
# Lesser GNU General Public License for more details. #
|
|
|
|
|
# #
|
|
|
|
|
# You should have received a copy of the Lesser GNU General Public License #
|
|
|
|
|
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
|
|
|
|
|
# #
|
|
|
|
|
###############################################################################
|
2017-11-01 10:41:27 +01:00
|
|
|
|
|
|
|
|
from __future__ import absolute_import
|
|
|
|
|
from __future__ import division
|
2017-03-09 12:04:07 +01:00
|
|
|
from __future__ import print_function
|
2016-06-22 15:03:18 +02:00
|
|
|
|
|
|
|
|
import functools
|
2017-01-04 09:15:52 +01:00
|
|
|
import numbers
|
2016-06-22 15:03:18 +02:00
|
|
|
import itertools
|
|
|
|
|
|
|
|
|
|
from . import ifcopenshell_wrapper
|
|
|
|
|
|
2017-03-09 11:47:54 +01:00
|
|
|
try:
|
|
|
|
|
import logging
|
|
|
|
|
except ImportError as e:
|
2017-07-17 18:09:49 +02:00
|
|
|
logging = type('logger', (object,), {'exception': staticmethod(lambda s: print(s))})
|
2017-03-09 11:47:54 +01:00
|
|
|
|
2017-01-04 09:15:52 +01:00
|
|
|
|
2016-06-22 15:03:18 +02:00
|
|
|
class entity_instance(object):
|
2016-07-18 15:53:20 +02:00
|
|
|
def __init__(self, e):
|
2017-06-05 17:26:58 +02:00
|
|
|
if isinstance(e, str):
|
|
|
|
|
e = ifcopenshell_wrapper.new_IfcBaseClass(e)
|
2016-07-18 15:53:20 +02:00
|
|
|
super(entity_instance, self).__setattr__('wrapped_data', e)
|
2017-01-04 09:15:52 +01:00
|
|
|
|
2016-07-18 15:53:20 +02:00
|
|
|
def __getattr__(self, name):
|
|
|
|
|
INVALID, FORWARD, INVERSE = range(3)
|
|
|
|
|
attr_cat = self.wrapped_data.get_attribute_category(name)
|
|
|
|
|
if attr_cat == FORWARD:
|
2017-01-04 09:15:52 +01:00
|
|
|
return entity_instance.wrap_value(
|
|
|
|
|
self.wrapped_data.get_argument(self.wrapped_data.get_argument_index(name)))
|
2016-07-18 15:53:20 +02:00
|
|
|
elif attr_cat == INVERSE:
|
|
|
|
|
return entity_instance.wrap_value(self.wrapped_data.get_inverse(name))
|
2017-01-04 09:15:52 +01:00
|
|
|
else:
|
|
|
|
|
raise AttributeError(
|
|
|
|
|
"entity instance of type '%s' has no attribute '%s'" % (self.wrapped_data.is_a(), name))
|
|
|
|
|
|
2016-07-18 15:53:20 +02:00
|
|
|
@staticmethod
|
|
|
|
|
def walk(f, g, value):
|
2017-01-04 09:15:52 +01:00
|
|
|
if isinstance(value, (tuple, list)):
|
|
|
|
|
return tuple(map(functools.partial(entity_instance.walk, f, g), value))
|
|
|
|
|
elif f(value):
|
|
|
|
|
return g(value)
|
|
|
|
|
else:
|
|
|
|
|
return value
|
|
|
|
|
|
2016-07-18 15:53:20 +02:00
|
|
|
@staticmethod
|
|
|
|
|
def wrap_value(v):
|
2017-11-06 09:10:28 +01:00
|
|
|
def wrap(e): return entity_instance(e)
|
|
|
|
|
|
|
|
|
|
def is_instance(e): return isinstance(e, ifcopenshell_wrapper.entity_instance)
|
2017-11-06 11:06:40 +01:00
|
|
|
|
2016-07-18 15:53:20 +02:00
|
|
|
return entity_instance.walk(is_instance, wrap, v)
|
2017-01-04 09:15:52 +01:00
|
|
|
|
2016-07-18 15:53:20 +02:00
|
|
|
@staticmethod
|
|
|
|
|
def unwrap_value(v):
|
2017-11-06 09:10:28 +01:00
|
|
|
def unwrap(e): return e.wrapped_data
|
|
|
|
|
|
|
|
|
|
def is_instance(e): return isinstance(e, entity_instance)
|
2017-11-06 11:06:40 +01:00
|
|
|
|
2016-07-18 15:53:20 +02:00
|
|
|
return entity_instance.walk(is_instance, unwrap, v)
|
2017-01-04 09:15:52 +01:00
|
|
|
|
2016-07-18 15:53:20 +02:00
|
|
|
def attribute_type(self, 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)
|
2017-01-04 09:15:52 +01:00
|
|
|
|
2016-07-18 15:53:20 +02:00
|
|
|
def attribute_name(self, attr_idx):
|
|
|
|
|
return self.wrapped_data.get_argument_name(attr_idx)
|
2017-01-04 09:15:52 +01:00
|
|
|
|
2016-07-18 15:53:20 +02:00
|
|
|
def __setattr__(self, key, value):
|
|
|
|
|
self[self.wrapped_data.get_argument_index(key)] = value
|
2017-01-04 09:15:52 +01:00
|
|
|
|
2016-07-18 15:53:20 +02:00
|
|
|
def __getitem__(self, key):
|
2017-08-02 16:05:56 +02:00
|
|
|
if key < 0 or key >= len(self):
|
|
|
|
|
raise IndexError("Attribute index {} out of range for instance of type {}".format(key, self.is_a()))
|
2016-07-18 15:53:20 +02:00
|
|
|
return entity_instance.wrap_value(self.wrapped_data.get_argument(key))
|
2017-01-04 09:15:52 +01:00
|
|
|
|
2016-07-18 15:53:20 +02:00
|
|
|
def __setitem__(self, idx, value):
|
|
|
|
|
if value is None:
|
|
|
|
|
self.wrapped_data.setArgumentAsNull(idx)
|
|
|
|
|
else:
|
2017-10-06 16:02:34 +02:00
|
|
|
attr_type = real_attr_type = self.attribute_type(idx).title().replace(' ', '')
|
2016-07-18 15:53:20 +02:00
|
|
|
attr_type = attr_type.replace('Binary', 'String')
|
|
|
|
|
attr_type = attr_type.replace('Enumeration', 'String')
|
|
|
|
|
try:
|
2017-11-06 09:10:28 +01:00
|
|
|
if isinstance(value, unicode):
|
|
|
|
|
value = value.encode("utf-8")
|
2017-11-06 11:06:40 +01:00
|
|
|
except BaseException:
|
2017-01-04 09:15:52 +01:00
|
|
|
pass
|
2017-10-06 16:02:34 +02:00
|
|
|
try:
|
|
|
|
|
getattr(self.wrapped_data, "setArgumentAs%s" % attr_type)(idx, entity_instance.unwrap_value(value))
|
2017-11-06 11:06:40 +01:00
|
|
|
except BaseException:
|
|
|
|
|
raise ValueError("Expected %s for attribute %s.%s, got %r" % (
|
|
|
|
|
real_attr_type, self.is_a(), self.attribute_name(idx), value))
|
2016-07-18 15:53:20 +02:00
|
|
|
return value
|
2017-01-04 09:15:52 +01:00
|
|
|
|
|
|
|
|
def __len__(self):
|
|
|
|
|
return len(self.wrapped_data)
|
|
|
|
|
|
|
|
|
|
def __repr__(self):
|
|
|
|
|
return repr(self.wrapped_data)
|
|
|
|
|
|
|
|
|
|
def is_a(self, *args):
|
|
|
|
|
return self.wrapped_data.is_a(*args)
|
|
|
|
|
|
|
|
|
|
def id(self):
|
|
|
|
|
return self.wrapped_data.id()
|
|
|
|
|
|
2016-07-18 15:53:20 +02:00
|
|
|
def __eq__(self, other):
|
2017-11-06 11:06:40 +01:00
|
|
|
if not isinstance(self, type(other)):
|
2017-11-06 09:10:28 +01:00
|
|
|
return False
|
2016-07-18 15:53:20 +02:00
|
|
|
return self.wrapped_data == other.wrapped_data
|
2017-01-04 09:15:52 +01:00
|
|
|
|
2016-07-18 15:53:20 +02:00
|
|
|
def __hash__(self):
|
|
|
|
|
return hash((self.id(), self.wrapped_data.file_pointer()))
|
2017-01-04 09:15:52 +01:00
|
|
|
|
2016-07-18 15:53:20 +02:00
|
|
|
def __dir__(self):
|
|
|
|
|
return sorted(set(itertools.chain(
|
|
|
|
|
dir(type(self)),
|
2017-08-02 16:08:07 +02:00
|
|
|
map(str, self.wrapped_data.get_attribute_names()),
|
|
|
|
|
map(str, self.wrapped_data.get_inverse_attribute_names())
|
2016-07-18 15:53:20 +02:00
|
|
|
)))
|
2017-01-04 09:15:52 +01:00
|
|
|
|
2017-08-04 16:30:43 +02:00
|
|
|
def get_info(self, include_identifier=True, recursive=False, return_type=dict, ignore=()):
|
|
|
|
|
def _():
|
2017-01-01 16:19:39 +01:00
|
|
|
try:
|
2017-08-04 16:30:43 +02:00
|
|
|
if include_identifier:
|
|
|
|
|
yield "id", self.id()
|
|
|
|
|
yield "type", self.is_a()
|
2017-11-06 11:06:40 +01:00
|
|
|
except BaseException:
|
2017-08-04 16:30:43 +02:00
|
|
|
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:
|
|
|
|
|
continue
|
|
|
|
|
attr_value = self[i]
|
|
|
|
|
if recursive:
|
2017-11-06 09:10:28 +01:00
|
|
|
def is_instance(e): return isinstance(e, entity_instance)
|
|
|
|
|
|
2017-08-04 16:30:43 +02:00
|
|
|
def get_info_(inst):
|
|
|
|
|
# for ty in ignore:
|
|
|
|
|
# if inst.is_a(ty):
|
|
|
|
|
# return None
|
|
|
|
|
return entity_instance.get_info(inst,
|
2017-11-06 09:10:28 +01:00
|
|
|
include_identifier=include_identifier,
|
|
|
|
|
recursive=recursive,
|
|
|
|
|
return_type=return_type,
|
|
|
|
|
ignore=ignore
|
|
|
|
|
)
|
2017-11-06 11:06:40 +01:00
|
|
|
|
2017-08-04 16:30:43 +02:00
|
|
|
attr_value = entity_instance.walk(is_instance, get_info_, attr_value)
|
|
|
|
|
yield self.attribute_name(i), attr_value
|
2017-11-06 11:06:40 +01:00
|
|
|
except BaseException:
|
2017-08-04 16:30:43 +02:00
|
|
|
logging.exception("unhandled exception occured setting attribute name for {}".format(self))
|
2017-11-06 11:06:40 +01:00
|
|
|
|
2017-08-04 16:30:43 +02:00
|
|
|
return return_type(_())
|
2017-01-04 09:15:52 +01:00
|
|
|
|
|
|
|
|
__dict__ = property(get_info)
|