Fixes to validation of selected simple type / enum

This commit is contained in:
Thomas Krijnen
2023-04-13 13:16:48 +02:00
parent a56eac0131
commit f0bb19d48d
5 changed files with 51 additions and 9 deletions
@@ -154,7 +154,13 @@ def get_select_members(schema, ty):
for st in ty.subtypes():
yield from inner(st)
elif isinstance(ty, type_declaration):
# @todo shouldn't we list subtypes (e.g IfcPositiveLengthMeasure -> IfcLengthMeasure) here as well?
yield ty.name()
elif isinstance(ty, enumeration_type):
yield ty.name()
else:
# @todo raise exception?
pass
v = select_members_cache[cache_key] = set(inner(ty))
return v
@@ -182,20 +188,22 @@ def assert_valid(attr_type, val, schema, no_throw=False, attr=None):
elif isinstance(attr_type, (entity_type, type_declaration)):
invalid = not isinstance(val, ifcopenshell.entity_instance) or not val.is_a(attr_type.name())
elif isinstance(attr_type, select_type):
val_to_use = val
if isinstance(schema.declaration_by_name(val.is_a()), enumeration_type):
if isinstance(val, ifcopenshell.entity_instance):
val_to_use = val.wrappedValue
else:
invalid = True
if not invalid:
if not isinstance(val, ifcopenshell.entity_instance):
invalid = True
else:
value_type = schema.declaration_by_name(val.is_a())
if not isinstance(value_type, entity_type):
# we need to check two things: is (enumeration) literal/value valid
# for this type and is enumeration/value type valid for this select.
assert_valid(value_type, val.wrappedValue, schema, no_throw=no_throw)
# Previously we relied on `is_a(x) for x in attr_type.select_items()`
# this was linear in the number of select leafs, which is very large
# for e.g IfcValue, which is an often used select. Therefore, we now
# calculate (and cache) the select leafs (including entity subtypes)
# for the select definition and simply check for membership in this
# set.
invalid = val_to_use.is_a() not in get_select_members(schema, attr_type)
invalid = val.is_a() not in get_select_members(schema, attr_type)
elif isinstance(attr_type, enumeration_type):
invalid = val not in attr_type.enumeration_items()
elif isinstance(attr_type, aggregation_type):
@@ -0,0 +1,10 @@
ISO-10303-21;
HEADER;
FILE_DESCRIPTION(('ViewDefinition [CoordinationView]'),'2;1');
FILE_NAME('','2023-04-13T10:27:43',(),(),'IfcOpenShell v0.7.0-198fa67cc','IfcOpenShell v0.7.0-198fa67cc','');
FILE_SCHEMA(('IFC4X3_RC4'));
ENDSEC;
DATA;
#1=IFCFACILITYPART('0DYKeUG9993PtW$2icoR4v',$,$,$,$,$,$,$,$,IFCBRIDGEPARTTYPEENUM('NOT_EXISTING_ENUM'),.LATERAL.);
ENDSEC;
END-ISO-10303-21;
@@ -0,0 +1,10 @@
ISO-10303-21;
HEADER;
FILE_DESCRIPTION(('ViewDefinition [CoordinationView]'),'2;1');
FILE_NAME('','2023-04-13T10:24:46',(),(),'IfcOpenShell v0.7.0-198fa67cc','IfcOpenShell v0.7.0-198fa67cc','');
FILE_SCHEMA(('IFC4'));
ENDSEC;
DATA;
#1=IFCPROPERTYSINGLEVALUE('x',$,IFCPOSITIVELENGTHMEASURE('1'),$);
ENDSEC;
END-ISO-10303-21;
@@ -0,0 +1,10 @@
ISO-10303-21;
HEADER;
FILE_DESCRIPTION(('ViewDefinition [CoordinationView]'),'2;1');
FILE_NAME('','2023-04-13T10:27:43',(),(),'IfcOpenShell v0.7.0-198fa67cc','IfcOpenShell v0.7.0-198fa67cc','');
FILE_SCHEMA(('IFC4X3_RC4'));
ENDSEC;
DATA;
#1=IFCFACILITYPART('0DYKeUG9993PtW$2icoR4v',$,$,$,$,$,$,$,$,IFCBRIDGEPARTTYPEENUM('DECK'),.LATERAL.);
ENDSEC;
END-ISO-10303-21;
@@ -30,7 +30,11 @@ import ifcopenshell.validate
)
def test_file(file):
logger = ifcopenshell.validate.json_logger()
ifcopenshell.validate.validate(file, logger)
try:
ifcopenshell.validate.validate(file, logger)
except ifcopenshell.SchemaError as e:
pytest.skip()
file = os.path.basename(file)
if file.startswith("fail-"):
assert len(logger.statements) > 0
if file.startswith("pass-"):