Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(47)

Side by Side Diff: third_party/google-endpoints/future/backports/misc.py

Issue 2666783008: Add google-endpoints to third_party/. (Closed)
Patch Set: Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 """
2 Miscellaneous function (re)definitions from the Py3.4+ standard library
3 for Python 2.6/2.7.
4
5 - math.ceil (for Python 2.7)
6 - collections.OrderedDict (for Python 2.6)
7 - collections.Counter (for Python 2.6)
8 - collections.ChainMap (for all versions prior to Python 3.3)
9 - itertools.count (for Python 2.6, with step parameter)
10 - subprocess.check_output (for Python 2.6)
11 - reprlib.recursive_repr (for Python 2.6+)
12 - functools.cmp_to_key (for Python 2.6)
13 """
14
15 from __future__ import absolute_import
16
17 import subprocess
18 from math import ceil as oldceil
19 from collections import Mapping, MutableMapping
20
21 from operator import itemgetter as _itemgetter, eq as _eq
22 import sys
23 import heapq as _heapq
24 from _weakref import proxy as _proxy
25 from itertools import repeat as _repeat, chain as _chain, starmap as _starmap
26 from socket import getaddrinfo, SOCK_STREAM, error, socket
27
28 from future.utils import iteritems, itervalues, PY26, PY3
29
30
31 def ceil(x):
32 """
33 Return the ceiling of x as an int.
34 This is the smallest integral value >= x.
35 """
36 return int(oldceil(x))
37
38
39 ########################################################################
40 ### reprlib.recursive_repr decorator from Py3.4
41 ########################################################################
42
43 from itertools import islice
44
45 if PY3:
46 try:
47 from _thread import get_ident
48 except ImportError:
49 from _dummy_thread import get_ident
50 else:
51 try:
52 from thread import get_ident
53 except ImportError:
54 from dummy_thread import get_ident
55
56
57 def recursive_repr(fillvalue='...'):
58 'Decorator to make a repr function return fillvalue for a recursive call'
59
60 def decorating_function(user_function):
61 repr_running = set()
62
63 def wrapper(self):
64 key = id(self), get_ident()
65 if key in repr_running:
66 return fillvalue
67 repr_running.add(key)
68 try:
69 result = user_function(self)
70 finally:
71 repr_running.discard(key)
72 return result
73
74 # Can't use functools.wraps() here because of bootstrap issues
75 wrapper.__module__ = getattr(user_function, '__module__')
76 wrapper.__doc__ = getattr(user_function, '__doc__')
77 wrapper.__name__ = getattr(user_function, '__name__')
78 wrapper.__annotations__ = getattr(user_function, '__annotations__', {})
79 return wrapper
80
81 return decorating_function
82
83
84 ################################################################################
85 ### OrderedDict
86 ################################################################################
87
88 class _Link(object):
89 __slots__ = 'prev', 'next', 'key', '__weakref__'
90
91 class OrderedDict(dict):
92 'Dictionary that remembers insertion order'
93 # An inherited dict maps keys to values.
94 # The inherited dict provides __getitem__, __len__, __contains__, and get.
95 # The remaining methods are order-aware.
96 # Big-O running times for all methods are the same as regular dictionaries.
97
98 # The internal self.__map dict maps keys to links in a doubly linked list.
99 # The circular doubly linked list starts and ends with a sentinel element.
100 # The sentinel element never gets deleted (this simplifies the algorithm).
101 # The sentinel is in self.__hardroot with a weakref proxy in self.__root.
102 # The prev links are weakref proxies (to prevent circular references).
103 # Individual links are kept alive by the hard reference in self.__map.
104 # Those hard references disappear when a key is deleted from an OrderedDict.
105
106 def __init__(*args, **kwds):
107 '''Initialize an ordered dictionary. The signature is the same as
108 regular dictionaries, but keyword arguments are not recommended because
109 their insertion order is arbitrary.
110
111 '''
112 if not args:
113 raise TypeError("descriptor '__init__' of 'OrderedDict' object "
114 "needs an argument")
115 self = args[0]
116 args = args[1:]
117 if len(args) > 1:
118 raise TypeError('expected at most 1 arguments, got %d' % len(args))
119 try:
120 self.__root
121 except AttributeError:
122 self.__hardroot = _Link()
123 self.__root = root = _proxy(self.__hardroot)
124 root.prev = root.next = root
125 self.__map = {}
126 self.__update(*args, **kwds)
127
128 def __setitem__(self, key, value,
129 dict_setitem=dict.__setitem__, proxy=_proxy, Link=_Link):
130 'od.__setitem__(i, y) <==> od[i]=y'
131 # Setting a new item creates a new link at the end of the linked list,
132 # and the inherited dictionary is updated with the new key/value pair.
133 if key not in self:
134 self.__map[key] = link = Link()
135 root = self.__root
136 last = root.prev
137 link.prev, link.next, link.key = last, root, key
138 last.next = link
139 root.prev = proxy(link)
140 dict_setitem(self, key, value)
141
142 def __delitem__(self, key, dict_delitem=dict.__delitem__):
143 'od.__delitem__(y) <==> del od[y]'
144 # Deleting an existing item uses self.__map to find the link which gets
145 # removed by updating the links in the predecessor and successor nodes.
146 dict_delitem(self, key)
147 link = self.__map.pop(key)
148 link_prev = link.prev
149 link_next = link.next
150 link_prev.next = link_next
151 link_next.prev = link_prev
152
153 def __iter__(self):
154 'od.__iter__() <==> iter(od)'
155 # Traverse the linked list in order.
156 root = self.__root
157 curr = root.next
158 while curr is not root:
159 yield curr.key
160 curr = curr.next
161
162 def __reversed__(self):
163 'od.__reversed__() <==> reversed(od)'
164 # Traverse the linked list in reverse order.
165 root = self.__root
166 curr = root.prev
167 while curr is not root:
168 yield curr.key
169 curr = curr.prev
170
171 def clear(self):
172 'od.clear() -> None. Remove all items from od.'
173 root = self.__root
174 root.prev = root.next = root
175 self.__map.clear()
176 dict.clear(self)
177
178 def popitem(self, last=True):
179 '''od.popitem() -> (k, v), return and remove a (key, value) pair.
180 Pairs are returned in LIFO order if last is true or FIFO order if false.
181
182 '''
183 if not self:
184 raise KeyError('dictionary is empty')
185 root = self.__root
186 if last:
187 link = root.prev
188 link_prev = link.prev
189 link_prev.next = root
190 root.prev = link_prev
191 else:
192 link = root.next
193 link_next = link.next
194 root.next = link_next
195 link_next.prev = root
196 key = link.key
197 del self.__map[key]
198 value = dict.pop(self, key)
199 return key, value
200
201 def move_to_end(self, key, last=True):
202 '''Move an existing element to the end (or beginning if last==False).
203
204 Raises KeyError if the element does not exist.
205 When last=True, acts like a fast version of self[key]=self.pop(key).
206
207 '''
208 link = self.__map[key]
209 link_prev = link.prev
210 link_next = link.next
211 link_prev.next = link_next
212 link_next.prev = link_prev
213 root = self.__root
214 if last:
215 last = root.prev
216 link.prev = last
217 link.next = root
218 last.next = root.prev = link
219 else:
220 first = root.next
221 link.prev = root
222 link.next = first
223 root.next = first.prev = link
224
225 def __sizeof__(self):
226 sizeof = sys.getsizeof
227 n = len(self) + 1 # number of links including root
228 size = sizeof(self.__dict__) # instance dictionary
229 size += sizeof(self.__map) * 2 # internal dict and inherited di ct
230 size += sizeof(self.__hardroot) * n # link objects
231 size += sizeof(self.__root) * n # proxy objects
232 return size
233
234 update = __update = MutableMapping.update
235 keys = MutableMapping.keys
236 values = MutableMapping.values
237 items = MutableMapping.items
238 __ne__ = MutableMapping.__ne__
239
240 __marker = object()
241
242 def pop(self, key, default=__marker):
243 '''od.pop(k[,d]) -> v, remove specified key and return the corresponding
244 value. If key is not found, d is returned if given, otherwise KeyError
245 is raised.
246
247 '''
248 if key in self:
249 result = self[key]
250 del self[key]
251 return result
252 if default is self.__marker:
253 raise KeyError(key)
254 return default
255
256 def setdefault(self, key, default=None):
257 'od.setdefault(k[,d]) -> od.get(k,d), also set od[k]=d if k not in od'
258 if key in self:
259 return self[key]
260 self[key] = default
261 return default
262
263 @recursive_repr()
264 def __repr__(self):
265 'od.__repr__() <==> repr(od)'
266 if not self:
267 return '%s()' % (self.__class__.__name__,)
268 return '%s(%r)' % (self.__class__.__name__, list(self.items()))
269
270 def __reduce__(self):
271 'Return state information for pickling'
272 inst_dict = vars(self).copy()
273 for k in vars(OrderedDict()):
274 inst_dict.pop(k, None)
275 return self.__class__, (), inst_dict or None, None, iter(self.items())
276
277 def copy(self):
278 'od.copy() -> a shallow copy of od'
279 return self.__class__(self)
280
281 @classmethod
282 def fromkeys(cls, iterable, value=None):
283 '''OD.fromkeys(S[, v]) -> New ordered dictionary with keys from S.
284 If not specified, the value defaults to None.
285
286 '''
287 self = cls()
288 for key in iterable:
289 self[key] = value
290 return self
291
292 def __eq__(self, other):
293 '''od.__eq__(y) <==> od==y. Comparison to another OD is order-sensitive
294 while comparison to a regular mapping is order-insensitive.
295
296 '''
297 if isinstance(other, OrderedDict):
298 return dict.__eq__(self, other) and all(map(_eq, self, other))
299 return dict.__eq__(self, other)
300
301
302 # {{{ http://code.activestate.com/recipes/576611/ (r11)
303
304 try:
305 from operator import itemgetter
306 from heapq import nlargest
307 except ImportError:
308 pass
309
310 ########################################################################
311 ### Counter
312 ########################################################################
313
314 def _count_elements(mapping, iterable):
315 'Tally elements from the iterable.'
316 mapping_get = mapping.get
317 for elem in iterable:
318 mapping[elem] = mapping_get(elem, 0) + 1
319
320 class Counter(dict):
321 '''Dict subclass for counting hashable items. Sometimes called a bag
322 or multiset. Elements are stored as dictionary keys and their counts
323 are stored as dictionary values.
324
325 >>> c = Counter('abcdeabcdabcaba') # count elements from a string
326
327 >>> c.most_common(3) # three most common elements
328 [('a', 5), ('b', 4), ('c', 3)]
329 >>> sorted(c) # list all unique elements
330 ['a', 'b', 'c', 'd', 'e']
331 >>> ''.join(sorted(c.elements())) # list elements with repetitions
332 'aaaaabbbbcccdde'
333 >>> sum(c.values()) # total of all counts
334 15
335
336 >>> c['a'] # count of letter 'a'
337 5
338 >>> for elem in 'shazam': # update counts from an iterable
339 ... c[elem] += 1 # by adding 1 to each element's count
340 >>> c['a'] # now there are seven 'a'
341 7
342 >>> del c['b'] # remove all 'b'
343 >>> c['b'] # now there are zero 'b'
344 0
345
346 >>> d = Counter('simsalabim') # make another counter
347 >>> c.update(d) # add in the second counter
348 >>> c['a'] # now there are nine 'a'
349 9
350
351 >>> c.clear() # empty the counter
352 >>> c
353 Counter()
354
355 Note: If a count is set to zero or reduced to zero, it will remain
356 in the counter until the entry is deleted or the counter is cleared:
357
358 >>> c = Counter('aaabbc')
359 >>> c['b'] -= 2 # reduce the count of 'b' by two
360 >>> c.most_common() # 'b' is still in, but its count is zero
361 [('a', 3), ('c', 1), ('b', 0)]
362
363 '''
364 # References:
365 # http://en.wikipedia.org/wiki/Multiset
366 # http://www.gnu.org/software/smalltalk/manual-base/html_node/Bag.html
367 # http://www.demo2s.com/Tutorial/Cpp/0380__set-multiset/Catalog0380__set-m ultiset.htm
368 # http://code.activestate.com/recipes/259174/
369 # Knuth, TAOCP Vol. II section 4.6.3
370
371 def __init__(*args, **kwds):
372 '''Create a new, empty Counter object. And if given, count elements
373 from an input iterable. Or, initialize the count from another mapping
374 of elements to their counts.
375
376 >>> c = Counter() # a new, empty counter
377 >>> c = Counter('gallahad') # a new counter from an iter able
378 >>> c = Counter({'a': 4, 'b': 2}) # a new counter from a mappi ng
379 >>> c = Counter(a=4, b=2) # a new counter from keyword args
380
381 '''
382 if not args:
383 raise TypeError("descriptor '__init__' of 'Counter' object "
384 "needs an argument")
385 self = args[0]
386 args = args[1:]
387 if len(args) > 1:
388 raise TypeError('expected at most 1 arguments, got %d' % len(args))
389 super(Counter, self).__init__()
390 self.update(*args, **kwds)
391
392 def __missing__(self, key):
393 'The count of elements not in the Counter is zero.'
394 # Needed so that self[missing_item] does not raise KeyError
395 return 0
396
397 def most_common(self, n=None):
398 '''List the n most common elements and their counts from the most
399 common to the least. If n is None, then list all element counts.
400
401 >>> Counter('abcdeabcdabcaba').most_common(3)
402 [('a', 5), ('b', 4), ('c', 3)]
403
404 '''
405 # Emulate Bag.sortedByCount from Smalltalk
406 if n is None:
407 return sorted(self.items(), key=_itemgetter(1), reverse=True)
408 return _heapq.nlargest(n, self.items(), key=_itemgetter(1))
409
410 def elements(self):
411 '''Iterator over elements repeating each as many times as its count.
412
413 >>> c = Counter('ABCABC')
414 >>> sorted(c.elements())
415 ['A', 'A', 'B', 'B', 'C', 'C']
416
417 # Knuth's example for prime factors of 1836: 2**2 * 3**3 * 17**1
418 >>> prime_factors = Counter({2: 2, 3: 3, 17: 1})
419 >>> product = 1
420 >>> for factor in prime_factors.elements(): # loop over factors
421 ... product *= factor # and multiply them
422 >>> product
423 1836
424
425 Note, if an element's count has been set to zero or is a negative
426 number, elements() will ignore it.
427
428 '''
429 # Emulate Bag.do from Smalltalk and Multiset.begin from C++.
430 return _chain.from_iterable(_starmap(_repeat, self.items()))
431
432 # Override dict methods where necessary
433
434 @classmethod
435 def fromkeys(cls, iterable, v=None):
436 # There is no equivalent method for counters because setting v=1
437 # means that no element can have a count greater than one.
438 raise NotImplementedError(
439 'Counter.fromkeys() is undefined. Use Counter(iterable) instead.')
440
441 def update(*args, **kwds):
442 '''Like dict.update() but add counts instead of replacing them.
443
444 Source can be an iterable, a dictionary, or another Counter instance.
445
446 >>> c = Counter('which')
447 >>> c.update('witch') # add elements from another iterable
448 >>> d = Counter('watch')
449 >>> c.update(d) # add elements from another counter
450 >>> c['h'] # four 'h' in which, witch, and watch
451 4
452
453 '''
454 # The regular dict.update() operation makes no sense here because the
455 # replace behavior results in the some of original untouched counts
456 # being mixed-in with all of the other counts for a mismash that
457 # doesn't have a straight-forward interpretation in most counting
458 # contexts. Instead, we implement straight-addition. Both the inputs
459 # and outputs are allowed to contain zero and negative counts.
460
461 if not args:
462 raise TypeError("descriptor 'update' of 'Counter' object "
463 "needs an argument")
464 self = args[0]
465 args = args[1:]
466 if len(args) > 1:
467 raise TypeError('expected at most 1 arguments, got %d' % len(args))
468 iterable = args[0] if args else None
469 if iterable is not None:
470 if isinstance(iterable, Mapping):
471 if self:
472 self_get = self.get
473 for elem, count in iterable.items():
474 self[elem] = count + self_get(elem, 0)
475 else:
476 super(Counter, self).update(iterable) # fast path when count er is empty
477 else:
478 _count_elements(self, iterable)
479 if kwds:
480 self.update(kwds)
481
482 def subtract(*args, **kwds):
483 '''Like dict.update() but subtracts counts instead of replacing them.
484 Counts can be reduced below zero. Both the inputs and outputs are
485 allowed to contain zero and negative counts.
486
487 Source can be an iterable, a dictionary, or another Counter instance.
488
489 >>> c = Counter('which')
490 >>> c.subtract('witch') # subtract elements from another ite rable
491 >>> c.subtract(Counter('watch')) # subtract elements from another cou nter
492 >>> c['h'] # 2 in which, minus 1 in witch, minu s 1 in watch
493 0
494 >>> c['w'] # 1 in which, minus 1 in witch, minu s 1 in watch
495 -1
496
497 '''
498 if not args:
499 raise TypeError("descriptor 'subtract' of 'Counter' object "
500 "needs an argument")
501 self = args[0]
502 args = args[1:]
503 if len(args) > 1:
504 raise TypeError('expected at most 1 arguments, got %d' % len(args))
505 iterable = args[0] if args else None
506 if iterable is not None:
507 self_get = self.get
508 if isinstance(iterable, Mapping):
509 for elem, count in iterable.items():
510 self[elem] = self_get(elem, 0) - count
511 else:
512 for elem in iterable:
513 self[elem] = self_get(elem, 0) - 1
514 if kwds:
515 self.subtract(kwds)
516
517 def copy(self):
518 'Return a shallow copy.'
519 return self.__class__(self)
520
521 def __reduce__(self):
522 return self.__class__, (dict(self),)
523
524 def __delitem__(self, elem):
525 'Like dict.__delitem__() but does not raise KeyError for missing values. '
526 if elem in self:
527 super(Counter, self).__delitem__(elem)
528
529 def __repr__(self):
530 if not self:
531 return '%s()' % self.__class__.__name__
532 try:
533 items = ', '.join(map('%r: %r'.__mod__, self.most_common()))
534 return '%s({%s})' % (self.__class__.__name__, items)
535 except TypeError:
536 # handle case where values are not orderable
537 return '{0}({1!r})'.format(self.__class__.__name__, dict(self))
538
539 # Multiset-style mathematical operations discussed in:
540 # Knuth TAOCP Volume II section 4.6.3 exercise 19
541 # and at http://en.wikipedia.org/wiki/Multiset
542 #
543 # Outputs guaranteed to only include positive counts.
544 #
545 # To strip negative and zero counts, add-in an empty counter:
546 # c += Counter()
547
548 def __add__(self, other):
549 '''Add counts from two counters.
550
551 >>> Counter('abbb') + Counter('bcc')
552 Counter({'b': 4, 'c': 2, 'a': 1})
553
554 '''
555 if not isinstance(other, Counter):
556 return NotImplemented
557 result = Counter()
558 for elem, count in self.items():
559 newcount = count + other[elem]
560 if newcount > 0:
561 result[elem] = newcount
562 for elem, count in other.items():
563 if elem not in self and count > 0:
564 result[elem] = count
565 return result
566
567 def __sub__(self, other):
568 ''' Subtract count, but keep only results with positive counts.
569
570 >>> Counter('abbbc') - Counter('bccd')
571 Counter({'b': 2, 'a': 1})
572
573 '''
574 if not isinstance(other, Counter):
575 return NotImplemented
576 result = Counter()
577 for elem, count in self.items():
578 newcount = count - other[elem]
579 if newcount > 0:
580 result[elem] = newcount
581 for elem, count in other.items():
582 if elem not in self and count < 0:
583 result[elem] = 0 - count
584 return result
585
586 def __or__(self, other):
587 '''Union is the maximum of value in either of the input counters.
588
589 >>> Counter('abbb') | Counter('bcc')
590 Counter({'b': 3, 'c': 2, 'a': 1})
591
592 '''
593 if not isinstance(other, Counter):
594 return NotImplemented
595 result = Counter()
596 for elem, count in self.items():
597 other_count = other[elem]
598 newcount = other_count if count < other_count else count
599 if newcount > 0:
600 result[elem] = newcount
601 for elem, count in other.items():
602 if elem not in self and count > 0:
603 result[elem] = count
604 return result
605
606 def __and__(self, other):
607 ''' Intersection is the minimum of corresponding counts.
608
609 >>> Counter('abbb') & Counter('bcc')
610 Counter({'b': 1})
611
612 '''
613 if not isinstance(other, Counter):
614 return NotImplemented
615 result = Counter()
616 for elem, count in self.items():
617 other_count = other[elem]
618 newcount = count if count < other_count else other_count
619 if newcount > 0:
620 result[elem] = newcount
621 return result
622
623 def __pos__(self):
624 'Adds an empty counter, effectively stripping negative and zero counts'
625 return self + Counter()
626
627 def __neg__(self):
628 '''Subtracts from an empty counter. Strips positive and zero counts,
629 and flips the sign on negative counts.
630
631 '''
632 return Counter() - self
633
634 def _keep_positive(self):
635 '''Internal method to strip elements with a negative or zero count'''
636 nonpositive = [elem for elem, count in self.items() if not count > 0]
637 for elem in nonpositive:
638 del self[elem]
639 return self
640
641 def __iadd__(self, other):
642 '''Inplace add from another counter, keeping only positive counts.
643
644 >>> c = Counter('abbb')
645 >>> c += Counter('bcc')
646 >>> c
647 Counter({'b': 4, 'c': 2, 'a': 1})
648
649 '''
650 for elem, count in other.items():
651 self[elem] += count
652 return self._keep_positive()
653
654 def __isub__(self, other):
655 '''Inplace subtract counter, but keep only results with positive counts.
656
657 >>> c = Counter('abbbc')
658 >>> c -= Counter('bccd')
659 >>> c
660 Counter({'b': 2, 'a': 1})
661
662 '''
663 for elem, count in other.items():
664 self[elem] -= count
665 return self._keep_positive()
666
667 def __ior__(self, other):
668 '''Inplace union is the maximum of value from either counter.
669
670 >>> c = Counter('abbb')
671 >>> c |= Counter('bcc')
672 >>> c
673 Counter({'b': 3, 'c': 2, 'a': 1})
674
675 '''
676 for elem, other_count in other.items():
677 count = self[elem]
678 if other_count > count:
679 self[elem] = other_count
680 return self._keep_positive()
681
682 def __iand__(self, other):
683 '''Inplace intersection is the minimum of corresponding counts.
684
685 >>> c = Counter('abbb')
686 >>> c &= Counter('bcc')
687 >>> c
688 Counter({'b': 1})
689
690 '''
691 for elem, count in self.items():
692 other_count = other[elem]
693 if other_count < count:
694 self[elem] = other_count
695 return self._keep_positive()
696
697
698 def check_output(*popenargs, **kwargs):
699 """
700 For Python 2.6 compatibility: see
701 http://stackoverflow.com/questions/4814970/
702 """
703
704 if 'stdout' in kwargs:
705 raise ValueError('stdout argument not allowed, it will be overridden.')
706 process = subprocess.Popen(stdout=subprocess.PIPE, *popenargs, **kwargs)
707 output, unused_err = process.communicate()
708 retcode = process.poll()
709 if retcode:
710 cmd = kwargs.get("args")
711 if cmd is None:
712 cmd = popenargs[0]
713 raise subprocess.CalledProcessError(retcode, cmd)
714 return output
715
716
717 def count(start=0, step=1):
718 """
719 ``itertools.count`` in Py 2.6 doesn't accept a step
720 parameter. This is an enhanced version of ``itertools.count``
721 for Py2.6 equivalent to ``itertools.count`` in Python 2.7+.
722 """
723 while True:
724 yield start
725 start += step
726
727
728 ########################################################################
729 ### ChainMap (helper for configparser and string.Template)
730 ### From the Py3.4 source code. See also:
731 ### https://github.com/kkxue/Py2ChainMap/blob/master/py2chainmap.py
732 ########################################################################
733
734 class ChainMap(MutableMapping):
735 ''' A ChainMap groups multiple dicts (or other mappings) together
736 to create a single, updateable view.
737
738 The underlying mappings are stored in a list. That list is public and can
739 accessed or updated using the *maps* attribute. There is no other state.
740
741 Lookups search the underlying mappings successively until a key is found.
742 In contrast, writes, updates, and deletions only operate on the first
743 mapping.
744
745 '''
746
747 def __init__(self, *maps):
748 '''Initialize a ChainMap by setting *maps* to the given mappings.
749 If no mappings are provided, a single empty dictionary is used.
750
751 '''
752 self.maps = list(maps) or [{}] # always at least one map
753
754 def __missing__(self, key):
755 raise KeyError(key)
756
757 def __getitem__(self, key):
758 for mapping in self.maps:
759 try:
760 return mapping[key] # can't use 'key in mapping' wit h defaultdict
761 except KeyError:
762 pass
763 return self.__missing__(key) # support subclasses that define __missing__
764
765 def get(self, key, default=None):
766 return self[key] if key in self else default
767
768 def __len__(self):
769 return len(set().union(*self.maps)) # reuses stored hash values if p ossible
770
771 def __iter__(self):
772 return iter(set().union(*self.maps))
773
774 def __contains__(self, key):
775 return any(key in m for m in self.maps)
776
777 def __bool__(self):
778 return any(self.maps)
779
780 # Py2 compatibility:
781 __nonzero__ = __bool__
782
783 @recursive_repr()
784 def __repr__(self):
785 return '{0.__class__.__name__}({1})'.format(
786 self, ', '.join(map(repr, self.maps)))
787
788 @classmethod
789 def fromkeys(cls, iterable, *args):
790 'Create a ChainMap with a single dict created from the iterable.'
791 return cls(dict.fromkeys(iterable, *args))
792
793 def copy(self):
794 'New ChainMap or subclass with a new copy of maps[0] and refs to maps[1: ]'
795 return self.__class__(self.maps[0].copy(), *self.maps[1:])
796
797 __copy__ = copy
798
799 def new_child(self, m=None): # like Django's Context.push()
800 '''
801 New ChainMap with a new map followed by all previous maps. If no
802 map is provided, an empty dict is used.
803 '''
804 if m is None:
805 m = {}
806 return self.__class__(m, *self.maps)
807
808 @property
809 def parents(self): # like Django's Context.pop()
810 'New ChainMap from maps[1:].'
811 return self.__class__(*self.maps[1:])
812
813 def __setitem__(self, key, value):
814 self.maps[0][key] = value
815
816 def __delitem__(self, key):
817 try:
818 del self.maps[0][key]
819 except KeyError:
820 raise KeyError('Key not found in the first mapping: {!r}'.format(key ))
821
822 def popitem(self):
823 'Remove and return an item pair from maps[0]. Raise KeyError is maps[0] is empty.'
824 try:
825 return self.maps[0].popitem()
826 except KeyError:
827 raise KeyError('No keys found in the first mapping.')
828
829 def pop(self, key, *args):
830 'Remove *key* from maps[0] and return its value. Raise KeyError if *key* not in maps[0].'
831 try:
832 return self.maps[0].pop(key, *args)
833 except KeyError:
834 raise KeyError('Key not found in the first mapping: {!r}'.format(key ))
835
836 def clear(self):
837 'Clear maps[0], leaving maps[1:] intact.'
838 self.maps[0].clear()
839
840
841 # Re-use the same sentinel as in the Python stdlib socket module:
842 from socket import _GLOBAL_DEFAULT_TIMEOUT
843 # Was: _GLOBAL_DEFAULT_TIMEOUT = object()
844
845
846 def create_connection(address, timeout=_GLOBAL_DEFAULT_TIMEOUT,
847 source_address=None):
848 """Backport of 3-argument create_connection() for Py2.6.
849
850 Connect to *address* and return the socket object.
851
852 Convenience function. Connect to *address* (a 2-tuple ``(host,
853 port)``) and return the socket object. Passing the optional
854 *timeout* parameter will set the timeout on the socket instance
855 before attempting to connect. If no *timeout* is supplied, the
856 global default timeout setting returned by :func:`getdefaulttimeout`
857 is used. If *source_address* is set it must be a tuple of (host, port)
858 for the socket to bind as a source address before making the connection.
859 An host of '' or port 0 tells the OS to use the default.
860 """
861
862 host, port = address
863 err = None
864 for res in getaddrinfo(host, port, 0, SOCK_STREAM):
865 af, socktype, proto, canonname, sa = res
866 sock = None
867 try:
868 sock = socket(af, socktype, proto)
869 if timeout is not _GLOBAL_DEFAULT_TIMEOUT:
870 sock.settimeout(timeout)
871 if source_address:
872 sock.bind(source_address)
873 sock.connect(sa)
874 return sock
875
876 except error as _:
877 err = _
878 if sock is not None:
879 sock.close()
880
881 if err is not None:
882 raise err
883 else:
884 raise error("getaddrinfo returns an empty list")
885
886 # Backport from Py2.7 for Py2.6:
887 def cmp_to_key(mycmp):
888 """Convert a cmp= function into a key= function"""
889 class K(object):
890 __slots__ = ['obj']
891 def __init__(self, obj, *args):
892 self.obj = obj
893 def __lt__(self, other):
894 return mycmp(self.obj, other.obj) < 0
895 def __gt__(self, other):
896 return mycmp(self.obj, other.obj) > 0
897 def __eq__(self, other):
898 return mycmp(self.obj, other.obj) == 0
899 def __le__(self, other):
900 return mycmp(self.obj, other.obj) <= 0
901 def __ge__(self, other):
902 return mycmp(self.obj, other.obj) >= 0
903 def __ne__(self, other):
904 return mycmp(self.obj, other.obj) != 0
905 def __hash__(self):
906 raise TypeError('hash not implemented')
907 return K
908
909 # Back up our definitions above in case they're useful
910 _OrderedDict = OrderedDict
911 _Counter = Counter
912 _check_output = check_output
913 _count = count
914 _ceil = ceil
915 __count_elements = _count_elements
916 _recursive_repr = recursive_repr
917 _ChainMap = ChainMap
918 _create_connection = create_connection
919 _cmp_to_key = cmp_to_key
920
921 # Overwrite the definitions above with the usual ones
922 # from the standard library:
923 if sys.version_info >= (2, 7):
924 from collections import OrderedDict, Counter
925 from itertools import count
926 from functools import cmp_to_key
927 try:
928 from subprocess import check_output
929 except ImportError:
930 # Not available. This happens with Google App Engine: see issue #231
931 pass
932 from socket import create_connection
933
934 if sys.version_info >= (3, 0):
935 from math import ceil
936 from collections import _count_elements
937
938 if sys.version_info >= (3, 3):
939 from reprlib import recursive_repr
940 from collections import ChainMap
OLDNEW
« no previous file with comments | « third_party/google-endpoints/future/backports/http/server.py ('k') | third_party/google-endpoints/future/backports/socket.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698