(
attr_type: attribute_types,
val: Any,
schema: schema_definition,
no_throw=False,
attr: Optional[attribute] = None,
)
| 232 | |
| 233 | |
| 234 | def assert_valid( |
| 235 | attr_type: attribute_types, |
| 236 | val: Any, |
| 237 | schema: schema_definition, |
| 238 | no_throw=False, |
| 239 | attr: Optional[attribute] = None, |
| 240 | ): |
| 241 | type_wrappers = (named_type,) |
| 242 | if not isinstance(val, ifcopenshell.entity_instance): |
| 243 | # If val is not an entity instance we need to |
| 244 | # flatten the type declaration to something that |
| 245 | # maps to the python types |
| 246 | type_wrappers += (type_declaration,) |
| 247 | |
| 248 | while isinstance(attr_type, type_wrappers): |
| 249 | attr_type = attr_type.declared_type() |
| 250 | |
| 251 | invalid = False |
| 252 | |
| 253 | if isinstance(attr_type, simple_type): |
| 254 | simple_type_python = simple_type_python_mapping[attr_type.declared_type()] |
| 255 | if type(simple_type_python) == set: |
| 256 | invalid = val not in simple_type_python |
| 257 | elif type(simple_type_python) == tuple: |
| 258 | invalid = not any(type(val) == t for t in simple_type_python) |
| 259 | else: |
| 260 | invalid = type(val) != simple_type_python |
| 261 | elif isinstance(attr_type, entity_type): |
| 262 | invalid = not isinstance(val, ifcopenshell.entity_instance) or not val.is_a(attr_type.name()) |
| 263 | elif isinstance(attr_type, type_declaration): |
| 264 | # @nb this only applies to direct type declarations, not those indirectly referenced |
| 265 | # by means of one or more selects. |
| 266 | invalid = isinstance(val, ifcopenshell.entity_instance) |
| 267 | elif isinstance(attr_type, select_type): |
| 268 | if not isinstance(val, ifcopenshell.entity_instance): |
| 269 | invalid = True |
| 270 | else: |
| 271 | value_type = schema.declaration_by_name(val.is_a()) |
| 272 | if not isinstance(value_type, entity_type): |
| 273 | # we need to check two things: is (enumeration) literal/value valid |
| 274 | # for this type and is enumeration/value type valid for this select. |
| 275 | try: |
| 276 | invalid = invalid or not assert_valid(value_type, val.wrappedValue, schema, no_throw=True) |
| 277 | except RuntimeError as _: |
| 278 | invalid = True |
| 279 | |
| 280 | # Previously we relied on `is_a(x) for x in attr_type.select_items()` |
| 281 | # this was linear in the number of select leafs, which is very large |
| 282 | # for e.g IfcValue, which is an often used select. Therefore, we now |
| 283 | # calculate (and cache) the select leafs (including entity subtypes) |
| 284 | # for the select definition and simply check for membership in this |
| 285 | # set. |
| 286 | invalid = invalid or val.is_a() not in get_select_members(schema, attr_type) |
| 287 | elif isinstance(attr_type, enumeration_type): |
| 288 | invalid = val not in attr_type.enumeration_items() |
| 289 | elif isinstance(attr_type, aggregation_type): |
| 290 | b1, b2 = attr_type.bound1(), attr_type.bound2() |
| 291 | ty = attr_type.type_of_element() |
no test coverage detected