Skip to content

Commit 1aabc04

Browse files
authored
Merge pull request #1408 from compas-dev/fix-serialisation-colordict
Fix serialisation of color dicts
2 parents 21bbd2a + 2196a44 commit 1aabc04

File tree

3 files changed

+71
-10
lines changed

3 files changed

+71
-10
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
99

1010
### Added
1111

12+
* Added key conversion map to `compas.colors.ColorDict` to avoid serialisation problems with tuple keys when used in combination with edges.
13+
1214
### Changed
1315

1416
* Fixed bug in `VolMesh.delete_cell`.

src/compas/colors/colordict.py

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -24,16 +24,23 @@ class ColorDict(Data):
2424
2525
"""
2626

27+
KEYMAP = {
28+
int: lambda x: str(x),
29+
tuple: lambda x: ",".join(map(str, sorted(x))),
30+
list: lambda x: ",".join(map(str, sorted(x))),
31+
}
32+
2733
@property
2834
def __data__(self):
29-
return {"default": self.default, "dict": self._dict}
35+
return {
36+
"default": self.default,
37+
"dict": self._dict,
38+
}
3039

3140
@classmethod
3241
def __from_data__(cls, data):
3342
colordict = cls(data["default"])
34-
# note: this is specific to color dicts for vertices of meshes
35-
# perhaps the color dict needs to be subclassed per scene object type
36-
colordict.update({int(key): value for key, value in data["dict"].items()})
43+
colordict.update(data["dict"])
3744
return colordict
3845

3946
def __init__(self, default, name=None):
@@ -54,14 +61,19 @@ def default(self, default):
5461
default = Color.coerce(default)
5562
self._default = default
5663

64+
def keymapper(self, key):
65+
if key.__class__ in self.KEYMAP:
66+
return self.KEYMAP[key.__class__](key)
67+
return key
68+
5769
def __getitem__(self, key):
58-
return self._dict.get(key, self.default)
70+
return self._dict.get(self.keymapper(key), self.default)
5971

6072
def __setitem__(self, key, value):
61-
self._dict[key] = Color.coerce(value)
73+
self._dict[self.keymapper(key)] = Color.coerce(value)
6274

6375
def __delitem__(self, key):
64-
del self._dict[key]
76+
del self._dict[self.keymapper(key)]
6577

6678
def __iter__(self):
6779
return iter(self._dict)
@@ -70,7 +82,7 @@ def __len__(self):
7082
return len(self._dict)
7183

7284
def __contains__(self, key):
73-
return key in self._dict
85+
return self.keymapper(key) in self._dict
7486

7587
def items(self):
7688
return self._dict.items()
@@ -82,7 +94,7 @@ def values(self):
8294
return self._dict.values()
8395

8496
def get(self, key, default=None):
85-
return self._dict.get(key, default or self.default)
97+
return self._dict.get(self.keymapper(key), default or self.default)
8698

8799
def clear(self):
88100
"""Clear the previously stored items.
@@ -108,4 +120,4 @@ def update(self, other):
108120
109121
"""
110122
for key, value in other.items():
111-
self[key] = value
123+
self[self.keymapper(key)] = value
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import pytest
2+
import json
3+
import compas
4+
5+
from compas.colors import Color
6+
from compas.colors import ColorDict
7+
8+
9+
def test_colordict():
10+
cd = ColorDict(Color.red())
11+
assert cd.default == Color.red()
12+
13+
cd = ColorDict((255, 0, 0))
14+
assert cd.default == Color.red()
15+
16+
cd = ColorDict((1.0, 0.0, 0.0))
17+
assert cd.default == Color.red()
18+
19+
20+
def test_colordict_keys():
21+
cd = ColorDict(Color.red())
22+
cd[1] = Color.blue()
23+
cd[(1, 0)] = Color.green()
24+
25+
assert cd[1] == Color.blue()
26+
assert cd["1"] == Color.blue()
27+
28+
assert cd[(1, 0)] == Color.green()
29+
assert cd["0,1"] == Color.green()
30+
31+
assert cd["1,0"] == Color.red()
32+
33+
34+
def test_colordict_json():
35+
cd1 = ColorDict(Color.red())
36+
cd1[1] = Color.blue()
37+
cd1[(1, 0)] = Color.green()
38+
39+
cd2 = compas.json_loads(compas.json_dumps(cd1))
40+
41+
assert cd2[1] == Color.blue()
42+
assert cd2["1"] == Color.blue()
43+
44+
assert cd2[(1, 0)] == Color.green()
45+
assert cd2["0,1"] == Color.green()
46+
47+
assert cd2["1,0"] == Color.red()

0 commit comments

Comments
 (0)