blob: 2b6abd879fc939deacc88302d883dcfd6d20e699 [file] [log] [blame]
Tor Norbye3a2425a2013-11-04 10:16:08 -08001__all__ = ['deque', 'defaultdict', 'namedtuple', 'UserDict', 'UserList',
2 'UserString', 'Counter', 'OrderedDict']
3# For bootstrapping reasons, the collection ABCs are defined in _abcoll.py.
4# They should however be considered an integral part of collections.py.
5from _abcoll import *
6import _abcoll
7__all__ += _abcoll.__all__
8
9from _collections import deque, defaultdict
10from operator import itemgetter as _itemgetter
11from keyword import iskeyword as _iskeyword
12import sys as _sys
13import heapq as _heapq
14from weakref import proxy as _proxy
15from itertools import repeat as _repeat, chain as _chain, starmap as _starmap
16from reprlib import recursive_repr as _recursive_repr
17
18################################################################################
19### OrderedDict
20################################################################################
21
22class _Link(object):
23 __slots__ = 'prev', 'next', 'key', '__weakref__'
24
25class OrderedDict(dict):
26 'Dictionary that remembers insertion order'
27 # An inherited dict maps keys to values.
28 # The inherited dict provides __getitem__, __len__, __contains__, and get.
29 # The remaining methods are order-aware.
30 # Big-O running times for all methods are the same as regular dictionaries.
31
32 # The internal self.__map dict maps keys to links in a doubly linked list.
33 # The circular doubly linked list starts and ends with a sentinel element.
34 # The sentinel element never gets deleted (this simplifies the algorithm).
35 # The sentinel is in self.__hardroot with a weakref proxy in self.__root.
36 # The prev/next links are weakref proxies (to prevent circular references).
37 # Individual links are kept alive by the hard reference in self.__map.
38 # Those hard references disappear when a key is deleted from an OrderedDict.
39
40 def __init__(self, *args, **kwds):
41 '''Initialize an ordered dictionary. The signature is the same as
42 regular dictionaries, but keyword arguments are not recommended because
43 their insertion order is arbitrary.
44
45 '''
46 if len(args) > 1:
47 raise TypeError('expected at most 1 arguments, got %d' % len(args))
48 try:
49 self.__root
50 except AttributeError:
51 self.__hardroot = _Link()
52 self.__root = root = _proxy(self.__hardroot)
53 root.prev = root.next = root
54 self.__map = {}
55 self.__update(*args, **kwds)
56
57 def __setitem__(self, key, value,
58 dict_setitem=dict.__setitem__, proxy=_proxy, Link=_Link):
59 'od.__setitem__(i, y) <==> od[i]=y'
60 # Setting a new item creates a new link at the end of the linked list,
61 # and the inherited dictionary is updated with the new key/value pair.
62 if key not in self:
63 self.__map[key] = link = Link()
64 root = self.__root
65 last = root.prev
66 link.prev, link.next, link.key = last, root, key
67 last.next = link
68 root.prev = proxy(link)
69 dict_setitem(self, key, value)
70
71 def __delitem__(self, key, dict_delitem=dict.__delitem__):
72 'od.__delitem__(y) <==> del od[y]'
73 # Deleting an existing item uses self.__map to find the link which gets
74 # removed by updating the links in the predecessor and successor nodes.
75 dict_delitem(self, key)
76 link = self.__map.pop(key)
77 link_prev = link.prev
78 link_next = link.next
79 link_prev.next = link_next
80 link_next.prev = link_prev
81
82 def __iter__(self):
83 'od.__iter__() <==> iter(od)'
84 # Traverse the linked list in order.
85 root = self.__root
86 curr = root.next
87 while curr is not root:
88 yield curr.key
89 curr = curr.next
90
91 def __reversed__(self):
92 'od.__reversed__() <==> reversed(od)'
93 # Traverse the linked list in reverse order.
94 root = self.__root
95 curr = root.prev
96 while curr is not root:
97 yield curr.key
98 curr = curr.prev
99
100 def clear(self):
101 'od.clear() -> None. Remove all items from od.'
102 root = self.__root
103 root.prev = root.next = root
104 self.__map.clear()
105 dict.clear(self)
106
107 def popitem(self, last=True):
108 '''od.popitem() -> (k, v), return and remove a (key, value) pair.
109 Pairs are returned in LIFO order if last is true or FIFO order if false.
110
111 '''
112 if not self:
113 raise KeyError('dictionary is empty')
114 root = self.__root
115 if last:
116 link = root.prev
117 link_prev = link.prev
118 link_prev.next = root
119 root.prev = link_prev
120 else:
121 link = root.next
122 link_next = link.next
123 root.next = link_next
124 link_next.prev = root
125 key = link.key
126 del self.__map[key]
127 value = dict.pop(self, key)
128 return key, value
129
130 def move_to_end(self, key, last=True):
131 '''Move an existing element to the end (or beginning if last==False).
132
133 Raises KeyError if the element does not exist.
134 When last=True, acts like a fast version of self[key]=self.pop(key).
135
136 '''
137 link = self.__map[key]
138 link_prev = link.prev
139 link_next = link.next
140 link_prev.next = link_next
141 link_next.prev = link_prev
142 root = self.__root
143 if last:
144 last = root.prev
145 link.prev = last
146 link.next = root
147 last.next = root.prev = link
148 else:
149 first = root.next
150 link.prev = root
151 link.next = first
152 root.next = first.prev = link
153
154 def __sizeof__(self):
155 sizeof = _sys.getsizeof
156 n = len(self) + 1 # number of links including root
157 size = sizeof(self.__dict__) # instance dictionary
158 size += sizeof(self.__map) * 2 # internal dict and inherited dict
159 size += sizeof(self.__hardroot) * n # link objects
160 size += sizeof(self.__root) * n # proxy objects
161 return size
162
163 update = __update = MutableMapping.update
164 keys = MutableMapping.keys
165 values = MutableMapping.values
166 items = MutableMapping.items
167 __ne__ = MutableMapping.__ne__
168
169 __marker = object()
170
171 def pop(self, key, default=__marker):
172 '''od.pop(k[,d]) -> v, remove specified key and return the corresponding
173 value. If key is not found, d is returned if given, otherwise KeyError
174 is raised.
175
176 '''
177 if key in self:
178 result = self[key]
179 del self[key]
180 return result
181 if default is self.__marker:
182 raise KeyError(key)
183 return default
184
185 def setdefault(self, key, default=None):
186 'od.setdefault(k[,d]) -> od.get(k,d), also set od[k]=d if k not in od'
187 if key in self:
188 return self[key]
189 self[key] = default
190 return default
191
192 @_recursive_repr()
193 def __repr__(self):
194 'od.__repr__() <==> repr(od)'
195 if not self:
196 return '%s()' % (self.__class__.__name__,)
197 return '%s(%r)' % (self.__class__.__name__, list(self.items()))
198
199 def __reduce__(self):
200 'Return state information for pickling'
201 items = [[k, self[k]] for k in self]
202 inst_dict = vars(self).copy()
203 for k in vars(OrderedDict()):
204 inst_dict.pop(k, None)
205 if inst_dict:
206 return (self.__class__, (items,), inst_dict)
207 return self.__class__, (items,)
208
209 def copy(self):
210 'od.copy() -> a shallow copy of od'
211 return self.__class__(self)
212
213 @classmethod
214 def fromkeys(cls, iterable, value=None):
215 '''OD.fromkeys(S[, v]) -> New ordered dictionary with keys from S.
216 If not specified, the value defaults to None.
217
218 '''
219 self = cls()
220 for key in iterable:
221 self[key] = value
222 return self
223
224 def __eq__(self, other):
225 '''od.__eq__(y) <==> od==y. Comparison to another OD is order-sensitive
226 while comparison to a regular mapping is order-insensitive.
227
228 '''
229 if isinstance(other, OrderedDict):
230 return len(self)==len(other) and \
231 all(p==q for p, q in zip(self.items(), other.items()))
232 return dict.__eq__(self, other)
233
234
235################################################################################
236### namedtuple
237################################################################################
238
239_class_template = '''\
240from builtins import property as _property, tuple as _tuple
241from operator import itemgetter as _itemgetter
242from collections import OrderedDict
243
244class {typename}(tuple):
245 '{typename}({arg_list})'
246
247 __slots__ = ()
248
249 _fields = {field_names!r}
250
251 def __new__(_cls, {arg_list}):
252 'Create new instance of {typename}({arg_list})'
253 return _tuple.__new__(_cls, ({arg_list}))
254
255 @classmethod
256 def _make(cls, iterable, new=tuple.__new__, len=len):
257 'Make a new {typename} object from a sequence or iterable'
258 result = new(cls, iterable)
259 if len(result) != {num_fields:d}:
260 raise TypeError('Expected {num_fields:d} arguments, got %d' % len(result))
261 return result
262
263 def __repr__(self):
264 'Return a nicely formatted representation string'
265 return self.__class__.__name__ + '({repr_fmt})' % self
266
267 def _asdict(self):
268 'Return a new OrderedDict which maps field names to their values'
269 return OrderedDict(zip(self._fields, self))
270
271 __dict__ = property(_asdict)
272
273 def _replace(_self, **kwds):
274 'Return a new {typename} object replacing specified fields with new values'
275 result = _self._make(map(kwds.pop, {field_names!r}, _self))
276 if kwds:
277 raise ValueError('Got unexpected field names: %r' % list(kwds))
278 return result
279
280 def __getnewargs__(self):
281 'Return self as a plain tuple. Used by copy and pickle.'
282 return tuple(self)
283
284{field_defs}
285'''
286
287_repr_template = '{name}=%r'
288
289_field_template = '''\
290 {name} = _property(_itemgetter({index:d}), doc='Alias for field number {index:d}')
291'''
292
293def namedtuple(typename, field_names, verbose=False, rename=False):
294 """Returns a new subclass of tuple with named fields.
295
296 >>> Point = namedtuple('Point', ['x', 'y'])
297 >>> Point.__doc__ # docstring for the new class
298 'Point(x, y)'
299 >>> p = Point(11, y=22) # instantiate with positional args or keywords
300 >>> p[0] + p[1] # indexable like a plain tuple
301 33
302 >>> x, y = p # unpack like a regular tuple
303 >>> x, y
304 (11, 22)
305 >>> p.x + p.y # fields also accessable by name
306 33
307 >>> d = p._asdict() # convert to a dictionary
308 >>> d['x']
309 11
310 >>> Point(**d) # convert from a dictionary
311 Point(x=11, y=22)
312 >>> p._replace(x=100) # _replace() is like str.replace() but targets named fields
313 Point(x=100, y=22)
314
315 """
316
317 # Parse and validate the field names. Validation serves two purposes,
318 # generating informative error messages and preventing template injection attacks.
319 if isinstance(field_names, str):
320 field_names = field_names.replace(',', ' ').split() # names separated by whitespace and/or commas
321 field_names = list(map(str, field_names))
322 if rename:
323 seen = set()
324 for index, name in enumerate(field_names):
325 if (not all(c.isalnum() or c=='_' for c in name)
326 or _iskeyword(name)
327 or not name
328 or name[0].isdigit()
329 or name.startswith('_')
330 or name in seen):
331 field_names[index] = '_%d' % index
332 seen.add(name)
333 for name in [typename] + field_names:
334 if not all(c.isalnum() or c=='_' for c in name):
335 raise ValueError('Type names and field names can only contain alphanumeric characters and underscores: %r' % name)
336 if _iskeyword(name):
337 raise ValueError('Type names and field names cannot be a keyword: %r' % name)
338 if name[0].isdigit():
339 raise ValueError('Type names and field names cannot start with a number: %r' % name)
340 seen = set()
341 for name in field_names:
342 if name.startswith('_') and not rename:
343 raise ValueError('Field names cannot start with an underscore: %r' % name)
344 if name in seen:
345 raise ValueError('Encountered duplicate field name: %r' % name)
346 seen.add(name)
347
348 # Fill-in the class template
349 class_definition = _class_template.format(
350 typename = typename,
351 field_names = tuple(field_names),
352 num_fields = len(field_names),
353 arg_list = repr(tuple(field_names)).replace("'", "")[1:-1],
354 repr_fmt = ', '.join(_repr_template.format(name=name) for name in field_names),
355 field_defs = '\n'.join(_field_template.format(index=index, name=name)
356 for index, name in enumerate(field_names))
357 )
358
359 # Execute the template string in a temporary namespace and
360 # support tracing utilities by setting a value for frame.f_globals['__name__']
361 namespace = dict(__name__='namedtuple_%s' % typename)
362 try:
363 exec(class_definition, namespace)
364 except SyntaxError as e:
365 raise SyntaxError(e.msg + ':\n\n' + class_definition)
366 result = namespace[typename]
367 if verbose:
368 print(class_definition)
369
370 # For pickling to work, the __module__ variable needs to be set to the frame
371 # where the named tuple is created. Bypass this step in enviroments where
372 # sys._getframe is not defined (Jython for example) or sys._getframe is not
373 # defined for arguments greater than 0 (IronPython).
374 try:
375 result.__module__ = _sys._getframe(1).f_globals.get('__name__', '__main__')
376 except (AttributeError, ValueError):
377 pass
378
379 return result
380
381
382########################################################################
383### Counter
384########################################################################
385
386def _count_elements(mapping, iterable):
387 'Tally elements from the iterable.'
388 mapping_get = mapping.get
389 for elem in iterable:
390 mapping[elem] = mapping_get(elem, 0) + 1
391
392try: # Load C helper function if available
393 from _collections import _count_elements
394except ImportError:
395 pass
396
397class Counter(dict):
398 '''Dict subclass for counting hashable items. Sometimes called a bag
399 or multiset. Elements are stored as dictionary keys and their counts
400 are stored as dictionary values.
401
402 >>> c = Counter('abcdeabcdabcaba') # count elements from a string
403
404 >>> c.most_common(3) # three most common elements
405 [('a', 5), ('b', 4), ('c', 3)]
406 >>> sorted(c) # list all unique elements
407 ['a', 'b', 'c', 'd', 'e']
408 >>> ''.join(sorted(c.elements())) # list elements with repetitions
409 'aaaaabbbbcccdde'
410 >>> sum(c.values()) # total of all counts
411 15
412
413 >>> c['a'] # count of letter 'a'
414 5
415 >>> for elem in 'shazam': # update counts from an iterable
416 ... c[elem] += 1 # by adding 1 to each element's count
417 >>> c['a'] # now there are seven 'a'
418 7
419 >>> del c['b'] # remove all 'b'
420 >>> c['b'] # now there are zero 'b'
421 0
422
423 >>> d = Counter('simsalabim') # make another counter
424 >>> c.update(d) # add in the second counter
425 >>> c['a'] # now there are nine 'a'
426 9
427
428 >>> c.clear() # empty the counter
429 >>> c
430 Counter()
431
432 Note: If a count is set to zero or reduced to zero, it will remain
433 in the counter until the entry is deleted or the counter is cleared:
434
435 >>> c = Counter('aaabbc')
436 >>> c['b'] -= 2 # reduce the count of 'b' by two
437 >>> c.most_common() # 'b' is still in, but its count is zero
438 [('a', 3), ('c', 1), ('b', 0)]
439
440 '''
441 # References:
442 # http://en.wikipedia.org/wiki/Multiset
443 # http://www.gnu.org/software/smalltalk/manual-base/html_node/Bag.html
444 # http://www.demo2s.com/Tutorial/Cpp/0380__set-multiset/Catalog0380__set-multiset.htm
445 # http://code.activestate.com/recipes/259174/
446 # Knuth, TAOCP Vol. II section 4.6.3
447
448 def __init__(self, iterable=None, **kwds):
449 '''Create a new, empty Counter object. And if given, count elements
450 from an input iterable. Or, initialize the count from another mapping
451 of elements to their counts.
452
453 >>> c = Counter() # a new, empty counter
454 >>> c = Counter('gallahad') # a new counter from an iterable
455 >>> c = Counter({'a': 4, 'b': 2}) # a new counter from a mapping
456 >>> c = Counter(a=4, b=2) # a new counter from keyword args
457
458 '''
459 super().__init__()
460 self.update(iterable, **kwds)
461
462 def __missing__(self, key):
463 'The count of elements not in the Counter is zero.'
464 # Needed so that self[missing_item] does not raise KeyError
465 return 0
466
467 def most_common(self, n=None):
468 '''List the n most common elements and their counts from the most
469 common to the least. If n is None, then list all element counts.
470
471 >>> Counter('abcdeabcdabcaba').most_common(3)
472 [('a', 5), ('b', 4), ('c', 3)]
473
474 '''
475 # Emulate Bag.sortedByCount from Smalltalk
476 if n is None:
477 return sorted(self.items(), key=_itemgetter(1), reverse=True)
478 return _heapq.nlargest(n, self.items(), key=_itemgetter(1))
479
480 def elements(self):
481 '''Iterator over elements repeating each as many times as its count.
482
483 >>> c = Counter('ABCABC')
484 >>> sorted(c.elements())
485 ['A', 'A', 'B', 'B', 'C', 'C']
486
487 # Knuth's example for prime factors of 1836: 2**2 * 3**3 * 17**1
488 >>> prime_factors = Counter({2: 2, 3: 3, 17: 1})
489 >>> product = 1
490 >>> for factor in prime_factors.elements(): # loop over factors
491 ... product *= factor # and multiply them
492 >>> product
493 1836
494
495 Note, if an element's count has been set to zero or is a negative
496 number, elements() will ignore it.
497
498 '''
499 # Emulate Bag.do from Smalltalk and Multiset.begin from C++.
500 return _chain.from_iterable(_starmap(_repeat, self.items()))
501
502 # Override dict methods where necessary
503
504 @classmethod
505 def fromkeys(cls, iterable, v=None):
506 # There is no equivalent method for counters because setting v=1
507 # means that no element can have a count greater than one.
508 raise NotImplementedError(
509 'Counter.fromkeys() is undefined. Use Counter(iterable) instead.')
510
511 def update(self, iterable=None, **kwds):
512 '''Like dict.update() but add counts instead of replacing them.
513
514 Source can be an iterable, a dictionary, or another Counter instance.
515
516 >>> c = Counter('which')
517 >>> c.update('witch') # add elements from another iterable
518 >>> d = Counter('watch')
519 >>> c.update(d) # add elements from another counter
520 >>> c['h'] # four 'h' in which, witch, and watch
521 4
522
523 '''
524 # The regular dict.update() operation makes no sense here because the
525 # replace behavior results in the some of original untouched counts
526 # being mixed-in with all of the other counts for a mismash that
527 # doesn't have a straight-forward interpretation in most counting
528 # contexts. Instead, we implement straight-addition. Both the inputs
529 # and outputs are allowed to contain zero and negative counts.
530
531 if iterable is not None:
532 if isinstance(iterable, Mapping):
533 if self:
534 self_get = self.get
535 for elem, count in iterable.items():
536 self[elem] = count + self_get(elem, 0)
537 else:
538 super().update(iterable) # fast path when counter is empty
539 else:
540 _count_elements(self, iterable)
541 if kwds:
542 self.update(kwds)
543
544 def subtract(self, iterable=None, **kwds):
545 '''Like dict.update() but subtracts counts instead of replacing them.
546 Counts can be reduced below zero. Both the inputs and outputs are
547 allowed to contain zero and negative counts.
548
549 Source can be an iterable, a dictionary, or another Counter instance.
550
551 >>> c = Counter('which')
552 >>> c.subtract('witch') # subtract elements from another iterable
553 >>> c.subtract(Counter('watch')) # subtract elements from another counter
554 >>> c['h'] # 2 in which, minus 1 in witch, minus 1 in watch
555 0
556 >>> c['w'] # 1 in which, minus 1 in witch, minus 1 in watch
557 -1
558
559 '''
560 if iterable is not None:
561 self_get = self.get
562 if isinstance(iterable, Mapping):
563 for elem, count in iterable.items():
564 self[elem] = self_get(elem, 0) - count
565 else:
566 for elem in iterable:
567 self[elem] = self_get(elem, 0) - 1
568 if kwds:
569 self.subtract(kwds)
570
571 def copy(self):
572 'Return a shallow copy.'
573 return self.__class__(self)
574
575 def __reduce__(self):
576 return self.__class__, (dict(self),)
577
578 def __delitem__(self, elem):
579 'Like dict.__delitem__() but does not raise KeyError for missing values.'
580 if elem in self:
581 super().__delitem__(elem)
582
583 def __repr__(self):
584 if not self:
585 return '%s()' % self.__class__.__name__
586 items = ', '.join(map('%r: %r'.__mod__, self.most_common()))
587 return '%s({%s})' % (self.__class__.__name__, items)
588
589 # Multiset-style mathematical operations discussed in:
590 # Knuth TAOCP Volume II section 4.6.3 exercise 19
591 # and at http://en.wikipedia.org/wiki/Multiset
592 #
593 # Outputs guaranteed to only include positive counts.
594 #
595 # To strip negative and zero counts, add-in an empty counter:
596 # c += Counter()
597
598 def __add__(self, other):
599 '''Add counts from two counters.
600
601 >>> Counter('abbb') + Counter('bcc')
602 Counter({'b': 4, 'c': 2, 'a': 1})
603
604 '''
605 if not isinstance(other, Counter):
606 return NotImplemented
607 result = Counter()
608 for elem, count in self.items():
609 newcount = count + other[elem]
610 if newcount > 0:
611 result[elem] = newcount
612 for elem, count in other.items():
613 if elem not in self and count > 0:
614 result[elem] = count
615 return result
616
617 def __sub__(self, other):
618 ''' Subtract count, but keep only results with positive counts.
619
620 >>> Counter('abbbc') - Counter('bccd')
621 Counter({'b': 2, 'a': 1})
622
623 '''
624 if not isinstance(other, Counter):
625 return NotImplemented
626 result = Counter()
627 for elem, count in self.items():
628 newcount = count - other[elem]
629 if newcount > 0:
630 result[elem] = newcount
631 for elem, count in other.items():
632 if elem not in self and count < 0:
633 result[elem] = 0 - count
634 return result
635
636 def __or__(self, other):
637 '''Union is the maximum of value in either of the input counters.
638
639 >>> Counter('abbb') | Counter('bcc')
640 Counter({'b': 3, 'c': 2, 'a': 1})
641
642 '''
643 if not isinstance(other, Counter):
644 return NotImplemented
645 result = Counter()
646 for elem, count in self.items():
647 other_count = other[elem]
648 newcount = other_count if count < other_count else count
649 if newcount > 0:
650 result[elem] = newcount
651 for elem, count in other.items():
652 if elem not in self and count > 0:
653 result[elem] = count
654 return result
655
656 def __and__(self, other):
657 ''' Intersection is the minimum of corresponding counts.
658
659 >>> Counter('abbb') & Counter('bcc')
660 Counter({'b': 1})
661
662 '''
663 if not isinstance(other, Counter):
664 return NotImplemented
665 result = Counter()
666 for elem, count in self.items():
667 other_count = other[elem]
668 newcount = count if count < other_count else other_count
669 if newcount > 0:
670 result[elem] = newcount
671 return result
672
673
674########################################################################
675### ChainMap (helper for configparser)
676########################################################################
677
678class _ChainMap(MutableMapping):
679 ''' A ChainMap groups multiple dicts (or other mappings) together
680 to create a single, updateable view.
681
682 The underlying mappings are stored in a list. That list is public and can
683 accessed or updated using the *maps* attribute. There is no other state.
684
685 Lookups search the underlying mappings successively until a key is found.
686 In contrast, writes, updates, and deletions only operate on the first
687 mapping.
688
689 '''
690
691 def __init__(self, *maps):
692 '''Initialize a ChainMap by setting *maps* to the given mappings.
693 If no mappings are provided, a single empty dictionary is used.
694
695 '''
696 self.maps = list(maps) or [{}] # always at least one map
697
698 def __missing__(self, key):
699 raise KeyError(key)
700
701 def __getitem__(self, key):
702 for mapping in self.maps:
703 try:
704 return mapping[key] # can't use 'key in mapping' with defaultdict
705 except KeyError:
706 pass
707 return self.__missing__(key) # support subclasses that define __missing__
708
709 def get(self, key, default=None):
710 return self[key] if key in self else default
711
712 def __len__(self):
713 return len(set().union(*self.maps)) # reuses stored hash values if possible
714
715 def __iter__(self):
716 return iter(set().union(*self.maps))
717
718 def __contains__(self, key):
719 return any(key in m for m in self.maps)
720
721 def __bool__(self):
722 return any(self.maps)
723
724 @_recursive_repr()
725 def __repr__(self):
726 return '{0.__class__.__name__}({1})'.format(
727 self, ', '.join(map(repr, self.maps)))
728
729 @classmethod
730 def fromkeys(cls, iterable, *args):
731 'Create a ChainMap with a single dict created from the iterable.'
732 return cls(dict.fromkeys(iterable, *args))
733
734 def copy(self):
735 'New ChainMap or subclass with a new copy of maps[0] and refs to maps[1:]'
736 return self.__class__(self.maps[0].copy(), *self.maps[1:])
737
738 __copy__ = copy
739
740 def new_child(self): # like Django's Context.push()
741 'New ChainMap with a new dict followed by all previous maps.'
742 return self.__class__({}, *self.maps)
743
744 @property
745 def parents(self): # like Django's Context.pop()
746 'New ChainMap from maps[1:].'
747 return self.__class__(*self.maps[1:])
748
749 def __setitem__(self, key, value):
750 self.maps[0][key] = value
751
752 def __delitem__(self, key):
753 try:
754 del self.maps[0][key]
755 except KeyError:
756 raise KeyError('Key not found in the first mapping: {!r}'.format(key))
757
758 def popitem(self):
759 'Remove and return an item pair from maps[0]. Raise KeyError is maps[0] is empty.'
760 try:
761 return self.maps[0].popitem()
762 except KeyError:
763 raise KeyError('No keys found in the first mapping.')
764
765 def pop(self, key, *args):
766 'Remove *key* from maps[0] and return its value. Raise KeyError if *key* not in maps[0].'
767 try:
768 return self.maps[0].pop(key, *args)
769 except KeyError:
770 raise KeyError('Key not found in the first mapping: {!r}'.format(key))
771
772 def clear(self):
773 'Clear maps[0], leaving maps[1:] intact.'
774 self.maps[0].clear()
775
776
777################################################################################
778### UserDict
779################################################################################
780
781class UserDict(MutableMapping):
782
783 # Start by filling-out the abstract methods
784 def __init__(self, dict=None, **kwargs):
785 self.data = {}
786 if dict is not None:
787 self.update(dict)
788 if len(kwargs):
789 self.update(kwargs)
790 def __len__(self): return len(self.data)
791 def __getitem__(self, key):
792 if key in self.data:
793 return self.data[key]
794 if hasattr(self.__class__, "__missing__"):
795 return self.__class__.__missing__(self, key)
796 raise KeyError(key)
797 def __setitem__(self, key, item): self.data[key] = item
798 def __delitem__(self, key): del self.data[key]
799 def __iter__(self):
800 return iter(self.data)
801
802 # Modify __contains__ to work correctly when __missing__ is present
803 def __contains__(self, key):
804 return key in self.data
805
806 # Now, add the methods in dicts but not in MutableMapping
807 def __repr__(self): return repr(self.data)
808 def copy(self):
809 if self.__class__ is UserDict:
810 return UserDict(self.data.copy())
811 import copy
812 data = self.data
813 try:
814 self.data = {}
815 c = copy.copy(self)
816 finally:
817 self.data = data
818 c.update(self)
819 return c
820 @classmethod
821 def fromkeys(cls, iterable, value=None):
822 d = cls()
823 for key in iterable:
824 d[key] = value
825 return d
826
827
828
829################################################################################
830### UserList
831################################################################################
832
833class UserList(MutableSequence):
834 """A more or less complete user-defined wrapper around list objects."""
835 def __init__(self, initlist=None):
836 self.data = []
837 if initlist is not None:
838 # XXX should this accept an arbitrary sequence?
839 if type(initlist) == type(self.data):
840 self.data[:] = initlist
841 elif isinstance(initlist, UserList):
842 self.data[:] = initlist.data[:]
843 else:
844 self.data = list(initlist)
845 def __repr__(self): return repr(self.data)
846 def __lt__(self, other): return self.data < self.__cast(other)
847 def __le__(self, other): return self.data <= self.__cast(other)
848 def __eq__(self, other): return self.data == self.__cast(other)
849 def __ne__(self, other): return self.data != self.__cast(other)
850 def __gt__(self, other): return self.data > self.__cast(other)
851 def __ge__(self, other): return self.data >= self.__cast(other)
852 def __cast(self, other):
853 return other.data if isinstance(other, UserList) else other
854 def __contains__(self, item): return item in self.data
855 def __len__(self): return len(self.data)
856 def __getitem__(self, i): return self.data[i]
857 def __setitem__(self, i, item): self.data[i] = item
858 def __delitem__(self, i): del self.data[i]
859 def __add__(self, other):
860 if isinstance(other, UserList):
861 return self.__class__(self.data + other.data)
862 elif isinstance(other, type(self.data)):
863 return self.__class__(self.data + other)
864 return self.__class__(self.data + list(other))
865 def __radd__(self, other):
866 if isinstance(other, UserList):
867 return self.__class__(other.data + self.data)
868 elif isinstance(other, type(self.data)):
869 return self.__class__(other + self.data)
870 return self.__class__(list(other) + self.data)
871 def __iadd__(self, other):
872 if isinstance(other, UserList):
873 self.data += other.data
874 elif isinstance(other, type(self.data)):
875 self.data += other
876 else:
877 self.data += list(other)
878 return self
879 def __mul__(self, n):
880 return self.__class__(self.data*n)
881 __rmul__ = __mul__
882 def __imul__(self, n):
883 self.data *= n
884 return self
885 def append(self, item): self.data.append(item)
886 def insert(self, i, item): self.data.insert(i, item)
887 def pop(self, i=-1): return self.data.pop(i)
888 def remove(self, item): self.data.remove(item)
889 def count(self, item): return self.data.count(item)
890 def index(self, item, *args): return self.data.index(item, *args)
891 def reverse(self): self.data.reverse()
892 def sort(self, *args, **kwds): self.data.sort(*args, **kwds)
893 def extend(self, other):
894 if isinstance(other, UserList):
895 self.data.extend(other.data)
896 else:
897 self.data.extend(other)
898
899
900
901################################################################################
902### UserString
903################################################################################
904
905class UserString(Sequence):
906 def __init__(self, seq):
907 if isinstance(seq, str):
908 self.data = seq
909 elif isinstance(seq, UserString):
910 self.data = seq.data[:]
911 else:
912 self.data = str(seq)
913 def __str__(self): return str(self.data)
914 def __repr__(self): return repr(self.data)
915 def __int__(self): return int(self.data)
916 def __float__(self): return float(self.data)
917 def __complex__(self): return complex(self.data)
918 def __hash__(self): return hash(self.data)
919
920 def __eq__(self, string):
921 if isinstance(string, UserString):
922 return self.data == string.data
923 return self.data == string
924 def __ne__(self, string):
925 if isinstance(string, UserString):
926 return self.data != string.data
927 return self.data != string
928 def __lt__(self, string):
929 if isinstance(string, UserString):
930 return self.data < string.data
931 return self.data < string
932 def __le__(self, string):
933 if isinstance(string, UserString):
934 return self.data <= string.data
935 return self.data <= string
936 def __gt__(self, string):
937 if isinstance(string, UserString):
938 return self.data > string.data
939 return self.data > string
940 def __ge__(self, string):
941 if isinstance(string, UserString):
942 return self.data >= string.data
943 return self.data >= string
944
945 def __contains__(self, char):
946 if isinstance(char, UserString):
947 char = char.data
948 return char in self.data
949
950 def __len__(self): return len(self.data)
951 def __getitem__(self, index): return self.__class__(self.data[index])
952 def __add__(self, other):
953 if isinstance(other, UserString):
954 return self.__class__(self.data + other.data)
955 elif isinstance(other, str):
956 return self.__class__(self.data + other)
957 return self.__class__(self.data + str(other))
958 def __radd__(self, other):
959 if isinstance(other, str):
960 return self.__class__(other + self.data)
961 return self.__class__(str(other) + self.data)
962 def __mul__(self, n):
963 return self.__class__(self.data*n)
964 __rmul__ = __mul__
965 def __mod__(self, args):
966 return self.__class__(self.data % args)
967
968 # the following methods are defined in alphabetical order:
969 def capitalize(self): return self.__class__(self.data.capitalize())
970 def center(self, width, *args):
971 return self.__class__(self.data.center(width, *args))
972 def count(self, sub, start=0, end=_sys.maxsize):
973 if isinstance(sub, UserString):
974 sub = sub.data
975 return self.data.count(sub, start, end)
976 def encode(self, encoding=None, errors=None): # XXX improve this?
977 if encoding:
978 if errors:
979 return self.__class__(self.data.encode(encoding, errors))
980 return self.__class__(self.data.encode(encoding))
981 return self.__class__(self.data.encode())
982 def endswith(self, suffix, start=0, end=_sys.maxsize):
983 return self.data.endswith(suffix, start, end)
984 def expandtabs(self, tabsize=8):
985 return self.__class__(self.data.expandtabs(tabsize))
986 def find(self, sub, start=0, end=_sys.maxsize):
987 if isinstance(sub, UserString):
988 sub = sub.data
989 return self.data.find(sub, start, end)
990 def format(self, *args, **kwds):
991 return self.data.format(*args, **kwds)
992 def index(self, sub, start=0, end=_sys.maxsize):
993 return self.data.index(sub, start, end)
994 def isalpha(self): return self.data.isalpha()
995 def isalnum(self): return self.data.isalnum()
996 def isdecimal(self): return self.data.isdecimal()
997 def isdigit(self): return self.data.isdigit()
998 def isidentifier(self): return self.data.isidentifier()
999 def islower(self): return self.data.islower()
1000 def isnumeric(self): return self.data.isnumeric()
1001 def isspace(self): return self.data.isspace()
1002 def istitle(self): return self.data.istitle()
1003 def isupper(self): return self.data.isupper()
1004 def join(self, seq): return self.data.join(seq)
1005 def ljust(self, width, *args):
1006 return self.__class__(self.data.ljust(width, *args))
1007 def lower(self): return self.__class__(self.data.lower())
1008 def lstrip(self, chars=None): return self.__class__(self.data.lstrip(chars))
1009 def partition(self, sep):
1010 return self.data.partition(sep)
1011 def replace(self, old, new, maxsplit=-1):
1012 if isinstance(old, UserString):
1013 old = old.data
1014 if isinstance(new, UserString):
1015 new = new.data
1016 return self.__class__(self.data.replace(old, new, maxsplit))
1017 def rfind(self, sub, start=0, end=_sys.maxsize):
1018 if isinstance(sub, UserString):
1019 sub = sub.data
1020 return self.data.rfind(sub, start, end)
1021 def rindex(self, sub, start=0, end=_sys.maxsize):
1022 return self.data.rindex(sub, start, end)
1023 def rjust(self, width, *args):
1024 return self.__class__(self.data.rjust(width, *args))
1025 def rpartition(self, sep):
1026 return self.data.rpartition(sep)
1027 def rstrip(self, chars=None):
1028 return self.__class__(self.data.rstrip(chars))
1029 def split(self, sep=None, maxsplit=-1):
1030 return self.data.split(sep, maxsplit)
1031 def rsplit(self, sep=None, maxsplit=-1):
1032 return self.data.rsplit(sep, maxsplit)
1033 def splitlines(self, keepends=0): return self.data.splitlines(keepends)
1034 def startswith(self, prefix, start=0, end=_sys.maxsize):
1035 return self.data.startswith(prefix, start, end)
1036 def strip(self, chars=None): return self.__class__(self.data.strip(chars))
1037 def swapcase(self): return self.__class__(self.data.swapcase())
1038 def title(self): return self.__class__(self.data.title())
1039 def translate(self, *args):
1040 return self.__class__(self.data.translate(*args))
1041 def upper(self): return self.__class__(self.data.upper())
1042 def zfill(self, width): return self.__class__(self.data.zfill(width))
1043
1044
1045
1046################################################################################
1047### Simple tests
1048################################################################################
1049
1050if __name__ == '__main__':
1051 # verify that instances can be pickled
1052 from pickle import loads, dumps
1053 Point = namedtuple('Point', 'x, y', True)
1054 p = Point(x=10, y=20)
1055 assert p == loads(dumps(p))
1056
1057 # test and demonstrate ability to override methods
1058 class Point(namedtuple('Point', 'x y')):
1059 __slots__ = ()
1060 @property
1061 def hypot(self):
1062 return (self.x ** 2 + self.y ** 2) ** 0.5
1063 def __str__(self):
1064 return 'Point: x=%6.3f y=%6.3f hypot=%6.3f' % (self.x, self.y, self.hypot)
1065
1066 for p in Point(3, 4), Point(14, 5/7.):
1067 print (p)
1068
1069 class Point(namedtuple('Point', 'x y')):
1070 'Point class with optimized _make() and _replace() without error-checking'
1071 __slots__ = ()
1072 _make = classmethod(tuple.__new__)
1073 def _replace(self, _map=map, **kwds):
1074 return self._make(_map(kwds.get, ('x', 'y'), self))
1075
1076 print(Point(11, 22)._replace(x=100))
1077
1078 Point3D = namedtuple('Point3D', Point._fields + ('z',))
1079 print(Point3D.__doc__)
1080
1081 import doctest
1082 TestResults = namedtuple('TestResults', 'failed attempted')
1083 print(TestResults(*doctest.testmod()))