a6b19025e6
These are helpful to iterate over chunked lists of encoded geometry objects and decode them into base objects (and vice versa)
127 lines
3.2 KiB
Python
127 lines
3.2 KiB
Python
from contextlib import ExitStack as does_not_raise
|
|
from typing import Dict, List
|
|
|
|
import pytest
|
|
from specklepy.api import operations
|
|
from specklepy.logging.exceptions import SpeckleException
|
|
from specklepy.objects.base import Base, DataChunk
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"invalid_prop_name",
|
|
[
|
|
(""),
|
|
("@"),
|
|
("@@wow"),
|
|
("this.is.bad"),
|
|
("super/bad"),
|
|
],
|
|
)
|
|
def test_empty_prop_names(invalid_prop_name: str) -> None:
|
|
base = Base()
|
|
with pytest.raises(ValueError):
|
|
base[invalid_prop_name] = "🐛️"
|
|
|
|
|
|
class FakeModel(Base):
|
|
"""Just a test class type."""
|
|
|
|
foo: str = ""
|
|
|
|
|
|
def test_new_type_registration() -> None:
|
|
"""Test if a new subclass is registered into the type register."""
|
|
assert Base.get_registered_type("FakeModel") == FakeModel
|
|
assert Base.get_registered_type("🐺️") is None
|
|
|
|
|
|
def test_fake_base_serialization() -> None:
|
|
fake_model = FakeModel(foo="bar")
|
|
|
|
serialized = operations.serialize(fake_model)
|
|
deserialized = operations.deserialize(serialized)
|
|
|
|
assert fake_model.get_id() == deserialized.get_id()
|
|
|
|
|
|
def test_duplicate_speckle_type_raises_error():
|
|
with pytest.raises(ValueError):
|
|
|
|
class NaughtyClass(Base, speckle_type="Base"):
|
|
"""This class has a speckle_type that is already taken."""
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"forbidden_attribute_name, expectation",
|
|
[
|
|
("", pytest.raises(ValueError)),
|
|
("@", pytest.raises(ValueError)),
|
|
("@@", pytest.raises(ValueError)),
|
|
("im.cheeky", pytest.raises(ValueError)),
|
|
("im.cheeky", pytest.raises(ValueError)),
|
|
("imgood", does_not_raise()),
|
|
],
|
|
)
|
|
def test_attribute_name_validation(
|
|
forbidden_attribute_name: str,
|
|
expectation,
|
|
base: Base,
|
|
):
|
|
with expectation:
|
|
base[forbidden_attribute_name] = None
|
|
|
|
|
|
def test_speckle_type_cannot_be_set(base: Base) -> None:
|
|
assert base.speckle_type == "Base"
|
|
base.speckle_type = "unset"
|
|
assert base.speckle_type == "Base"
|
|
|
|
|
|
def test_base_of_custom_speckle_type() -> None:
|
|
b1 = Base.of_type("BirdHouse", name="Tweety's Crib")
|
|
assert b1.speckle_type == "BirdHouse"
|
|
assert b1.name == "Tweety's Crib"
|
|
|
|
|
|
class FrozenYoghurt(Base):
|
|
"""Testing type checking"""
|
|
|
|
servings: int
|
|
flavours: List[str] = None # list item types won't be checked
|
|
customer: str
|
|
add_ons: Dict[str, float] # dict item types won't be checked
|
|
price: float = 0.0
|
|
|
|
|
|
def test_type_checking() -> None:
|
|
order = FrozenYoghurt()
|
|
|
|
order.servings = 2
|
|
order.price = "7" # will get converted
|
|
order.customer = "izzy"
|
|
|
|
with pytest.raises(SpeckleException):
|
|
order.flavours = "not a list"
|
|
with pytest.raises(SpeckleException):
|
|
order.servings = "five"
|
|
with pytest.raises(SpeckleException):
|
|
order.add_ons = ["sprinkles"]
|
|
|
|
order.add_ons = {"sprinkles": 0.2, "chocolate": 1.0}
|
|
order.flavours = ["strawberry", "lychee", "peach", "pineapple"]
|
|
|
|
assert order.price == 7.0
|
|
|
|
|
|
def test_data_chunk_decoder():
|
|
chunk = DataChunk()
|
|
chunk.data = [
|
|
5, 1, 1, 1, 1, 1,
|
|
4, 1, 1, 1, 1,
|
|
3, 1, 1, 1,
|
|
2, 1, 1,
|
|
1, 1
|
|
]
|
|
|
|
assert chunk.decode(decoder=sum) == [5, 4, 3, 2, 1]
|