mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-09 09:21:46 +00:00
Fixes to validation of selected simple type / enum
This commit is contained in:
@@ -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):
|
||||
|
||||
+10
@@ -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;
|
||||
+10
@@ -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;
|
||||
+10
@@ -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;
|
||||
+5
-1
@@ -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-"):
|
||||
Reference in New Issue
Block a user