2007-11-21 20:55:51 -04:00
|
|
|
# Copyright 2007 Google, Inc. All Rights Reserved.
|
|
|
|
# Licensed to PSF under a Contributor Agreement.
|
|
|
|
|
|
|
|
"""Abstract Base Classes (ABCs) for collections, according to PEP 3119.
|
|
|
|
|
|
|
|
DON'T USE THIS MODULE DIRECTLY! The classes here should be imported
|
|
|
|
via collections; they are defined here only to alleviate certain
|
|
|
|
bootstrapping issues. Unit tests are in test_collections.
|
|
|
|
"""
|
|
|
|
|
|
|
|
from abc import ABCMeta, abstractmethod
|
2008-06-23 00:29:28 -03:00
|
|
|
import sys
|
2007-11-21 20:55:51 -04:00
|
|
|
|
|
|
|
__all__ = ["Hashable", "Iterable", "Iterator",
|
|
|
|
"Sized", "Container", "Callable",
|
|
|
|
"Set", "MutableSet",
|
|
|
|
"Mapping", "MutableMapping",
|
|
|
|
"MappingView", "KeysView", "ItemsView", "ValuesView",
|
|
|
|
"Sequence", "MutableSequence",
|
|
|
|
]
|
|
|
|
|
|
|
|
### ONE-TRICK PONIES ###
|
|
|
|
|
|
|
|
class Hashable:
|
|
|
|
__metaclass__ = ABCMeta
|
|
|
|
|
|
|
|
@abstractmethod
|
|
|
|
def __hash__(self):
|
|
|
|
return 0
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def __subclasshook__(cls, C):
|
|
|
|
if cls is Hashable:
|
|
|
|
for B in C.__mro__:
|
|
|
|
if "__hash__" in B.__dict__:
|
|
|
|
if B.__dict__["__hash__"]:
|
|
|
|
return True
|
|
|
|
break
|
|
|
|
return NotImplemented
|
|
|
|
|
|
|
|
|
|
|
|
class Iterable:
|
|
|
|
__metaclass__ = ABCMeta
|
|
|
|
|
|
|
|
@abstractmethod
|
|
|
|
def __iter__(self):
|
|
|
|
while False:
|
|
|
|
yield None
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def __subclasshook__(cls, C):
|
|
|
|
if cls is Iterable:
|
|
|
|
if any("__iter__" in B.__dict__ for B in C.__mro__):
|
|
|
|
return True
|
|
|
|
return NotImplemented
|
|
|
|
|
|
|
|
Iterable.register(str)
|
|
|
|
|
|
|
|
|
2008-02-08 21:18:42 -04:00
|
|
|
class Iterator(Iterable):
|
2007-11-21 20:55:51 -04:00
|
|
|
|
|
|
|
@abstractmethod
|
2009-01-28 19:14:58 -04:00
|
|
|
def next(self):
|
2007-11-21 20:55:51 -04:00
|
|
|
raise StopIteration
|
|
|
|
|
|
|
|
def __iter__(self):
|
|
|
|
return self
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def __subclasshook__(cls, C):
|
|
|
|
if cls is Iterator:
|
|
|
|
if any("next" in B.__dict__ for B in C.__mro__):
|
|
|
|
return True
|
|
|
|
return NotImplemented
|
|
|
|
|
|
|
|
|
|
|
|
class Sized:
|
|
|
|
__metaclass__ = ABCMeta
|
|
|
|
|
|
|
|
@abstractmethod
|
|
|
|
def __len__(self):
|
|
|
|
return 0
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def __subclasshook__(cls, C):
|
|
|
|
if cls is Sized:
|
|
|
|
if any("__len__" in B.__dict__ for B in C.__mro__):
|
|
|
|
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 any("__contains__" in B.__dict__ for B in C.__mro__):
|
|
|
|
return True
|
|
|
|
return NotImplemented
|
|
|
|
|
|
|
|
|
|
|
|
class Callable:
|
|
|
|
__metaclass__ = ABCMeta
|
|
|
|
|
|
|
|
@abstractmethod
|
2008-03-03 18:19:58 -04:00
|
|
|
def __call__(self, *args, **kwds):
|
2007-11-21 20:55:51 -04:00
|
|
|
return False
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def __subclasshook__(cls, C):
|
|
|
|
if cls is Callable:
|
|
|
|
if any("__call__" in B.__dict__ for B in C.__mro__):
|
|
|
|
return True
|
|
|
|
return NotImplemented
|
|
|
|
|
|
|
|
|
|
|
|
### SETS ###
|
|
|
|
|
|
|
|
|
2008-02-08 21:18:42 -04:00
|
|
|
class Set(Sized, Iterable, Container):
|
2007-11-21 20:55:51 -04:00
|
|
|
"""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)
|
|
|
|
|
2008-02-08 19:34:21 -04:00
|
|
|
def __gt__(self, other):
|
|
|
|
if not isinstance(other, Set):
|
|
|
|
return NotImplemented
|
|
|
|
return other < self
|
|
|
|
|
|
|
|
def __ge__(self, other):
|
|
|
|
if not isinstance(other, Set):
|
|
|
|
return NotImplemented
|
|
|
|
return other <= self
|
|
|
|
|
2007-11-21 20:55:51 -04:00
|
|
|
def __eq__(self, other):
|
|
|
|
if not isinstance(other, Set):
|
|
|
|
return NotImplemented
|
|
|
|
return len(self) == len(other) and self.__le__(other)
|
|
|
|
|
2008-02-08 19:34:21 -04:00
|
|
|
def __ne__(self, other):
|
|
|
|
return not (self == other)
|
|
|
|
|
2007-11-21 20:55:51 -04:00
|
|
|
@classmethod
|
|
|
|
def _from_iterable(cls, it):
|
2008-02-06 23:10:33 -04:00
|
|
|
'''Construct an instance of the class from any iterable input.
|
|
|
|
|
|
|
|
Must override this method if the class constructor signature
|
2008-02-08 23:34:52 -04:00
|
|
|
does not accept an iterable for an input.
|
2008-02-06 23:10:33 -04:00
|
|
|
'''
|
2008-02-08 23:34:52 -04:00
|
|
|
return cls(it)
|
2007-11-21 20:55:51 -04:00
|
|
|
|
|
|
|
def __and__(self, other):
|
|
|
|
if not isinstance(other, Iterable):
|
|
|
|
return NotImplemented
|
|
|
|
return self._from_iterable(value for value in other if value in self)
|
|
|
|
|
2008-01-29 20:01:07 -04:00
|
|
|
def isdisjoint(self, other):
|
|
|
|
for value in other:
|
|
|
|
if value in self:
|
|
|
|
return False
|
|
|
|
return True
|
|
|
|
|
2007-11-21 20:55:51 -04:00
|
|
|
def __or__(self, other):
|
|
|
|
if not isinstance(other, Iterable):
|
|
|
|
return NotImplemented
|
2008-03-03 18:04:55 -04:00
|
|
|
chain = (e for s in (self, other) for e in s)
|
|
|
|
return self._from_iterable(chain)
|
2007-11-21 20:55:51 -04:00
|
|
|
|
|
|
|
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 __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)
|
|
|
|
|
2008-08-11 12:45:58 -03:00
|
|
|
# Sets are not hashable by default, but subclasses can change this
|
|
|
|
__hash__ = None
|
|
|
|
|
2007-11-21 20:55:51 -04:00
|
|
|
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):
|
|
|
|
|
|
|
|
@abstractmethod
|
|
|
|
def add(self, value):
|
Merged revisions 68521,68527,68534-68536,68540,68547,68552,68563,68570,68572,68575,68579-68580,68584 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk
........
r68521 | hirokazu.yamamoto | 2009-01-11 04:28:13 +0100 (So, 11 Jan 2009) | 1 line
Fixed version number in build_ssl.bat.
........
r68527 | martin.v.loewis | 2009-01-11 10:43:55 +0100 (So, 11 Jan 2009) | 2 lines
Issue #4895: Use _strdup on Windows CE.
........
r68534 | gregory.p.smith | 2009-01-11 18:53:33 +0100 (So, 11 Jan 2009) | 2 lines
correct email address
........
r68535 | gregory.p.smith | 2009-01-11 18:57:54 +0100 (So, 11 Jan 2009) | 9 lines
Update the documentation for binascii and zlib crc32/adler32 functions
to better describe the signed vs unsigned return value behavior on
different platforms and versions of python. Mention the workaround to
make them all return the same thing by using & 0xffffffff.
Fixes issue4903.
Also needs to be merged into release26-maint, release30-maint, & py3k.
........
r68536 | benjamin.peterson | 2009-01-11 20:48:15 +0100 (So, 11 Jan 2009) | 1 line
add email addresses
........
r68540 | martin.v.loewis | 2009-01-12 08:57:11 +0100 (Mo, 12 Jan 2009) | 2 lines
Issue #4915: Port sysmodule to Windows CE.
........
r68547 | kristjan.jonsson | 2009-01-12 19:09:27 +0100 (Mo, 12 Jan 2009) | 1 line
Add tests for invalid format specifiers in strftime, and for handling of invalid file descriptors in the os module.
........
r68552 | vinay.sajip | 2009-01-12 21:36:18 +0100 (Mo, 12 Jan 2009) | 1 line
Minor changes/corrections in markup.
........
r68563 | benjamin.peterson | 2009-01-13 02:49:10 +0100 (Di, 13 Jan 2009) | 1 line
small logic correction
........
r68570 | raymond.hettinger | 2009-01-13 10:08:32 +0100 (Di, 13 Jan 2009) | 5 lines
Issue 4922: Incorrect comments for MutableSet.add() and MutableSet.discard().
Needs to be backported to 2.6 and forward ported to 3.0 and 3.1.
........
r68572 | andrew.kuchling | 2009-01-13 14:40:54 +0100 (Di, 13 Jan 2009) | 1 line
Note that first coord. is left alone
........
r68575 | thomas.heller | 2009-01-13 18:32:28 +0100 (Di, 13 Jan 2009) | 1 line
Fix refcount leak in error cases. Bug found by coverity.
........
r68579 | benjamin.peterson | 2009-01-13 22:42:23 +0100 (Di, 13 Jan 2009) | 1 line
make bytearrayobject.o depend on the stringlib #4936
........
r68580 | benjamin.peterson | 2009-01-13 22:43:11 +0100 (Di, 13 Jan 2009) | 1 line
add bytearrayobject.h to PYTHON_HEADERS
........
r68584 | benjamin.peterson | 2009-01-13 23:22:41 +0100 (Di, 13 Jan 2009) | 1 line
de-spacify
........
2009-01-13 20:08:09 -04:00
|
|
|
"""Add an element."""
|
2007-11-21 20:55:51 -04:00
|
|
|
raise NotImplementedError
|
|
|
|
|
|
|
|
@abstractmethod
|
|
|
|
def discard(self, value):
|
Merged revisions 68521,68527,68534-68536,68540,68547,68552,68563,68570,68572,68575,68579-68580,68584 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk
........
r68521 | hirokazu.yamamoto | 2009-01-11 04:28:13 +0100 (So, 11 Jan 2009) | 1 line
Fixed version number in build_ssl.bat.
........
r68527 | martin.v.loewis | 2009-01-11 10:43:55 +0100 (So, 11 Jan 2009) | 2 lines
Issue #4895: Use _strdup on Windows CE.
........
r68534 | gregory.p.smith | 2009-01-11 18:53:33 +0100 (So, 11 Jan 2009) | 2 lines
correct email address
........
r68535 | gregory.p.smith | 2009-01-11 18:57:54 +0100 (So, 11 Jan 2009) | 9 lines
Update the documentation for binascii and zlib crc32/adler32 functions
to better describe the signed vs unsigned return value behavior on
different platforms and versions of python. Mention the workaround to
make them all return the same thing by using & 0xffffffff.
Fixes issue4903.
Also needs to be merged into release26-maint, release30-maint, & py3k.
........
r68536 | benjamin.peterson | 2009-01-11 20:48:15 +0100 (So, 11 Jan 2009) | 1 line
add email addresses
........
r68540 | martin.v.loewis | 2009-01-12 08:57:11 +0100 (Mo, 12 Jan 2009) | 2 lines
Issue #4915: Port sysmodule to Windows CE.
........
r68547 | kristjan.jonsson | 2009-01-12 19:09:27 +0100 (Mo, 12 Jan 2009) | 1 line
Add tests for invalid format specifiers in strftime, and for handling of invalid file descriptors in the os module.
........
r68552 | vinay.sajip | 2009-01-12 21:36:18 +0100 (Mo, 12 Jan 2009) | 1 line
Minor changes/corrections in markup.
........
r68563 | benjamin.peterson | 2009-01-13 02:49:10 +0100 (Di, 13 Jan 2009) | 1 line
small logic correction
........
r68570 | raymond.hettinger | 2009-01-13 10:08:32 +0100 (Di, 13 Jan 2009) | 5 lines
Issue 4922: Incorrect comments for MutableSet.add() and MutableSet.discard().
Needs to be backported to 2.6 and forward ported to 3.0 and 3.1.
........
r68572 | andrew.kuchling | 2009-01-13 14:40:54 +0100 (Di, 13 Jan 2009) | 1 line
Note that first coord. is left alone
........
r68575 | thomas.heller | 2009-01-13 18:32:28 +0100 (Di, 13 Jan 2009) | 1 line
Fix refcount leak in error cases. Bug found by coverity.
........
r68579 | benjamin.peterson | 2009-01-13 22:42:23 +0100 (Di, 13 Jan 2009) | 1 line
make bytearrayobject.o depend on the stringlib #4936
........
r68580 | benjamin.peterson | 2009-01-13 22:43:11 +0100 (Di, 13 Jan 2009) | 1 line
add bytearrayobject.h to PYTHON_HEADERS
........
r68584 | benjamin.peterson | 2009-01-13 23:22:41 +0100 (Di, 13 Jan 2009) | 1 line
de-spacify
........
2009-01-13 20:08:09 -04:00
|
|
|
"""Remove an element. Do not raise an exception if absent."""
|
2007-11-21 20:55:51 -04:00
|
|
|
raise NotImplementedError
|
|
|
|
|
2008-01-29 20:08:31 -04:00
|
|
|
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)
|
|
|
|
|
2007-11-21 20:55:51 -04:00
|
|
|
def pop(self):
|
|
|
|
"""Return the popped value. Raise KeyError if empty."""
|
|
|
|
it = iter(self)
|
|
|
|
try:
|
2009-01-28 19:14:58 -04:00
|
|
|
value = next(it)
|
2007-11-21 20:55:51 -04:00
|
|
|
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
|
|
|
|
|
2009-04-01 15:55:57 -03:00
|
|
|
def __iand__(self, it):
|
|
|
|
for value in (self - it):
|
|
|
|
self.discard(value)
|
2007-11-21 20:55:51 -04:00
|
|
|
return self
|
|
|
|
|
|
|
|
def __ixor__(self, it):
|
2008-01-30 21:38:15 -04:00
|
|
|
if not isinstance(it, Set):
|
|
|
|
it = self._from_iterable(it)
|
2007-11-21 20:55:51 -04:00
|
|
|
for value in it:
|
2008-01-30 21:38:15 -04:00
|
|
|
if value in self:
|
|
|
|
self.discard(value)
|
|
|
|
else:
|
|
|
|
self.add(value)
|
2008-01-30 21:42:11 -04:00
|
|
|
return self
|
2007-11-21 20:55:51 -04:00
|
|
|
|
|
|
|
def __isub__(self, it):
|
|
|
|
for value in it:
|
|
|
|
self.discard(value)
|
|
|
|
return self
|
|
|
|
|
|
|
|
MutableSet.register(set)
|
|
|
|
|
|
|
|
|
|
|
|
### MAPPINGS ###
|
|
|
|
|
|
|
|
|
2008-02-08 21:18:42 -04:00
|
|
|
class Mapping(Sized, Iterable, Container):
|
2007-11-21 20:55:51 -04:00
|
|
|
|
|
|
|
@abstractmethod
|
|
|
|
def __getitem__(self, key):
|
|
|
|
raise KeyError
|
|
|
|
|
|
|
|
def get(self, key, default=None):
|
|
|
|
try:
|
|
|
|
return self[key]
|
|
|
|
except KeyError:
|
|
|
|
return default
|
|
|
|
|
|
|
|
def __contains__(self, key):
|
|
|
|
try:
|
|
|
|
self[key]
|
|
|
|
except KeyError:
|
|
|
|
return False
|
|
|
|
else:
|
|
|
|
return True
|
|
|
|
|
2008-06-07 14:03:28 -03:00
|
|
|
def iterkeys(self):
|
|
|
|
return iter(self)
|
|
|
|
|
|
|
|
def itervalues(self):
|
|
|
|
for key in self:
|
|
|
|
yield self[key]
|
|
|
|
|
|
|
|
def iteritems(self):
|
|
|
|
for key in self:
|
|
|
|
yield (key, self[key])
|
|
|
|
|
2007-11-21 20:55:51 -04:00
|
|
|
def keys(self):
|
2008-06-07 14:03:28 -03:00
|
|
|
return list(self)
|
2007-11-21 20:55:51 -04:00
|
|
|
|
|
|
|
def items(self):
|
2008-06-07 14:03:28 -03:00
|
|
|
return [(key, self[key]) for key in self]
|
2007-11-21 20:55:51 -04:00
|
|
|
|
|
|
|
def values(self):
|
2008-06-07 14:03:28 -03:00
|
|
|
return [self[key] for key in self]
|
2007-11-21 20:55:51 -04:00
|
|
|
|
2008-08-11 12:45:58 -03:00
|
|
|
# Mappings are not hashable by default, but subclasses can change this
|
|
|
|
__hash__ = None
|
|
|
|
|
2008-02-05 21:49:00 -04:00
|
|
|
def __eq__(self, other):
|
|
|
|
return isinstance(other, Mapping) and \
|
|
|
|
dict(self.items()) == dict(other.items())
|
|
|
|
|
|
|
|
def __ne__(self, other):
|
|
|
|
return not (self == other)
|
2007-11-21 20:55:51 -04:00
|
|
|
|
2008-02-08 21:18:42 -04:00
|
|
|
class MappingView(Sized):
|
2007-11-21 20:55:51 -04:00
|
|
|
|
|
|
|
def __init__(self, mapping):
|
|
|
|
self._mapping = mapping
|
|
|
|
|
|
|
|
def __len__(self):
|
|
|
|
return len(self._mapping)
|
|
|
|
|
|
|
|
|
|
|
|
class KeysView(MappingView, Set):
|
|
|
|
|
|
|
|
def __contains__(self, key):
|
|
|
|
return key in self._mapping
|
|
|
|
|
|
|
|
def __iter__(self):
|
|
|
|
for key in self._mapping:
|
|
|
|
yield key
|
|
|
|
|
|
|
|
|
|
|
|
class ItemsView(MappingView, Set):
|
|
|
|
|
|
|
|
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):
|
|
|
|
|
|
|
|
@abstractmethod
|
|
|
|
def __setitem__(self, key, value):
|
|
|
|
raise KeyError
|
|
|
|
|
|
|
|
@abstractmethod
|
|
|
|
def __delitem__(self, key):
|
|
|
|
raise KeyError
|
|
|
|
|
|
|
|
__marker = object()
|
|
|
|
|
|
|
|
def pop(self, key, default=__marker):
|
|
|
|
try:
|
|
|
|
value = self[key]
|
|
|
|
except KeyError:
|
|
|
|
if default is self.__marker:
|
|
|
|
raise
|
|
|
|
return default
|
|
|
|
else:
|
|
|
|
del self[key]
|
|
|
|
return value
|
|
|
|
|
|
|
|
def popitem(self):
|
|
|
|
try:
|
|
|
|
key = next(iter(self))
|
|
|
|
except StopIteration:
|
|
|
|
raise KeyError
|
|
|
|
value = self[key]
|
|
|
|
del self[key]
|
|
|
|
return key, value
|
|
|
|
|
|
|
|
def clear(self):
|
|
|
|
try:
|
|
|
|
while True:
|
|
|
|
self.popitem()
|
|
|
|
except KeyError:
|
|
|
|
pass
|
|
|
|
|
|
|
|
def update(self, other=(), **kwds):
|
|
|
|
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
|
|
|
|
|
2008-02-05 21:49:00 -04:00
|
|
|
def setdefault(self, key, default=None):
|
|
|
|
try:
|
|
|
|
return self[key]
|
|
|
|
except KeyError:
|
|
|
|
self[key] = default
|
|
|
|
return default
|
|
|
|
|
2007-11-21 20:55:51 -04:00
|
|
|
MutableMapping.register(dict)
|
|
|
|
|
|
|
|
|
|
|
|
### SEQUENCES ###
|
|
|
|
|
|
|
|
|
2008-02-08 21:18:42 -04:00
|
|
|
class Sequence(Sized, Iterable, Container):
|
2007-11-21 20:55:51 -04:00
|
|
|
"""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
|
2008-02-08 19:02:27 -04:00
|
|
|
try:
|
|
|
|
while True:
|
2007-11-21 20:55:51 -04:00
|
|
|
v = self[i]
|
2008-02-08 19:02:27 -04:00
|
|
|
yield v
|
|
|
|
i += 1
|
|
|
|
except IndexError:
|
|
|
|
return
|
2007-11-21 20:55:51 -04:00
|
|
|
|
|
|
|
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):
|
|
|
|
for i, v in enumerate(self):
|
|
|
|
if v == value:
|
|
|
|
return i
|
|
|
|
raise ValueError
|
|
|
|
|
|
|
|
def count(self, value):
|
|
|
|
return sum(1 for v in self if v == value)
|
|
|
|
|
|
|
|
Sequence.register(tuple)
|
|
|
|
Sequence.register(basestring)
|
|
|
|
Sequence.register(buffer)
|
2009-02-24 08:25:32 -04:00
|
|
|
Sequence.register(xrange)
|
2007-11-21 20:55:51 -04:00
|
|
|
|
|
|
|
|
|
|
|
class MutableSequence(Sequence):
|
|
|
|
|
|
|
|
@abstractmethod
|
|
|
|
def __setitem__(self, index, value):
|
|
|
|
raise IndexError
|
|
|
|
|
|
|
|
@abstractmethod
|
|
|
|
def __delitem__(self, index):
|
|
|
|
raise IndexError
|
|
|
|
|
|
|
|
@abstractmethod
|
|
|
|
def insert(self, index, value):
|
|
|
|
raise IndexError
|
|
|
|
|
|
|
|
def append(self, value):
|
|
|
|
self.insert(len(self), value)
|
|
|
|
|
|
|
|
def reverse(self):
|
|
|
|
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):
|
|
|
|
for v in values:
|
|
|
|
self.append(v)
|
|
|
|
|
|
|
|
def pop(self, index=-1):
|
|
|
|
v = self[index]
|
|
|
|
del self[index]
|
|
|
|
return v
|
|
|
|
|
|
|
|
def remove(self, value):
|
|
|
|
del self[self.index(value)]
|
|
|
|
|
|
|
|
def __iadd__(self, values):
|
|
|
|
self.extend(values)
|
2009-05-18 12:56:38 -03:00
|
|
|
return self
|
2007-11-21 20:55:51 -04:00
|
|
|
|
|
|
|
MutableSequence.register(list)
|