2022-01-19 12:18:33 +11:00
|
|
|
# IfcOpenShell - IFC toolkit and geometry engine
|
|
|
|
|
# Copyright (C) 2021 Thomas Krijnen <thomas@aecgeeks.com>
|
|
|
|
|
#
|
|
|
|
|
# This file is part of IfcOpenShell.
|
|
|
|
|
#
|
|
|
|
|
# IfcOpenShell is free software: you can redistribute it and/or modify
|
|
|
|
|
# it under the terms of the GNU Lesser General Public License as published by
|
|
|
|
|
# the Free Software Foundation, either version 3 of the License, or
|
|
|
|
|
# (at your option) any later version.
|
|
|
|
|
#
|
|
|
|
|
# IfcOpenShell is distributed in the hope that it will be useful,
|
|
|
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
# GNU Lesser General Public License for more details.
|
|
|
|
|
#
|
|
|
|
|
# You should have received a copy of the GNU Lesser General Public License
|
|
|
|
|
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
2021-07-09 08:44:36 +02:00
|
|
|
import os
|
2022-05-10 19:26:12 +10:00
|
|
|
import pytest
|
2021-08-24 12:57:44 +02:00
|
|
|
import logging
|
2021-08-31 14:10:43 +10:00
|
|
|
import unittest
|
|
|
|
|
import tempfile
|
2022-05-10 19:26:12 +10:00
|
|
|
import xmlschema
|
2021-08-24 12:57:44 +02:00
|
|
|
from bcf import bcfxml
|
2021-09-24 17:18:38 +02:00
|
|
|
import ifcopenshell
|
2021-08-31 14:10:43 +10:00
|
|
|
from ifcopenshell import ids
|
2021-07-09 08:44:36 +02:00
|
|
|
|
2021-07-02 17:27:09 +02:00
|
|
|
|
2021-11-23 17:53:32 +01:00
|
|
|
TEST_PATH = os.path.join(tempfile.gettempdir(), "test.ifc")
|
|
|
|
|
IFC_URL = os.path.join(os.path.dirname(__file__), "Sample-BIM-Files/IFC/", "IFC4_Wall_3_with_properties.ifc")
|
|
|
|
|
IDS_URL = os.path.join(os.path.dirname(__file__), "Sample-BIM-Files/IDS/", "IDS_Wall_needs_all_fields.xml")
|
2021-07-02 17:27:09 +02:00
|
|
|
|
2021-11-23 17:53:32 +01:00
|
|
|
logger = logging.getLogger("IDS_Logger")
|
|
|
|
|
# logging.basicConfig(level=logging.INFO, format="%(message)s")
|
|
|
|
|
# logging.basicConfig(filename=os.path.join(os.path.dirname(__file__), "log.txt"), level=logging.INFO, format="%(message)s")
|
|
|
|
|
|
|
|
|
|
file = open(os.path.join(tempfile.gettempdir(), "test.ifc"), "w")
|
|
|
|
|
file.write(IFC_URL)
|
|
|
|
|
file.close()
|
|
|
|
|
ifc_file = ifcopenshell.open(IFC_URL)
|
|
|
|
|
os.remove(os.path.join(tempfile.gettempdir(), "test.ifc"))
|
2021-07-02 17:27:09 +02:00
|
|
|
|
2022-05-10 16:17:38 +10:00
|
|
|
|
2021-07-09 08:44:36 +02:00
|
|
|
class TestIdsParsing(unittest.TestCase):
|
2021-07-02 17:27:09 +02:00
|
|
|
|
2021-08-24 12:57:44 +02:00
|
|
|
"""Parsing basic IDS files"""
|
|
|
|
|
|
|
|
|
|
def test_parse_basic_ids(self):
|
2021-09-24 17:18:38 +02:00
|
|
|
IDS_URL = os.path.join(os.path.dirname(__file__), "Sample-BIM-Files/IDS/", "IDS_Wall_needs_all_fields.xml")
|
|
|
|
|
ids_file = ids.ids.open(IDS_URL)
|
2021-07-09 08:44:36 +02:00
|
|
|
self.assertEqual(type(ids_file).__name__, "ids")
|
|
|
|
|
|
2021-08-24 12:57:44 +02:00
|
|
|
def test_parse_entity_facet(self):
|
2021-09-24 17:18:38 +02:00
|
|
|
IDS_URL = os.path.join(os.path.dirname(__file__), "Sample-BIM-Files/IDS/", "IDS_Wall_needs_entity.xml")
|
|
|
|
|
ids_file = ids.ids.open(IDS_URL)
|
2021-08-24 12:57:44 +02:00
|
|
|
self.assertEqual(ids_file.specifications[0].requirements.terms[0].node["name"]["simpleValue"], "IfcWall")
|
2021-07-02 17:27:09 +02:00
|
|
|
|
2022-02-23 00:24:40 +01:00
|
|
|
def test_parse_predefinedType_facet(self):
|
2022-05-10 16:17:38 +10:00
|
|
|
IDS_URL = os.path.join(os.path.dirname(__file__), "Sample-BIM-Files/IDS/", "IDS_Wall_needs_predefinedtype.xml")
|
2021-09-24 17:18:38 +02:00
|
|
|
ids_file = ids.ids.open(IDS_URL)
|
2021-08-24 12:57:44 +02:00
|
|
|
self.assertEqual(
|
2022-02-23 00:24:40 +01:00
|
|
|
ids_file.specifications[0].requirements.terms[0].node["predefinedType"]["simpleValue"], "CLADDING"
|
2021-08-24 12:57:44 +02:00
|
|
|
)
|
2021-07-05 13:21:36 +02:00
|
|
|
|
2021-08-24 12:57:44 +02:00
|
|
|
def test_parse_property_facet(self):
|
2021-09-24 17:18:38 +02:00
|
|
|
IDS_URL = os.path.join(os.path.dirname(__file__), "Sample-BIM-Files/IDS/", "IDS_Wall_needs_property.xml")
|
|
|
|
|
ids_file = ids.ids.open(IDS_URL)
|
2021-08-24 12:57:44 +02:00
|
|
|
self.assertEqual(
|
2022-02-23 00:24:40 +01:00
|
|
|
ids_file.specifications[0].requirements.terms[0].node["propertySet"]["simpleValue"], "Test_PropertySet"
|
2021-08-24 12:57:44 +02:00
|
|
|
)
|
|
|
|
|
self.assertEqual(ids_file.specifications[0].requirements.terms[0].node["name"]["simpleValue"], "Test_Parameter")
|
|
|
|
|
self.assertEqual(ids_file.specifications[0].requirements.terms[0].node["value"]["simpleValue"], "Test_Value")
|
2021-07-05 13:21:36 +02:00
|
|
|
|
2021-08-24 12:57:44 +02:00
|
|
|
def test_parse_material_facet(self):
|
2021-09-24 17:18:38 +02:00
|
|
|
IDS_URL = os.path.join(os.path.dirname(__file__), "Sample-BIM-Files/IDS/", "IDS_Wall_needs_material.xml")
|
|
|
|
|
ids_file = ids.ids.open(IDS_URL)
|
2021-08-24 12:57:44 +02:00
|
|
|
self.assertEqual(ids_file.specifications[0].requirements.terms[0].node["value"]["simpleValue"], "Test_Material")
|
2021-07-05 13:21:36 +02:00
|
|
|
|
2021-08-24 12:57:44 +02:00
|
|
|
def test_parse_classification_facet(self):
|
2022-05-10 16:17:38 +10:00
|
|
|
IDS_URL = os.path.join(os.path.dirname(__file__), "Sample-BIM-Files/IDS/", "IDS_Wall_needs_classification.xml")
|
2021-09-24 17:18:38 +02:00
|
|
|
ids_file = ids.ids.open(IDS_URL)
|
2021-08-24 12:57:44 +02:00
|
|
|
self.assertEqual(
|
|
|
|
|
ids_file.specifications[0].requirements.terms[0].node["value"]["simpleValue"], "Test_Classification"
|
|
|
|
|
)
|
|
|
|
|
self.assertEqual(ids_file.specifications[0].requirements.terms[0].node["system"]["simpleValue"], "Test_System")
|
2021-07-05 13:21:36 +02:00
|
|
|
|
|
|
|
|
""" Parsing invalid IDS.xml """
|
|
|
|
|
# TODO
|
|
|
|
|
# def test_invalid_classification_facet(self):
|
2021-09-24 17:18:38 +02:00
|
|
|
# IDS_URL = os.path.join(os.path.dirname(__file__), "Sample-BIM-Files/IDS/", "Invalid_IDS_Wall_needs_classification.xml")
|
|
|
|
|
# self.assertRaises( XMLSchemaChildrenValidationError, ids.open(IDS_URL) )
|
2021-07-02 17:27:09 +02:00
|
|
|
|
2021-07-09 08:44:36 +02:00
|
|
|
""" Saving parsed IDS to IDS.xml """
|
|
|
|
|
|
|
|
|
|
def test_parsed_ids_to_xml(self):
|
2022-05-10 16:17:38 +10:00
|
|
|
IDS_URL = os.path.join(os.path.dirname(__file__), "Sample-BIM-Files", "IDS", "IDS_Wall_needs_all_fields.xml")
|
2021-09-24 17:18:38 +02:00
|
|
|
ids_file = ids.ids.open(IDS_URL)
|
2022-05-10 16:22:12 +10:00
|
|
|
fn = "output.xml"
|
2021-07-09 08:44:36 +02:00
|
|
|
result = ids_file.to_xml(fn)
|
2022-05-10 16:22:12 +10:00
|
|
|
assert os.path.isfile(fn)
|
2021-07-09 08:44:36 +02:00
|
|
|
os.remove(fn)
|
|
|
|
|
self.assertTrue(result)
|
|
|
|
|
|
2022-05-10 16:22:12 +10:00
|
|
|
def test_parsed_ids_to_string(self):
|
|
|
|
|
IDS_URL = os.path.join(os.path.dirname(__file__), "Sample-BIM-Files", "IDS", "IDS_Wall_needs_all_fields.xml")
|
|
|
|
|
ids_file = ids.ids.open(IDS_URL)
|
|
|
|
|
output = ids_file.to_string()
|
|
|
|
|
assert output and "http://standards.buildingsmart.org/IDS" in output
|
|
|
|
|
|
2021-08-24 12:57:44 +02:00
|
|
|
""" Parsing IDS files with restrictions """
|
|
|
|
|
|
|
|
|
|
def test_parse_restrictions_enumeration(self):
|
2022-05-10 16:17:38 +10:00
|
|
|
IDS_URL = os.path.join(
|
|
|
|
|
os.path.dirname(__file__),
|
|
|
|
|
"Sample-BIM-Files/IDS/",
|
|
|
|
|
"IDS_Wall_needs_property_with_restriction_enumeration.xml",
|
|
|
|
|
)
|
2021-09-24 17:18:38 +02:00
|
|
|
ids_file = ids.ids.open(IDS_URL)
|
2021-08-24 12:57:44 +02:00
|
|
|
self.assertEqual(ids_file.specifications[0].requirements.terms[0].node["name"]["simpleValue"], "Test_Parameter")
|
|
|
|
|
self.assertEqual(
|
|
|
|
|
[
|
|
|
|
|
x["@value"]
|
|
|
|
|
for x in ids_file.specifications[0].requirements.terms[0].node["value"]["restriction"][0]["enumeration"]
|
|
|
|
|
],
|
|
|
|
|
["testA", "testB"],
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
def test_parse_restrictions_bounds(self):
|
2022-05-10 16:17:38 +10:00
|
|
|
IDS_URL = os.path.join(
|
|
|
|
|
os.path.dirname(__file__), "Sample-BIM-Files/IDS/", "IDS_Wall_needs_property_with_restriction_bounds.xml"
|
|
|
|
|
)
|
2021-09-24 17:18:38 +02:00
|
|
|
ids_file = ids.ids.open(IDS_URL)
|
2021-08-24 12:57:44 +02:00
|
|
|
self.assertEqual(ids_file.specifications[0].requirements.terms[0].node["name"]["simpleValue"], "Test_Parameter")
|
|
|
|
|
self.assertEqual(
|
|
|
|
|
ids_file.specifications[0].requirements.terms[0].node["value"]["restriction"][0]["minInclusive"]["@value"],
|
|
|
|
|
"0",
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
def test_parse_restrictions_pattern_simple(self):
|
2022-05-10 16:17:38 +10:00
|
|
|
IDS_URL = os.path.join(
|
|
|
|
|
os.path.dirname(__file__), "Sample-BIM-Files/IDS/", "IDS_Wall_needs_property_with_restriction_pattern.xml"
|
|
|
|
|
)
|
2021-09-24 17:18:38 +02:00
|
|
|
ids_file = ids.ids.open(IDS_URL)
|
2021-08-24 12:57:44 +02:00
|
|
|
self.assertEqual(ids_file.specifications[0].requirements.terms[0].node["name"]["simpleValue"], "Test_Parameter")
|
|
|
|
|
self.assertEqual(
|
|
|
|
|
ids_file.specifications[0].requirements.terms[0].node["value"]["restriction"][0]["pattern"]["@value"],
|
|
|
|
|
"[A-Z]{2,4}",
|
|
|
|
|
)
|
|
|
|
|
|
2021-07-09 08:44:36 +02:00
|
|
|
|
|
|
|
|
class TestIdsAuthoring(unittest.TestCase):
|
2022-05-10 16:23:07 +10:00
|
|
|
def test_creating_a_minimal_ids_and_validating(self):
|
|
|
|
|
specs = ids.ids(title="Title")
|
|
|
|
|
spec = ids.specification(name="Name")
|
|
|
|
|
spec.add_applicability(ids.entity.create(name="IfcWall"))
|
|
|
|
|
spec.add_requirement(ids.attribute.create(name="Name", value="Waldo"))
|
|
|
|
|
specs.specifications.append(spec)
|
|
|
|
|
assert "http://standards.buildingsmart.org/IDS" in specs.to_string()
|
|
|
|
|
|
|
|
|
|
model = ifcopenshell.file()
|
|
|
|
|
model.createIfcWall(Name="Waldo")
|
|
|
|
|
specs.validate(model)
|
|
|
|
|
# TODO test this without resorting to hooking into logger output
|
|
|
|
|
|
2022-05-10 17:36:24 +10:00
|
|
|
def test_create_an_ids_with_minimal_information(self):
|
2022-05-10 19:26:12 +10:00
|
|
|
specs = ids.ids()
|
|
|
|
|
assert specs.asdict() == {
|
|
|
|
|
"@xmlns": "http://standards.buildingsmart.org/IDS",
|
|
|
|
|
"@xmlns:xs": "http://www.w3.org/2001/XMLSchema",
|
|
|
|
|
"@xmlns:xsi": "http://www.w3.org/2001/XMLSchema-instance",
|
|
|
|
|
"@xsi:schemaLocation": "http://standards.buildingsmart.org/IDS/ids_05.xsd",
|
|
|
|
|
"info": {"title": "Untitled"},
|
|
|
|
|
"specifications": [],
|
|
|
|
|
}
|
2022-05-10 17:36:24 +10:00
|
|
|
|
|
|
|
|
def test_create_an_ids_with_all_possible_information(self):
|
|
|
|
|
specs = ids.ids(
|
|
|
|
|
title="title",
|
|
|
|
|
copyright="copyright",
|
|
|
|
|
version="version",
|
|
|
|
|
description="description",
|
|
|
|
|
author="author@test.com",
|
|
|
|
|
date="2020-01-01",
|
|
|
|
|
purpose="purpose",
|
|
|
|
|
milestone="milestone",
|
|
|
|
|
)
|
2022-05-10 19:26:12 +10:00
|
|
|
assert specs.asdict() == {
|
|
|
|
|
"@xmlns": "http://standards.buildingsmart.org/IDS",
|
|
|
|
|
"@xmlns:xs": "http://www.w3.org/2001/XMLSchema",
|
|
|
|
|
"@xmlns:xsi": "http://www.w3.org/2001/XMLSchema-instance",
|
|
|
|
|
"@xsi:schemaLocation": "http://standards.buildingsmart.org/IDS/ids_05.xsd",
|
|
|
|
|
"info": {
|
|
|
|
|
"title": "title",
|
|
|
|
|
"copyright": "copyright",
|
|
|
|
|
"version": "version",
|
|
|
|
|
"description": "description",
|
|
|
|
|
"author": "author@test.com",
|
|
|
|
|
"date": "2020-01-01",
|
|
|
|
|
"purpose": "purpose",
|
|
|
|
|
"milestone": "milestone",
|
|
|
|
|
},
|
|
|
|
|
"specifications": [],
|
|
|
|
|
}
|
2022-05-10 17:36:24 +10:00
|
|
|
|
|
|
|
|
def test_check_invalid_ids_information(self):
|
2022-05-10 19:26:12 +10:00
|
|
|
specs = ids.ids(title=None, author="author", date="9999-99-99")
|
|
|
|
|
assert specs.asdict() == {
|
|
|
|
|
"@xmlns": "http://standards.buildingsmart.org/IDS",
|
|
|
|
|
"@xmlns:xs": "http://www.w3.org/2001/XMLSchema",
|
|
|
|
|
"@xmlns:xsi": "http://www.w3.org/2001/XMLSchema-instance",
|
|
|
|
|
"@xsi:schemaLocation": "http://standards.buildingsmart.org/IDS/ids_05.xsd",
|
|
|
|
|
"info": {"title": "Untitled"},
|
|
|
|
|
"specifications": [],
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
def test_authoring_an_ids_with_no_specifications_is_invalid(self):
|
|
|
|
|
specs = ids.ids()
|
|
|
|
|
with pytest.raises(xmlschema.validators.exceptions.XMLSchemaChildrenValidationError):
|
|
|
|
|
specs.to_string()
|
|
|
|
|
|
|
|
|
|
def test_create_specification_with_minimal_information(self):
|
|
|
|
|
spec = ids.specification()
|
|
|
|
|
assert spec.asdict() == {
|
|
|
|
|
"@name": "Unnamed",
|
|
|
|
|
"@use": "required",
|
2022-05-10 22:13:28 +10:00
|
|
|
"@ifcVersion": ["IFC2X3", "IFC4"],
|
2022-05-10 19:26:12 +10:00
|
|
|
"applicability": {},
|
|
|
|
|
"requirements": {},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
def test_create_specification_with_all_possible_information(self):
|
|
|
|
|
spec = ids.specification(
|
|
|
|
|
name="name",
|
|
|
|
|
use="use",
|
2022-05-10 22:13:28 +10:00
|
|
|
ifcVersion="IFC4",
|
2022-05-10 19:26:12 +10:00
|
|
|
identifier="identifier",
|
|
|
|
|
description="description",
|
|
|
|
|
instructions="instructions",
|
|
|
|
|
)
|
|
|
|
|
assert spec.asdict() == {
|
|
|
|
|
"@name": "name",
|
|
|
|
|
"@use": "use",
|
2022-05-10 22:13:28 +10:00
|
|
|
"@ifcVersion": "IFC4",
|
2022-05-10 19:26:12 +10:00
|
|
|
"@identifier": "identifier",
|
|
|
|
|
"@description": "description",
|
|
|
|
|
"@instructions": "instructions",
|
|
|
|
|
"applicability": {},
|
|
|
|
|
"requirements": {},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
def test_ids_add_content(self):
|
|
|
|
|
i = ids.ids(title="My IDS")
|
|
|
|
|
i.specifications.append(ids.specification(name="Test_Specification"))
|
|
|
|
|
self.assertEqual(i.specifications[0].name, "Test_Specification")
|
|
|
|
|
m = ids.material.create(location="any", value="Test_Value")
|
|
|
|
|
i.specifications[0].add_applicability(m)
|
|
|
|
|
self.assertEqual(i.specifications[0].applicability.terms[0].value, "Test_Value")
|
|
|
|
|
i.specifications[0].add_applicability(m)
|
|
|
|
|
self.assertEqual(i.specifications[0].applicability.terms[1].value, "Test_Value")
|
|
|
|
|
i.specifications[0].add_requirement(m)
|
|
|
|
|
self.assertEqual(i.specifications[0].requirements.terms[0].value, "Test_Value")
|
|
|
|
|
i.specifications[0].add_requirement(m)
|
|
|
|
|
self.assertEqual(i.specifications[0].requirements.terms[1].value, "Test_Value")
|
2022-05-10 17:36:24 +10:00
|
|
|
|
2022-05-10 21:20:10 +10:00
|
|
|
def test_create_an_entity_facet(self):
|
|
|
|
|
facet = ids.entity.create(name="IfcName")
|
|
|
|
|
assert facet.asdict() == {"name": {"simpleValue": "IfcName"}}
|
|
|
|
|
facet = ids.entity.create(name="IfcName", predefinedType="predefinedType")
|
|
|
|
|
assert facet.asdict() == {
|
|
|
|
|
"name": {"simpleValue": "IfcName"},
|
|
|
|
|
"predefinedType": {"simpleValue": "predefinedType"},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
def test_filtering_using_an_entity_facet(self):
|
|
|
|
|
ifc = ifcopenshell.file()
|
|
|
|
|
|
|
|
|
|
facet = ids.entity.create(name="IfcWall")
|
|
|
|
|
assert bool(facet(ifc.createIfcWall())) is True
|
|
|
|
|
assert bool(facet(ifc.createIfcWall(PredefinedType="SOLIDWALL"))) is True
|
|
|
|
|
assert bool(facet(ifc.createIfcSlab())) is False
|
2022-05-10 23:49:14 +10:00
|
|
|
assert bool(facet(ifc.createIfcWallStandardCase())) is False
|
2022-05-10 21:20:10 +10:00
|
|
|
|
2022-05-10 21:40:35 +10:00
|
|
|
facet = ids.entity.create(name="IFCWALL")
|
|
|
|
|
assert bool(facet(ifc.createIfcWall())) is True
|
|
|
|
|
assert bool(facet(ifc.createIfcWall(PredefinedType="SOLIDWALL"))) is True
|
|
|
|
|
assert bool(facet(ifc.createIfcSlab())) is False
|
|
|
|
|
|
2022-05-10 21:20:10 +10:00
|
|
|
facet = ids.entity.create(name="IfcWall", predefinedType="SOLIDWALL")
|
|
|
|
|
assert bool(facet(ifc.createIfcWall())) is False
|
|
|
|
|
assert bool(facet(ifc.createIfcWall(PredefinedType="SOLIDWALL"))) is True
|
|
|
|
|
assert bool(facet(ifc.createIfcWall(PredefinedType="PARTITIONING"))) is False
|
|
|
|
|
|
|
|
|
|
facet = ids.entity.create(name="IfcWall", predefinedType="WALDO")
|
|
|
|
|
assert bool(facet(ifc.createIfcWall(PredefinedType="USERDEFINED", ObjectType="WALDO"))) is True
|
|
|
|
|
|
|
|
|
|
facet = ids.entity.create(name="IfcWallType", predefinedType="WALDO")
|
|
|
|
|
assert bool(facet(ifc.createIfcWallType(PredefinedType="USERDEFINED", ElementType="WALDO"))) is True
|
2021-07-09 08:44:36 +02:00
|
|
|
|
2022-05-10 21:40:35 +10:00
|
|
|
restriction = ids.restriction.create(options=["IfcWall", "IfcSlab"], type="enumeration", base="string")
|
|
|
|
|
facet = ids.entity.create(name=restriction)
|
|
|
|
|
assert bool(facet(ifc.createIfcWall())) is True
|
|
|
|
|
assert bool(facet(ifc.createIfcSlab())) is True
|
|
|
|
|
assert bool(facet(ifc.createIfcBeam())) is False
|
|
|
|
|
|
|
|
|
|
restriction = ids.restriction.create(options="Ifc.*Type", type="pattern", base="string")
|
|
|
|
|
facet = ids.entity.create(name=restriction)
|
|
|
|
|
assert bool(facet(ifc.createIfcWall())) is False
|
|
|
|
|
assert bool(facet(ifc.createIfcWallType())) is True
|
|
|
|
|
|
2022-05-10 22:42:21 +10:00
|
|
|
def test_creating_an_attribute_facet(self):
|
2022-05-10 16:23:07 +10:00
|
|
|
attribute = ids.attribute.create(name="Name", value="Value")
|
|
|
|
|
assert attribute.name == "Name"
|
|
|
|
|
assert attribute.value == "Value"
|
|
|
|
|
assert attribute.asdict() == {
|
|
|
|
|
"name": {"simpleValue": "Name"},
|
|
|
|
|
"value": {"simpleValue": "Value"},
|
|
|
|
|
"@location": "any",
|
|
|
|
|
}
|
|
|
|
|
|
2022-05-10 22:42:21 +10:00
|
|
|
def test_filtering_using_an_attribute_facet(self):
|
|
|
|
|
ifc = ifcopenshell.file()
|
|
|
|
|
|
|
|
|
|
facet = ids.attribute.create(name="Foobar")
|
|
|
|
|
assert bool(facet(ifc.createIfcWall())) is False
|
|
|
|
|
|
|
|
|
|
facet = ids.attribute.create(name="Name")
|
|
|
|
|
assert bool(facet(ifc.createIfcWall())) is False
|
|
|
|
|
assert bool(facet(ifc.createIfcWall(Name=""))) is False
|
|
|
|
|
assert bool(facet(ifc.createIfcWall(Name="Foobar"))) is True
|
|
|
|
|
|
|
|
|
|
facet = ids.attribute.create(name="Name", value="Foobar")
|
|
|
|
|
assert bool(facet(ifc.createIfcWall(Name="Foobar"))) is True
|
|
|
|
|
assert bool(facet(ifc.createIfcWall(Name="Foobaz"))) is False
|
|
|
|
|
|
|
|
|
|
facet = ids.attribute.create(name="Eastings")
|
|
|
|
|
assert bool(facet(ifc.createIfcMapConversion(Eastings=0))) is True
|
|
|
|
|
|
|
|
|
|
facet = ids.attribute.create(name="Eastings", value=42)
|
|
|
|
|
assert bool(facet(ifc.createIfcMapConversion(Eastings=0))) is False
|
|
|
|
|
assert bool(facet(ifc.createIfcMapConversion(Eastings=42))) is True
|
|
|
|
|
|
|
|
|
|
restriction = ids.restriction.create(options=["Foo", "Bar"], type="enumeration", base="string")
|
|
|
|
|
facet = ids.attribute.create(name="Name", value=restriction)
|
|
|
|
|
assert bool(facet(ifc.createIfcWall(Name="Foo"))) is True
|
|
|
|
|
assert bool(facet(ifc.createIfcWall(Name="Bar"))) is True
|
|
|
|
|
assert bool(facet(ifc.createIfcWall(Name="Foobar"))) is False
|
|
|
|
|
|
2021-07-09 08:44:36 +02:00
|
|
|
def test_classification_create(self):
|
|
|
|
|
c = ids.classification.create(location="any", value="Test_Value", system="Test_System")
|
|
|
|
|
self.assertEqual(c.location, "any")
|
|
|
|
|
self.assertEqual(c.value, "Test_Value")
|
|
|
|
|
self.assertEqual(c.system, "Test_System")
|
|
|
|
|
|
|
|
|
|
def test_property_create(self):
|
|
|
|
|
p = ids.property.create(
|
2022-02-23 00:24:40 +01:00
|
|
|
location="any", propertySet="Test_PropertySet", name="Test_Parameter", value="Test_Value"
|
2021-07-09 08:44:36 +02:00
|
|
|
)
|
|
|
|
|
self.assertEqual(p.location, "any")
|
2022-02-23 00:24:40 +01:00
|
|
|
self.assertEqual(p.propertySet, "Test_PropertySet")
|
2021-07-09 08:44:36 +02:00
|
|
|
self.assertEqual(p.name, "Test_Parameter")
|
|
|
|
|
self.assertEqual(p.value, "Test_Value")
|
|
|
|
|
|
|
|
|
|
def test_material_create(self):
|
|
|
|
|
m = ids.material.create(location="any", value="Test_Value")
|
|
|
|
|
self.assertEqual(m.location, "any")
|
|
|
|
|
self.assertEqual(m.value, "Test_Value")
|
|
|
|
|
|
2021-08-24 12:57:44 +02:00
|
|
|
""" Creating IDS with restrictions """
|
|
|
|
|
|
|
|
|
|
def test_create_restrictions_enumeration(self):
|
2022-02-23 00:24:40 +01:00
|
|
|
i = ids.ids(title="My IDS")
|
2021-08-24 12:57:44 +02:00
|
|
|
i.specifications.append(ids.specification(name="Test_Specification"))
|
|
|
|
|
i.specifications[0].add_applicability(ids.entity.create(name="Test_Name"))
|
|
|
|
|
r = ids.restriction.create(options=["testA", "testB"], type="enumeration", base="string")
|
|
|
|
|
m = ids.material.create(location="any", value=r)
|
|
|
|
|
i.specifications[0].add_requirement(m)
|
|
|
|
|
self.assertEqual(i.specifications[0].requirements.terms[0].value, "testA")
|
|
|
|
|
self.assertEqual(i.specifications[0].requirements.terms[0].value, "testB")
|
|
|
|
|
self.assertNotEqual(i.specifications[0].requirements.terms[0].value, "testC")
|
|
|
|
|
|
|
|
|
|
def test_create_restrictions_bounds(self):
|
2022-02-23 00:24:40 +01:00
|
|
|
i = ids.ids(title="My IDS")
|
2021-08-24 12:57:44 +02:00
|
|
|
i.specifications.append(ids.specification(name="Test_Specification"))
|
|
|
|
|
i.specifications[0].add_applicability(ids.entity.create(name="Test_Name"))
|
|
|
|
|
r = ids.restriction.create(options={"minInclusive": 0, "maxExclusive": 10}, type="bounds", base="integer")
|
2022-02-23 00:24:40 +01:00
|
|
|
p = ids.property.create(location="any", propertySet="Test", name="Test", value=r)
|
2021-08-24 12:57:44 +02:00
|
|
|
i.specifications[0].add_requirement(p)
|
|
|
|
|
self.assertEqual(i.specifications[0].requirements.terms[0].value, 0)
|
|
|
|
|
self.assertEqual(i.specifications[0].requirements.terms[0].value, 5)
|
|
|
|
|
self.assertNotEqual(i.specifications[0].requirements.terms[0].value, -1)
|
|
|
|
|
self.assertNotEqual(i.specifications[0].requirements.terms[0].value, 10)
|
|
|
|
|
|
|
|
|
|
def test_create_restrictions_pattern_simple(self):
|
2022-02-23 00:24:40 +01:00
|
|
|
i = ids.ids(title="My IDS")
|
2021-08-24 12:57:44 +02:00
|
|
|
i.specifications.append(ids.specification(name="Test_Specification"))
|
|
|
|
|
i.specifications[0].add_applicability(ids.entity.create(name="Test_Name"))
|
|
|
|
|
r = ids.restriction.create(options="[A-Z]{2,4}", type="pattern", base="string")
|
2022-02-23 00:24:40 +01:00
|
|
|
p = ids.property.create(location="any", propertySet="Test", name="Test", value=r)
|
2021-08-24 12:57:44 +02:00
|
|
|
i.specifications[0].add_requirement(p)
|
|
|
|
|
self.assertEqual(i.specifications[0].requirements.terms[0].value, "XYZ")
|
|
|
|
|
self.assertNotEqual(i.specifications[0].requirements.terms[0].value, "abc")
|
|
|
|
|
self.assertNotEqual(i.specifications[0].requirements.terms[0].value, "ABCDE")
|
|
|
|
|
self.assertNotEqual(i.specifications[0].requirements.terms[0].value, "A")
|
|
|
|
|
|
|
|
|
|
def test_create_restrictions_pattern_advanced(self):
|
2022-02-23 00:24:40 +01:00
|
|
|
i = ids.ids(title="My IDS")
|
2021-08-24 12:57:44 +02:00
|
|
|
i.specifications.append(ids.specification(name="Test_Specification"))
|
|
|
|
|
i.specifications[0].add_applicability(ids.entity.create(name="Test_Name"))
|
|
|
|
|
r = ids.restriction.create(options="(Wanddurchbruch|Deckendurchbruch).*", type="pattern", base="string")
|
2022-02-23 00:24:40 +01:00
|
|
|
p = ids.property.create(location="any", propertySet="Test", name="Test", value=r)
|
2021-08-24 12:57:44 +02:00
|
|
|
i.specifications[0].add_requirement(p)
|
|
|
|
|
self.assertEqual(i.specifications[0].requirements.terms[0].value, "Wanddurchbruch")
|
|
|
|
|
self.assertEqual(i.specifications[0].requirements.terms[0].value, "Deckendurchbruch")
|
|
|
|
|
self.assertNotEqual(i.specifications[0].requirements.terms[0].value, "Deeckendurchbruch")
|
|
|
|
|
|
2021-11-23 17:53:32 +01:00
|
|
|
def test_create_restrictions_pattern_utf(self):
|
2022-02-23 00:24:40 +01:00
|
|
|
i = ids.ids(title="My IDS")
|
2021-11-23 17:53:32 +01:00
|
|
|
i.specifications.append(ids.specification(name="Test_Specification"))
|
|
|
|
|
i.specifications[0].add_applicability(ids.entity.create(name="Test_Name"))
|
|
|
|
|
r = ids.restriction.create(options="èêóòâôæøåążźćęóʑʒʓʔʕʗʘʙʚʛʜʝʞ", type="pattern", base="string")
|
2022-02-23 00:24:40 +01:00
|
|
|
p = ids.property.create(location="any", propertySet="Test", name="Test", value=r)
|
2021-11-23 17:53:32 +01:00
|
|
|
i.specifications[0].add_requirement(p)
|
|
|
|
|
self.assertEqual(i.specifications[0].requirements.terms[0].value, "èêóòâôæøåążźćęóʑʒʓʔʕʗʘʙʚʛʜʝʞ")
|
2021-07-09 08:44:36 +02:00
|
|
|
|
2021-11-23 17:53:32 +01:00
|
|
|
""" Saving created IDS to IDS.xml """
|
2021-09-24 17:18:38 +02:00
|
|
|
|
2021-11-23 17:53:32 +01:00
|
|
|
def test_created_ids_to_xml(self):
|
2022-02-23 00:24:40 +01:00
|
|
|
i = ids.ids(title="My IDS")
|
2021-11-23 17:53:32 +01:00
|
|
|
i.specifications.append(ids.specification(name="Test_Specification"))
|
2022-02-23 00:24:40 +01:00
|
|
|
e = ids.entity.create(name="Test_Name", predefinedType="Test_PredefinedType")
|
2021-11-23 17:53:32 +01:00
|
|
|
c = ids.classification.create(location="any", value="Test_Value", system="Test_System")
|
|
|
|
|
m = ids.material.create(location="any", value="Test_Value")
|
|
|
|
|
re = ids.restriction.create(options=["testA", "testB"], type="enumeration", base="string")
|
|
|
|
|
rb = ids.restriction.create(options={"minInclusive": 0, "maxExclusive": 10}, type="bounds", base="integer")
|
|
|
|
|
rp1 = ids.restriction.create(options="[A-Z]{2,4}", type="pattern", base="string")
|
|
|
|
|
rp2 = ids.restriction.create(options="èêóòâôæøåążźćęóʑʒʓʔʕʗʘʙʚʛʜʝʞ", type="pattern", base="string")
|
2022-02-23 00:24:40 +01:00
|
|
|
p1 = ids.property.create(location="any", propertySet="Test_PropertySet", name="Test_Parameter", value=re)
|
|
|
|
|
p2 = ids.property.create(location="any", propertySet="Test_PropertySet", name="Test_Parameter", value=rb)
|
|
|
|
|
p3 = ids.property.create(location="any", propertySet="Test_PropertySet", name="Test_Parameter", value=rp1)
|
|
|
|
|
p4 = ids.property.create(location="any", propertySet="Test_PropertySet", name="Test_Parameter", value=rp2)
|
2021-11-23 17:53:32 +01:00
|
|
|
p5 = ids.property.create(
|
2022-02-23 00:24:40 +01:00
|
|
|
location="any", propertySet="Test_PropertySet", name="Test_Parameter", value=[re, rb, rp1]
|
2021-11-23 17:53:32 +01:00
|
|
|
)
|
|
|
|
|
i.specifications[0].add_applicability(e)
|
|
|
|
|
i.specifications[0].add_applicability(m)
|
|
|
|
|
i.specifications[0].add_requirement(c)
|
|
|
|
|
i.specifications[0].add_requirement(p1)
|
2022-05-10 16:17:38 +10:00
|
|
|
# TODO i.specifications[0].add_requirement(p2)
|
2021-11-23 17:53:32 +01:00
|
|
|
i.specifications[0].add_requirement(p3)
|
|
|
|
|
i.specifications[0].add_requirement(p4)
|
2022-05-10 16:17:38 +10:00
|
|
|
# TODO i.specifications[0].add_requirement(p5)
|
2021-11-23 17:53:32 +01:00
|
|
|
fn = "TEST_FILE.xml"
|
|
|
|
|
result = i.to_xml(fn)
|
|
|
|
|
os.remove(fn)
|
|
|
|
|
self.assertTrue(result)
|
2022-05-10 16:17:38 +10:00
|
|
|
|
2021-07-09 08:44:36 +02:00
|
|
|
|
|
|
|
|
class TestIfcValidation(unittest.TestCase):
|
2021-08-24 12:57:44 +02:00
|
|
|
def test_validate_simple(self):
|
2022-05-10 16:17:38 +10:00
|
|
|
# Same test as in reporting...
|
2021-11-23 17:53:32 +01:00
|
|
|
ids_file = ids.ids.open(IDS_URL)
|
|
|
|
|
report = ids.SimpleHandler()
|
|
|
|
|
logger.addHandler(report)
|
|
|
|
|
ids_file.validate(ifc_file, logger)
|
|
|
|
|
self.assertEqual(len(report.statements), 5)
|
2021-12-22 12:45:16 +01:00
|
|
|
logger.handlers.pop()
|
|
|
|
|
|
|
|
|
|
def test_validate_all_facets(self):
|
2022-05-10 16:17:38 +10:00
|
|
|
# Those are true:
|
2021-12-22 12:45:16 +01:00
|
|
|
e = ids.entity.create(name="IfcWall")
|
2022-02-23 00:24:40 +01:00
|
|
|
p1 = ids.property.create(location="any", propertySet="MySet", name="Param1", value="banan")
|
|
|
|
|
p2 = ids.property.create(location="any", propertySet="MySet", name="Param2", value=120.0)
|
|
|
|
|
p3 = ids.property.create(location="any", propertySet="Pset_WallCommon", name="LoadBearing", value=False)
|
2022-05-10 16:17:38 +10:00
|
|
|
# Those are false:
|
2022-02-23 00:24:40 +01:00
|
|
|
p4 = ids.property.create(location="any", propertySet="MySet", name="Param1", value="orange")
|
|
|
|
|
p5 = ids.property.create(location="any", propertySet="MySet", name="Param2", value=123.4)
|
|
|
|
|
p6 = ids.property.create(location="any", propertySet="Pset_WallCommon", name="LoadBearing", value=True)
|
2022-05-10 16:17:38 +10:00
|
|
|
|
2022-02-23 00:24:40 +01:00
|
|
|
i = ids.ids(title="My IDS")
|
2021-12-22 12:45:16 +01:00
|
|
|
i.specifications.append(ids.specification(name="Test_Specification"))
|
|
|
|
|
i.specifications[0].add_applicability(e)
|
|
|
|
|
i.specifications[0].add_requirement(p1)
|
|
|
|
|
i.specifications[0].add_requirement(p2)
|
|
|
|
|
i.specifications[0].add_requirement(p3)
|
|
|
|
|
i.specifications[0].add_requirement(p4)
|
|
|
|
|
i.specifications[0].add_requirement(p5)
|
|
|
|
|
i.specifications[0].add_requirement(p6)
|
|
|
|
|
|
|
|
|
|
report = ids.SimpleHandler(report_valid=True)
|
|
|
|
|
logger.addHandler(report)
|
|
|
|
|
|
|
|
|
|
i.validate(ifc_file, logger)
|
|
|
|
|
# TODO self.assertEqual(len(report.statements), 27) #there are 5 walls in the IFC, one passed 3 criteria, est should fail (27 failures)
|
|
|
|
|
logger.handlers.pop()
|
|
|
|
|
|
2021-08-24 12:57:44 +02:00
|
|
|
""" Validating IDS files with restrictions """
|
|
|
|
|
|
2021-12-22 12:45:16 +01:00
|
|
|
def test_validate_restrictions_enumeration(self):
|
2022-05-10 16:17:38 +10:00
|
|
|
IDS_URL = os.path.join(
|
|
|
|
|
os.path.dirname(__file__),
|
|
|
|
|
"Sample-BIM-Files/IDS/",
|
|
|
|
|
"IDS_Wall_needs_property_with_restriction_enumeration.xml",
|
|
|
|
|
)
|
2021-12-22 12:45:16 +01:00
|
|
|
ids_file = ids.ids.open(IDS_URL)
|
2022-05-10 16:17:38 +10:00
|
|
|
self.assertEqual(ids_file.specifications[0].requirements.terms[0].node["name"]["simpleValue"], "Test_Parameter")
|
|
|
|
|
self.assertEqual(
|
|
|
|
|
[
|
|
|
|
|
x["@value"]
|
|
|
|
|
for x in ids_file.specifications[0].requirements.terms[0].node["value"]["restriction"][0]["enumeration"]
|
|
|
|
|
],
|
|
|
|
|
["testA", "testB"],
|
|
|
|
|
)
|
2021-12-22 12:45:16 +01:00
|
|
|
# TODO actual test of validation result
|
|
|
|
|
# self.assertTrue( )
|
|
|
|
|
|
|
|
|
|
def test_validate_restrictions_boundsInclusive(self):
|
2022-05-10 16:17:38 +10:00
|
|
|
IDS_URL = os.path.join(
|
|
|
|
|
os.path.dirname(__file__), "Sample-BIM-Files/IDS/", "IDS_Wall_needs_property_with_restriction_bounds.xml"
|
|
|
|
|
)
|
2021-12-22 12:45:16 +01:00
|
|
|
ids_file = ids.ids.open(IDS_URL)
|
2022-05-10 16:17:38 +10:00
|
|
|
self.assertEqual(ids_file.specifications[0].requirements.terms[0].node["name"]["simpleValue"], "Test_Parameter")
|
|
|
|
|
self.assertEqual(
|
|
|
|
|
ids_file.specifications[0].requirements.terms[0].node["value"]["restriction"][0]["minInclusive"]["@value"],
|
|
|
|
|
"0",
|
|
|
|
|
)
|
2021-12-22 12:45:16 +01:00
|
|
|
# TODO actual test of validation result
|
|
|
|
|
# self.assertTrue( )
|
|
|
|
|
|
|
|
|
|
def test_validate_restrictions_boundsExclusive(self):
|
2022-05-10 16:17:38 +10:00
|
|
|
# TODO
|
2021-12-22 12:45:16 +01:00
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
def test_validate_restrictions_pattern_simple(self):
|
2022-05-10 16:17:38 +10:00
|
|
|
IDS_URL = os.path.join(
|
|
|
|
|
os.path.dirname(__file__), "Sample-BIM-Files/IDS/", "IDS_Wall_needs_property_with_restriction_pattern.xml"
|
|
|
|
|
)
|
2021-12-22 12:45:16 +01:00
|
|
|
ids_file = ids.ids.open(IDS_URL)
|
2022-05-10 16:17:38 +10:00
|
|
|
self.assertEqual(ids_file.specifications[0].requirements.terms[0].node["name"]["simpleValue"], "Test_Parameter")
|
|
|
|
|
self.assertEqual(
|
|
|
|
|
ids_file.specifications[0].requirements.terms[0].node["value"]["restriction"][0]["pattern"]["@value"],
|
|
|
|
|
"[A-Z]{2,4}",
|
|
|
|
|
)
|
2021-12-22 12:45:16 +01:00
|
|
|
# TODO actual test of validation result
|
|
|
|
|
# self.assertTrue( )
|
2021-08-24 12:57:44 +02:00
|
|
|
|
|
|
|
|
|
2021-11-23 17:53:32 +01:00
|
|
|
class TestIdsReporting(unittest.TestCase):
|
|
|
|
|
def test_simple_report(self):
|
2022-05-10 16:17:38 +10:00
|
|
|
# Same test as in validation...
|
2021-11-23 17:53:32 +01:00
|
|
|
ids_file = ids.ids.open(IDS_URL)
|
|
|
|
|
report = ids.SimpleHandler()
|
|
|
|
|
logger.addHandler(report)
|
|
|
|
|
ids_file.validate(ifc_file, logger)
|
|
|
|
|
self.assertEqual(len(report.statements), 5)
|
2021-12-22 12:45:16 +01:00
|
|
|
logger.handlers.pop()
|
|
|
|
|
|
2021-11-23 17:53:32 +01:00
|
|
|
def test_bcf_report(self):
|
|
|
|
|
ids_file = ids.ids.open(IDS_URL)
|
|
|
|
|
fn = os.path.join(tempfile.gettempdir(), "test.bcf")
|
|
|
|
|
bcf_handler = ids.BcfHandler(project_name="Default IDS Project", author="your@email.com", filepath=fn)
|
|
|
|
|
logger.addHandler(bcf_handler)
|
|
|
|
|
ids_file.validate(ifc_file, logger)
|
|
|
|
|
my_bcfxml = bcfxml.load(fn)
|
|
|
|
|
topics = my_bcfxml.get_topics()
|
|
|
|
|
self.assertEqual(len(topics), 5)
|
2021-12-22 12:45:16 +01:00
|
|
|
logger.handlers.pop()
|
2021-07-02 17:27:09 +02:00
|
|
|
|
|
|
|
|
|
2021-07-09 08:44:36 +02:00
|
|
|
if __name__ == "__main__":
|
|
|
|
|
unittest.main()
|