mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-18 06:21:40 +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():
|
for st in ty.subtypes():
|
||||||
yield from inner(st)
|
yield from inner(st)
|
||||||
elif isinstance(ty, type_declaration):
|
elif isinstance(ty, type_declaration):
|
||||||
|
# @todo shouldn't we list subtypes (e.g IfcPositiveLengthMeasure -> IfcLengthMeasure) here as well?
|
||||||
yield ty.name()
|
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))
|
v = select_members_cache[cache_key] = set(inner(ty))
|
||||||
return v
|
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)):
|
elif isinstance(attr_type, (entity_type, type_declaration)):
|
||||||
invalid = not isinstance(val, ifcopenshell.entity_instance) or not val.is_a(attr_type.name())
|
invalid = not isinstance(val, ifcopenshell.entity_instance) or not val.is_a(attr_type.name())
|
||||||
elif isinstance(attr_type, select_type):
|
elif isinstance(attr_type, select_type):
|
||||||
val_to_use = val
|
if not isinstance(val, ifcopenshell.entity_instance):
|
||||||
if isinstance(schema.declaration_by_name(val.is_a()), enumeration_type):
|
invalid = True
|
||||||
if isinstance(val, ifcopenshell.entity_instance):
|
else:
|
||||||
val_to_use = val.wrappedValue
|
value_type = schema.declaration_by_name(val.is_a())
|
||||||
else:
|
if not isinstance(value_type, entity_type):
|
||||||
invalid = True
|
# we need to check two things: is (enumeration) literal/value valid
|
||||||
if not invalid:
|
# 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()`
|
# 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
|
# 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
|
# for e.g IfcValue, which is an often used select. Therefore, we now
|
||||||
# calculate (and cache) the select leafs (including entity subtypes)
|
# calculate (and cache) the select leafs (including entity subtypes)
|
||||||
# for the select definition and simply check for membership in this
|
# for the select definition and simply check for membership in this
|
||||||
# set.
|
# 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):
|
elif isinstance(attr_type, enumeration_type):
|
||||||
invalid = val not in attr_type.enumeration_items()
|
invalid = val not in attr_type.enumeration_items()
|
||||||
elif isinstance(attr_type, aggregation_type):
|
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):
|
def test_file(file):
|
||||||
logger = ifcopenshell.validate.json_logger()
|
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-"):
|
if file.startswith("fail-"):
|
||||||
assert len(logger.statements) > 0
|
assert len(logger.statements) > 0
|
||||||
if file.startswith("pass-"):
|
if file.startswith("pass-"):
|
||||||
Reference in New Issue
Block a user