Compare commits

..

6 Commits

Author SHA1 Message Date
izzy lyseggen f7ae62ade2 Merge pull request #149 from specklesystems/izzy/null-units-hotfix
fix(units): warn and don't set for invalid args
2021-12-22 09:07:40 +00:00
izzy lyseggen 38ffbc27b7 test(units): goddamnit codecov 2021-12-22 09:06:28 +00:00
izzy lyseggen 8cebccf250 fix(units): warn and don't set for invalid args 2021-12-22 09:00:39 +00:00
izzy lyseggen 17aac0b552 Merge pull request #148 from specklesystems/izzy/allow-nulls
feat(serialisation): allow null values
2021-12-16 16:59:51 +00:00
izzy lyseggen c281a329a4 fix(serialisation): nulls & things ^^ 2021-12-16 16:57:36 +00:00
izzy lyseggen ca472716db feat(serialisation): allow null values 2021-12-16 16:41:09 +00:00
6 changed files with 35 additions and 34 deletions
+6 -1
View File
@@ -252,6 +252,9 @@ class Base(_RegisteringBase):
if t is None: if t is None:
return value return value
if value is None:
return None
if t.__module__ == "typing": if t.__module__ == "typing":
origin = getattr(t, "__origin__") origin = getattr(t, "__origin__")
t = ( t = (
@@ -310,7 +313,9 @@ class Base(_RegisteringBase):
@units.setter @units.setter
def units(self, value: str): def units(self, value: str):
self._units = get_units_from_string(value) units = get_units_from_string(value)
if units:
self._units = units
def get_member_names(self) -> List[str]: def get_member_names(self) -> List[str]:
"""Get all of the property names on this object, dynamic or not""" """Get all of the property names on this object, dynamic or not"""
-9
View File
@@ -391,15 +391,6 @@ class Mesh(
area: float = None area: float = None
volume: float = None volume: float = None
def transform_to(self, transform: "Transform") -> "Mesh":
mesh = Mesh(vertices=transform.apply_to_points_values(self.vertices))
for attr in set(self.get_serializable_attributes()) - {"vertices"}:
orig_val = getattr(self, attr, None)
if orig_val:
setattr(mesh, attr, orig_val)
return mesh
class Surface(Base, speckle_type=GEOMETRY + "Surface"): class Surface(Base, speckle_type=GEOMETRY + "Surface"):
degreeU: int = None degreeU: int = None
+8 -1
View File
@@ -1,4 +1,5 @@
from specklepy.logging.exceptions import SpeckleException from warnings import warn
from specklepy.logging.exceptions import SpeckleException, SpeckleWarning
UNITS = ["mm", "cm", "m", "in", "ft", "yd", "mi"] UNITS = ["mm", "cm", "m", "in", "ft", "yd", "mi"]
@@ -28,6 +29,12 @@ UNITS_ENCODINGS = {
def get_units_from_string(unit: str): def get_units_from_string(unit: str):
if not isinstance(unit, str):
warn(
f"Invalid units: expected type str but received {type(unit)} ({unit}). Skipping - no units will be set.",
SpeckleWarning,
)
return
unit = str.lower(unit) unit = str.lower(unit)
for name, alternates in UNITS_STRINGS.items(): for name, alternates in UNITS_STRINGS.items():
if unit in alternates: if unit in alternates:
@@ -60,14 +60,19 @@ class BaseObjectSerializer:
chunkable = False chunkable = False
detach = False detach = False
# skip nulls or props marked to be ignored with "__" or "_" # skip props marked to be ignored with "__" or "_"
if value is None or prop.startswith(("__", "_")): if prop.startswith(("__", "_")):
continue continue
# don't prepopulate id as this will mess up hashing # don't prepopulate id as this will mess up hashing
if prop == "id": if prop == "id":
continue continue
# allow serialisation of nulls
if value is None:
object_builder[prop] = value
continue
# only bother with chunking and detaching if there is a write transport # only bother with chunking and detaching if there is a write transport
if self.write_transports: if self.write_transports:
dynamic_chunk_match = prop.startswith("@") and re.match( dynamic_chunk_match = prop.startswith("@") and re.match(
+12
View File
@@ -77,6 +77,18 @@ def test_speckle_type_cannot_be_set(base: Base) -> None:
assert base.speckle_type == "Base" assert base.speckle_type == "Base"
def test_setting_units():
b = Base(units="foot")
assert b.units == "ft"
with pytest.raises(SpeckleException):
b.units = "big"
b.units = None # invalid args are skipped
b.units = 7
assert b.units == "ft"
def test_base_of_custom_speckle_type() -> None: def test_base_of_custom_speckle_type() -> None:
b1 = Base.of_type("BirdHouse", name="Tweety's Crib") b1 = Base.of_type("BirdHouse", name="Tweety's Crib")
assert b1.speckle_type == "BirdHouse" assert b1.speckle_type == "BirdHouse"
+2 -21
View File
@@ -1,7 +1,7 @@
from typing import List from typing import List
import pytest import pytest
from specklepy.api import operations from specklepy.api import operations
from specklepy.objects.geometry import Mesh, Point, Vector from specklepy.objects.geometry import Point, Vector
from specklepy.objects.other import ( from specklepy.objects.other import (
Transform, Transform,
BlockInstance, BlockInstance,
@@ -43,15 +43,6 @@ def vector_value():
return [1, 1, 2] return [1, 1, 2]
@pytest.fixture()
def mesh():
return Mesh(
vertices=[-7, 5, 1, -8, 4, 0, -7, 3, 0, -6, 4, 0],
faces=[1, 1, 2, 3, 0],
units="feet",
)
@pytest.fixture() @pytest.fixture()
def transform(): def transform():
"""Translates to [1, 2, 0] and scales z by 0.5""" """Translates to [1, 2, 0] and scales z by 0.5"""
@@ -138,14 +129,4 @@ def test_transform_serialisation(transform: Transform):
serialized = operations.serialize(transform) serialized = operations.serialize(transform)
deserialized = operations.deserialize(serialized) deserialized = operations.deserialize(serialized)
assert transform.get_id() == deserialized.get_id() assert transform.get_id() == deserialized.get_id()
def test_mesh_transform(mesh: Mesh, transform: Transform):
new_mesh = mesh.transform_to(transform)
assert mesh.vertices != new_mesh.vertices
new_mesh.vertices = mesh.vertices
assert mesh.get_id() == new_mesh.get_id()