mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-10 01:41:57 +00:00
Add tests for PR #5257 (using cache for fetching units)
This commit is contained in:
@@ -222,7 +222,7 @@ class file:
|
||||
"""
|
||||
|
||||
wrapped_data: ifcopenshell_wrapper.file
|
||||
units: dict[str: ifcopenshell.entity_instance] = None
|
||||
units: dict[str, entity_instance] = {}
|
||||
history_size: int = 64
|
||||
|
||||
def __init__(
|
||||
@@ -358,7 +358,6 @@ class file:
|
||||
:param args: The positional arguments of the IFC class
|
||||
:param kwargs: The keyword arguments of the IFC class
|
||||
:returns: An entity instance
|
||||
:rtype: ifcopenshell.entity_instance
|
||||
|
||||
Example:
|
||||
|
||||
|
||||
@@ -413,12 +413,24 @@ def get_unit_assignment(ifc_file: ifcopenshell.file) -> Union[ifcopenshell.entit
|
||||
|
||||
|
||||
def cache_units(ifc_file: ifcopenshell.file) -> None:
|
||||
"""Cache the default units for performance
|
||||
|
||||
Repetitively fetching project units (such as for determining the unit of a
|
||||
property) can be costly. This enables a cache to make it faster. If the
|
||||
project units change, you can update the cache by rerunning this function.
|
||||
|
||||
:param ifc_file: The IFC file.
|
||||
"""
|
||||
ifc_file.units = {}
|
||||
if assignment := get_unit_assignment(ifc_file):
|
||||
ifc_file.units = {u.UnitType: u for u in assignment.Units if getattr(u, "UnitType", None)}
|
||||
|
||||
|
||||
def clear_unit_cache(ifc_file: ifcopenshell.file) -> None:
|
||||
"""Clears the unit cache of the project
|
||||
|
||||
:param ifc_file: The IFC file.
|
||||
"""
|
||||
ifc_file.units = {}
|
||||
|
||||
|
||||
@@ -472,8 +484,11 @@ def get_property_unit(
|
||||
elif prop.is_a("IfcPropertySingleValue"):
|
||||
measure_class = prop.NominalValue.is_a()
|
||||
elif prop.is_a("IfcPropertyEnumeratedValue"):
|
||||
if unit := prop.EnumerationReference.Unit:
|
||||
return unit
|
||||
if prop.EnumerationReference:
|
||||
if unit := prop.EnumerationReference.Unit:
|
||||
return unit
|
||||
if value := next(iter(prop.EnumerationReference.EnumerationValues or ()), None):
|
||||
measure_class = value.is_a()
|
||||
if value := next(iter(prop.EnumerationValues or ()), None):
|
||||
measure_class = value.is_a()
|
||||
elif prop.is_a("IfcPropertyListValue"):
|
||||
@@ -484,7 +499,7 @@ def get_property_unit(
|
||||
measure_class = value.is_a()
|
||||
|
||||
if measure_class and (unit_type := get_measure_unit_type(measure_class)):
|
||||
return get_project_unit(ifc_file, unit_type)
|
||||
return get_project_unit(ifc_file, unit_type, use_cache=use_cache)
|
||||
|
||||
|
||||
def get_property_table_unit(
|
||||
@@ -513,14 +528,14 @@ def get_property_table_unit(
|
||||
defining_unit = unit
|
||||
elif value := next(iter(prop.DefiningValues or ()), None):
|
||||
if unit_type := get_measure_unit_type(value.is_a()):
|
||||
defining_unit = get_project_unit(ifc_file, unit_type)
|
||||
defining_unit = get_project_unit(ifc_file, unit_type, use_cache=use_cache)
|
||||
|
||||
defined_unit = None
|
||||
if unit := prop.DefinedUnit:
|
||||
defined_unit = unit
|
||||
elif value := next(iter(prop.DefinedValues or ()), None):
|
||||
if unit_type := get_measure_unit_type(value.is_a()):
|
||||
defining_unit = get_project_unit(ifc_file, unit_type)
|
||||
defining_unit = get_project_unit(ifc_file, unit_type, use_cache=use_cache)
|
||||
|
||||
return {
|
||||
"DefiningUnit": defining_unit,
|
||||
|
||||
@@ -25,6 +25,133 @@ import ifcopenshell.util.unit as subject
|
||||
from math import pi
|
||||
|
||||
|
||||
class TestCacheUnits(test.bootstrap.IFC4):
|
||||
def test_run(self):
|
||||
ifcopenshell.api.root.create_entity(self.file, ifc_class="IfcProject")
|
||||
length = ifcopenshell.api.unit.add_si_unit(self.file, unit_type="LENGTHUNIT", prefix="MILLI")
|
||||
area = ifcopenshell.api.unit.add_si_unit(self.file, unit_type="AREAUNIT")
|
||||
ifcopenshell.api.unit.assign_unit(self.file, units=[length, area])
|
||||
assert self.file.units == {}
|
||||
subject.cache_units(self.file)
|
||||
assert self.file.units == {"LENGTHUNIT": length, "AREAUNIT": area}
|
||||
|
||||
|
||||
class TestClearUnitCache(test.bootstrap.IFC4):
|
||||
def test_run(self):
|
||||
ifcopenshell.api.root.create_entity(self.file, ifc_class="IfcProject")
|
||||
length = ifcopenshell.api.unit.add_si_unit(self.file, unit_type="LENGTHUNIT", prefix="MILLI")
|
||||
area = ifcopenshell.api.unit.add_si_unit(self.file, unit_type="AREAUNIT")
|
||||
ifcopenshell.api.unit.assign_unit(self.file, units=[length, area])
|
||||
subject.cache_units(self.file)
|
||||
subject.clear_unit_cache(self.file)
|
||||
assert self.file.units == {}
|
||||
|
||||
|
||||
class TestGetProjectUnit(test.bootstrap.IFC4):
|
||||
def test_run(self):
|
||||
ifcopenshell.api.root.create_entity(self.file, ifc_class="IfcProject")
|
||||
length = ifcopenshell.api.unit.add_si_unit(self.file, unit_type="LENGTHUNIT", prefix="MILLI")
|
||||
area = ifcopenshell.api.unit.add_si_unit(self.file, unit_type="AREAUNIT")
|
||||
ifcopenshell.api.unit.assign_unit(self.file, units=[length, area])
|
||||
assert subject.get_project_unit(self.file, "LENGTHUNIT") == length
|
||||
assert subject.get_project_unit(self.file, "AREAUNIT") == area
|
||||
|
||||
def test_using_a_cache(self):
|
||||
ifcopenshell.api.root.create_entity(self.file, ifc_class="IfcProject")
|
||||
length = ifcopenshell.api.unit.add_si_unit(self.file, unit_type="LENGTHUNIT", prefix="MILLI")
|
||||
length2 = ifcopenshell.api.unit.add_si_unit(self.file, unit_type="LENGTHUNIT", prefix="CENTI")
|
||||
area = ifcopenshell.api.unit.add_si_unit(self.file, unit_type="AREAUNIT")
|
||||
ifcopenshell.api.unit.assign_unit(self.file, units=[length, area])
|
||||
assert self.file.units == {}
|
||||
assert subject.get_project_unit(self.file, "LENGTHUNIT", use_cache=True) == length
|
||||
assert self.file.units == {"LENGTHUNIT": length, "AREAUNIT": area}
|
||||
ifcopenshell.api.unit.assign_unit(self.file, units=[length2])
|
||||
assert subject.get_project_unit(self.file, "LENGTHUNIT", use_cache=True) == length
|
||||
subject.clear_unit_cache(self.file)
|
||||
assert subject.get_project_unit(self.file, "LENGTHUNIT", use_cache=True) == length2
|
||||
assert self.file.units == {"LENGTHUNIT": length2, "AREAUNIT": area}
|
||||
|
||||
|
||||
class TestGetPropertyUnit(test.bootstrap.IFC4):
|
||||
def test_no_unit(self):
|
||||
ifcopenshell.api.root.create_entity(self.file, ifc_class="IfcProject")
|
||||
prop = self.file.createIfcQuantityLength(Name="Foo", LengthValue=42.0)
|
||||
assert subject.get_property_unit(prop, self.file) is None
|
||||
|
||||
def test_simple_quantity(self):
|
||||
ifcopenshell.api.root.create_entity(self.file, ifc_class="IfcProject")
|
||||
length = ifcopenshell.api.unit.add_si_unit(self.file, unit_type="LENGTHUNIT", prefix="MILLI")
|
||||
length2 = ifcopenshell.api.unit.add_si_unit(self.file, unit_type="LENGTHUNIT", prefix="CENTI")
|
||||
area = ifcopenshell.api.unit.add_si_unit(self.file, unit_type="AREAUNIT")
|
||||
ifcopenshell.api.unit.assign_unit(self.file, units=[length, area])
|
||||
prop = self.file.createIfcQuantityLength(Name="Foo", LengthValue=42.0)
|
||||
assert subject.get_property_unit(prop, self.file) == length
|
||||
prop.Unit = length2
|
||||
assert subject.get_property_unit(prop, self.file) == length2
|
||||
|
||||
def test_single_value(self):
|
||||
ifcopenshell.api.root.create_entity(self.file, ifc_class="IfcProject")
|
||||
length = ifcopenshell.api.unit.add_si_unit(self.file, unit_type="LENGTHUNIT", prefix="MILLI")
|
||||
length2 = ifcopenshell.api.unit.add_si_unit(self.file, unit_type="LENGTHUNIT", prefix="CENTI")
|
||||
area = ifcopenshell.api.unit.add_si_unit(self.file, unit_type="AREAUNIT")
|
||||
ifcopenshell.api.unit.assign_unit(self.file, units=[length, area])
|
||||
prop = self.file.createIfcPropertySingleValue(Name="Foo", NominalValue=self.file.createIfcLengthMeasure(42.0))
|
||||
assert subject.get_property_unit(prop, self.file) == length
|
||||
prop.Unit = length2
|
||||
assert subject.get_property_unit(prop, self.file) == length2
|
||||
|
||||
def test_enumerated_value(self):
|
||||
ifcopenshell.api.root.create_entity(self.file, ifc_class="IfcProject")
|
||||
length = ifcopenshell.api.unit.add_si_unit(self.file, unit_type="LENGTHUNIT", prefix="MILLI")
|
||||
length2 = ifcopenshell.api.unit.add_si_unit(self.file, unit_type="LENGTHUNIT", prefix="CENTI")
|
||||
area = ifcopenshell.api.unit.add_si_unit(self.file, unit_type="AREAUNIT")
|
||||
ifcopenshell.api.unit.assign_unit(self.file, units=[length, area])
|
||||
prop = self.file.createIfcPropertyEnumeratedValue(Name="Foo", EnumerationValues=[self.file.createIfcLengthMeasure(42.0)])
|
||||
assert subject.get_property_unit(prop, self.file) == length
|
||||
prop.EnumerationValues = []
|
||||
prop.EnumerationReference = self.file.createIfcPropertyEnumeration("Foo", [self.file.createIfcAreaMeasure(42.0)])
|
||||
assert subject.get_property_unit(prop, self.file) == area
|
||||
prop.EnumerationReference = self.file.createIfcPropertyEnumeration("Foo", [self.file.createIfcAreaMeasure(42.0)], Unit=length2)
|
||||
assert subject.get_property_unit(prop, self.file) == length2
|
||||
prop.EnumerationValues = [self.file.createIfcAreaMeasure(42.0)]
|
||||
assert subject.get_property_unit(prop, self.file) == length2
|
||||
prop.EnumerationReference.Unit = None
|
||||
assert subject.get_property_unit(prop, self.file) == area
|
||||
|
||||
def test_list_value(self):
|
||||
ifcopenshell.api.root.create_entity(self.file, ifc_class="IfcProject")
|
||||
length = ifcopenshell.api.unit.add_si_unit(self.file, unit_type="LENGTHUNIT", prefix="MILLI")
|
||||
length2 = ifcopenshell.api.unit.add_si_unit(self.file, unit_type="LENGTHUNIT", prefix="CENTI")
|
||||
area = ifcopenshell.api.unit.add_si_unit(self.file, unit_type="AREAUNIT")
|
||||
ifcopenshell.api.unit.assign_unit(self.file, units=[length, area])
|
||||
prop = self.file.createIfcPropertyListValue(Name="Foo", ListValues=[self.file.createIfcLengthMeasure(42.0)])
|
||||
assert subject.get_property_unit(prop, self.file) == length
|
||||
prop.Unit = length2
|
||||
assert subject.get_property_unit(prop, self.file) == length2
|
||||
prop.Unit = None
|
||||
prop.ListValues = []
|
||||
assert subject.get_property_unit(prop, self.file) is None
|
||||
|
||||
def test_bounded_value(self):
|
||||
ifcopenshell.api.root.create_entity(self.file, ifc_class="IfcProject")
|
||||
length = ifcopenshell.api.unit.add_si_unit(self.file, unit_type="LENGTHUNIT", prefix="MILLI")
|
||||
length2 = ifcopenshell.api.unit.add_si_unit(self.file, unit_type="LENGTHUNIT", prefix="CENTI")
|
||||
area = ifcopenshell.api.unit.add_si_unit(self.file, unit_type="AREAUNIT")
|
||||
ifcopenshell.api.unit.assign_unit(self.file, units=[length, area])
|
||||
prop = self.file.createIfcPropertyBoundedValue(Name="Foo")
|
||||
assert subject.get_property_unit(prop, self.file) is None
|
||||
prop.UpperBoundValue = self.file.createIfcLengthMeasure(42.0)
|
||||
assert subject.get_property_unit(prop, self.file) == length
|
||||
prop.UpperBoundValue = None
|
||||
prop.LowerBoundValue = self.file.createIfcLengthMeasure(42.0)
|
||||
assert subject.get_property_unit(prop, self.file) == length
|
||||
prop.LowerBoundValue = None
|
||||
prop.SetPointValue = self.file.createIfcLengthMeasure(42.0)
|
||||
assert subject.get_property_unit(prop, self.file) == length
|
||||
prop.Unit = length2
|
||||
assert subject.get_property_unit(prop, self.file) == length2
|
||||
|
||||
|
||||
class TestConvert(test.bootstrap.IFC4):
|
||||
def test_run(self):
|
||||
assert subject.convert(1, None, "METRE", None, "METRE") == 1
|
||||
|
||||
Reference in New Issue
Block a user