Skip to content

Commit 9bbbc6e

Browse files
committed
Extend Python's dir() function on entity instances with attribute and inverse attribute names of entities
1 parent d41dbc3 commit 9bbbc6e

9 files changed

Lines changed: 413 additions & 292 deletions

File tree

src/ifcexpressparser/templates.py

Lines changed: 41 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@
9494
bool GetAttributeDerived(Enum t, unsigned char a);
9595
std::pair<const char*, int> GetEnumerationIndex(Enum t, const std::string& a);
9696
std::pair<Enum, unsigned> GetInverseAttribute(Enum t, const std::string& a);
97+
std::set<std::string> GetInverseAttributeNames(Enum t);
9798
void PopulateDerivedFields(IfcWrite::IfcWritableEntity* e);
9899
}}
99100
@@ -168,10 +169,15 @@
168169
using namespace IfcWrite;
169170
using namespace IfcUtil;
170171
171-
std::map<Type::Enum,IfcEntityDescriptor*> entity_descriptor_map;
172-
std::map<Type::Enum,IfcEnumerationDescriptor*> enumeration_descriptor_map;
173-
std::map<std::pair<Type::Enum, std::string>, std::pair<Type::Enum, int> > inverse_map;
174-
std::map<Type::Enum,std::set<int> > derived_map;
172+
typedef std::map<Type::Enum,IfcEntityDescriptor*> entity_descriptor_map_t;
173+
typedef std::map<Type::Enum,IfcEnumerationDescriptor*> enumeration_descriptor_map_t;
174+
typedef std::map<Type::Enum, std::map<std::string, std::pair<Type::Enum, int> > > inverse_map_t;
175+
typedef std::map<Type::Enum,std::set<int> > derived_map_t;
176+
177+
entity_descriptor_map_t entity_descriptor_map;
178+
enumeration_descriptor_map_t enumeration_descriptor_map;
179+
inverse_map_t inverse_map;
180+
derived_map_t derived_map;
175181
176182
void InitDescriptorMap() {
177183
IfcEntityDescriptor* current;
@@ -247,16 +253,41 @@
247253
248254
std::pair<Type::Enum, unsigned> Type::GetInverseAttribute(Enum t, const std::string& a) {
249255
if (inverse_map.empty()) ::InitInverseMap();
250-
std::map<std::pair<Type::Enum, std::string>, std::pair<Type::Enum, int> >::const_iterator it;
251-
std::pair<Type::Enum, std::string> key = std::make_pair(t, a);
256+
inverse_map_t::const_iterator it;
257+
inverse_map_t::mapped_type::const_iterator jt;
252258
while (true) {
253-
it = inverse_map.find(key);
254-
if (it != inverse_map.end()) return it->second;
255-
if ((key.first = Parent(key.first)) == -1) break;
259+
it = inverse_map.find(t);
260+
if (it != inverse_map.end()) {
261+
jt = it->second.find(a);
262+
if (jt != it->second.end()) {
263+
return jt->second;
264+
}
265+
}
266+
if ((t = Parent(t)) == -1) break;
256267
}
257268
throw IfcException("Attribute not found");
258269
}
259270
271+
std::set<std::string> Type::GetInverseAttributeNames(Enum t) {
272+
if (inverse_map.empty()) ::InitInverseMap();
273+
inverse_map_t::const_iterator it;
274+
inverse_map_t::mapped_type::const_iterator jt;
275+
276+
std::set<std::string> return_value;
277+
278+
while (true) {
279+
it = inverse_map.find(t);
280+
if (it != inverse_map.end()) {
281+
for (jt = it->second.begin(); jt != it->second.end(); ++jt) {
282+
return_value.insert(jt->first);
283+
}
284+
}
285+
if ((t = Parent(t)) == -1) break;
286+
}
287+
288+
return return_value;
289+
}
290+
260291
void Type::PopulateDerivedFields(IfcWrite::IfcWritableEntity* e) {
261292
std::map<Type::Enum, std::set<int> >::const_iterator i = derived_map.find(e->type());
262293
if (i != derived_map.end()) {
@@ -401,7 +432,7 @@ class %(name)s %(superclass)s{
401432
constructor_stmt_optional = " if (%(name)s) {%(stmt)s } else { e->setArgument(%(index)d); }"
402433
constructor_stmt_derived = " e->setArgumentDerived(%(index)d);"
403434

404-
inverse_implementation = " inverse_map.insert(std::make_pair(std::make_pair(Type::%(type)s, \"%(name)s\"), std::make_pair(Type::%(related_type)s, %(index)d)));"
435+
inverse_implementation = " inverse_map[Type::%(type)s].insert(std::make_pair(\"%(name)s\", std::make_pair(Type::%(related_type)s, %(index)d)));"
405436

406437
def multi_line_comment(li):
407438
return ("/// %s"%("\n/// ".join(li))) if len(li) else ""

src/ifcopenshell-python/ifcopenshell/__init__.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import sys
2222
import platform
2323
import functools
24+
import itertools
2425

2526
from functools import reduce
2627

@@ -79,6 +80,12 @@ def __len__(self): return len(self.wrapped_data)
7980
def __repr__(self): return repr(self.wrapped_data)
8081
def is_a(self, *args): return self.wrapped_data.is_a(*args)
8182
def id(self): return self.wrapped_data.id()
83+
def __dir__(self):
84+
return sorted(set(itertools.chain(
85+
dir(type(self)),
86+
self.wrapped_data.get_attribute_names(),
87+
self.wrapped_data.get_inverse_attribute_names()
88+
)))
8289

8390

8491
class file(object):

src/ifcparse/Ifc2x3-latebound.cpp

Lines changed: 154 additions & 124 deletions
Large diffs are not rendered by default.

src/ifcparse/Ifc2x3-latebound.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ namespace Type {
4444
bool GetAttributeDerived(Enum t, unsigned char a);
4545
std::pair<const char*, int> GetEnumerationIndex(Enum t, const std::string& a);
4646
std::pair<Enum, unsigned> GetInverseAttribute(Enum t, const std::string& a);
47+
std::set<std::string> GetInverseAttributeNames(Enum t);
4748
void PopulateDerivedFields(IfcWrite::IfcWritableEntity* e);
4849
}}
4950

src/ifcparse/Ifc4-latebound.cpp

Lines changed: 188 additions & 158 deletions
Large diffs are not rendered by default.

src/ifcparse/Ifc4-latebound.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ namespace Type {
4444
bool GetAttributeDerived(Enum t, unsigned char a);
4545
std::pair<const char*, int> GetEnumerationIndex(Enum t, const std::string& a);
4646
std::pair<Enum, unsigned> GetInverseAttribute(Enum t, const std::string& a);
47+
std::set<std::string> GetInverseAttributeNames(Enum t);
4748
void PopulateDerivedFields(IfcWrite::IfcWritableEntity* e);
4849
}}
4950

src/ifcparse/IfcLateBoundEntity.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,3 +216,19 @@ bool IfcParse::IfcLateBoundEntity::is_valid() {
216216
}
217217
return valid;
218218
}
219+
220+
std::vector<std::string> IfcParse::IfcLateBoundEntity::getAttributeNames() const {
221+
std::vector<std::string> return_value;
222+
return_value.reserve(getArgumentCount());
223+
for (unsigned i = 0; i < getArgumentCount(); ++i) {
224+
return_value.push_back(getArgumentName(i));
225+
}
226+
return return_value;
227+
}
228+
229+
std::vector<std::string> IfcParse::IfcLateBoundEntity::getInverseAttributeNames() const {
230+
std::vector<std::string> return_value;
231+
std::set<std::string> values = IfcSchema::Type::GetInverseAttributeNames(_type);
232+
std::copy(values.begin(), values.end(), std::back_inserter(return_value));
233+
return return_value;
234+
}

src/ifcparse/IfcLateBoundEntity.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,9 @@ namespace IfcParse {
5757

5858
IfcEntityList::ptr get_inverse(const std::string& a);
5959

60+
std::vector<std::string> getAttributeNames() const;
61+
std::vector<std::string> getInverseAttributeNames() const;
62+
6063
void setArgument(unsigned int i);
6164
void setArgument(unsigned int i, int v);
6265
void setArgument(unsigned int i, bool v);

src/ifcwrap/IfcParseWrapper.i

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@ namespace IfcUtil {
6060
%rename("get_argument_name") getArgumentName;
6161
%rename("get_argument_index") getArgumentIndex;
6262
%rename("get_argument_optionality") getArgumentOptionality;
63+
%rename("get_attribute_names") getAttributeNames;
64+
%rename("get_inverse_attribute_names") getInverseAttributeNames;
6365
%rename("_set_argument") setArgument;
6466
%rename("__repr__") toString;
6567
%rename("entity_instance") IfcLateBoundEntity;

0 commit comments

Comments
 (0)