mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-13 19:07:57 +00:00
express: include referencing SELECT types in typeof() (#3187)
Per ISO 10303-11 12.4.3, TYPEOF() must return every type a value conforms to, including any SELECT data type that references it (transitively) as a member. The previous implementation only walked entity supertypes and defined-type chains, so it never reported SELECT types. This silently broke every WHERE rule that tests SELECT membership through typeof: for example IfcFillAreaStyle.MaxOneColour and ConsistentHatchStyleDef test `'ifc4.ifccolour' in typeof(style)`, so an IfcFillAreaStyle with two IfcColourRgb entries was never rejected. typeof() now builds a per-schema (cached) reverse map from a type name to the SELECT types that reference it as a direct member, then closes the base type set over that map so selects-of-selects are also included. The canonical implementation lives in the rule_compiler.py preamble and is copied verbatim into every generated rules/*.py, so the source of truth and the generated files are updated in lockstep. Verified: typeof(IfcColourRgb) now yields ifccolour, ifccolourorfactor, and ifcfillstyleselect; an IfcFillAreaStyle with two colours now fails MaxOneColour. All 138 express rule fixtures still pass (75 pass-cases at 0 errors, 63 fail-cases still flagged), no regressions. Generated with the assistance of an AI coding tool. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -939,10 +939,27 @@ def typeof(inst):
|
||||
# If V evaluates to indeterminate (?), an empty set is returned.
|
||||
return express_set([])
|
||||
schema_name = inst.is_a(True).split('.')[0].lower()
|
||||
schema = ifcopenshell.ifcopenshell_wrapper.schema_by_name(schema_name)
|
||||
# Per ISO 10303-11 12.4.3, TYPEOF() also includes every select data type
|
||||
# that references (transitively) any of the value's types as a member of
|
||||
# its select list. Cache, per schema, the reverse map type name -> select
|
||||
# types directly referencing it.
|
||||
select_parents = getattr(typeof, '_select_parents', None)
|
||||
if select_parents is None:
|
||||
select_parents = typeof._select_parents = {}
|
||||
schema_selects = select_parents.get(schema_name)
|
||||
if schema_selects is None:
|
||||
schema_selects = {}
|
||||
for decl in schema.declarations():
|
||||
if isinstance(decl, ifcopenshell.ifcopenshell_wrapper.select_type):
|
||||
sel_name = decl.name().lower()
|
||||
for member in decl.select_list():
|
||||
schema_selects.setdefault(member.name().lower(), []).append(sel_name)
|
||||
select_parents[schema_name] = schema_selects
|
||||
def inner():
|
||||
decl = ifcopenshell.ifcopenshell_wrapper.schema_by_name(schema_name).declaration_by_name(inst.is_a())
|
||||
decl = schema.declaration_by_name(inst.is_a())
|
||||
while decl:
|
||||
yield '.'.join((schema_name, decl.name().lower()))
|
||||
yield decl.name().lower()
|
||||
if isinstance(decl, ifcopenshell.ifcopenshell_wrapper.entity):
|
||||
decl = decl.supertype()
|
||||
else:
|
||||
@@ -951,7 +968,15 @@ def typeof(inst):
|
||||
decl = decl.declared_type()
|
||||
if not isinstance(decl, ifcopenshell.ifcopenshell_wrapper.type_declaration):
|
||||
break
|
||||
return express_set(inner())
|
||||
names = set(inner())
|
||||
queue = list(names)
|
||||
while queue:
|
||||
name = queue.pop()
|
||||
for sel_name in schema_selects.get(name, ()):
|
||||
if sel_name not in names:
|
||||
names.add(sel_name)
|
||||
queue.append(sel_name)
|
||||
return express_set('.'.join((schema_name, name)) for name in names)
|
||||
|
||||
class indeterminate_type:
|
||||
def __bool__(self):
|
||||
|
||||
@@ -96,11 +96,24 @@ def typeof(inst):
|
||||
if not inst:
|
||||
return express_set([])
|
||||
schema_name = inst.is_a(True).split('.')[0].lower()
|
||||
schema = ifcopenshell.ifcopenshell_wrapper.schema_by_name(schema_name)
|
||||
select_parents = getattr(typeof, '_select_parents', None)
|
||||
if select_parents is None:
|
||||
select_parents = typeof._select_parents = {}
|
||||
schema_selects = select_parents.get(schema_name)
|
||||
if schema_selects is None:
|
||||
schema_selects = {}
|
||||
for decl in schema.declarations():
|
||||
if isinstance(decl, ifcopenshell.ifcopenshell_wrapper.select_type):
|
||||
sel_name = decl.name().lower()
|
||||
for member in decl.select_list():
|
||||
schema_selects.setdefault(member.name().lower(), []).append(sel_name)
|
||||
select_parents[schema_name] = schema_selects
|
||||
|
||||
def inner():
|
||||
decl = ifcopenshell.ifcopenshell_wrapper.schema_by_name(schema_name).declaration_by_name(inst.is_a())
|
||||
decl = schema.declaration_by_name(inst.is_a())
|
||||
while decl:
|
||||
yield '.'.join((schema_name, decl.name().lower()))
|
||||
yield decl.name().lower()
|
||||
if isinstance(decl, ifcopenshell.ifcopenshell_wrapper.entity):
|
||||
decl = decl.supertype()
|
||||
else:
|
||||
@@ -109,7 +122,15 @@ def typeof(inst):
|
||||
decl = decl.declared_type()
|
||||
if not isinstance(decl, ifcopenshell.ifcopenshell_wrapper.type_declaration):
|
||||
break
|
||||
return express_set(inner())
|
||||
names = set(inner())
|
||||
queue = list(names)
|
||||
while queue:
|
||||
name = queue.pop()
|
||||
for sel_name in schema_selects.get(name, ()):
|
||||
if sel_name not in names:
|
||||
names.add(sel_name)
|
||||
queue.append(sel_name)
|
||||
return express_set('.'.join((schema_name, name)) for name in names)
|
||||
|
||||
class indeterminate_type:
|
||||
|
||||
|
||||
@@ -96,11 +96,24 @@ def typeof(inst):
|
||||
if not inst:
|
||||
return express_set([])
|
||||
schema_name = inst.is_a(True).split('.')[0].lower()
|
||||
schema = ifcopenshell.ifcopenshell_wrapper.schema_by_name(schema_name)
|
||||
select_parents = getattr(typeof, '_select_parents', None)
|
||||
if select_parents is None:
|
||||
select_parents = typeof._select_parents = {}
|
||||
schema_selects = select_parents.get(schema_name)
|
||||
if schema_selects is None:
|
||||
schema_selects = {}
|
||||
for decl in schema.declarations():
|
||||
if isinstance(decl, ifcopenshell.ifcopenshell_wrapper.select_type):
|
||||
sel_name = decl.name().lower()
|
||||
for member in decl.select_list():
|
||||
schema_selects.setdefault(member.name().lower(), []).append(sel_name)
|
||||
select_parents[schema_name] = schema_selects
|
||||
|
||||
def inner():
|
||||
decl = ifcopenshell.ifcopenshell_wrapper.schema_by_name(schema_name).declaration_by_name(inst.is_a())
|
||||
decl = schema.declaration_by_name(inst.is_a())
|
||||
while decl:
|
||||
yield '.'.join((schema_name, decl.name().lower()))
|
||||
yield decl.name().lower()
|
||||
if isinstance(decl, ifcopenshell.ifcopenshell_wrapper.entity):
|
||||
decl = decl.supertype()
|
||||
else:
|
||||
@@ -109,7 +122,15 @@ def typeof(inst):
|
||||
decl = decl.declared_type()
|
||||
if not isinstance(decl, ifcopenshell.ifcopenshell_wrapper.type_declaration):
|
||||
break
|
||||
return express_set(inner())
|
||||
names = set(inner())
|
||||
queue = list(names)
|
||||
while queue:
|
||||
name = queue.pop()
|
||||
for sel_name in schema_selects.get(name, ()):
|
||||
if sel_name not in names:
|
||||
names.add(sel_name)
|
||||
queue.append(sel_name)
|
||||
return express_set('.'.join((schema_name, name)) for name in names)
|
||||
|
||||
class indeterminate_type:
|
||||
|
||||
|
||||
@@ -96,11 +96,24 @@ def typeof(inst):
|
||||
if not inst:
|
||||
return express_set([])
|
||||
schema_name = inst.is_a(True).split('.')[0].lower()
|
||||
schema = ifcopenshell.ifcopenshell_wrapper.schema_by_name(schema_name)
|
||||
select_parents = getattr(typeof, '_select_parents', None)
|
||||
if select_parents is None:
|
||||
select_parents = typeof._select_parents = {}
|
||||
schema_selects = select_parents.get(schema_name)
|
||||
if schema_selects is None:
|
||||
schema_selects = {}
|
||||
for decl in schema.declarations():
|
||||
if isinstance(decl, ifcopenshell.ifcopenshell_wrapper.select_type):
|
||||
sel_name = decl.name().lower()
|
||||
for member in decl.select_list():
|
||||
schema_selects.setdefault(member.name().lower(), []).append(sel_name)
|
||||
select_parents[schema_name] = schema_selects
|
||||
|
||||
def inner():
|
||||
decl = ifcopenshell.ifcopenshell_wrapper.schema_by_name(schema_name).declaration_by_name(inst.is_a())
|
||||
decl = schema.declaration_by_name(inst.is_a())
|
||||
while decl:
|
||||
yield '.'.join((schema_name, decl.name().lower()))
|
||||
yield decl.name().lower()
|
||||
if isinstance(decl, ifcopenshell.ifcopenshell_wrapper.entity):
|
||||
decl = decl.supertype()
|
||||
else:
|
||||
@@ -109,7 +122,15 @@ def typeof(inst):
|
||||
decl = decl.declared_type()
|
||||
if not isinstance(decl, ifcopenshell.ifcopenshell_wrapper.type_declaration):
|
||||
break
|
||||
return express_set(inner())
|
||||
names = set(inner())
|
||||
queue = list(names)
|
||||
while queue:
|
||||
name = queue.pop()
|
||||
for sel_name in schema_selects.get(name, ()):
|
||||
if sel_name not in names:
|
||||
names.add(sel_name)
|
||||
queue.append(sel_name)
|
||||
return express_set('.'.join((schema_name, name)) for name in names)
|
||||
|
||||
class indeterminate_type:
|
||||
|
||||
|
||||
@@ -96,11 +96,24 @@ def typeof(inst):
|
||||
if not inst:
|
||||
return express_set([])
|
||||
schema_name = inst.is_a(True).split('.')[0].lower()
|
||||
schema = ifcopenshell.ifcopenshell_wrapper.schema_by_name(schema_name)
|
||||
select_parents = getattr(typeof, '_select_parents', None)
|
||||
if select_parents is None:
|
||||
select_parents = typeof._select_parents = {}
|
||||
schema_selects = select_parents.get(schema_name)
|
||||
if schema_selects is None:
|
||||
schema_selects = {}
|
||||
for decl in schema.declarations():
|
||||
if isinstance(decl, ifcopenshell.ifcopenshell_wrapper.select_type):
|
||||
sel_name = decl.name().lower()
|
||||
for member in decl.select_list():
|
||||
schema_selects.setdefault(member.name().lower(), []).append(sel_name)
|
||||
select_parents[schema_name] = schema_selects
|
||||
|
||||
def inner():
|
||||
decl = ifcopenshell.ifcopenshell_wrapper.schema_by_name(schema_name).declaration_by_name(inst.is_a())
|
||||
decl = schema.declaration_by_name(inst.is_a())
|
||||
while decl:
|
||||
yield '.'.join((schema_name, decl.name().lower()))
|
||||
yield decl.name().lower()
|
||||
if isinstance(decl, ifcopenshell.ifcopenshell_wrapper.entity):
|
||||
decl = decl.supertype()
|
||||
else:
|
||||
@@ -109,7 +122,15 @@ def typeof(inst):
|
||||
decl = decl.declared_type()
|
||||
if not isinstance(decl, ifcopenshell.ifcopenshell_wrapper.type_declaration):
|
||||
break
|
||||
return express_set(inner())
|
||||
names = set(inner())
|
||||
queue = list(names)
|
||||
while queue:
|
||||
name = queue.pop()
|
||||
for sel_name in schema_selects.get(name, ()):
|
||||
if sel_name not in names:
|
||||
names.add(sel_name)
|
||||
queue.append(sel_name)
|
||||
return express_set('.'.join((schema_name, name)) for name in names)
|
||||
|
||||
class indeterminate_type:
|
||||
|
||||
|
||||
@@ -96,11 +96,24 @@ def typeof(inst):
|
||||
if not inst:
|
||||
return express_set([])
|
||||
schema_name = inst.is_a(True).split('.')[0].lower()
|
||||
schema = ifcopenshell.ifcopenshell_wrapper.schema_by_name(schema_name)
|
||||
select_parents = getattr(typeof, '_select_parents', None)
|
||||
if select_parents is None:
|
||||
select_parents = typeof._select_parents = {}
|
||||
schema_selects = select_parents.get(schema_name)
|
||||
if schema_selects is None:
|
||||
schema_selects = {}
|
||||
for decl in schema.declarations():
|
||||
if isinstance(decl, ifcopenshell.ifcopenshell_wrapper.select_type):
|
||||
sel_name = decl.name().lower()
|
||||
for member in decl.select_list():
|
||||
schema_selects.setdefault(member.name().lower(), []).append(sel_name)
|
||||
select_parents[schema_name] = schema_selects
|
||||
|
||||
def inner():
|
||||
decl = ifcopenshell.ifcopenshell_wrapper.schema_by_name(schema_name).declaration_by_name(inst.is_a())
|
||||
decl = schema.declaration_by_name(inst.is_a())
|
||||
while decl:
|
||||
yield '.'.join((schema_name, decl.name().lower()))
|
||||
yield decl.name().lower()
|
||||
if isinstance(decl, ifcopenshell.ifcopenshell_wrapper.entity):
|
||||
decl = decl.supertype()
|
||||
else:
|
||||
@@ -109,7 +122,15 @@ def typeof(inst):
|
||||
decl = decl.declared_type()
|
||||
if not isinstance(decl, ifcopenshell.ifcopenshell_wrapper.type_declaration):
|
||||
break
|
||||
return express_set(inner())
|
||||
names = set(inner())
|
||||
queue = list(names)
|
||||
while queue:
|
||||
name = queue.pop()
|
||||
for sel_name in schema_selects.get(name, ()):
|
||||
if sel_name not in names:
|
||||
names.add(sel_name)
|
||||
queue.append(sel_name)
|
||||
return express_set('.'.join((schema_name, name)) for name in names)
|
||||
|
||||
class indeterminate_type:
|
||||
|
||||
|
||||
@@ -96,11 +96,24 @@ def typeof(inst):
|
||||
if not inst:
|
||||
return express_set([])
|
||||
schema_name = inst.is_a(True).split('.')[0].lower()
|
||||
schema = ifcopenshell.ifcopenshell_wrapper.schema_by_name(schema_name)
|
||||
select_parents = getattr(typeof, '_select_parents', None)
|
||||
if select_parents is None:
|
||||
select_parents = typeof._select_parents = {}
|
||||
schema_selects = select_parents.get(schema_name)
|
||||
if schema_selects is None:
|
||||
schema_selects = {}
|
||||
for decl in schema.declarations():
|
||||
if isinstance(decl, ifcopenshell.ifcopenshell_wrapper.select_type):
|
||||
sel_name = decl.name().lower()
|
||||
for member in decl.select_list():
|
||||
schema_selects.setdefault(member.name().lower(), []).append(sel_name)
|
||||
select_parents[schema_name] = schema_selects
|
||||
|
||||
def inner():
|
||||
decl = ifcopenshell.ifcopenshell_wrapper.schema_by_name(schema_name).declaration_by_name(inst.is_a())
|
||||
decl = schema.declaration_by_name(inst.is_a())
|
||||
while decl:
|
||||
yield '.'.join((schema_name, decl.name().lower()))
|
||||
yield decl.name().lower()
|
||||
if isinstance(decl, ifcopenshell.ifcopenshell_wrapper.entity):
|
||||
decl = decl.supertype()
|
||||
else:
|
||||
@@ -109,7 +122,15 @@ def typeof(inst):
|
||||
decl = decl.declared_type()
|
||||
if not isinstance(decl, ifcopenshell.ifcopenshell_wrapper.type_declaration):
|
||||
break
|
||||
return express_set(inner())
|
||||
names = set(inner())
|
||||
queue = list(names)
|
||||
while queue:
|
||||
name = queue.pop()
|
||||
for sel_name in schema_selects.get(name, ()):
|
||||
if sel_name not in names:
|
||||
names.add(sel_name)
|
||||
queue.append(sel_name)
|
||||
return express_set('.'.join((schema_name, name)) for name in names)
|
||||
|
||||
class indeterminate_type:
|
||||
|
||||
|
||||
@@ -96,11 +96,24 @@ def typeof(inst):
|
||||
if not inst:
|
||||
return express_set([])
|
||||
schema_name = inst.is_a(True).split('.')[0].lower()
|
||||
schema = ifcopenshell.ifcopenshell_wrapper.schema_by_name(schema_name)
|
||||
select_parents = getattr(typeof, '_select_parents', None)
|
||||
if select_parents is None:
|
||||
select_parents = typeof._select_parents = {}
|
||||
schema_selects = select_parents.get(schema_name)
|
||||
if schema_selects is None:
|
||||
schema_selects = {}
|
||||
for decl in schema.declarations():
|
||||
if isinstance(decl, ifcopenshell.ifcopenshell_wrapper.select_type):
|
||||
sel_name = decl.name().lower()
|
||||
for member in decl.select_list():
|
||||
schema_selects.setdefault(member.name().lower(), []).append(sel_name)
|
||||
select_parents[schema_name] = schema_selects
|
||||
|
||||
def inner():
|
||||
decl = ifcopenshell.ifcopenshell_wrapper.schema_by_name(schema_name).declaration_by_name(inst.is_a())
|
||||
decl = schema.declaration_by_name(inst.is_a())
|
||||
while decl:
|
||||
yield '.'.join((schema_name, decl.name().lower()))
|
||||
yield decl.name().lower()
|
||||
if isinstance(decl, ifcopenshell.ifcopenshell_wrapper.entity):
|
||||
decl = decl.supertype()
|
||||
else:
|
||||
@@ -109,7 +122,15 @@ def typeof(inst):
|
||||
decl = decl.declared_type()
|
||||
if not isinstance(decl, ifcopenshell.ifcopenshell_wrapper.type_declaration):
|
||||
break
|
||||
return express_set(inner())
|
||||
names = set(inner())
|
||||
queue = list(names)
|
||||
while queue:
|
||||
name = queue.pop()
|
||||
for sel_name in schema_selects.get(name, ()):
|
||||
if sel_name not in names:
|
||||
names.add(sel_name)
|
||||
queue.append(sel_name)
|
||||
return express_set('.'.join((schema_name, name)) for name in names)
|
||||
|
||||
class indeterminate_type:
|
||||
|
||||
|
||||
@@ -96,11 +96,24 @@ def typeof(inst):
|
||||
if not inst:
|
||||
return express_set([])
|
||||
schema_name = inst.is_a(True).split('.')[0].lower()
|
||||
schema = ifcopenshell.ifcopenshell_wrapper.schema_by_name(schema_name)
|
||||
select_parents = getattr(typeof, '_select_parents', None)
|
||||
if select_parents is None:
|
||||
select_parents = typeof._select_parents = {}
|
||||
schema_selects = select_parents.get(schema_name)
|
||||
if schema_selects is None:
|
||||
schema_selects = {}
|
||||
for decl in schema.declarations():
|
||||
if isinstance(decl, ifcopenshell.ifcopenshell_wrapper.select_type):
|
||||
sel_name = decl.name().lower()
|
||||
for member in decl.select_list():
|
||||
schema_selects.setdefault(member.name().lower(), []).append(sel_name)
|
||||
select_parents[schema_name] = schema_selects
|
||||
|
||||
def inner():
|
||||
decl = ifcopenshell.ifcopenshell_wrapper.schema_by_name(schema_name).declaration_by_name(inst.is_a())
|
||||
decl = schema.declaration_by_name(inst.is_a())
|
||||
while decl:
|
||||
yield '.'.join((schema_name, decl.name().lower()))
|
||||
yield decl.name().lower()
|
||||
if isinstance(decl, ifcopenshell.ifcopenshell_wrapper.entity):
|
||||
decl = decl.supertype()
|
||||
else:
|
||||
@@ -109,7 +122,15 @@ def typeof(inst):
|
||||
decl = decl.declared_type()
|
||||
if not isinstance(decl, ifcopenshell.ifcopenshell_wrapper.type_declaration):
|
||||
break
|
||||
return express_set(inner())
|
||||
names = set(inner())
|
||||
queue = list(names)
|
||||
while queue:
|
||||
name = queue.pop()
|
||||
for sel_name in schema_selects.get(name, ()):
|
||||
if sel_name not in names:
|
||||
names.add(sel_name)
|
||||
queue.append(sel_name)
|
||||
return express_set('.'.join((schema_name, name)) for name in names)
|
||||
|
||||
class indeterminate_type:
|
||||
|
||||
|
||||
@@ -96,11 +96,24 @@ def typeof(inst):
|
||||
if not inst:
|
||||
return express_set([])
|
||||
schema_name = inst.is_a(True).split('.')[0].lower()
|
||||
schema = ifcopenshell.ifcopenshell_wrapper.schema_by_name(schema_name)
|
||||
select_parents = getattr(typeof, '_select_parents', None)
|
||||
if select_parents is None:
|
||||
select_parents = typeof._select_parents = {}
|
||||
schema_selects = select_parents.get(schema_name)
|
||||
if schema_selects is None:
|
||||
schema_selects = {}
|
||||
for decl in schema.declarations():
|
||||
if isinstance(decl, ifcopenshell.ifcopenshell_wrapper.select_type):
|
||||
sel_name = decl.name().lower()
|
||||
for member in decl.select_list():
|
||||
schema_selects.setdefault(member.name().lower(), []).append(sel_name)
|
||||
select_parents[schema_name] = schema_selects
|
||||
|
||||
def inner():
|
||||
decl = ifcopenshell.ifcopenshell_wrapper.schema_by_name(schema_name).declaration_by_name(inst.is_a())
|
||||
decl = schema.declaration_by_name(inst.is_a())
|
||||
while decl:
|
||||
yield '.'.join((schema_name, decl.name().lower()))
|
||||
yield decl.name().lower()
|
||||
if isinstance(decl, ifcopenshell.ifcopenshell_wrapper.entity):
|
||||
decl = decl.supertype()
|
||||
else:
|
||||
@@ -109,7 +122,15 @@ def typeof(inst):
|
||||
decl = decl.declared_type()
|
||||
if not isinstance(decl, ifcopenshell.ifcopenshell_wrapper.type_declaration):
|
||||
break
|
||||
return express_set(inner())
|
||||
names = set(inner())
|
||||
queue = list(names)
|
||||
while queue:
|
||||
name = queue.pop()
|
||||
for sel_name in schema_selects.get(name, ()):
|
||||
if sel_name not in names:
|
||||
names.add(sel_name)
|
||||
queue.append(sel_name)
|
||||
return express_set('.'.join((schema_name, name)) for name in names)
|
||||
|
||||
class indeterminate_type:
|
||||
|
||||
|
||||
@@ -96,11 +96,24 @@ def typeof(inst):
|
||||
if not inst:
|
||||
return express_set([])
|
||||
schema_name = inst.is_a(True).split('.')[0].lower()
|
||||
schema = ifcopenshell.ifcopenshell_wrapper.schema_by_name(schema_name)
|
||||
select_parents = getattr(typeof, '_select_parents', None)
|
||||
if select_parents is None:
|
||||
select_parents = typeof._select_parents = {}
|
||||
schema_selects = select_parents.get(schema_name)
|
||||
if schema_selects is None:
|
||||
schema_selects = {}
|
||||
for decl in schema.declarations():
|
||||
if isinstance(decl, ifcopenshell.ifcopenshell_wrapper.select_type):
|
||||
sel_name = decl.name().lower()
|
||||
for member in decl.select_list():
|
||||
schema_selects.setdefault(member.name().lower(), []).append(sel_name)
|
||||
select_parents[schema_name] = schema_selects
|
||||
|
||||
def inner():
|
||||
decl = ifcopenshell.ifcopenshell_wrapper.schema_by_name(schema_name).declaration_by_name(inst.is_a())
|
||||
decl = schema.declaration_by_name(inst.is_a())
|
||||
while decl:
|
||||
yield '.'.join((schema_name, decl.name().lower()))
|
||||
yield decl.name().lower()
|
||||
if isinstance(decl, ifcopenshell.ifcopenshell_wrapper.entity):
|
||||
decl = decl.supertype()
|
||||
else:
|
||||
@@ -109,7 +122,15 @@ def typeof(inst):
|
||||
decl = decl.declared_type()
|
||||
if not isinstance(decl, ifcopenshell.ifcopenshell_wrapper.type_declaration):
|
||||
break
|
||||
return express_set(inner())
|
||||
names = set(inner())
|
||||
queue = list(names)
|
||||
while queue:
|
||||
name = queue.pop()
|
||||
for sel_name in schema_selects.get(name, ()):
|
||||
if sel_name not in names:
|
||||
names.add(sel_name)
|
||||
queue.append(sel_name)
|
||||
return express_set('.'.join((schema_name, name)) for name in names)
|
||||
|
||||
class indeterminate_type:
|
||||
|
||||
|
||||
@@ -96,11 +96,24 @@ def typeof(inst):
|
||||
if not inst:
|
||||
return express_set([])
|
||||
schema_name = inst.is_a(True).split('.')[0].lower()
|
||||
schema = ifcopenshell.ifcopenshell_wrapper.schema_by_name(schema_name)
|
||||
select_parents = getattr(typeof, '_select_parents', None)
|
||||
if select_parents is None:
|
||||
select_parents = typeof._select_parents = {}
|
||||
schema_selects = select_parents.get(schema_name)
|
||||
if schema_selects is None:
|
||||
schema_selects = {}
|
||||
for decl in schema.declarations():
|
||||
if isinstance(decl, ifcopenshell.ifcopenshell_wrapper.select_type):
|
||||
sel_name = decl.name().lower()
|
||||
for member in decl.select_list():
|
||||
schema_selects.setdefault(member.name().lower(), []).append(sel_name)
|
||||
select_parents[schema_name] = schema_selects
|
||||
|
||||
def inner():
|
||||
decl = ifcopenshell.ifcopenshell_wrapper.schema_by_name(schema_name).declaration_by_name(inst.is_a())
|
||||
decl = schema.declaration_by_name(inst.is_a())
|
||||
while decl:
|
||||
yield '.'.join((schema_name, decl.name().lower()))
|
||||
yield decl.name().lower()
|
||||
if isinstance(decl, ifcopenshell.ifcopenshell_wrapper.entity):
|
||||
decl = decl.supertype()
|
||||
else:
|
||||
@@ -109,7 +122,15 @@ def typeof(inst):
|
||||
decl = decl.declared_type()
|
||||
if not isinstance(decl, ifcopenshell.ifcopenshell_wrapper.type_declaration):
|
||||
break
|
||||
return express_set(inner())
|
||||
names = set(inner())
|
||||
queue = list(names)
|
||||
while queue:
|
||||
name = queue.pop()
|
||||
for sel_name in schema_selects.get(name, ()):
|
||||
if sel_name not in names:
|
||||
names.add(sel_name)
|
||||
queue.append(sel_name)
|
||||
return express_set('.'.join((schema_name, name)) for name in names)
|
||||
|
||||
class indeterminate_type:
|
||||
|
||||
|
||||
@@ -96,11 +96,24 @@ def typeof(inst):
|
||||
if not inst:
|
||||
return express_set([])
|
||||
schema_name = inst.is_a(True).split('.')[0].lower()
|
||||
schema = ifcopenshell.ifcopenshell_wrapper.schema_by_name(schema_name)
|
||||
select_parents = getattr(typeof, '_select_parents', None)
|
||||
if select_parents is None:
|
||||
select_parents = typeof._select_parents = {}
|
||||
schema_selects = select_parents.get(schema_name)
|
||||
if schema_selects is None:
|
||||
schema_selects = {}
|
||||
for decl in schema.declarations():
|
||||
if isinstance(decl, ifcopenshell.ifcopenshell_wrapper.select_type):
|
||||
sel_name = decl.name().lower()
|
||||
for member in decl.select_list():
|
||||
schema_selects.setdefault(member.name().lower(), []).append(sel_name)
|
||||
select_parents[schema_name] = schema_selects
|
||||
|
||||
def inner():
|
||||
decl = ifcopenshell.ifcopenshell_wrapper.schema_by_name(schema_name).declaration_by_name(inst.is_a())
|
||||
decl = schema.declaration_by_name(inst.is_a())
|
||||
while decl:
|
||||
yield '.'.join((schema_name, decl.name().lower()))
|
||||
yield decl.name().lower()
|
||||
if isinstance(decl, ifcopenshell.ifcopenshell_wrapper.entity):
|
||||
decl = decl.supertype()
|
||||
else:
|
||||
@@ -109,7 +122,15 @@ def typeof(inst):
|
||||
decl = decl.declared_type()
|
||||
if not isinstance(decl, ifcopenshell.ifcopenshell_wrapper.type_declaration):
|
||||
break
|
||||
return express_set(inner())
|
||||
names = set(inner())
|
||||
queue = list(names)
|
||||
while queue:
|
||||
name = queue.pop()
|
||||
for sel_name in schema_selects.get(name, ()):
|
||||
if sel_name not in names:
|
||||
names.add(sel_name)
|
||||
queue.append(sel_name)
|
||||
return express_set('.'.join((schema_name, name)) for name in names)
|
||||
|
||||
class indeterminate_type:
|
||||
|
||||
|
||||
Reference in New Issue
Block a user