Updated with core developer feedback: fixed for Tonne and added tests

This commit is contained in:
falken10vdl
2025-09-05 20:22:56 +02:00
parent 146301b0c0
commit a4e76ed6ee
7 changed files with 535 additions and 8 deletions
@@ -32,7 +32,7 @@ def add_conversion_based_unit(
function. You can choose from one of: inch, foot, yard, mile, square
inch, square foot, square yard, acre, square mile, cubic inch, cubic
foot, cubic yard, litre, fluid ounce UK, fluid ounce US, pint UK, pint
US, gallon UK, gallon US, degree, ounce, pound, ton UK, ton US, lbf,
US, gallon UK, gallon US, degree, ounce, pound, ton UK, ton US, tonne, lbf,
kip, psi, ksi, minute, hour, day, btu, and fahrenheit.
:param name: A converted name chosen from the list above.
@@ -209,6 +209,7 @@ si_conversions = {
"pound": 0.454,
"ton UK": 1016.0469088,
"ton US": 907.18474,
"tonne": 1000.0,
"lbf": 4.4482216153,
"kip": 4448.2216153,
"psi": 6894.7572932,
@@ -253,6 +254,7 @@ imperial_types = {
"pound": "MASSUNIT",
"ton UK": "MASSUNIT",
"ton US": "MASSUNIT",
"tonne": "MASSUNIT",
"lbf": "FORCEUNIT",
"kip": "FORCEUNIT",
"psi": "PRESSUREUNIT",
@@ -323,6 +325,7 @@ unit_symbols = {
"pound": "lb",
"ton UK": "ton",
"ton US": "ton",
"tonne": "t",
"lbf": "lbf",
"kip": "kip",
"psi": "psi",
@@ -391,3 +391,233 @@ class TestConvertFileLengthUnitsIFC4(test.bootstrap.IFC4, TestConvertFileLengthU
class TestConvertFileLengthUnitsIFC4X3(test.bootstrap.IFC4X3, TestConvertFileLengthUnits):
pass
class TestAddConversionBasedUnitMassAndTime(test.bootstrap.IFC4):
def test_adding_mass_units_creates_proper_massunit(self):
mass_units = [
("tonne", 1000.0),
("pound", 0.454),
("ounce", 0.02835),
("ton UK", 1016.0469088),
("ton US", 907.18474),
]
for name, expected_conversion in mass_units:
unit = ifcopenshell.api.unit.add_conversion_based_unit(self.file, name=name)
assert unit.is_a("IfcConversionBasedUnit")
assert unit.UnitType == "MASSUNIT"
assert unit.Name == name
actual_conversion = unit.ConversionFactor.ValueComponent.wrappedValue
assert actual_conversion == expected_conversion
target_unit = unit.ConversionFactor.UnitComponent
assert target_unit.is_a("IfcSIUnit")
assert target_unit.UnitType == "MASSUNIT"
assert target_unit.Name == "GRAM"
assert target_unit.Prefix == "KILO"
def test_adding_time_units_creates_proper_timeunit(self):
time_units = [
("minute", 60),
("hour", 3600),
("day", 86400),
]
for name, expected_conversion in time_units:
unit = ifcopenshell.api.unit.add_conversion_based_unit(self.file, name=name)
assert unit.is_a("IfcConversionBasedUnit")
assert unit.UnitType == "TIMEUNIT"
assert unit.Name == name
actual_conversion = unit.ConversionFactor.ValueComponent.wrappedValue
assert actual_conversion == expected_conversion
target_unit = unit.ConversionFactor.UnitComponent
assert target_unit.is_a("IfcSIUnit")
assert target_unit.UnitType == "TIMEUNIT"
assert target_unit.Name == "SECOND"
assert target_unit.Prefix is None
def test_mass_unit_integration_with_project(self):
ifcopenshell.api.root.create_entity(self.file, ifc_class="IfcProject")
kg_unit = ifcopenshell.api.unit.add_si_unit(self.file, unit_type="MASSUNIT", prefix="KILO")
tonne_unit = ifcopenshell.api.unit.add_conversion_based_unit(self.file, name="tonne")
pound_unit = ifcopenshell.api.unit.add_conversion_based_unit(self.file, name="pound")
ifcopenshell.api.unit.assign_unit(self.file, units=[kg_unit])
project_mass_unit = subject.get_project_unit(self.file, "MASSUNIT")
assert project_mass_unit == kg_unit
unit_assignment = subject.get_unit_assignment(self.file)
assert unit_assignment
assigned_units = list(unit_assignment.Units or [])
assert kg_unit in assigned_units
ifcopenshell.api.unit.assign_unit(self.file, units=[tonne_unit])
project_mass_unit = subject.get_project_unit(self.file, "MASSUNIT")
assert project_mass_unit == tonne_unit
unit_assignment = subject.get_unit_assignment(self.file)
assigned_units = list(unit_assignment.Units or [])
assert tonne_unit in assigned_units
length_unit = ifcopenshell.api.unit.add_si_unit(self.file, unit_type="LENGTHUNIT")
ifcopenshell.api.unit.assign_unit(self.file, units=[pound_unit, length_unit])
unit_assignment = subject.get_unit_assignment(self.file)
assigned_units = list(unit_assignment.Units or [])
assert pound_unit in assigned_units
assert length_unit in assigned_units
def test_time_unit_integration_with_project(self):
ifcopenshell.api.root.create_entity(self.file, ifc_class="IfcProject")
second_unit = ifcopenshell.api.unit.add_si_unit(self.file, unit_type="TIMEUNIT")
minute_unit = ifcopenshell.api.unit.add_conversion_based_unit(self.file, name="minute")
hour_unit = ifcopenshell.api.unit.add_conversion_based_unit(self.file, name="hour")
ifcopenshell.api.unit.assign_unit(self.file, units=[second_unit])
project_time_unit = subject.get_project_unit(self.file, "TIMEUNIT")
assert project_time_unit == second_unit
unit_assignment = subject.get_unit_assignment(self.file)
assert unit_assignment
assigned_units = list(unit_assignment.Units or [])
assert second_unit in assigned_units
ifcopenshell.api.unit.assign_unit(self.file, units=[minute_unit])
project_time_unit = subject.get_project_unit(self.file, "TIMEUNIT")
assert project_time_unit == minute_unit
unit_assignment = subject.get_unit_assignment(self.file)
assigned_units = list(unit_assignment.Units or [])
assert minute_unit in assigned_units
length_unit = ifcopenshell.api.unit.add_si_unit(self.file, unit_type="LENGTHUNIT")
ifcopenshell.api.unit.assign_unit(self.file, units=[hour_unit, length_unit])
unit_assignment = subject.get_unit_assignment(self.file)
assigned_units = list(unit_assignment.Units or [])
assert hour_unit in assigned_units
assert length_unit in assigned_units
def test_multiple_unit_types_can_coexist(self):
ifcopenshell.api.root.create_entity(self.file, ifc_class="IfcProject")
kg_unit = ifcopenshell.api.unit.add_si_unit(self.file, unit_type="MASSUNIT", prefix="KILO")
minute_unit = ifcopenshell.api.unit.add_conversion_based_unit(self.file, name="minute")
meter_unit = ifcopenshell.api.unit.add_si_unit(self.file, unit_type="LENGTHUNIT")
ifcopenshell.api.unit.assign_unit(self.file, units=[kg_unit, minute_unit, meter_unit])
unit_assignment = subject.get_unit_assignment(self.file)
assigned_units = list(unit_assignment.Units or [])
assert kg_unit in assigned_units
assert minute_unit in assigned_units
assert meter_unit in assigned_units
assert subject.get_project_unit(self.file, "MASSUNIT") == kg_unit
assert subject.get_project_unit(self.file, "TIMEUNIT") == minute_unit
assert subject.get_project_unit(self.file, "LENGTHUNIT") == meter_unit
def test_unknown_mass_or_time_units_fall_back_to_userdefined(self):
unknown_mass_unit = ifcopenshell.api.unit.add_conversion_based_unit(self.file, name="unknown_mass_unit")
assert unknown_mass_unit.UnitType == "USERDEFINED"
unknown_time_unit = ifcopenshell.api.unit.add_conversion_based_unit(self.file, name="unknown_time_unit")
assert unknown_time_unit.UnitType == "USERDEFINED"
def test_mass_units_individually(self):
tonne_unit = ifcopenshell.api.unit.add_conversion_based_unit(self.file, name="tonne")
assert tonne_unit.UnitType == "MASSUNIT"
assert tonne_unit.ConversionFactor.ValueComponent.wrappedValue == 1000.0
pound_unit = ifcopenshell.api.unit.add_conversion_based_unit(self.file, name="pound")
assert pound_unit.UnitType == "MASSUNIT"
assert pound_unit.ConversionFactor.ValueComponent.wrappedValue == 0.454
ounce_unit = ifcopenshell.api.unit.add_conversion_based_unit(self.file, name="ounce")
assert ounce_unit.UnitType == "MASSUNIT"
assert ounce_unit.ConversionFactor.ValueComponent.wrappedValue == 0.02835
def test_time_units_individually(self):
minute_unit = ifcopenshell.api.unit.add_conversion_based_unit(self.file, name="minute")
assert minute_unit.UnitType == "TIMEUNIT"
assert minute_unit.ConversionFactor.ValueComponent.wrappedValue == 60
hour_unit = ifcopenshell.api.unit.add_conversion_based_unit(self.file, name="hour")
assert hour_unit.UnitType == "TIMEUNIT"
assert hour_unit.ConversionFactor.ValueComponent.wrappedValue == 3600
day_unit = ifcopenshell.api.unit.add_conversion_based_unit(self.file, name="day")
assert day_unit.UnitType == "TIMEUNIT"
assert day_unit.ConversionFactor.ValueComponent.wrappedValue == 86400
class TestMassAndTimeUnitDictionaries(test.bootstrap.IFC4):
def test_mass_units_in_imperial_types(self):
expected_mass_units = ["ounce", "pound", "ton UK", "ton US", "tonne"]
def test_mass_units_in_imperial_types(self):
expected_mass_units = ["ounce", "pound", "ton UK", "ton US", "tonne"]
for unit_name in expected_mass_units:
assert unit_name in subject.imperial_types
assert subject.imperial_types[unit_name] == "MASSUNIT"
def test_time_units_in_imperial_types(self):
expected_time_units = ["minute", "hour", "day"]
for unit_name in expected_time_units:
assert unit_name in subject.imperial_types
assert subject.imperial_types[unit_name] == "TIMEUNIT"
def test_mass_units_have_conversion_factors(self):
expected_mass_conversions = {
"ounce": 0.02835,
"pound": 0.454,
"ton UK": 1016.0469088,
"ton US": 907.18474,
"tonne": 1000.0,
}
for unit_name, expected_factor in expected_mass_conversions.items():
assert unit_name in subject.si_conversions
assert subject.si_conversions[unit_name] == expected_factor
def test_time_units_have_conversion_factors(self):
expected_time_conversions = {
"minute": 60,
"hour": 3600,
"day": 86400,
}
for unit_name, expected_factor in expected_time_conversions.items():
assert unit_name in subject.si_conversions
assert subject.si_conversions[unit_name] == expected_factor
def test_mass_and_time_units_have_symbols(self):
expected_symbols = {
"ounce": "oz",
"pound": "lb",
"ton UK": "ton",
"ton US": "ton",
"tonne": "t",
"minute": "min",
"hour": "hr",
"day": "day",
}
for unit_name, expected_symbol in expected_symbols.items():
assert unit_name in subject.unit_symbols
assert subject.unit_symbols[unit_name] == expected_symbol