fix(serialisation): EMBARASSING BUG

so i'm a bit of a dumbo here.
i didn't realise that doing `.update()` on attr would update the parent
attr as well and extend to all objects every ahhhhhh

you have to do `self.thing = self.thing + blah blah` to just update
the instance attr. the more ya know!

#roastme @cristi8
This commit is contained in:
izzy lyseggen
2021-03-18 18:45:24 +00:00
parent d5b506f298
commit 614eefc393
5 changed files with 30 additions and 25 deletions
+2 -2
View File
@@ -1,7 +1,7 @@
from inspect import getattr_static
from pydantic import BaseModel, validator
from pydantic.main import Extra
from typing import ClassVar, Dict, List, Optional, Any, Type
from typing import ClassVar, Dict, List, Optional, Any, Set, Type
from speckle.transports.memory import MemoryTransport
from speckle.logging.exceptions import SpeckleException
from speckle.objects.units import get_units_from_string
@@ -61,7 +61,7 @@ class Base(_RegisteringBase):
_units: str = "m"
_chunkable: Dict[str, int] = {} # dict of chunkable props and their max chunk size
_chunk_size_default: int = 1000
_detachable: List[str] = [] # list of defined detachable props
_detachable: Set[str] = set() # list of defined detachable props
def __repr__(self) -> str:
return (
+4 -4
View File
@@ -11,7 +11,7 @@ CHUNKABLE_PROPS = {
"test_bases": 10,
}
DETACHABLE = ["detach_this", "origin", "detached_list"]
DETACHABLE = {"detach_this", "origin", "detached_list"}
class FakeMesh(Base):
@@ -25,9 +25,9 @@ class FakeMesh(Base):
_origin: Point = None
def __init__(self, **kwargs) -> None:
super().__init__(**kwargs)
self._chunkable.update(CHUNKABLE_PROPS)
self._detachable.extend(DETACHABLE)
super(FakeMesh, self).__init__(**kwargs)
self._chunkable = dict(self._chunkable, **CHUNKABLE_PROPS)
self._detachable = self._detachable.union(DETACHABLE)
@property
def origin(self):
+15 -13
View File
@@ -102,7 +102,7 @@ class Polyline(Base, speckle_type=GEOMETRY + "Polyline"):
def __init__(self, **data: Any) -> None:
super().__init__(**data)
self._chunkable.update({"value": 20000})
self._chunkable = dict(self._chunkable, value=20000)
@classmethod
def from_points(cls, points: List[Point]):
@@ -150,7 +150,9 @@ class Curve(Base, speckle_type=GEOMETRY + "Curve"):
def __init__(self, **data: Any) -> None:
super().__init__(**data)
self._chunkable.update({"points": 20000, "weights": 20000, "knots": 20000})
self._chunkable = dict(
self._chunkable, points=20000, weights=20000, knots=20000
)
def as_points(self) -> List[Point]:
"""Converts the `value` attribute to a list of Points"""
@@ -198,13 +200,12 @@ class Mesh(Base, speckle_type=GEOMETRY + "Mesh"):
def __init__(self, **data) -> None:
super().__init__(**data)
self._chunkable.update(
{
"vertices": 2000,
"faces": 2000,
"colors": 2000,
"textureCoordinates": 2000,
}
self._chunkable = dict(
self._chunkable,
vertices=2000,
faces=2000,
colors=2000,
textureCoordinates=2000,
)
@@ -329,9 +330,10 @@ class Brep(Base, speckle_type=GEOMETRY + "Brep"):
def __init__(self, **data: Any) -> None:
super().__init__(**data)
self._detachable.append("displayValue")
self._chunkable.update(
{
self._detachable.update({"displayValue"})
self._chunkable = dict(
self._chunkable,
**{
"Surfaces": 200,
"Curve3D": 200,
"Curve2D": 200,
@@ -340,7 +342,7 @@ class Brep(Base, speckle_type=GEOMETRY + "Brep"):
"Loops": 5000,
"Trims": 5000,
"Faces": 5000,
}
},
)
def __setattr__(self, name: str, value: Any) -> None:
@@ -127,7 +127,8 @@ class BaseObjectSerializer:
hash = hash_obj(object_builder)
object_builder["id"] = hash
object_builder["__closure"] = self.closure_table[hash] = closure
if closure:
object_builder["__closure"] = self.closure_table[hash] = closure
# write detached or root objects to transports
if detached and self.write_transports:
+7 -5
View File
@@ -1,4 +1,5 @@
import json
from attr import has
import pytest
from speckle.api import operations
from speckle.transports.server import ServerTransport
@@ -32,7 +33,7 @@ class TestSerialization:
assert serialized_dict["@detach"]["speckle_type"] == "reference"
assert serialized_dict["origin"]["speckle_type"] == "reference"
assert serialized_dict["@detached_list"][-1]["speckle_type"] == "reference"
assert mesh.get_id(True) == deserialized.get_id()
assert mesh.get_id() == deserialized.get_id()
def test_chunking(self, mesh):
transport = MemoryTransport()
@@ -48,7 +49,7 @@ class TestSerialization:
assert serialized_dict["vertices"][0]["speckle_type"] == "reference"
assert serialized_dict["@(100)colours"][0]["speckle_type"] == "reference"
assert serialized_dict["@()default_chunk"][0]["speckle_type"] == "reference"
assert mesh.get_id(True) == deserialized.get_id()
assert mesh.get_id() == deserialized.get_id()
def test_send_and_receive(self, client, sample_stream, mesh):
transport = ServerTransport(client=client, stream_id=sample_stream.id)
@@ -62,15 +63,16 @@ class TestSerialization:
assert received.vertices == mesh.vertices
assert isinstance(received.origin, Point)
assert received.origin.value == mesh.origin.value
assert mesh.get_id(True) == received.get_id()
# not comparing hashes as order is not guaranteed back from server
mesh.id = hash # populate with decomposed id for use in proceeding tests
def test_receive_local(self, client, mesh):
received = operations.receive(mesh.id) # defaults to SQLiteTransport
hash = operations.send(mesh) # defaults to SQLiteTransport
received = operations.receive(hash)
assert isinstance(received, Base)
assert mesh.get_id(True) == received.get_id()
assert mesh.get_id() == received.get_id()
def test_unknown_type(self):
unknown = '{"speckle_type": "mysterious.type"}'