mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-18 11:20:21 +00:00
130 lines
3.9 KiB
Python
130 lines
3.9 KiB
Python
import json
|
|
from typing import Literal, Optional, Union
|
|
|
|
import ifcopenshell
|
|
import pytest
|
|
|
|
from ifcedit.coerce import coerce_value
|
|
|
|
|
|
class TestStringCoercion:
|
|
def test_plain_string(self):
|
|
assert coerce_value("hello", str) == "hello"
|
|
|
|
def test_empty_string(self):
|
|
assert coerce_value("", str) == ""
|
|
|
|
|
|
class TestIntCoercion:
|
|
def test_plain_int(self):
|
|
assert coerce_value("42", int) == 42
|
|
|
|
def test_hash_prefix(self):
|
|
assert coerce_value("#42", int) == 42
|
|
|
|
def test_negative(self):
|
|
assert coerce_value("-5", int) == -5
|
|
|
|
|
|
class TestFloatCoercion:
|
|
def test_plain_float(self):
|
|
assert coerce_value("3.14", float) == pytest.approx(3.14)
|
|
|
|
def test_integer_as_float(self):
|
|
assert coerce_value("5", float) == 5.0
|
|
|
|
|
|
class TestBoolCoercion:
|
|
def test_true_values(self):
|
|
for val in ("true", "True", "TRUE", "1", "yes"):
|
|
assert coerce_value(val, bool) is True
|
|
|
|
def test_false_values(self):
|
|
for val in ("false", "False", "0", "no"):
|
|
assert coerce_value(val, bool) is False
|
|
|
|
|
|
class TestOptionalCoercion:
|
|
def test_optional_string(self):
|
|
assert coerce_value("hello", Optional[str]) == "hello"
|
|
|
|
def test_optional_none(self):
|
|
assert coerce_value("none", Optional[str]) is None
|
|
assert coerce_value("None", Optional[str]) is None
|
|
|
|
def test_optional_int(self):
|
|
assert coerce_value("42", Optional[int]) == 42
|
|
|
|
|
|
class TestUnionCoercion:
|
|
def test_union_str_int(self):
|
|
# Tries str first (or int first depending on order), both work
|
|
result = coerce_value("hello", Union[str, int])
|
|
assert result == "hello"
|
|
|
|
def test_union_int_none(self):
|
|
result = coerce_value("42", Union[int, None])
|
|
assert result == 42
|
|
|
|
|
|
class TestLiteralCoercion:
|
|
def test_valid_literal(self):
|
|
assert coerce_value("IFC4", Literal["IFC2X3", "IFC4", "IFC4X3"]) == "IFC4"
|
|
|
|
def test_invalid_literal(self):
|
|
with pytest.raises(ValueError, match="not one of"):
|
|
coerce_value("IFC5", Literal["IFC2X3", "IFC4", "IFC4X3"])
|
|
|
|
|
|
class TestDictCoercion:
|
|
def test_json_dict(self):
|
|
result = coerce_value('{"IsExternal": true, "FireRating": "2HR"}', dict[str, object])
|
|
assert result == {"IsExternal": True, "FireRating": "2HR"}
|
|
|
|
|
|
class TestListCoercion:
|
|
def test_comma_separated(self):
|
|
result = coerce_value("a,b,c", list[str])
|
|
assert result == ["a", "b", "c"]
|
|
|
|
def test_json_array(self):
|
|
result = coerce_value("[1, 2, 3]", list[int])
|
|
assert result == [1, 2, 3]
|
|
|
|
|
|
class TestEntityCoercion:
|
|
def test_entity_by_id(self, model):
|
|
wall = model.by_type("IfcWall")[0]
|
|
result = coerce_value(str(wall.id()), ifcopenshell.entity_instance, model)
|
|
assert result == wall
|
|
|
|
def test_entity_with_hash(self, model):
|
|
wall = model.by_type("IfcWall")[0]
|
|
result = coerce_value(f"#{wall.id()}", ifcopenshell.entity_instance, model)
|
|
assert result == wall
|
|
|
|
def test_entity_not_found(self, model):
|
|
with pytest.raises(ValueError, match="not found"):
|
|
coerce_value("999999", ifcopenshell.entity_instance, model)
|
|
|
|
def test_entity_list(self, model):
|
|
wall = model.by_type("IfcWall")[0]
|
|
result = coerce_value(str(wall.id()), list[ifcopenshell.entity_instance], model)
|
|
assert len(result) == 1
|
|
assert result[0] == wall
|
|
|
|
def test_entity_list_multiple(self, model):
|
|
wall = model.by_type("IfcWall")[0]
|
|
storey = model.by_type("IfcBuildingStorey")[0]
|
|
result = coerce_value(f"{wall.id()},{storey.id()}", list[ifcopenshell.entity_instance], model)
|
|
assert len(result) == 2
|
|
|
|
def test_entity_no_model(self):
|
|
with pytest.raises(ValueError, match="without an IFC model"):
|
|
coerce_value("42", ifcopenshell.entity_instance, None)
|
|
|
|
|
|
class TestFallback:
|
|
def test_no_type_hint(self):
|
|
assert coerce_value("hello", None) == "hello"
|