Editing psets can now accept user specified data types and auto-detect non-string data types

This commit is contained in:
Dion Moult
2021-09-20 15:37:01 +10:00
parent 92e519de9e
commit 8cde074fd8
3 changed files with 195 additions and 10 deletions
@@ -39,7 +39,7 @@ class Usecase:
if value is None:
prop.NominalValue = None
else:
primary_measure_type = self.get_primary_measure_type(prop.Name, previous_value=prop.NominalValue)
primary_measure_type = self.get_primary_measure_type(prop.Name, old_value=prop.NominalValue, new_value=value)
prop.NominalValue = self.file.create_entity(primary_measure_type, value)
del self.settings["properties"][prop.Name]
@@ -48,7 +48,9 @@ class Usecase:
for name, value in self.settings["properties"].items():
if value is None:
continue
primary_measure_type = self.get_primary_measure_type(name)
primary_measure_type = self.get_primary_measure_type(name, new_value=value)
if hasattr(value, "is_a"):
value = value.wrappedValue
properties.append(
self.file.create_entity(
"IfcPropertySingleValue",
@@ -71,11 +73,22 @@ class Usecase:
elif hasattr(self.settings["pset"], "Properties"): # For IfcMaterialProperties
return self.settings["pset"].Properties or []
def get_primary_measure_type(self, name, previous_value=None):
if not self.pset_template:
return previous_value.is_a() if previous_value else "IfcLabel"
for prop_template in self.pset_template.HasPropertyTemplates:
if prop_template.Name != name:
continue
return prop_template.PrimaryMeasureType or "IfcLabel"
return previous_value.is_a() if previous_value else "IfcLabel"
def get_primary_measure_type(self, name, old_value=None, new_value=None):
if self.pset_template:
for prop_template in self.pset_template.HasPropertyTemplates:
if prop_template.Name != name:
continue
return prop_template.PrimaryMeasureType or "IfcLabel"
if old_value:
return old_value.is_a()
elif new_value and hasattr(new_value, "is_a"):
return new_value.is_a()
elif new_value is not None:
if isinstance(new_value, str):
return "IfcLabel"
elif isinstance(new_value, float):
return "IfcReal"
elif isinstance(new_value, bool):
return "IfcBoolean"
elif isinstance(new_value, int):
return "IfcInteger"
@@ -0,0 +1,172 @@
import test.bootstrap
import ifcopenshell.api
class TestEditPset(test.bootstrap.IFC4):
def test_editing_a_blank_buildingsmart_templated_pset(self):
element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall")
pset = ifcopenshell.api.run("pset.add_pset", self.file, product=element, name="Pset_WallCommon")
ifcopenshell.api.run(
"pset.edit_pset",
self.file,
pset=pset,
properties={"Reference": "reference", "Status": "NEW", "Combustible": True, "ThermalTransmittance": 42},
)
pset = element.IsDefinedBy[0].RelatingPropertyDefinition
assert pset.HasProperties[0].Name == "Reference"
assert pset.HasProperties[0].NominalValue.is_a("IfcIdentifier")
assert pset.HasProperties[0].NominalValue.wrappedValue == "reference"
assert pset.HasProperties[1].Name == "Status"
assert pset.HasProperties[1].NominalValue.is_a("IfcLabel")
assert pset.HasProperties[1].NominalValue.wrappedValue == "NEW"
assert pset.HasProperties[2].Name == "Combustible"
assert pset.HasProperties[2].NominalValue.is_a("IfcBoolean")
assert pset.HasProperties[2].NominalValue.wrappedValue == True
assert pset.HasProperties[3].Name == "ThermalTransmittance"
assert pset.HasProperties[3].NominalValue.is_a("IfcThermalTransmittanceMeasure")
assert pset.HasProperties[3].NominalValue.wrappedValue == 42
def test_editing_an_existing_buildingsmart_templated_pset(self):
element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall")
pset = ifcopenshell.api.run("pset.add_pset", self.file, product=element, name="Pset_WallCommon")
ifcopenshell.api.run(
"pset.edit_pset",
self.file,
pset=pset,
properties={"Reference": "foo", "Status": "NEW", "Combustible": True, "ThermalTransmittance": 42},
)
ifcopenshell.api.run("pset.edit_pset", self.file, pset=pset, properties={"Reference": "bar", "Status": None})
pset = element.IsDefinedBy[0].RelatingPropertyDefinition
assert pset.HasProperties[0].Name == "Reference"
assert pset.HasProperties[0].NominalValue.is_a("IfcIdentifier")
assert pset.HasProperties[0].NominalValue.wrappedValue == "bar"
assert pset.HasProperties[1].Name == "Status"
assert pset.HasProperties[1].NominalValue is None
def test_not_adding_a_property_if_it_is_none(self):
element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall")
pset = ifcopenshell.api.run("pset.add_pset", self.file, product=element, name="Pset_WallCommon")
ifcopenshell.api.run("pset.edit_pset", self.file, pset=pset, properties={"Reference": None})
pset = element.IsDefinedBy[0].RelatingPropertyDefinition
assert len(pset.HasProperties) == 0
def test_editing_a_pset_name(self):
element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall")
pset = ifcopenshell.api.run("pset.add_pset", self.file, product=element, name="foo")
ifcopenshell.api.run("pset.edit_pset", self.file, pset=pset, name="bar")
pset = element.IsDefinedBy[0].RelatingPropertyDefinition
assert pset.Name == "bar"
def test_adding_properties_without_a_template_with_autodetected_and_manual_data_types(self):
element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall")
pset = ifcopenshell.api.run("pset.add_pset", self.file, product=element, name="Foo_Bar")
ifcopenshell.api.run(
"pset.edit_pset",
self.file,
pset=pset,
properties={
"MyLabel": "foobar",
"MyBool": True,
"MyInteger": 42,
"MyFloat": 42.0,
"MyCustom": self.file.createIfcContextDependentMeasure(123),
},
)
pset = element.IsDefinedBy[0].RelatingPropertyDefinition
assert pset.HasProperties[0].Name == "MyLabel"
assert pset.HasProperties[0].NominalValue.is_a("IfcLabel")
assert pset.HasProperties[0].NominalValue.wrappedValue == "foobar"
assert pset.HasProperties[1].Name == "MyBool"
assert pset.HasProperties[1].NominalValue.is_a("IfcBoolean")
assert pset.HasProperties[1].NominalValue.wrappedValue == True
assert pset.HasProperties[2].Name == "MyInteger"
assert pset.HasProperties[2].NominalValue.is_a("IfcInteger")
assert pset.HasProperties[2].NominalValue.wrappedValue == 42
assert pset.HasProperties[3].Name == "MyFloat"
assert pset.HasProperties[3].NominalValue.is_a("IfcReal")
assert pset.HasProperties[3].NominalValue.wrappedValue == 42.0
assert pset.HasProperties[4].Name == "MyCustom"
assert pset.HasProperties[4].NominalValue.is_a("IfcContextDependentMeasure")
assert pset.HasProperties[4].NominalValue.wrappedValue == 123.0
def test_editing_properties_with_autodetected_existing_types(self):
element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall")
pset = ifcopenshell.api.run("pset.add_pset", self.file, product=element, name="Foo_Bar")
ifcopenshell.api.run(
"pset.edit_pset",
self.file,
pset=pset,
properties={
"MyCustom": self.file.createIfcContextDependentMeasure(12),
},
)
ifcopenshell.api.run(
"pset.edit_pset",
self.file,
pset=pset,
properties={
"MyCustom": 34,
},
)
pset = element.IsDefinedBy[0].RelatingPropertyDefinition
assert pset.HasProperties[0].Name == "MyCustom"
assert pset.HasProperties[0].NominalValue.is_a("IfcContextDependentMeasure")
assert pset.HasProperties[0].NominalValue.wrappedValue == 34
def test_editing_properties_of_non_rooted_elements(self):
element = self.file.createIfcMaterial()
pset = ifcopenshell.api.run("pset.add_pset", self.file, product=element, name="Foo_Bar")
ifcopenshell.api.run("pset.edit_pset", self.file, pset=pset, properties={"foo": "bar"})
assert element.HasProperties[0] == pset
assert pset.Properties[0].Name == "foo"
assert pset.Properties[0].NominalValue.is_a("IfcLabel")
assert pset.Properties[0].NominalValue.wrappedValue == "bar"
def test_editing_a_custom_templated_pset(self):
template = self.file.create_entity(
"IfcPropertySetTemplate",
**{
"GlobalId": ifcopenshell.guid.new(),
"Name": "Foo_Bar",
"TemplateType": "PSET_TYPEDRIVENOVERRIDE",
"ApplicableEntity": "IfcWall",
"HasPropertyTemplates": [
self.file.create_entity(
"IfcSimplePropertyTemplate",
**{
"GlobalId": ifcopenshell.guid.new(),
"Name": "foo",
"TemplateType": "P_SINGLEVALUE",
"PrimaryMeasureType": "IfcContextDependentMeasure",
}
)
],
}
)
element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall")
pset = ifcopenshell.api.run("pset.add_pset", self.file, product=element, name="Foo_Bar")
ifcopenshell.api.run(
"pset.edit_pset",
self.file,
pset=pset,
pset_template=template,
properties={
"foo": 12,
},
)
pset = element.IsDefinedBy[0].RelatingPropertyDefinition
assert pset.HasProperties[0].Name == "foo"
assert pset.HasProperties[0].NominalValue.is_a("IfcContextDependentMeasure")
assert pset.HasProperties[0].NominalValue.wrappedValue == 12