44import collections
55
66from python_toolbox import comparison_tools
7+ from python_toolbox import context_management
8+ from python_toolbox import caching
9+ from python_toolbox import freezing
10+
11+
712
813KEY , PREV , NEXT = range (3 )
914
@@ -16,10 +21,10 @@ class BaseOrderedSet(collections.Set, collections.Sequence):
1621 ordered by insertion order, but that order can be changed.)
1722 '''
1823
19- def __init__ (self , iterable = None ):
20- self .clear ()
21- if iterable is not None :
22- self |= iterable
24+ def __init__ (self , iterable = () ):
25+ self .__clear ()
26+ for item in iterable :
27+ self . __add ( item )
2328
2429 def __getitem__ (self , index ):
2530 for i , item in enumerate (self ):
@@ -34,27 +39,6 @@ def __len__(self):
3439 def __contains__ (self , key ):
3540 return key in self ._map
3641
37- def add (self , key ):
38- '''
39- Add an element to a set.
40-
41- This has no effect if the element is already present.
42- '''
43- if key not in self ._map :
44- end = self ._end
45- curr = end [PREV ]
46- curr [NEXT ] = end [PREV ] = self ._map [key ] = [key , curr , end ]
47-
48- def discard (self , key ):
49- """
50- Remove an element from a set if it is a member.
51-
52- If the element is not a member, do nothing.
53- """
54- if key in self ._map :
55- key , prev , next = self ._map .pop (key )
56- prev [NEXT ] = next
57- next [PREV ] = prev
5842
5943 def __iter__ (self ):
6044 end = self ._end
@@ -82,7 +66,33 @@ def __eq__(self, other):
8266 len (self ) == len (other ) and
8367 tuple (self ) == tuple (other )
8468 )
69+
70+ def __clear (self ):
71+ '''Clear the ordered set, removing all items.'''
72+ self ._end = []
73+ self ._end += [None , self ._end , self ._end ]
74+ self ._map = {}
75+
76+
77+ def __add (self , key , last = True ):
78+ '''
79+ Add an element to a set.
80+
81+ This has no effect if the element is already present.
82+
83+ Specify `last=False` to add the item at the start of the ordered set.
84+ '''
85+
86+ if key not in self ._map :
87+ end = self ._end
88+ if last :
89+ last = end [PREV ]
90+ last [NEXT ] = end [PREV ] = self ._map [key ] = [key , last , end ]
91+ else :
92+ first = end [NEXT ]
93+ first [PREV ] = end [NEXT ] = self ._map [key ] = [key , end , first ]
8594
95+
8696
8797class FrozenOrderedSet (BaseOrderedSet ):
8898 '''
@@ -93,6 +103,7 @@ class FrozenOrderedSet(BaseOrderedSet):
93103 insertion order, but that order can be changed.)
94104 '''
95105
106+
96107class OrderedSet (BaseOrderedSet , collections .MutableSet ):
97108 '''
98109 A `set` with an order.
@@ -101,18 +112,16 @@ class OrderedSet(BaseOrderedSet, collections.MutableSet):
101112 ordered by insertion order, but that order can be changed.)
102113 '''
103114
104- def move_to_end (self , key ):
105- '''
106- Move an existing element to the end (or beginning if last==False).
107-
108- Raises KeyError if the element does not exist.
109- When last=True, acts like a fast version of self[key]=self.pop(key).
115+ add = BaseOrderedSet ._BaseOrderedSet__add
116+ clear = BaseOrderedSet ._BaseOrderedSet__clear
110117
118+ def move_to_end (self , key , last = True ):
119+ '''
120+ Move an existing element to the end (or start if `last=False`.)
111121 '''
112122 # Inefficient implementation until someone cares.
113- if key in self :
114- self .remove (key )
115- self .add (key )
123+ self .remove (key )
124+ self .add (key , last = last )
116125
117126
118127 def sort (self , key = None , reverse = False ):
@@ -130,23 +139,7 @@ def sort(self, key=None, reverse=False):
130139 self .clear ()
131140 self |= sorted_members
132141
133- def clear (self ):
134- self ._end = []
135- self ._end += [None , self ._end , self ._end ]
136- self ._map = {}
137-
138-
139- def add (self , key ):
140- '''
141- Add an element to a set.
142142
143- This has no effect if the element is already present.
144- '''
145- if key not in self ._map :
146- end = self ._end
147- curr = end [PREV ]
148- curr [NEXT ] = end [PREV ] = self ._map [key ] = [key , curr , end ]
149-
150143 def discard (self , key ):
151144 """
152145 Remove an element from a set if it is a member.
@@ -170,42 +163,54 @@ def pop(self, last=True):
170163class EmittingOrderedSet (OrderedSet ):
171164 '''An ordered set that emits to `.emitter` every time it's modified.'''
172165
173- def __init__ (self , emitter , items = ()):
166+ def __init__ (self , iterable = (), * , emitter = None ):
174167 if emitter :
175168 from python_toolbox .emitting import Emitter
176169 assert isinstance (emitter , Emitter )
177170 self .emitter = emitter
178- OrderedSet .__init__ (self , items )
171+ OrderedSet .__init__ (self , iterable )
179172
180-
181- def add (self , key ):
173+ def add (self , key , last = True ):
182174 '''
183175 Add an element to a set.
184176
185177 This has no effect if the element is already present.
186178 '''
187179 if key not in self ._map :
188- end = self ._end
189- curr = end [PREV ]
190- curr [NEXT ] = end [PREV ] = self ._map [key ] = [key , curr , end ]
191- if self .emitter :
192- self .emitter .emit ()
180+ super ().add (key , last = last )
181+ self ._emit ()
193182
194-
195183 def discard (self , key ):
196184 '''
197185 Remove an element from a set if it is a member.
198186
199187 If the element is not a member, do nothing.
200188 '''
201189 if key in self ._map :
202- key , prev , next = self ._map .pop (key )
203- prev [NEXT ] = next
204- next [PREV ] = prev
205- if self .emitter :
206- self .emitter .emit ()
207-
190+ super ().discard (key )
191+ self ._emit ()
192+
193+ def clear (self ):
194+ '''Clear the ordered set, removing all items.'''
195+ if self :
196+ super ().clear ()
197+ self ._emit ()
208198
209199 def set_emitter (self , emitter ):
210200 '''Set `emitter` to be emitted with on every modification.'''
211- self .emitter = emitter
201+ self .emitter = emitter
202+
203+ def _emit (self ):
204+ if (self .emitter is not None ) and not self ._emitter_freezer .frozen :
205+ self .emitter .emit ()
206+
207+ def move_to_end (self , key , last = True ):
208+ '''
209+ Move an existing element to the end (or start if `last=False`.)
210+ '''
211+ # Inefficient implementation until someone cares.
212+ with self ._emitter_freezer :
213+ self .remove (key )
214+ self .add (key , last = last )
215+
216+ _emitter_freezer = freezing .FreezerProperty ()
0 commit comments