mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-16 21:42:19 +00:00
Fix #1266. Standardise BIMTester quotes, always translate, and refactor.
This commit is contained in:
@@ -0,0 +1,144 @@
|
||||
from behave import step, given, when, then, use_step_matcher
|
||||
|
||||
use_step_matcher("parse")
|
||||
|
||||
|
||||
@step("There must be exactly {number} {ifc_class} element")
|
||||
@step("There must be exactly {number} {ifc_class} elements")
|
||||
def step_impl(context, number, ifc_class):
|
||||
num = len(IfcStore.file.by_type(ifc_class))
|
||||
assert num == int(number), "Could not find {} elements of {}. Found {} element(s).".format(number, ifc_class, num)
|
||||
|
||||
|
||||
@given("a set of specific related elements")
|
||||
def step_impl(context):
|
||||
model = getattr(context, "model", None)
|
||||
if not model:
|
||||
context.model = TableModel()
|
||||
for row in context.table:
|
||||
context.model.add_row(row["RelatedObjects"], row["RelatingGroup"])
|
||||
|
||||
|
||||
@given('a set of specific related elements taken from the file "{path_file}"')
|
||||
def step_impl(context, path_file):
|
||||
import csv
|
||||
import os
|
||||
|
||||
model = getattr(context, "model", None)
|
||||
if not model:
|
||||
context.model = TableModel()
|
||||
if context.config.userdata.get("path"):
|
||||
path_file = os.path.join(context.config.userdata.get("path"), path_file)
|
||||
if not os.path.exists(path_file):
|
||||
assert False, "File {} not found".format(path_file)
|
||||
with open(path_file, "r", encoding="utf-8-sig") as csvfile:
|
||||
reader = csv.DictReader(csvfile)
|
||||
for row in reader:
|
||||
context.model.add_row(row["RelatedObjects"], row["RelatingGroup"])
|
||||
|
||||
|
||||
@then("there must be exactly a number of {ifc_class} equals to the number of distinct row value")
|
||||
def step_impl(context, ifc_class):
|
||||
try:
|
||||
context.execute_steps(
|
||||
"""
|
||||
then There must be exactly {number} {ifc_class} elements
|
||||
""".format(
|
||||
ifc_class=ifc_class, number=context.model.get_count_distinct_values()
|
||||
)
|
||||
)
|
||||
except AssertionError as error:
|
||||
str_error = str(error)
|
||||
assert False, str_error[: str_error.find("Traceback")]
|
||||
assert True
|
||||
|
||||
|
||||
@then(
|
||||
"there is a relationship {ifc_class} with {left_attribute} and {right_attribute} between the two elements of each row"
|
||||
)
|
||||
def step_impl(context, ifc_class, left_attribute, right_attribute):
|
||||
rows = context.model.rows
|
||||
elements = IfcStore.file.by_type(ifc_class)
|
||||
errors = []
|
||||
for key, value in rows.items():
|
||||
found = False
|
||||
for element in elements:
|
||||
if (
|
||||
any(x.Name == key for x in getattr(element, left_attribute))
|
||||
and getattr(element, right_attribute).Name == value
|
||||
):
|
||||
found = True
|
||||
if not found:
|
||||
errors.append(f"The row ({key}, {value}) does not have the relationship.")
|
||||
assert not errors, "Errors occured:\n{}".format("\n".join(errors))
|
||||
|
||||
|
||||
use_step_matcher("re")
|
||||
|
||||
|
||||
@step("all IfcGroup must be linked to a type in the list (?P<linked_ifc_classes>.*)")
|
||||
def step_impl(context, linked_ifc_classes):
|
||||
groups = IfcStore.file.by_type("IfcGroup")
|
||||
errors = []
|
||||
for group in groups:
|
||||
if not hasattr(group, "IsGroupedBy"):
|
||||
errors.append(f'The element "{group.Name}" has no "IsGroupedBy" attribute.')
|
||||
else:
|
||||
for grouped_by in getattr(group, "IsGroupedBy"):
|
||||
if not hasattr(grouped_by, "RelatedObjects"):
|
||||
errors.append(f'The element "{grouped_by.Name}" has no "RelatedObjects" attribute.')
|
||||
else:
|
||||
for related_object in getattr(grouped_by, "RelatedObjects"):
|
||||
found = False
|
||||
for linked_ifc_class in linked_ifc_classes.split(","):
|
||||
if related_object.is_a(linked_ifc_class):
|
||||
found = True
|
||||
if not found:
|
||||
errors.append(
|
||||
f'The element "{related_object.Name}" does not have the right associated type.'
|
||||
)
|
||||
assert not errors, "Errors occured:\n{}".format("\n".join(errors))
|
||||
|
||||
|
||||
@then("there is an element of type (?P<ifc_types>.*) with a (?P<attribute_name>.*) attribute for each row key")
|
||||
def step_impl(context, ifc_types, attribute_name):
|
||||
check_if_element_exists_by_types_with_attribute_name(ifc_types, attribute_name, context.model.rows.keys())
|
||||
|
||||
|
||||
@then("there is an element of type (?P<ifc_types>.*) with a (?P<attribute_name>.*) attribute for each row value")
|
||||
def step_impl(context, ifc_types, attribute_name):
|
||||
values = set(context.model.rows.values())
|
||||
check_if_element_exists_by_types_with_attribute_name(ifc_types, attribute_name, values)
|
||||
|
||||
|
||||
def check_if_element_exists_by_types_with_attribute_name(ifc_types, attribute_name, attribute_values):
|
||||
errors = []
|
||||
|
||||
elements = []
|
||||
for ifc_type in ifc_types.split(","):
|
||||
elements += ifc.by_type(ifc_type.strip())
|
||||
|
||||
for attribute_value in attribute_values:
|
||||
found = False
|
||||
for element in elements:
|
||||
if hasattr(element, attribute_name) and getattr(element, attribute_name) == attribute_value:
|
||||
found = True
|
||||
if not found:
|
||||
errors.append(f'An element with {attribute_name} attribute "{attribute_value}" was not found.')
|
||||
assert not errors, "Errors occured:\n{}".format("\n".join(errors))
|
||||
|
||||
|
||||
class TableModel(object):
|
||||
"""This class represents a table of data."""
|
||||
|
||||
def __init__(self):
|
||||
self.rows = dict()
|
||||
|
||||
def add_row(self, related, relating):
|
||||
self.rows[related] = relating
|
||||
|
||||
def get_count(self):
|
||||
return len(self.rows)
|
||||
|
||||
def get_count_distinct_values(self):
|
||||
return len(set(self.rows.values()))
|
||||
@@ -0,0 +1,52 @@
|
||||
import gettext
|
||||
from behave import given
|
||||
from behave import step
|
||||
|
||||
from utils import IfcFile
|
||||
from bimtester.ifc import IfcStore
|
||||
from bimtester.lang import _
|
||||
|
||||
|
||||
@step("The IFC file must be exported by application full name {fullname}")
|
||||
def step_impl(context, fullname):
|
||||
|
||||
real_fullname = IfcStore.file.by_type("IfcApplication")[0].ApplicationFullName
|
||||
assert real_fullname == fullname, (
|
||||
"The IFC file was not exported by application full name {} "
|
||||
"instead it was exported by application full name {}".format(fullname, real_fullname)
|
||||
)
|
||||
|
||||
|
||||
@step("The IFC file must be exported by application identifier {identifier}")
|
||||
def step_impl(context, identifier):
|
||||
|
||||
real_identifier = IfcStore.file.by_type("IfcApplication")[0].ApplicationIdentifier
|
||||
assert (
|
||||
real_identifier == identifier
|
||||
), "The IFC file was not exported by application identifier {} " "instead it was exported by identifier {}".format(
|
||||
identifier, real_identifier
|
||||
)
|
||||
|
||||
|
||||
@step("The IFC file must be exported by the application version {version}")
|
||||
def step_impl(context, version):
|
||||
|
||||
real_version = IfcStore.file.by_type("IfcApplication")[0].Version
|
||||
assert (
|
||||
real_version == version
|
||||
), "The IFC file was not exported by application version {} " "instead it was exported by version {}".format(
|
||||
version, real_version
|
||||
)
|
||||
|
||||
|
||||
@step(
|
||||
"IFC data header must have a file description of {header_file_description} such as the new Allplan IFC exporter creates it"
|
||||
)
|
||||
def step_impl(context, header_file_description):
|
||||
|
||||
is_header_file_description = IfcStore.file.wrapped_data.header.file_description.description
|
||||
assert (
|
||||
str(is_header_file_description) == header_file_description
|
||||
), "The file was not exported by the new ifc exporter in Allplan. File description header: {}".format(
|
||||
is_header_file_description
|
||||
)
|
||||
@@ -0,0 +1,91 @@
|
||||
from behave import step
|
||||
|
||||
import attributes_eleclasses_methods as aem
|
||||
from utils import assert_elements
|
||||
from utils import IfcFile
|
||||
|
||||
|
||||
@step("There are no {ifc_class} elements")
|
||||
def step_impl(context, ifc_class):
|
||||
aem.no_eleclass(context, ifc_class)
|
||||
|
||||
|
||||
@step("There are no {ifc_class} elements because {reason}")
|
||||
def step_impl(context, ifc_class, reason):
|
||||
aem.no_eleclass(context, ifc_class)
|
||||
|
||||
|
||||
@step("All {ifc_class} elements class attributes have a value")
|
||||
def step_impl(context, ifc_class):
|
||||
aem.eleclass_have_class_attributes_with_a_value(context, ifc_class)
|
||||
|
||||
|
||||
@step("All {ifc_class} elements have a name given")
|
||||
def step_impl(context, ifc_class):
|
||||
aem.eleclass_has_name_with_a_value(context, ifc_class)
|
||||
|
||||
|
||||
@step("All {ifc_class} elements have a description given")
|
||||
def step_impl(context, ifc_class):
|
||||
aem.eleclass_has_description_with_a_value(context, ifc_class)
|
||||
|
||||
|
||||
@step('all {ifc_class} elements have a name matching the pattern "{pattern}"')
|
||||
def step_impl(context, ifc_class, pattern):
|
||||
import re
|
||||
|
||||
elements = IfcFile.get().by_type(ifc_class)
|
||||
for element in elements:
|
||||
if not re.search(pattern, element.Name):
|
||||
assert False
|
||||
|
||||
|
||||
@step('there is an {ifc_class} element with a {attribute_name} attribute with a value of "{attribute_value}"')
|
||||
def step_impl(context, ifc_class, attribute_name, attribute_value):
|
||||
elements = IfcFile.get().by_type(ifc_class)
|
||||
for element in elements:
|
||||
if hasattr(element, attribute_name) and getattr(element, attribute_name) == attribute_value:
|
||||
return
|
||||
assert False
|
||||
|
||||
|
||||
use_step_matcher("re")
|
||||
|
||||
|
||||
@step("all (?P<ifc_class>.*) elements have an? (?P<attribute>.*) attribute")
|
||||
def step_impl(context, ifc_class, attribute):
|
||||
elements = IfcFile.get().by_type(ifc_class)
|
||||
for element in elements:
|
||||
if not getattr(element, attribute):
|
||||
assert False
|
||||
|
||||
|
||||
@step('all (?P<ifc_class>.*) elements have an? (?P<attribute>.*) matching the pattern "(?P<pattern>.*)"')
|
||||
def step_impl(context, ifc_class, attribute, pattern):
|
||||
import re
|
||||
|
||||
elements = IfcFile.get().by_type(ifc_class)
|
||||
for element in elements:
|
||||
value = getattr(element, attribute)
|
||||
print(f'Checking value "{value}" for {element}')
|
||||
assert re.search(pattern, value)
|
||||
|
||||
|
||||
@step('all (?P<ifc_class>.*) elements have an? (?P<attributes>.*) taken from the list in "(?P<list_file>.*)"')
|
||||
def step_impl(context, ifc_class, attributes, list_file):
|
||||
import csv
|
||||
|
||||
values = []
|
||||
with open(list_file) as csvfile:
|
||||
reader = csv.reader(csvfile)
|
||||
for row in reader:
|
||||
values.append(row)
|
||||
elements = IfcFile.get().by_type(ifc_class)
|
||||
for element in elements:
|
||||
attribute_values = []
|
||||
for attribute in attributes.split(","):
|
||||
if not hasattr(element, attribute):
|
||||
assert False, f"Failed at element {element.GlobalId}"
|
||||
attribute_values.append(getattr(element, attribute))
|
||||
if attribute_values not in values:
|
||||
assert False, f"Failed at element {element.GlobalId}"
|
||||
@@ -0,0 +1,26 @@
|
||||
from behave import step
|
||||
|
||||
|
||||
@step("Es sind keine {ifc_class} Bauteile vorhanden")
|
||||
def step_impl(context, ifc_class):
|
||||
context.execute_steps(f"* There are no {ifc_class} elements")
|
||||
|
||||
|
||||
@step("Aus folgendem Grund gibt es keine {ifc_class} Bauteile: {reason}")
|
||||
def step_impl(context, ifc_class, reason):
|
||||
context.execute_steps(f"* There are no {ifc_class} elements because {reason}")
|
||||
|
||||
|
||||
@step("Alle {ifc_class} Bauteilklassenattribute haben einen Wert")
|
||||
def step_impl(context, ifc_class):
|
||||
context.execute_steps(f"* All {ifc_class} elements class attributes have a value")
|
||||
|
||||
|
||||
@step("Bei allen {ifc_class} Bauteile ist der Name angegeben")
|
||||
def step_impl(context, ifc_class):
|
||||
context.execute_steps(f"* All {ifc_class} elements have a name given")
|
||||
|
||||
|
||||
@step("Bei allen {ifc_class} Bauteile ist die Beschreibung angegeben")
|
||||
def step_impl(context, ifc_class):
|
||||
context.execute_steps(f"* All {ifc_class} elements have a description given")
|
||||
@@ -0,0 +1,140 @@
|
||||
import gettext # noqa
|
||||
|
||||
from utils import assert_elements
|
||||
from utils import IfcFile
|
||||
|
||||
|
||||
def no_eleclass(
|
||||
context, ifc_class
|
||||
):
|
||||
|
||||
context.falseelems = []
|
||||
context.falseguids = []
|
||||
|
||||
elements = IfcFile.get().by_type(ifc_class)
|
||||
for elem in elements:
|
||||
context.falseelems.append(str(elem))
|
||||
context.falseguids.append(elem.GlobalId)
|
||||
|
||||
context.elemcount = len(elements)
|
||||
context.falsecount = len(context.falseelems)
|
||||
|
||||
if context.elemcount == 0 and context.falsecount == 0:
|
||||
return # Test OK, thus we can not use the assert_elements method
|
||||
elif context.falsecount == context.elemcount:
|
||||
assert False, (
|
||||
_("All {elemcount} elements in the file are {ifc_class}.")
|
||||
.format(
|
||||
elemcount=context.elemcount,
|
||||
ifc_class=ifc_class
|
||||
)
|
||||
)
|
||||
elif context.falsecount > 0 and fcontext.alsecount < context.elemcount:
|
||||
assert False, (
|
||||
_("{falsecount} of {elemcount} element are {ifc_class} elements: {falseelems}")
|
||||
.format(
|
||||
falsecount=context.falsecount,
|
||||
elemcount=context.elemcount,
|
||||
ifc_class=ifc_class,
|
||||
falseelems=context.falseelems,
|
||||
)
|
||||
)
|
||||
else:
|
||||
assert False, _("Error in falsecount, something went wrong.")
|
||||
|
||||
|
||||
def eleclass_have_class_attributes_with_a_value(
|
||||
context, ifc_class
|
||||
):
|
||||
|
||||
from ifcopenshell.ifcopenshell_wrapper import schema_by_name
|
||||
# schema = schema_by_name("IFC2X3")
|
||||
schema = schema_by_name(IfcFile.get().schema)
|
||||
class_attributes = []
|
||||
for cl_attrib in schema.declaration_by_name(ifc_class).all_attributes():
|
||||
class_attributes.append(cl_attrib.name())
|
||||
# print(class_attributes)
|
||||
|
||||
context.falseelems = []
|
||||
context.falseguids = []
|
||||
context.falseprops = {}
|
||||
|
||||
elements = IfcFile.get().by_type(ifc_class)
|
||||
for elem in elements:
|
||||
failed_attribs = []
|
||||
elem_failed = False
|
||||
for cl_attrib in class_attributes:
|
||||
attrib_value = getattr(elem, cl_attrib)
|
||||
if not attrib_value:
|
||||
elem_failed = True
|
||||
failed_attribs.append(cl_attrib)
|
||||
# print(attrib_value)
|
||||
if elem_failed is True:
|
||||
context.falseelems.append(str(elem))
|
||||
context.falseguids.append(elem.GlobalId)
|
||||
context.falseprops[elem.id()] = failed_attribs
|
||||
|
||||
context.elemcount = len(elements)
|
||||
context.falsecount = len(context.falseelems)
|
||||
assert_elements(
|
||||
ifc_class,
|
||||
context.elemcount,
|
||||
context.falsecount,
|
||||
context.falseelems,
|
||||
message_all_falseelems=_("For all {elemcount} {ifc_class} elements at least one of these class attributes {parameter} has no value."),
|
||||
message_some_falseelems=_("For the following {falsecount} out of {elemcount} {ifc_class} elements at least one of these class attributes {parameter} has no value: {falseelems}"),
|
||||
message_no_elems=_("There are no {ifc_class} elements in the IFC file."),
|
||||
parameter=failed_attribs
|
||||
)
|
||||
|
||||
|
||||
def eleclass_has_name_with_a_value(context, ifc_class):
|
||||
|
||||
context.falseelems = []
|
||||
context.falseguids = []
|
||||
|
||||
elements = IfcFile.get().by_type(ifc_class)
|
||||
for elem in elements:
|
||||
# print(elem.Name)
|
||||
if not elem.Name:
|
||||
context.falseelems.append(str(elem))
|
||||
context.falseguids.append(elem.GlobalId)
|
||||
|
||||
context.elemcount = len(elements)
|
||||
context.falsecount = len(context.falseelems)
|
||||
assert_elements(
|
||||
ifc_class,
|
||||
context.elemcount,
|
||||
context.falsecount,
|
||||
context.falseelems,
|
||||
message_all_falseelems=_("The name of all {elemcount} {elemcount} elements is not set."),
|
||||
message_some_falseelems=_("The name of {falsecount} out of {elemcount} {ifc_class} elements is not set: {falseelems}"),
|
||||
message_no_elems=_("There are no {ifc_class} elements in the IFC file."),
|
||||
)
|
||||
|
||||
|
||||
def eleclass_has_description_with_a_value(
|
||||
context, ifc_class
|
||||
):
|
||||
|
||||
context.falseelems = []
|
||||
context.falseguids = []
|
||||
|
||||
elements = IfcFile.get().by_type(ifc_class)
|
||||
for elem in elements:
|
||||
# print(elem.Description)
|
||||
if not elem.Description:
|
||||
context.falseelems.append(str(elem))
|
||||
context.falseguids.append(elem.GlobalId)
|
||||
|
||||
context.elemcount = len(elements)
|
||||
context.falsecount = len(context.falseelems)
|
||||
assert_elements(
|
||||
ifc_class,
|
||||
context.elemcount,
|
||||
context.falsecount,
|
||||
context.falseelems,
|
||||
message_all_falseelems=_("The description of all {elemcount} {elemcount} elements is not set."),
|
||||
message_some_falseelems=_("The description of {falsecount} out of {elemcount} {ifc_class} elements is not set: {falseelems}"),
|
||||
message_no_elems=_("There are no {ifc_class} elements in the IFC file."),
|
||||
)
|
||||
@@ -0,0 +1,53 @@
|
||||
from behave import step
|
||||
|
||||
import attributes_psets_methods as apm
|
||||
from utils import assert_elements
|
||||
from utils import IfcFile
|
||||
from utils import switch_locale
|
||||
|
||||
|
||||
the_lang = "en"
|
||||
|
||||
|
||||
@step("all {ifc_class} elements have an {aproperty} property in the {pset} pset")
|
||||
def step_impl(context, ifc_class, aproperty, pset):
|
||||
switch_locale(context.localedir, the_lang)
|
||||
apm.eleclass_has_property_in_pset(
|
||||
context,
|
||||
ifc_class,
|
||||
aproperty,
|
||||
pset
|
||||
)
|
||||
|
||||
|
||||
# ------------------------------------------------------------------------
|
||||
# STEPS with Regular Expression Matcher ("re")
|
||||
# ------------------------------------------------------------------------
|
||||
use_step_matcher("re")
|
||||
|
||||
|
||||
@step("all (?P<ifc_class>.*) elements have an? (?P<property_path>.*\..*) property")
|
||||
def step_impl(context, ifc_class, property_path):
|
||||
pset_name, property_name = property_path.split(".")
|
||||
elements = IfcFile.get().by_type(ifc_class)
|
||||
for element in elements:
|
||||
if not IfcFile.get_property(element, pset_name, property_name):
|
||||
assert False
|
||||
|
||||
|
||||
@step(
|
||||
'all (?P<ifc_class>.*) elements have an? (?P<property_path>.*\..*) property value matching the pattern "(?P<pattern>.*)"'
|
||||
)
|
||||
def step_impl(context, ifc_class, property_path, pattern):
|
||||
import re
|
||||
|
||||
pset_name, property_name = property_path.split(".")
|
||||
elements = IfcFile.get().by_type(ifc_class)
|
||||
for element in elements:
|
||||
prop = IfcFile.get_property(element, pset_name, property_name)
|
||||
if not prop:
|
||||
assert False
|
||||
# For now, we only check single values
|
||||
if prop.is_a("IfcPropertySingleValue"):
|
||||
if not (prop.NominalValue and re.search(pattern, prop.NominalValue.wrappedValue)):
|
||||
assert False
|
||||
@@ -0,0 +1,18 @@
|
||||
from behave import step
|
||||
|
||||
import attributes_psets_methods as apm
|
||||
from utils import switch_locale
|
||||
|
||||
|
||||
the_lang = "de"
|
||||
|
||||
|
||||
@step("An alle {ifc_class} Bauteile ist im PSet {pset} das Attribut {aproperty} angehängt")
|
||||
def step_impl(context, ifc_class, aproperty, pset):
|
||||
switch_locale(context.localedir, the_lang)
|
||||
apm.eleclass_has_property_in_pset(
|
||||
context,
|
||||
ifc_class,
|
||||
aproperty,
|
||||
pset
|
||||
)
|
||||
@@ -0,0 +1,21 @@
|
||||
from behave import step
|
||||
|
||||
import attributes_psets_methods as apm
|
||||
from utils import switch_locale
|
||||
|
||||
|
||||
the_lang = "fr"
|
||||
|
||||
|
||||
"""
|
||||
# TODO the next line needs translation
|
||||
@step("All {ifc_class} elements have an {aproperty} property in the {pset} pset")
|
||||
def step_impl(context, ifc_class, aproperty, pset):
|
||||
switch_locale(context.localedir, the_lang)
|
||||
apm.eleclass_has_property_in_pset(
|
||||
context,
|
||||
ifc_class,
|
||||
aproperty,
|
||||
pset
|
||||
)
|
||||
"""
|
||||
@@ -0,0 +1,36 @@
|
||||
import gettext # noqa
|
||||
|
||||
from utils import assert_elements
|
||||
from utils import IfcFile
|
||||
|
||||
|
||||
def eleclass_has_property_in_pset(
|
||||
context, ifc_class, aproperty, pset
|
||||
):
|
||||
|
||||
context.falseelems = []
|
||||
context.falseguids = []
|
||||
context.falseprops = {}
|
||||
from ifcopenshell.util.element import get_psets
|
||||
|
||||
elements = IfcFile.get().by_type(ifc_class)
|
||||
for elem in elements:
|
||||
psets = get_psets(elem)
|
||||
if not (pset in psets and aproperty in psets[pset]):
|
||||
context.falseelems.append(str(elem))
|
||||
context.falseguids.append(elem.GlobalId)
|
||||
context.falseprops[elem.id()] = str(psets)
|
||||
|
||||
context.elemcount = len(elements)
|
||||
context.falsecount = len(context.falseelems)
|
||||
assert_elements(
|
||||
ifc_class,
|
||||
context.elemcount,
|
||||
context.falsecount,
|
||||
context.falseelems,
|
||||
message_all_falseelems=_("All {elemcount} {ifc_class} elements are missing the property {parameter} in the pset."),
|
||||
message_some_falseelems=_("The following {falsecount} of {elemcount} {ifc_class} elements are missing the property {parameter} in the pset: {falseelems}"),
|
||||
message_no_elems=_("There are no {ifc_class} elements in the IFC file."),
|
||||
parameter=aproperty
|
||||
)
|
||||
# the pset name is missing in the failing message, but it is in the step test name
|
||||
@@ -0,0 +1,19 @@
|
||||
from behave import step
|
||||
|
||||
from utils import IfcFile
|
||||
|
||||
|
||||
@step("all {ifc_class} elements have a {qto_name}.{quantity_name} quantity")
|
||||
def step_impl(context, ifc_class, qto_name, quantity_name):
|
||||
elements = IfcFile.get().by_type(ifc_class)
|
||||
for element in elements:
|
||||
is_successful = False
|
||||
if not element.IsDefinedBy:
|
||||
assert False
|
||||
for relationship in element.IsDefinedBy:
|
||||
if relationship.RelatingPropertyDefinition.Name == qto_name:
|
||||
for quantity in relationship.RelatingPropertyDefinition.Quantities:
|
||||
if quantity.Name == quantity_name:
|
||||
is_successful = True
|
||||
if not is_successful:
|
||||
assert False
|
||||
@@ -0,0 +1,47 @@
|
||||
from behave import step
|
||||
|
||||
import geometric_detail_methods as gdm
|
||||
from utils import assert_elements
|
||||
from utils import IfcFile
|
||||
from utils import switch_locale
|
||||
|
||||
|
||||
the_lang = "en"
|
||||
|
||||
|
||||
@step("All elements must be under {number} polygons")
|
||||
def step_impl(context, number):
|
||||
number = int(number)
|
||||
errors = []
|
||||
for element in IfcFile.get().by_type("IfcElement"):
|
||||
if not element.Representation:
|
||||
continue
|
||||
total_polygons = 0
|
||||
tree = IfcFile.get().traverse(element.Representation)
|
||||
for e in tree:
|
||||
if e.is_a("IfcFace"):
|
||||
total_polygons += 1
|
||||
elif e.is_a("IfcPolygonalFaceSet"):
|
||||
total_polygons += len(e.Faces)
|
||||
elif e.is_a("IfcTriangulatedFaceSet"):
|
||||
total_polygons += len(e.CoordIndex)
|
||||
if total_polygons > number:
|
||||
errors.append((total_polygons, element))
|
||||
if errors:
|
||||
message = (
|
||||
"The following {} elements are over 500 polygons:\n"
|
||||
.format(len(errors))
|
||||
)
|
||||
for error in errors:
|
||||
message += "Polygons: {} - {}\n".format(error[0], error[1])
|
||||
assert False, message
|
||||
|
||||
|
||||
@step("all {ifc_class} elements have an {representation_class} representation")
|
||||
def step_impl(context, ifc_class, representation_class):
|
||||
switch_locale(context.localedir, the_lang)
|
||||
gdm.eleclass_has_geometric_representation_of_specific_class(
|
||||
context,
|
||||
ifc_class,
|
||||
representation_class
|
||||
)
|
||||
@@ -0,0 +1,17 @@
|
||||
from behave import step
|
||||
|
||||
import geometric_detail_methods as gdm
|
||||
from utils import switch_locale
|
||||
|
||||
|
||||
the_lang = "de"
|
||||
|
||||
|
||||
@step("Alle {ifc_class} Bauteile müssen eine geometrische Repräsentation der Klasse {representation_class} verwenden")
|
||||
def step_impl(context, ifc_class, representation_class):
|
||||
switch_locale(context.localedir, the_lang)
|
||||
gdm.eleclass_has_geometric_representation_of_specific_class(
|
||||
context,
|
||||
ifc_class,
|
||||
representation_class
|
||||
)
|
||||
@@ -0,0 +1,58 @@
|
||||
import gettext # noqa
|
||||
from utils import assert_elements
|
||||
from utils import IfcFile
|
||||
|
||||
|
||||
def eleclass_has_geometric_representation_of_specific_class(
|
||||
context,
|
||||
ifc_class,
|
||||
representation_class
|
||||
):
|
||||
|
||||
def is_item_a_representation(item, representation):
|
||||
if "/" in representation:
|
||||
for cls in representation.split("/"):
|
||||
if item.is_a(cls):
|
||||
return True
|
||||
elif item.is_a(representation):
|
||||
return True
|
||||
|
||||
context.falseelems = []
|
||||
context.falseguids = []
|
||||
context.falseprops = {}
|
||||
rep = None
|
||||
|
||||
elements = IfcFile.get().by_type(ifc_class)
|
||||
for elem in elements:
|
||||
if not elem.Representation:
|
||||
continue
|
||||
has_representation = False
|
||||
for representation in elem.Representation.Representations:
|
||||
for item in representation.Items:
|
||||
if item.is_a("IfcMappedItem"):
|
||||
# We only check one more level deep.
|
||||
for item2 in item.MappingSource.MappedRepresentation.Items:
|
||||
if is_item_a_representation(item2, representation_class):
|
||||
has_representation = True
|
||||
rep = item2
|
||||
else:
|
||||
if is_item_a_representation(item, representation_class):
|
||||
has_representation = True
|
||||
rep = item
|
||||
if not has_representation:
|
||||
context.falseelems.append(str(elem))
|
||||
context.falseguids.append(elem.GlobalId)
|
||||
context.falseprops[elem.id()] = str(rep)
|
||||
|
||||
context.elemcount = len(elements)
|
||||
context.falsecount = len(context.falseelems)
|
||||
assert_elements(
|
||||
ifc_class,
|
||||
context.elemcount,
|
||||
context.falsecount,
|
||||
context.falseelems,
|
||||
message_all_falseelems=_("All {elemcount} {ifc_class} elements are not a {parameter} representation."),
|
||||
message_some_falseelems=_("The following {falsecount} of {elemcount} {ifc_class} elements are not a {parameter} representation: {falseelems}"),
|
||||
message_no_elems=_("There are no {ifc_class} elements in the IFC file."),
|
||||
parameter=representation_class
|
||||
)
|
||||
@@ -0,0 +1,10 @@
|
||||
from behave import step
|
||||
|
||||
from utils import IfcFile
|
||||
|
||||
|
||||
@step("all buildings have an address")
|
||||
def step_impl(context):
|
||||
for building in IfcFile.get().by_type("IfcBuilding"):
|
||||
if not building.BuildingAddress:
|
||||
assert False, f'The building "{building.Name}" has no address.'
|
||||
Reference in New Issue
Block a user