@@ -117,14 +117,18 @@ def __init__(self, left, right=None, op=None):
117117 if isinstance (left , Cycler ):
118118 self ._left = Cycler (left ._left , left ._right , left ._op )
119119 elif left is not None :
120- self ._left = list (left )
120+ # Need to copy the dictionary or else that will be a residual
121+ # mutable that could lead to strange errors
122+ self ._left = [copy .copy (v ) for v in left ]
121123 else :
122124 self ._left = None
123125
124126 if isinstance (right , Cycler ):
125127 self ._right = Cycler (right ._left , right ._right , right ._op )
126128 elif right is not None :
127- self ._right = list (right )
129+ # Need to copy the dictionary or else that will be a residual
130+ # mutable that could lead to strange errors
131+ self ._right = [copy .copy (v ) for v in right ]
128132 else :
129133 self ._right = None
130134
@@ -138,6 +142,41 @@ def keys(self):
138142 """
139143 return set (self ._keys )
140144
145+ def change_key (self , old , new ):
146+ """
147+ Change a key in this cycler to a new name.
148+ Modification is performed in-place.
149+
150+ Does nothing if the old key is the same as the new key.
151+ Raises a ValueError if the new key is already a key.
152+ Raises a KeyError if the old key isn't a key.
153+
154+ """
155+ if old == new :
156+ return
157+ if new in self ._keys :
158+ raise ValueError ("Can't replace %s with %s, %s is already a key" %
159+ (old , new , new ))
160+ if old not in self ._keys :
161+ raise KeyError ("Can't replace %s with %s, %s is not a key" %
162+ (old , new , old ))
163+
164+ self ._keys .remove (old )
165+ self ._keys .add (new )
166+
167+ if self ._right is not None and old in self ._right .keys :
168+ self ._right .change_key (old , new )
169+
170+ # self._left should always be non-None
171+ # if self._keys is non-empty.
172+ elif isinstance (self ._left , Cycler ):
173+ self ._left .change_key (old , new )
174+ else :
175+ # It should be completely safe at this point to
176+ # assume that the old key can be found in each
177+ # iteration.
178+ self ._left = [{new : entry [old ]} for entry in self ._left ]
179+
141180 def _compose (self ):
142181 """
143182 Compose the 'left' and 'right' components of this cycle
0 commit comments