mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-01 17:36:27 +00:00
Fix get_property_unit() crash on IfcPropertySingleValue.NominalValue = None
NominalValue is optional -- IfcPropertySingleValue permits a null value --
but get_property_unit() unconditionally accessed prop.NominalValue.is_a(),
crashing on any single-value property that's legitimately blank.
Also adds a regression test confirming IfcContextDependentUnit symbols
("each", "boxes", etc.) aren't shadowed by the IfcDerivedUnit branch added
in the previous commit.
This commit is contained in:
@@ -525,7 +525,8 @@ def get_property_unit(
|
|||||||
entity = prop.wrapped_data.declaration().as_entity()
|
entity = prop.wrapped_data.declaration().as_entity()
|
||||||
measure_class = entity.attribute_by_index(3).type_of_attribute().declared_type().name()
|
measure_class = entity.attribute_by_index(3).type_of_attribute().declared_type().name()
|
||||||
elif prop.is_a("IfcPropertySingleValue"):
|
elif prop.is_a("IfcPropertySingleValue"):
|
||||||
measure_class = prop.NominalValue.is_a()
|
if value := prop.NominalValue:
|
||||||
|
measure_class = value.is_a()
|
||||||
elif prop.is_a("IfcPropertyEnumeratedValue"):
|
elif prop.is_a("IfcPropertyEnumeratedValue"):
|
||||||
if prop.EnumerationReference:
|
if prop.EnumerationReference:
|
||||||
if unit := prop.EnumerationReference.Unit:
|
if unit := prop.EnumerationReference.Unit:
|
||||||
|
|||||||
@@ -123,6 +123,12 @@ class TestGetPropertyUnit(test.bootstrap.IFC4):
|
|||||||
prop.Unit = length2
|
prop.Unit = length2
|
||||||
assert subject.get_property_unit(prop, self.file) == length2
|
assert subject.get_property_unit(prop, self.file) == length2
|
||||||
|
|
||||||
|
def test_single_value_with_no_nominal_value(self):
|
||||||
|
# NominalValue is optional -- a property may be null. Must not crash.
|
||||||
|
ifcopenshell.api.root.create_entity(self.file, ifc_class="IfcProject")
|
||||||
|
prop = self.file.createIfcPropertySingleValue(Name="Foo", NominalValue=None)
|
||||||
|
assert subject.get_property_unit(prop, self.file) is None
|
||||||
|
|
||||||
def test_enumerated_value(self):
|
def test_enumerated_value(self):
|
||||||
ifcopenshell.api.root.create_entity(self.file, ifc_class="IfcProject")
|
ifcopenshell.api.root.create_entity(self.file, ifc_class="IfcProject")
|
||||||
length = ifcopenshell.api.unit.add_si_unit(self.file, unit_type="LENGTHUNIT", prefix="MILLI")
|
length = ifcopenshell.api.unit.add_si_unit(self.file, unit_type="LENGTHUNIT", prefix="MILLI")
|
||||||
@@ -311,6 +317,13 @@ class TestGetUnitSymbol(test.bootstrap.IFC4):
|
|||||||
weird = ifcopenshell.api.unit.add_derived_unit(self.file, "USERDEFINED", "force per time", {force: 1, time: -1})
|
weird = ifcopenshell.api.unit.add_derived_unit(self.file, "USERDEFINED", "force per time", {force: 1, time: -1})
|
||||||
assert subject.get_unit_symbol(weird) == "N/s"
|
assert subject.get_unit_symbol(weird) == "N/s"
|
||||||
|
|
||||||
|
def test_context_dependent_userdefined_unit_is_not_shadowed_by_the_derived_unit_check(self):
|
||||||
|
# IfcContextDependentUnit (e.g. "each", "boxes") is a distinct entity
|
||||||
|
# from IfcDerivedUnit, so the is_a("IfcDerivedUnit") check added for
|
||||||
|
# derived-unit symbol composition must not shadow this fallback.
|
||||||
|
each = ifcopenshell.api.unit.add_context_dependent_unit(self.file, name="EACH")
|
||||||
|
assert subject.get_unit_symbol(each) == "EACH"
|
||||||
|
|
||||||
|
|
||||||
class TestIdentifyUnitDimensions(test.bootstrap.IFC4):
|
class TestIdentifyUnitDimensions(test.bootstrap.IFC4):
|
||||||
def test_matches_a_named_unit_type_by_dimension(self):
|
def test_matches_a_named_unit_type_by_dimension(self):
|
||||||
|
|||||||
Reference in New Issue
Block a user