|
@@ -1,963 +0,0 @@
|
|
|
-# _compat.py -- For dealing with python2.6 oddness
|
|
|
-# Copyright (C) 2012-2014 Jelmer Vernooij and others.
|
|
|
-#
|
|
|
-# This program is free software; you can redistribute it and/or
|
|
|
-# modify it under the terms of the GNU General Public License
|
|
|
-# as published by the Free Software Foundation; version 2
|
|
|
-# of the License or (at your option) a later version of the License.
|
|
|
-#
|
|
|
-# This program is distributed in the hope that it will be useful,
|
|
|
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
-# GNU General Public License for more details.
|
|
|
-#
|
|
|
-# You should have received a copy of the GNU General Public License
|
|
|
-# along with this program; if not, write to the Free Software
|
|
|
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
|
-# MA 02110-1301, USA.
|
|
|
-
|
|
|
-"""Misc utilities to work with python <2.7.
|
|
|
-
|
|
|
-These utilities can all be deleted when dulwich decides it wants to stop
|
|
|
-support for python <2.7.
|
|
|
-"""
|
|
|
-
|
|
|
-# Backport of OrderedDict() class that runs on Python 2.4, 2.5, 2.6, 2.7 and
|
|
|
-# pypy. Passes Python2.7's test suite and incorporates all the latest updates.
|
|
|
-# Copyright (C) Raymond Hettinger, MIT license
|
|
|
-
|
|
|
-try:
|
|
|
- from thread import get_ident as _get_ident
|
|
|
-except ImportError:
|
|
|
- from dummy_thread import get_ident as _get_ident
|
|
|
-
|
|
|
-try:
|
|
|
- from _abcoll import KeysView, ValuesView, ItemsView
|
|
|
-except ImportError:
|
|
|
- pass
|
|
|
-
|
|
|
-class OrderedDict(dict):
|
|
|
- 'Dictionary that remembers insertion order'
|
|
|
- # An inherited dict maps keys to values.
|
|
|
- # The inherited dict provides __getitem__, __len__, __contains__, and get.
|
|
|
- # The remaining methods are order-aware.
|
|
|
- # Big-O running times for all methods are the same as for regular
|
|
|
- # dictionaries.
|
|
|
-
|
|
|
- # The internal self.__map dictionary maps keys to links in a doubly linked
|
|
|
- # list. The circular doubly linked list starts and ends with a sentinel
|
|
|
- # element. The sentinel element never gets deleted (this simplifies the
|
|
|
- # algorithm). Each link is stored as a list of length three: [PREV, NEXT,
|
|
|
- # KEY].
|
|
|
-
|
|
|
- def __init__(self, *args, **kwds):
|
|
|
- '''Initialize an ordered dictionary. Signature is the same as for
|
|
|
- regular dictionaries, but keyword arguments are not recommended
|
|
|
- because their insertion order is arbitrary.
|
|
|
-
|
|
|
- '''
|
|
|
- if len(args) > 1:
|
|
|
- raise TypeError('expected at most 1 arguments, got %d' % len(args))
|
|
|
- try:
|
|
|
- self.__root
|
|
|
- except AttributeError:
|
|
|
- self.__root = root = [] # sentinel node
|
|
|
- root[:] = [root, root, None]
|
|
|
- self.__map = {}
|
|
|
- self.__update(*args, **kwds)
|
|
|
-
|
|
|
- def __setitem__(self, key, value, dict_setitem=dict.__setitem__):
|
|
|
- 'od.__setitem__(i, y) <==> od[i]=y'
|
|
|
- # Setting a new item creates a new link which goes at the end of the
|
|
|
- # linked list, and the inherited dictionary is updated with the new
|
|
|
- # key/value pair.
|
|
|
- if key not in self:
|
|
|
- root = self.__root
|
|
|
- last = root[0]
|
|
|
- last[1] = root[0] = self.__map[key] = [last, root, key]
|
|
|
- dict_setitem(self, key, value)
|
|
|
-
|
|
|
- def __delitem__(self, key, dict_delitem=dict.__delitem__):
|
|
|
- 'od.__delitem__(y) <==> del od[y]'
|
|
|
- # Deleting an existing item uses self.__map to find the link which is
|
|
|
- # then removed by updating the links in the predecessor and successor
|
|
|
- # nodes.
|
|
|
- dict_delitem(self, key)
|
|
|
- link_prev, link_next, key = self.__map.pop(key)
|
|
|
- link_prev[1] = link_next
|
|
|
- link_next[0] = link_prev
|
|
|
-
|
|
|
- def __iter__(self):
|
|
|
- 'od.__iter__() <==> iter(od)'
|
|
|
- root = self.__root
|
|
|
- curr = root[1]
|
|
|
- while curr is not root:
|
|
|
- yield curr[2]
|
|
|
- curr = curr[1]
|
|
|
-
|
|
|
- def __reversed__(self):
|
|
|
- 'od.__reversed__() <==> reversed(od)'
|
|
|
- root = self.__root
|
|
|
- curr = root[0]
|
|
|
- while curr is not root:
|
|
|
- yield curr[2]
|
|
|
- curr = curr[0]
|
|
|
-
|
|
|
- def clear(self):
|
|
|
- 'od.clear() -> None. Remove all items from od.'
|
|
|
- try:
|
|
|
- for node in self.__map.itervalues():
|
|
|
- del node[:]
|
|
|
- root = self.__root
|
|
|
- root[:] = [root, root, None]
|
|
|
- self.__map.clear()
|
|
|
- except AttributeError:
|
|
|
- pass
|
|
|
- dict.clear(self)
|
|
|
-
|
|
|
- def popitem(self, last=True):
|
|
|
- """od.popitem() -> (k, v), return and remove a (key, value) pair.
|
|
|
- Pairs are returned in LIFO order if last is true or FIFO order if false.
|
|
|
-
|
|
|
- """
|
|
|
- if not self:
|
|
|
- raise KeyError('dictionary is empty')
|
|
|
- root = self.__root
|
|
|
- if last:
|
|
|
- link = root[0]
|
|
|
- link_prev = link[0]
|
|
|
- link_prev[1] = root
|
|
|
- root[0] = link_prev
|
|
|
- else:
|
|
|
- link = root[1]
|
|
|
- link_next = link[1]
|
|
|
- root[1] = link_next
|
|
|
- link_next[0] = root
|
|
|
- key = link[2]
|
|
|
- del self.__map[key]
|
|
|
- value = dict.pop(self, key)
|
|
|
- return key, value
|
|
|
-
|
|
|
- # -- the following methods do not depend on the internal structure --
|
|
|
-
|
|
|
- def keys(self):
|
|
|
- """'od.keys() -> list of keys in od"""
|
|
|
- return list(self)
|
|
|
-
|
|
|
- def values(self):
|
|
|
- """od.values() -> list of values in od"""
|
|
|
- return [self[key] for key in self]
|
|
|
-
|
|
|
- def items(self):
|
|
|
- """od.items() -> list of (key, value) pairs in od"""
|
|
|
- return [(key, self[key]) for key in self]
|
|
|
-
|
|
|
- def iterkeys(self):
|
|
|
- """od.iterkeys() -> an iterator over the keys in od"""
|
|
|
- return iter(self)
|
|
|
-
|
|
|
- def itervalues(self):
|
|
|
- """od.itervalues -> an iterator over the values in od"""
|
|
|
- for k in self:
|
|
|
- yield self[k]
|
|
|
-
|
|
|
- def iteritems(self):
|
|
|
- """od.iteritems -> an iterator over the (key, value) items in od"""
|
|
|
- for k in self:
|
|
|
- yield (k, self[k])
|
|
|
-
|
|
|
- def update(*args, **kwds):
|
|
|
- """od.update(E, F) -> None. Update od from dict/iterable E and F.
|
|
|
-
|
|
|
- If E is a dict instance, does: for k in E: od[k] = E[k]
|
|
|
- If E has a .keys() method, does: for k in E.keys(): od[k] = E[k]
|
|
|
- Or if E is an iterable of items, does: for k, v in E: od[k] = v
|
|
|
- In either case, this is followed by: for k, v in F.items(): od[k] = v
|
|
|
- """
|
|
|
- if len(args) > 2:
|
|
|
- raise TypeError('update() takes at most 2 positional '
|
|
|
- 'arguments (%d given)' % (len(args),))
|
|
|
- elif not args:
|
|
|
- raise TypeError('update() takes at least 1 argument (0 given)')
|
|
|
- self = args[0]
|
|
|
- # Make progressively weaker assumptions about "other"
|
|
|
- other = ()
|
|
|
- if len(args) == 2:
|
|
|
- other = args[1]
|
|
|
- if isinstance(other, dict):
|
|
|
- for key in other:
|
|
|
- self[key] = other[key]
|
|
|
- elif hasattr(other, 'keys'):
|
|
|
- for key in other.keys():
|
|
|
- self[key] = other[key]
|
|
|
- else:
|
|
|
- for key, value in other:
|
|
|
- self[key] = value
|
|
|
- for key, value in kwds.items():
|
|
|
- self[key] = value
|
|
|
-
|
|
|
- __update = update # let subclasses override update without breaking
|
|
|
- # __init__
|
|
|
-
|
|
|
- __marker = object()
|
|
|
-
|
|
|
- def pop(self, key, default=__marker):
|
|
|
- """od.pop(k[,d]) -> v, remove specified key and return the corresponding value.
|
|
|
- If key is not found, d is returned if given, otherwise KeyError is raised.
|
|
|
-
|
|
|
- """
|
|
|
- if key in self:
|
|
|
- result = self[key]
|
|
|
- del self[key]
|
|
|
- return result
|
|
|
- if default is self.__marker:
|
|
|
- raise KeyError(key)
|
|
|
- return default
|
|
|
-
|
|
|
- def setdefault(self, key, default=None):
|
|
|
- 'od.setdefault(k[,d]) -> od.get(k,d), also set od[k]=d if k not in od'
|
|
|
- if key in self:
|
|
|
- return self[key]
|
|
|
- self[key] = default
|
|
|
- return default
|
|
|
-
|
|
|
- def __repr__(self, _repr_running={}):
|
|
|
- 'od.__repr__() <==> repr(od)'
|
|
|
- call_key = id(self), _get_ident()
|
|
|
- if call_key in _repr_running:
|
|
|
- return '...'
|
|
|
- _repr_running[call_key] = 1
|
|
|
- try:
|
|
|
- if not self:
|
|
|
- return '%s()' % (self.__class__.__name__,)
|
|
|
- return '%s(%r)' % (self.__class__.__name__, self.items())
|
|
|
- finally:
|
|
|
- del _repr_running[call_key]
|
|
|
-
|
|
|
- def __reduce__(self):
|
|
|
- 'Return state information for pickling'
|
|
|
- items = [[k, self[k]] for k in self]
|
|
|
- inst_dict = vars(self).copy()
|
|
|
- for k in vars(OrderedDict()):
|
|
|
- inst_dict.pop(k, None)
|
|
|
- if inst_dict:
|
|
|
- return (self.__class__, (items,), inst_dict)
|
|
|
- return self.__class__, (items,)
|
|
|
-
|
|
|
- def copy(self):
|
|
|
- 'od.copy() -> a shallow copy of od'
|
|
|
- return self.__class__(self)
|
|
|
-
|
|
|
- @classmethod
|
|
|
- def fromkeys(cls, iterable, value=None):
|
|
|
- '''OD.fromkeys(S[, v]) -> New ordered dictionary with keys from S
|
|
|
- and values equal to v (which defaults to None).
|
|
|
-
|
|
|
- '''
|
|
|
- d = cls()
|
|
|
- for key in iterable:
|
|
|
- d[key] = value
|
|
|
- return d
|
|
|
-
|
|
|
- def __eq__(self, other):
|
|
|
- '''od.__eq__(y) <==> od==y. Comparison to another OD is order-sensitive
|
|
|
- while comparison to a regular mapping is order-insensitive.
|
|
|
-
|
|
|
- '''
|
|
|
- if isinstance(other, OrderedDict):
|
|
|
- return len(self)==len(other) and self.items() == other.items()
|
|
|
- return dict.__eq__(self, other)
|
|
|
-
|
|
|
- def __ne__(self, other):
|
|
|
- return not self == other
|
|
|
-
|
|
|
- # -- the following methods are only used in Python 2.7 --
|
|
|
-
|
|
|
- def viewkeys(self):
|
|
|
- "od.viewkeys() -> a set-like object providing a view on od's keys"
|
|
|
- return KeysView(self)
|
|
|
-
|
|
|
- def viewvalues(self):
|
|
|
- "od.viewvalues() -> an object providing a view on od's values"
|
|
|
- return ValuesView(self)
|
|
|
-
|
|
|
- def viewitems(self):
|
|
|
- "od.viewitems() -> a set-like object providing a view on od's items"
|
|
|
- return ItemsView(self)
|
|
|
-
|
|
|
-
|
|
|
-# Copyright 2007 Google, Inc. All Rights Reserved.
|
|
|
-# Licensed to PSF under a Contributor Agreement.
|
|
|
-
|
|
|
-from abc import ABCMeta, abstractmethod
|
|
|
-import sys
|
|
|
-
|
|
|
-### ONE-TRICK PONIES ###
|
|
|
-
|
|
|
-def _hasattr(C, attr):
|
|
|
- try:
|
|
|
- return any(attr in B.__dict__ for B in C.__mro__)
|
|
|
- except AttributeError:
|
|
|
- # Old-style class
|
|
|
- return hasattr(C, attr)
|
|
|
-
|
|
|
-
|
|
|
-class Hashable:
|
|
|
- __metaclass__ = ABCMeta
|
|
|
-
|
|
|
- @abstractmethod
|
|
|
- def __hash__(self):
|
|
|
- return 0
|
|
|
-
|
|
|
- @classmethod
|
|
|
- def __subclasshook__(cls, C):
|
|
|
- if cls is Hashable:
|
|
|
- try:
|
|
|
- for B in C.__mro__:
|
|
|
- if "__hash__" in B.__dict__:
|
|
|
- if B.__dict__["__hash__"]:
|
|
|
- return True
|
|
|
- break
|
|
|
- except AttributeError:
|
|
|
- # Old-style class
|
|
|
- if getattr(C, "__hash__", None):
|
|
|
- return True
|
|
|
- return NotImplemented
|
|
|
-
|
|
|
-
|
|
|
-class Iterable:
|
|
|
- __metaclass__ = ABCMeta
|
|
|
-
|
|
|
- @abstractmethod
|
|
|
- def __iter__(self):
|
|
|
- while False:
|
|
|
- yield None
|
|
|
-
|
|
|
- @classmethod
|
|
|
- def __subclasshook__(cls, C):
|
|
|
- if cls is Iterable:
|
|
|
- if _hasattr(C, "__iter__"):
|
|
|
- return True
|
|
|
- return NotImplemented
|
|
|
-
|
|
|
-Iterable.register(str)
|
|
|
-
|
|
|
-
|
|
|
-class Iterator(Iterable):
|
|
|
-
|
|
|
- @abstractmethod
|
|
|
- def next(self):
|
|
|
- 'Return the next item from the iterator. When exhausted, raise StopIteration'
|
|
|
- raise StopIteration
|
|
|
-
|
|
|
- def __iter__(self):
|
|
|
- return self
|
|
|
-
|
|
|
- @classmethod
|
|
|
- def __subclasshook__(cls, C):
|
|
|
- if cls is Iterator:
|
|
|
- if _hasattr(C, "next") and _hasattr(C, "__iter__"):
|
|
|
- return True
|
|
|
- return NotImplemented
|
|
|
-
|
|
|
-
|
|
|
-class Sized:
|
|
|
- __metaclass__ = ABCMeta
|
|
|
-
|
|
|
- @abstractmethod
|
|
|
- def __len__(self):
|
|
|
- return 0
|
|
|
-
|
|
|
- @classmethod
|
|
|
- def __subclasshook__(cls, C):
|
|
|
- if cls is Sized:
|
|
|
- if _hasattr(C, "__len__"):
|
|
|
- return True
|
|
|
- return NotImplemented
|
|
|
-
|
|
|
-
|
|
|
-class Container:
|
|
|
- __metaclass__ = ABCMeta
|
|
|
-
|
|
|
- @abstractmethod
|
|
|
- def __contains__(self, x):
|
|
|
- return False
|
|
|
-
|
|
|
- @classmethod
|
|
|
- def __subclasshook__(cls, C):
|
|
|
- if cls is Container:
|
|
|
- if _hasattr(C, "__contains__"):
|
|
|
- return True
|
|
|
- return NotImplemented
|
|
|
-
|
|
|
-
|
|
|
-class Callable:
|
|
|
- __metaclass__ = ABCMeta
|
|
|
-
|
|
|
- @abstractmethod
|
|
|
- def __call__(self, *args, **kwds):
|
|
|
- return False
|
|
|
-
|
|
|
- @classmethod
|
|
|
- def __subclasshook__(cls, C):
|
|
|
- if cls is Callable:
|
|
|
- if _hasattr(C, "__call__"):
|
|
|
- return True
|
|
|
- return NotImplemented
|
|
|
-
|
|
|
-
|
|
|
-### SETS ###
|
|
|
-
|
|
|
-
|
|
|
-class Set(Sized, Iterable, Container):
|
|
|
- """A set is a finite, iterable container.
|
|
|
-
|
|
|
- This class provides concrete generic implementations of all
|
|
|
- methods except for __contains__, __iter__ and __len__.
|
|
|
-
|
|
|
- To override the comparisons (presumably for speed, as the
|
|
|
- semantics are fixed), all you have to do is redefine __le__ and
|
|
|
- then the other operations will automatically follow suit.
|
|
|
- """
|
|
|
-
|
|
|
- def __le__(self, other):
|
|
|
- if not isinstance(other, Set):
|
|
|
- return NotImplemented
|
|
|
- if len(self) > len(other):
|
|
|
- return False
|
|
|
- for elem in self:
|
|
|
- if elem not in other:
|
|
|
- return False
|
|
|
- return True
|
|
|
-
|
|
|
- def __lt__(self, other):
|
|
|
- if not isinstance(other, Set):
|
|
|
- return NotImplemented
|
|
|
- return len(self) < len(other) and self.__le__(other)
|
|
|
-
|
|
|
- def __gt__(self, other):
|
|
|
- if not isinstance(other, Set):
|
|
|
- return NotImplemented
|
|
|
- return len(self) > len(other) and self.__ge__(other)
|
|
|
-
|
|
|
- def __ge__(self, other):
|
|
|
- if not isinstance(other, Set):
|
|
|
- return NotImplemented
|
|
|
- if len(self) < len(other):
|
|
|
- return False
|
|
|
- for elem in other:
|
|
|
- if elem not in self:
|
|
|
- return False
|
|
|
- return True
|
|
|
-
|
|
|
- def __eq__(self, other):
|
|
|
- if not isinstance(other, Set):
|
|
|
- return NotImplemented
|
|
|
- return len(self) == len(other) and self.__le__(other)
|
|
|
-
|
|
|
- def __ne__(self, other):
|
|
|
- return not (self == other)
|
|
|
-
|
|
|
- @classmethod
|
|
|
- def _from_iterable(cls, it):
|
|
|
- '''Construct an instance of the class from any iterable input.
|
|
|
-
|
|
|
- Must override this method if the class constructor signature
|
|
|
- does not accept an iterable for an input.
|
|
|
- '''
|
|
|
- return cls(it)
|
|
|
-
|
|
|
- def __and__(self, other):
|
|
|
- if not isinstance(other, Iterable):
|
|
|
- return NotImplemented
|
|
|
- return self._from_iterable(value for value in other if value in self)
|
|
|
-
|
|
|
- __rand__ = __and__
|
|
|
-
|
|
|
- def isdisjoint(self, other):
|
|
|
- 'Return True if two sets have a null intersection.'
|
|
|
- for value in other:
|
|
|
- if value in self:
|
|
|
- return False
|
|
|
- return True
|
|
|
-
|
|
|
- def __or__(self, other):
|
|
|
- if not isinstance(other, Iterable):
|
|
|
- return NotImplemented
|
|
|
- chain = (e for s in (self, other) for e in s)
|
|
|
- return self._from_iterable(chain)
|
|
|
-
|
|
|
- __ror__ = __or__
|
|
|
-
|
|
|
- def __sub__(self, other):
|
|
|
- if not isinstance(other, Set):
|
|
|
- if not isinstance(other, Iterable):
|
|
|
- return NotImplemented
|
|
|
- other = self._from_iterable(other)
|
|
|
- return self._from_iterable(value for value in self
|
|
|
- if value not in other)
|
|
|
-
|
|
|
- def __rsub__(self, other):
|
|
|
- if not isinstance(other, Set):
|
|
|
- if not isinstance(other, Iterable):
|
|
|
- return NotImplemented
|
|
|
- other = self._from_iterable(other)
|
|
|
- return self._from_iterable(value for value in other
|
|
|
- if value not in self)
|
|
|
-
|
|
|
- def __xor__(self, other):
|
|
|
- if not isinstance(other, Set):
|
|
|
- if not isinstance(other, Iterable):
|
|
|
- return NotImplemented
|
|
|
- other = self._from_iterable(other)
|
|
|
- return (self - other) | (other - self)
|
|
|
-
|
|
|
- __rxor__ = __xor__
|
|
|
-
|
|
|
- # Sets are not hashable by default, but subclasses can change this
|
|
|
- __hash__ = None
|
|
|
-
|
|
|
- def _hash(self):
|
|
|
- """Compute the hash value of a set.
|
|
|
-
|
|
|
- Note that we don't define __hash__: not all sets are hashable.
|
|
|
- But if you define a hashable set type, its __hash__ should
|
|
|
- call this function.
|
|
|
-
|
|
|
- This must be compatible __eq__.
|
|
|
-
|
|
|
- All sets ought to compare equal if they contain the same
|
|
|
- elements, regardless of how they are implemented, and
|
|
|
- regardless of the order of the elements; so there's not much
|
|
|
- freedom for __eq__ or __hash__. We match the algorithm used
|
|
|
- by the built-in frozenset type.
|
|
|
- """
|
|
|
- MAX = sys.maxint
|
|
|
- MASK = 2 * MAX + 1
|
|
|
- n = len(self)
|
|
|
- h = 1927868237 * (n + 1)
|
|
|
- h &= MASK
|
|
|
- for x in self:
|
|
|
- hx = hash(x)
|
|
|
- h ^= (hx ^ (hx << 16) ^ 89869747) * 3644798167
|
|
|
- h &= MASK
|
|
|
- h = h * 69069 + 907133923
|
|
|
- h &= MASK
|
|
|
- if h > MAX:
|
|
|
- h -= MASK + 1
|
|
|
- if h == -1:
|
|
|
- h = 590923713
|
|
|
- return h
|
|
|
-
|
|
|
-Set.register(frozenset)
|
|
|
-
|
|
|
-
|
|
|
-class MutableSet(Set):
|
|
|
- """A mutable set is a finite, iterable container.
|
|
|
-
|
|
|
- This class provides concrete generic implementations of all
|
|
|
- methods except for __contains__, __iter__, __len__,
|
|
|
- add(), and discard().
|
|
|
-
|
|
|
- To override the comparisons (presumably for speed, as the
|
|
|
- semantics are fixed), all you have to do is redefine __le__ and
|
|
|
- then the other operations will automatically follow suit.
|
|
|
- """
|
|
|
-
|
|
|
- @abstractmethod
|
|
|
- def add(self, value):
|
|
|
- """Add an element."""
|
|
|
- raise NotImplementedError
|
|
|
-
|
|
|
- @abstractmethod
|
|
|
- def discard(self, value):
|
|
|
- """Remove an element. Do not raise an exception if absent."""
|
|
|
- raise NotImplementedError
|
|
|
-
|
|
|
- def remove(self, value):
|
|
|
- """Remove an element. If not a member, raise a KeyError."""
|
|
|
- if value not in self:
|
|
|
- raise KeyError(value)
|
|
|
- self.discard(value)
|
|
|
-
|
|
|
- def pop(self):
|
|
|
- """Return the popped value. Raise KeyError if empty."""
|
|
|
- it = iter(self)
|
|
|
- try:
|
|
|
- value = next(it)
|
|
|
- except StopIteration:
|
|
|
- raise KeyError
|
|
|
- self.discard(value)
|
|
|
- return value
|
|
|
-
|
|
|
- def clear(self):
|
|
|
- """This is slow (creates N new iterators!) but effective."""
|
|
|
- try:
|
|
|
- while True:
|
|
|
- self.pop()
|
|
|
- except KeyError:
|
|
|
- pass
|
|
|
-
|
|
|
- def __ior__(self, it):
|
|
|
- for value in it:
|
|
|
- self.add(value)
|
|
|
- return self
|
|
|
-
|
|
|
- def __iand__(self, it):
|
|
|
- for value in (self - it):
|
|
|
- self.discard(value)
|
|
|
- return self
|
|
|
-
|
|
|
- def __ixor__(self, it):
|
|
|
- if it is self:
|
|
|
- self.clear()
|
|
|
- else:
|
|
|
- if not isinstance(it, Set):
|
|
|
- it = self._from_iterable(it)
|
|
|
- for value in it:
|
|
|
- if value in self:
|
|
|
- self.discard(value)
|
|
|
- else:
|
|
|
- self.add(value)
|
|
|
- return self
|
|
|
-
|
|
|
- def __isub__(self, it):
|
|
|
- if it is self:
|
|
|
- self.clear()
|
|
|
- else:
|
|
|
- for value in it:
|
|
|
- self.discard(value)
|
|
|
- return self
|
|
|
-
|
|
|
-MutableSet.register(set)
|
|
|
-
|
|
|
-
|
|
|
-### MAPPINGS ###
|
|
|
-
|
|
|
-
|
|
|
-class Mapping(Sized, Iterable, Container):
|
|
|
-
|
|
|
- """A Mapping is a generic container for associating key/value
|
|
|
- pairs.
|
|
|
-
|
|
|
- This class provides concrete generic implementations of all
|
|
|
- methods except for __getitem__, __iter__, and __len__.
|
|
|
-
|
|
|
- """
|
|
|
-
|
|
|
- @abstractmethod
|
|
|
- def __getitem__(self, key):
|
|
|
- raise KeyError
|
|
|
-
|
|
|
- def get(self, key, default=None):
|
|
|
- 'D.get(k[,d]) -> D[k] if k in D, else d. d defaults to None.'
|
|
|
- try:
|
|
|
- return self[key]
|
|
|
- except KeyError:
|
|
|
- return default
|
|
|
-
|
|
|
- def __contains__(self, key):
|
|
|
- try:
|
|
|
- self[key]
|
|
|
- except KeyError:
|
|
|
- return False
|
|
|
- else:
|
|
|
- return True
|
|
|
-
|
|
|
- def iterkeys(self):
|
|
|
- 'D.iterkeys() -> an iterator over the keys of D'
|
|
|
- return iter(self)
|
|
|
-
|
|
|
- def itervalues(self):
|
|
|
- 'D.itervalues() -> an iterator over the values of D'
|
|
|
- for key in self:
|
|
|
- yield self[key]
|
|
|
-
|
|
|
- def iteritems(self):
|
|
|
- 'D.iteritems() -> an iterator over the (key, value) items of D'
|
|
|
- for key in self:
|
|
|
- yield (key, self[key])
|
|
|
-
|
|
|
- def keys(self):
|
|
|
- "D.keys() -> list of D's keys"
|
|
|
- return list(self)
|
|
|
-
|
|
|
- def items(self):
|
|
|
- "D.items() -> list of D's (key, value) pairs, as 2-tuples"
|
|
|
- return [(key, self[key]) for key in self]
|
|
|
-
|
|
|
- def values(self):
|
|
|
- "D.values() -> list of D's values"
|
|
|
- return [self[key] for key in self]
|
|
|
-
|
|
|
- # Mappings are not hashable by default, but subclasses can change this
|
|
|
- __hash__ = None
|
|
|
-
|
|
|
- def __eq__(self, other):
|
|
|
- if not isinstance(other, Mapping):
|
|
|
- return NotImplemented
|
|
|
- return dict(self.items()) == dict(other.items())
|
|
|
-
|
|
|
- def __ne__(self, other):
|
|
|
- return not (self == other)
|
|
|
-
|
|
|
-class MappingView(Sized):
|
|
|
-
|
|
|
- def __init__(self, mapping):
|
|
|
- self._mapping = mapping
|
|
|
-
|
|
|
- def __len__(self):
|
|
|
- return len(self._mapping)
|
|
|
-
|
|
|
- def __repr__(self):
|
|
|
- return '{0.__class__.__name__}({0._mapping!r})'.format(self)
|
|
|
-
|
|
|
-
|
|
|
-class KeysView(MappingView, Set):
|
|
|
-
|
|
|
- @classmethod
|
|
|
- def _from_iterable(self, it):
|
|
|
- return set(it)
|
|
|
-
|
|
|
- def __contains__(self, key):
|
|
|
- return key in self._mapping
|
|
|
-
|
|
|
- def __iter__(self):
|
|
|
- for key in self._mapping:
|
|
|
- yield key
|
|
|
-
|
|
|
-
|
|
|
-class ItemsView(MappingView, Set):
|
|
|
-
|
|
|
- @classmethod
|
|
|
- def _from_iterable(self, it):
|
|
|
- return set(it)
|
|
|
-
|
|
|
- def __contains__(self, item):
|
|
|
- key, value = item
|
|
|
- try:
|
|
|
- v = self._mapping[key]
|
|
|
- except KeyError:
|
|
|
- return False
|
|
|
- else:
|
|
|
- return v == value
|
|
|
-
|
|
|
- def __iter__(self):
|
|
|
- for key in self._mapping:
|
|
|
- yield (key, self._mapping[key])
|
|
|
-
|
|
|
-
|
|
|
-class ValuesView(MappingView):
|
|
|
-
|
|
|
- def __contains__(self, value):
|
|
|
- for key in self._mapping:
|
|
|
- if value == self._mapping[key]:
|
|
|
- return True
|
|
|
- return False
|
|
|
-
|
|
|
- def __iter__(self):
|
|
|
- for key in self._mapping:
|
|
|
- yield self._mapping[key]
|
|
|
-
|
|
|
-
|
|
|
-class MutableMapping(Mapping):
|
|
|
-
|
|
|
- """A MutableMapping is a generic container for associating
|
|
|
- key/value pairs.
|
|
|
-
|
|
|
- This class provides concrete generic implementations of all
|
|
|
- methods except for __getitem__, __setitem__, __delitem__,
|
|
|
- __iter__, and __len__.
|
|
|
-
|
|
|
- """
|
|
|
-
|
|
|
- @abstractmethod
|
|
|
- def __setitem__(self, key, value):
|
|
|
- raise KeyError
|
|
|
-
|
|
|
- @abstractmethod
|
|
|
- def __delitem__(self, key):
|
|
|
- raise KeyError
|
|
|
-
|
|
|
- __marker = object()
|
|
|
-
|
|
|
- def pop(self, key, default=__marker):
|
|
|
- '''D.pop(k[,d]) -> v, remove specified key and return the corresponding value.
|
|
|
- If key is not found, d is returned if given, otherwise KeyError is raised.
|
|
|
- '''
|
|
|
- try:
|
|
|
- value = self[key]
|
|
|
- except KeyError:
|
|
|
- if default is self.__marker:
|
|
|
- raise
|
|
|
- return default
|
|
|
- else:
|
|
|
- del self[key]
|
|
|
- return value
|
|
|
-
|
|
|
- def popitem(self):
|
|
|
- '''D.popitem() -> (k, v), remove and return some (key, value) pair
|
|
|
- as a 2-tuple; but raise KeyError if D is empty.
|
|
|
- '''
|
|
|
- try:
|
|
|
- key = next(iter(self))
|
|
|
- except StopIteration:
|
|
|
- raise KeyError
|
|
|
- value = self[key]
|
|
|
- del self[key]
|
|
|
- return key, value
|
|
|
-
|
|
|
- def clear(self):
|
|
|
- 'D.clear() -> None. Remove all items from D.'
|
|
|
- try:
|
|
|
- while True:
|
|
|
- self.popitem()
|
|
|
- except KeyError:
|
|
|
- pass
|
|
|
-
|
|
|
- def update(*args, **kwds):
|
|
|
- ''' D.update([E, ]**F) -> None. Update D from mapping/iterable E and F.
|
|
|
- If E present and has a .keys() method, does: for k in E: D[k] = E[k]
|
|
|
- If E present and lacks .keys() method, does: for (k, v) in E: D[k] = v
|
|
|
- In either case, this is followed by: for k, v in F.items(): D[k] = v
|
|
|
- '''
|
|
|
- if len(args) > 2:
|
|
|
- raise TypeError("update() takes at most 2 positional "
|
|
|
- "arguments ({} given)".format(len(args)))
|
|
|
- elif not args:
|
|
|
- raise TypeError("update() takes at least 1 argument (0 given)")
|
|
|
- self = args[0]
|
|
|
- other = args[1] if len(args) >= 2 else ()
|
|
|
-
|
|
|
- if isinstance(other, Mapping):
|
|
|
- for key in other:
|
|
|
- self[key] = other[key]
|
|
|
- elif hasattr(other, "keys"):
|
|
|
- for key in other.keys():
|
|
|
- self[key] = other[key]
|
|
|
- else:
|
|
|
- for key, value in other:
|
|
|
- self[key] = value
|
|
|
- for key, value in kwds.items():
|
|
|
- self[key] = value
|
|
|
-
|
|
|
- def setdefault(self, key, default=None):
|
|
|
- 'D.setdefault(k[,d]) -> D.get(k,d), also set D[k]=d if k not in D'
|
|
|
- try:
|
|
|
- return self[key]
|
|
|
- except KeyError:
|
|
|
- self[key] = default
|
|
|
- return default
|
|
|
-
|
|
|
-MutableMapping.register(dict)
|
|
|
-
|
|
|
-
|
|
|
-### SEQUENCES ###
|
|
|
-
|
|
|
-
|
|
|
-class Sequence(Sized, Iterable, Container):
|
|
|
- """All the operations on a read-only sequence.
|
|
|
-
|
|
|
- Concrete subclasses must override __new__ or __init__,
|
|
|
- __getitem__, and __len__.
|
|
|
- """
|
|
|
-
|
|
|
- @abstractmethod
|
|
|
- def __getitem__(self, index):
|
|
|
- raise IndexError
|
|
|
-
|
|
|
- def __iter__(self):
|
|
|
- i = 0
|
|
|
- try:
|
|
|
- while True:
|
|
|
- v = self[i]
|
|
|
- yield v
|
|
|
- i += 1
|
|
|
- except IndexError:
|
|
|
- return
|
|
|
-
|
|
|
- def __contains__(self, value):
|
|
|
- for v in self:
|
|
|
- if v == value:
|
|
|
- return True
|
|
|
- return False
|
|
|
-
|
|
|
- def __reversed__(self):
|
|
|
- for i in reversed(range(len(self))):
|
|
|
- yield self[i]
|
|
|
-
|
|
|
- def index(self, value):
|
|
|
- '''S.index(value) -> integer -- return first index of value.
|
|
|
- Raises ValueError if the value is not present.
|
|
|
- '''
|
|
|
- for i, v in enumerate(self):
|
|
|
- if v == value:
|
|
|
- return i
|
|
|
- raise ValueError
|
|
|
-
|
|
|
- def count(self, value):
|
|
|
- 'S.count(value) -> integer -- return number of occurrences of value'
|
|
|
- return sum(1 for v in self if v == value)
|
|
|
-
|
|
|
-Sequence.register(tuple)
|
|
|
-Sequence.register(basestring)
|
|
|
-Sequence.register(buffer)
|
|
|
-Sequence.register(xrange)
|
|
|
-
|
|
|
-
|
|
|
-class MutableSequence(Sequence):
|
|
|
-
|
|
|
- """All the operations on a read-only sequence.
|
|
|
-
|
|
|
- Concrete subclasses must provide __new__ or __init__,
|
|
|
- __getitem__, __setitem__, __delitem__, __len__, and insert().
|
|
|
-
|
|
|
- """
|
|
|
-
|
|
|
- @abstractmethod
|
|
|
- def __setitem__(self, index, value):
|
|
|
- raise IndexError
|
|
|
-
|
|
|
- @abstractmethod
|
|
|
- def __delitem__(self, index):
|
|
|
- raise IndexError
|
|
|
-
|
|
|
- @abstractmethod
|
|
|
- def insert(self, index, value):
|
|
|
- 'S.insert(index, object) -- insert object before index'
|
|
|
- raise IndexError
|
|
|
-
|
|
|
- def append(self, value):
|
|
|
- 'S.append(object) -- append object to the end of the sequence'
|
|
|
- self.insert(len(self), value)
|
|
|
-
|
|
|
- def reverse(self):
|
|
|
- 'S.reverse() -- reverse *IN PLACE*'
|
|
|
- n = len(self)
|
|
|
- for i in range(n//2):
|
|
|
- self[i], self[n-i-1] = self[n-i-1], self[i]
|
|
|
-
|
|
|
- def extend(self, values):
|
|
|
- 'S.extend(iterable) -- extend sequence by appending elements from the iterable'
|
|
|
- for v in values:
|
|
|
- self.append(v)
|
|
|
-
|
|
|
- def pop(self, index=-1):
|
|
|
- '''S.pop([index]) -> item -- remove and return item at index (default last).
|
|
|
- Raise IndexError if list is empty or index is out of range.
|
|
|
- '''
|
|
|
- v = self[index]
|
|
|
- del self[index]
|
|
|
- return v
|
|
|
-
|
|
|
- def remove(self, value):
|
|
|
- '''S.remove(value) -- remove first occurrence of value.
|
|
|
- Raise ValueError if the value is not present.
|
|
|
- '''
|
|
|
- del self[self.index(value)]
|
|
|
-
|
|
|
- def __iadd__(self, values):
|
|
|
- self.extend(values)
|
|
|
- return self
|
|
|
-
|
|
|
-MutableSequence.register(list)
|