1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
|
from weakref import ref
cdef inline void observable_set_dispatch(object self) except *:
cdef Property prop = self.prop
obj = self.obj()
if obj is not None:
prop.dispatch(obj)
class ObservableSet(set):
# Internal class to observe changes inside a native python set.
def __init__(self, *largs):
self.prop = largs[0]
self.obj = ref(largs[1])
super(ObservableSet, self).__init__(*largs[2:])
def __iand__(self, *largs):
set.__iand__(self, *largs)
observable_set_dispatch(self)
def __ior__(self, *largs):
set.__ior__(self, *largs)
observable_set_dispatch(self)
def __isub__(self, *largs):
set.__isub__(self, *largs)
observable_set_dispatch(self)
def __ixor__(self, *largs):
set.__ixor__(self, *largs)
observable_set_dispatch(self)
def add(self, *largs):
set.add(self, *largs)
observable_set_dispatch(self)
def clear(self):
set.clear(self)
observable_set_dispatch(self)
def difference_update(self, *largs):
set.difference_update(self, *largs)
observable_set_dispatch(self)
def discard(self, *largs):
set.discard(self, *largs)
observable_set_dispatch(self)
def intersection_update(self, *largs):
set.intersection_update(self, *largs)
observable_set_dispatch(self)
def pop(self, *largs):
cdef object result = set.pop(self, *largs)
observable_set_dispatch(self)
return result
def remove(self, *largs):
set.remove(self, *largs)
observable_set_dispatch(self)
def symmetric_difference_update(self, *largs):
set.symmetric_difference_update(self, *largs)
observable_set_dispatch(self)
def update(self, *largs):
set.update(self, *largs)
observable_set_dispatch(self)
cdef class SetProperty(Property):
'''Property that represents a set.
:Parameters:
`defaultvalue`: set, defaults to set()
Specifies the default value of the property.
.. warning::
When assigning a set to a :class:`SetProperty`, the set stored in
the property is a shallow copy of the set and not the original set. This can
be demonstrated with the following example::
>>> class MyWidget(Widget):
>>> my_set = SetProperty([])
>>> widget = MyWidget()
>>> my_set = {1, 5, {'hi': 'hello'}}
>>> widget.my_set = my_set
>>> print(my_set is widget.my_set)
False
>>> my_set.add(10)
>>> print(my_set, widget.my_set)
{1, 5, {'hi': 'hello'}, 10} {1, 5, {'hi': 'hello'}}
However, changes to nested levels will affect the property as well,
since the property uses a shallow copy of my_set.
'''
def __init__(self, defaultvalue=0, **kw):
defaultvalue = set() if defaultvalue == 0 else defaultvalue
super(SetProperty, self).__init__(defaultvalue, **kw)
cpdef PropertyStorage link(self, EventDispatcher obj, str name):
Property.link(self, obj, name)
cdef PropertyStorage ps = obj.__storage[self._name]
if ps.value is not None:
ps.value = ObservableSet(self, obj, ps.value)
cdef check(self, EventDispatcher obj, value, PropertyStorage property_storage):
if Property.check(self, obj, value, property_storage):
return True
if type(value) is not ObservableSet:
raise ValueError('%s.%s accept only ObservableSet' % (
obj.__class__.__name__,
self.name))
cpdef set(self, EventDispatcher obj, value):
if value is not None:
value = ObservableSet(self, obj, value)
Property.set(self, obj, value)
|