| Guido van Rossum | 64c06e3 | 2007-11-22 00:55:51 +0000 | [diff] [blame] | 1 | # Copyright 2007 Google, Inc. All Rights Reserved. | 
|  | 2 | # Licensed to PSF under a Contributor Agreement. | 
|  | 3 |  | 
|  | 4 | """Abstract Base Classes (ABCs) for collections, according to PEP 3119. | 
|  | 5 |  | 
|  | 6 | DON'T USE THIS MODULE DIRECTLY!  The classes here should be imported | 
|  | 7 | via collections; they are defined here only to alleviate certain | 
|  | 8 | bootstrapping issues.  Unit tests are in test_collections. | 
|  | 9 | """ | 
|  | 10 |  | 
|  | 11 | from abc import ABCMeta, abstractmethod | 
| Raymond Hettinger | 4c52f52 | 2008-06-23 03:29:28 +0000 | [diff] [blame] | 12 | import sys | 
| Guido van Rossum | 64c06e3 | 2007-11-22 00:55:51 +0000 | [diff] [blame] | 13 |  | 
|  | 14 | __all__ = ["Hashable", "Iterable", "Iterator", | 
|  | 15 | "Sized", "Container", "Callable", | 
|  | 16 | "Set", "MutableSet", | 
|  | 17 | "Mapping", "MutableMapping", | 
|  | 18 | "MappingView", "KeysView", "ItemsView", "ValuesView", | 
|  | 19 | "Sequence", "MutableSequence", | 
|  | 20 | ] | 
|  | 21 |  | 
|  | 22 | ### ONE-TRICK PONIES ### | 
|  | 23 |  | 
| Florent Xicluna | 47627d5 | 2010-03-08 15:20:28 +0000 | [diff] [blame] | 24 | def _hasattr(C, attr): | 
|  | 25 | try: | 
|  | 26 | return any(attr in B.__dict__ for B in C.__mro__) | 
|  | 27 | except AttributeError: | 
|  | 28 | # Old-style class | 
|  | 29 | return hasattr(C, attr) | 
|  | 30 |  | 
|  | 31 |  | 
| Guido van Rossum | 64c06e3 | 2007-11-22 00:55:51 +0000 | [diff] [blame] | 32 | class Hashable: | 
|  | 33 | __metaclass__ = ABCMeta | 
|  | 34 |  | 
|  | 35 | @abstractmethod | 
|  | 36 | def __hash__(self): | 
|  | 37 | return 0 | 
|  | 38 |  | 
|  | 39 | @classmethod | 
|  | 40 | def __subclasshook__(cls, C): | 
|  | 41 | if cls is Hashable: | 
| Florent Xicluna | 47627d5 | 2010-03-08 15:20:28 +0000 | [diff] [blame] | 42 | try: | 
|  | 43 | for B in C.__mro__: | 
|  | 44 | if "__hash__" in B.__dict__: | 
|  | 45 | if B.__dict__["__hash__"]: | 
|  | 46 | return True | 
|  | 47 | break | 
|  | 48 | except AttributeError: | 
|  | 49 | # Old-style class | 
|  | 50 | if getattr(C, "__hash__", None): | 
|  | 51 | return True | 
| Guido van Rossum | 64c06e3 | 2007-11-22 00:55:51 +0000 | [diff] [blame] | 52 | return NotImplemented | 
|  | 53 |  | 
|  | 54 |  | 
|  | 55 | class Iterable: | 
|  | 56 | __metaclass__ = ABCMeta | 
|  | 57 |  | 
|  | 58 | @abstractmethod | 
|  | 59 | def __iter__(self): | 
|  | 60 | while False: | 
|  | 61 | yield None | 
|  | 62 |  | 
|  | 63 | @classmethod | 
|  | 64 | def __subclasshook__(cls, C): | 
|  | 65 | if cls is Iterable: | 
| Florent Xicluna | 47627d5 | 2010-03-08 15:20:28 +0000 | [diff] [blame] | 66 | if _hasattr(C, "__iter__"): | 
| Guido van Rossum | 64c06e3 | 2007-11-22 00:55:51 +0000 | [diff] [blame] | 67 | return True | 
|  | 68 | return NotImplemented | 
|  | 69 |  | 
|  | 70 | Iterable.register(str) | 
|  | 71 |  | 
|  | 72 |  | 
| Raymond Hettinger | c2bc0d1 | 2008-02-09 01:18:42 +0000 | [diff] [blame] | 73 | class Iterator(Iterable): | 
| Guido van Rossum | 64c06e3 | 2007-11-22 00:55:51 +0000 | [diff] [blame] | 74 |  | 
|  | 75 | @abstractmethod | 
| Raymond Hettinger | f779e6f | 2009-01-28 23:02:26 +0000 | [diff] [blame] | 76 | def next(self): | 
| Guido van Rossum | 64c06e3 | 2007-11-22 00:55:51 +0000 | [diff] [blame] | 77 | raise StopIteration | 
|  | 78 |  | 
|  | 79 | def __iter__(self): | 
|  | 80 | return self | 
|  | 81 |  | 
|  | 82 | @classmethod | 
|  | 83 | def __subclasshook__(cls, C): | 
|  | 84 | if cls is Iterator: | 
| Alexander Belopolsky | 1fea5c4 | 2010-11-30 01:18:17 +0000 | [diff] [blame] | 85 | if _hasattr(C, "next") and _hasattr(C, "__iter__"): | 
| Guido van Rossum | 64c06e3 | 2007-11-22 00:55:51 +0000 | [diff] [blame] | 86 | return True | 
|  | 87 | return NotImplemented | 
|  | 88 |  | 
|  | 89 |  | 
|  | 90 | class Sized: | 
|  | 91 | __metaclass__ = ABCMeta | 
|  | 92 |  | 
|  | 93 | @abstractmethod | 
|  | 94 | def __len__(self): | 
|  | 95 | return 0 | 
|  | 96 |  | 
|  | 97 | @classmethod | 
|  | 98 | def __subclasshook__(cls, C): | 
|  | 99 | if cls is Sized: | 
| Florent Xicluna | 47627d5 | 2010-03-08 15:20:28 +0000 | [diff] [blame] | 100 | if _hasattr(C, "__len__"): | 
| Guido van Rossum | 64c06e3 | 2007-11-22 00:55:51 +0000 | [diff] [blame] | 101 | return True | 
|  | 102 | return NotImplemented | 
|  | 103 |  | 
|  | 104 |  | 
|  | 105 | class Container: | 
|  | 106 | __metaclass__ = ABCMeta | 
|  | 107 |  | 
|  | 108 | @abstractmethod | 
|  | 109 | def __contains__(self, x): | 
|  | 110 | return False | 
|  | 111 |  | 
|  | 112 | @classmethod | 
|  | 113 | def __subclasshook__(cls, C): | 
|  | 114 | if cls is Container: | 
| Florent Xicluna | 47627d5 | 2010-03-08 15:20:28 +0000 | [diff] [blame] | 115 | if _hasattr(C, "__contains__"): | 
| Guido van Rossum | 64c06e3 | 2007-11-22 00:55:51 +0000 | [diff] [blame] | 116 | return True | 
|  | 117 | return NotImplemented | 
|  | 118 |  | 
|  | 119 |  | 
|  | 120 | class Callable: | 
|  | 121 | __metaclass__ = ABCMeta | 
|  | 122 |  | 
|  | 123 | @abstractmethod | 
| Raymond Hettinger | 10ac19b | 2008-03-03 22:19:58 +0000 | [diff] [blame] | 124 | def __call__(self, *args, **kwds): | 
| Guido van Rossum | 64c06e3 | 2007-11-22 00:55:51 +0000 | [diff] [blame] | 125 | return False | 
|  | 126 |  | 
|  | 127 | @classmethod | 
|  | 128 | def __subclasshook__(cls, C): | 
|  | 129 | if cls is Callable: | 
| Florent Xicluna | 47627d5 | 2010-03-08 15:20:28 +0000 | [diff] [blame] | 130 | if _hasattr(C, "__call__"): | 
| Guido van Rossum | 64c06e3 | 2007-11-22 00:55:51 +0000 | [diff] [blame] | 131 | return True | 
|  | 132 | return NotImplemented | 
|  | 133 |  | 
|  | 134 |  | 
|  | 135 | ### SETS ### | 
|  | 136 |  | 
|  | 137 |  | 
| Raymond Hettinger | c2bc0d1 | 2008-02-09 01:18:42 +0000 | [diff] [blame] | 138 | class Set(Sized, Iterable, Container): | 
| Guido van Rossum | 64c06e3 | 2007-11-22 00:55:51 +0000 | [diff] [blame] | 139 | """A set is a finite, iterable container. | 
|  | 140 |  | 
|  | 141 | This class provides concrete generic implementations of all | 
|  | 142 | methods except for __contains__, __iter__ and __len__. | 
|  | 143 |  | 
|  | 144 | To override the comparisons (presumably for speed, as the | 
|  | 145 | semantics are fixed), all you have to do is redefine __le__ and | 
|  | 146 | then the other operations will automatically follow suit. | 
|  | 147 | """ | 
|  | 148 |  | 
| Guido van Rossum | 64c06e3 | 2007-11-22 00:55:51 +0000 | [diff] [blame] | 149 | def __le__(self, other): | 
|  | 150 | if not isinstance(other, Set): | 
|  | 151 | return NotImplemented | 
|  | 152 | if len(self) > len(other): | 
|  | 153 | return False | 
|  | 154 | for elem in self: | 
|  | 155 | if elem not in other: | 
|  | 156 | return False | 
|  | 157 | return True | 
|  | 158 |  | 
|  | 159 | def __lt__(self, other): | 
|  | 160 | if not isinstance(other, Set): | 
|  | 161 | return NotImplemented | 
|  | 162 | return len(self) < len(other) and self.__le__(other) | 
|  | 163 |  | 
| Raymond Hettinger | d53f1c4 | 2008-02-08 23:34:21 +0000 | [diff] [blame] | 164 | def __gt__(self, other): | 
|  | 165 | if not isinstance(other, Set): | 
|  | 166 | return NotImplemented | 
|  | 167 | return other < self | 
|  | 168 |  | 
|  | 169 | def __ge__(self, other): | 
|  | 170 | if not isinstance(other, Set): | 
|  | 171 | return NotImplemented | 
|  | 172 | return other <= self | 
|  | 173 |  | 
| Guido van Rossum | 64c06e3 | 2007-11-22 00:55:51 +0000 | [diff] [blame] | 174 | def __eq__(self, other): | 
|  | 175 | if not isinstance(other, Set): | 
|  | 176 | return NotImplemented | 
|  | 177 | return len(self) == len(other) and self.__le__(other) | 
|  | 178 |  | 
| Raymond Hettinger | d53f1c4 | 2008-02-08 23:34:21 +0000 | [diff] [blame] | 179 | def __ne__(self, other): | 
|  | 180 | return not (self == other) | 
|  | 181 |  | 
| Guido van Rossum | 64c06e3 | 2007-11-22 00:55:51 +0000 | [diff] [blame] | 182 | @classmethod | 
|  | 183 | def _from_iterable(cls, it): | 
| Raymond Hettinger | 017b6a3 | 2008-02-07 03:10:33 +0000 | [diff] [blame] | 184 | '''Construct an instance of the class from any iterable input. | 
|  | 185 |  | 
|  | 186 | Must override this method if the class constructor signature | 
| Raymond Hettinger | 2e827bf | 2008-02-09 03:34:52 +0000 | [diff] [blame] | 187 | does not accept an iterable for an input. | 
| Raymond Hettinger | 017b6a3 | 2008-02-07 03:10:33 +0000 | [diff] [blame] | 188 | ''' | 
| Raymond Hettinger | 2e827bf | 2008-02-09 03:34:52 +0000 | [diff] [blame] | 189 | return cls(it) | 
| Guido van Rossum | 64c06e3 | 2007-11-22 00:55:51 +0000 | [diff] [blame] | 190 |  | 
|  | 191 | def __and__(self, other): | 
|  | 192 | if not isinstance(other, Iterable): | 
|  | 193 | return NotImplemented | 
|  | 194 | return self._from_iterable(value for value in other if value in self) | 
|  | 195 |  | 
| Raymond Hettinger | abf3fcf | 2008-01-30 00:01:07 +0000 | [diff] [blame] | 196 | def isdisjoint(self, other): | 
|  | 197 | for value in other: | 
|  | 198 | if value in self: | 
|  | 199 | return False | 
|  | 200 | return True | 
|  | 201 |  | 
| Guido van Rossum | 64c06e3 | 2007-11-22 00:55:51 +0000 | [diff] [blame] | 202 | def __or__(self, other): | 
|  | 203 | if not isinstance(other, Iterable): | 
|  | 204 | return NotImplemented | 
| Raymond Hettinger | 972fb07 | 2008-03-03 22:04:55 +0000 | [diff] [blame] | 205 | chain = (e for s in (self, other) for e in s) | 
|  | 206 | return self._from_iterable(chain) | 
| Guido van Rossum | 64c06e3 | 2007-11-22 00:55:51 +0000 | [diff] [blame] | 207 |  | 
|  | 208 | def __sub__(self, other): | 
|  | 209 | if not isinstance(other, Set): | 
|  | 210 | if not isinstance(other, Iterable): | 
|  | 211 | return NotImplemented | 
|  | 212 | other = self._from_iterable(other) | 
|  | 213 | return self._from_iterable(value for value in self | 
|  | 214 | if value not in other) | 
|  | 215 |  | 
|  | 216 | def __xor__(self, other): | 
|  | 217 | if not isinstance(other, Set): | 
|  | 218 | if not isinstance(other, Iterable): | 
|  | 219 | return NotImplemented | 
|  | 220 | other = self._from_iterable(other) | 
|  | 221 | return (self - other) | (other - self) | 
|  | 222 |  | 
| Nick Coghlan | 48361f5 | 2008-08-11 15:45:58 +0000 | [diff] [blame] | 223 | # Sets are not hashable by default, but subclasses can change this | 
|  | 224 | __hash__ = None | 
|  | 225 |  | 
| Guido van Rossum | 64c06e3 | 2007-11-22 00:55:51 +0000 | [diff] [blame] | 226 | def _hash(self): | 
|  | 227 | """Compute the hash value of a set. | 
|  | 228 |  | 
|  | 229 | Note that we don't define __hash__: not all sets are hashable. | 
|  | 230 | But if you define a hashable set type, its __hash__ should | 
|  | 231 | call this function. | 
|  | 232 |  | 
|  | 233 | This must be compatible __eq__. | 
|  | 234 |  | 
|  | 235 | All sets ought to compare equal if they contain the same | 
|  | 236 | elements, regardless of how they are implemented, and | 
|  | 237 | regardless of the order of the elements; so there's not much | 
|  | 238 | freedom for __eq__ or __hash__.  We match the algorithm used | 
|  | 239 | by the built-in frozenset type. | 
|  | 240 | """ | 
|  | 241 | MAX = sys.maxint | 
|  | 242 | MASK = 2 * MAX + 1 | 
|  | 243 | n = len(self) | 
|  | 244 | h = 1927868237 * (n + 1) | 
|  | 245 | h &= MASK | 
|  | 246 | for x in self: | 
|  | 247 | hx = hash(x) | 
|  | 248 | h ^= (hx ^ (hx << 16) ^ 89869747)  * 3644798167 | 
|  | 249 | h &= MASK | 
|  | 250 | h = h * 69069 + 907133923 | 
|  | 251 | h &= MASK | 
|  | 252 | if h > MAX: | 
|  | 253 | h -= MASK + 1 | 
|  | 254 | if h == -1: | 
|  | 255 | h = 590923713 | 
|  | 256 | return h | 
|  | 257 |  | 
|  | 258 | Set.register(frozenset) | 
|  | 259 |  | 
|  | 260 |  | 
|  | 261 | class MutableSet(Set): | 
|  | 262 |  | 
|  | 263 | @abstractmethod | 
|  | 264 | def add(self, value): | 
| Raymond Hettinger | 2d21d50 | 2009-01-13 09:08:32 +0000 | [diff] [blame] | 265 | """Add an element.""" | 
| Guido van Rossum | 64c06e3 | 2007-11-22 00:55:51 +0000 | [diff] [blame] | 266 | raise NotImplementedError | 
|  | 267 |  | 
|  | 268 | @abstractmethod | 
|  | 269 | def discard(self, value): | 
| Raymond Hettinger | 2d21d50 | 2009-01-13 09:08:32 +0000 | [diff] [blame] | 270 | """Remove an element.  Do not raise an exception if absent.""" | 
| Guido van Rossum | 64c06e3 | 2007-11-22 00:55:51 +0000 | [diff] [blame] | 271 | raise NotImplementedError | 
|  | 272 |  | 
| Raymond Hettinger | 7d518f4 | 2008-01-30 00:08:31 +0000 | [diff] [blame] | 273 | def remove(self, value): | 
|  | 274 | """Remove an element. If not a member, raise a KeyError.""" | 
|  | 275 | if value not in self: | 
|  | 276 | raise KeyError(value) | 
|  | 277 | self.discard(value) | 
|  | 278 |  | 
| Guido van Rossum | 64c06e3 | 2007-11-22 00:55:51 +0000 | [diff] [blame] | 279 | def pop(self): | 
|  | 280 | """Return the popped value.  Raise KeyError if empty.""" | 
|  | 281 | it = iter(self) | 
|  | 282 | try: | 
| Raymond Hettinger | f779e6f | 2009-01-28 23:02:26 +0000 | [diff] [blame] | 283 | value = next(it) | 
| Guido van Rossum | 64c06e3 | 2007-11-22 00:55:51 +0000 | [diff] [blame] | 284 | except StopIteration: | 
|  | 285 | raise KeyError | 
|  | 286 | self.discard(value) | 
|  | 287 | return value | 
|  | 288 |  | 
| Guido van Rossum | 64c06e3 | 2007-11-22 00:55:51 +0000 | [diff] [blame] | 289 | def clear(self): | 
|  | 290 | """This is slow (creates N new iterators!) but effective.""" | 
|  | 291 | try: | 
|  | 292 | while True: | 
|  | 293 | self.pop() | 
|  | 294 | except KeyError: | 
|  | 295 | pass | 
|  | 296 |  | 
|  | 297 | def __ior__(self, it): | 
|  | 298 | for value in it: | 
|  | 299 | self.add(value) | 
|  | 300 | return self | 
|  | 301 |  | 
| Raymond Hettinger | 66c4a6b | 2009-04-01 18:50:56 +0000 | [diff] [blame] | 302 | def __iand__(self, it): | 
|  | 303 | for value in (self - it): | 
|  | 304 | self.discard(value) | 
| Guido van Rossum | 64c06e3 | 2007-11-22 00:55:51 +0000 | [diff] [blame] | 305 | return self | 
|  | 306 |  | 
|  | 307 | def __ixor__(self, it): | 
| Daniel Stutzbach | 9128732 | 2010-08-24 21:09:30 +0000 | [diff] [blame] | 308 | if it is self: | 
|  | 309 | self.clear() | 
|  | 310 | else: | 
|  | 311 | if not isinstance(it, Set): | 
|  | 312 | it = self._from_iterable(it) | 
|  | 313 | for value in it: | 
|  | 314 | if value in self: | 
|  | 315 | self.discard(value) | 
|  | 316 | else: | 
|  | 317 | self.add(value) | 
| Raymond Hettinger | e973c61 | 2008-01-31 01:42:11 +0000 | [diff] [blame] | 318 | return self | 
| Guido van Rossum | 64c06e3 | 2007-11-22 00:55:51 +0000 | [diff] [blame] | 319 |  | 
|  | 320 | def __isub__(self, it): | 
| Daniel Stutzbach | 9128732 | 2010-08-24 21:09:30 +0000 | [diff] [blame] | 321 | if it is self: | 
|  | 322 | self.clear() | 
|  | 323 | else: | 
|  | 324 | for value in it: | 
|  | 325 | self.discard(value) | 
| Guido van Rossum | 64c06e3 | 2007-11-22 00:55:51 +0000 | [diff] [blame] | 326 | return self | 
|  | 327 |  | 
|  | 328 | MutableSet.register(set) | 
|  | 329 |  | 
|  | 330 |  | 
|  | 331 | ### MAPPINGS ### | 
|  | 332 |  | 
|  | 333 |  | 
| Raymond Hettinger | c2bc0d1 | 2008-02-09 01:18:42 +0000 | [diff] [blame] | 334 | class Mapping(Sized, Iterable, Container): | 
| Guido van Rossum | 64c06e3 | 2007-11-22 00:55:51 +0000 | [diff] [blame] | 335 |  | 
|  | 336 | @abstractmethod | 
|  | 337 | def __getitem__(self, key): | 
|  | 338 | raise KeyError | 
|  | 339 |  | 
|  | 340 | def get(self, key, default=None): | 
|  | 341 | try: | 
|  | 342 | return self[key] | 
|  | 343 | except KeyError: | 
|  | 344 | return default | 
|  | 345 |  | 
|  | 346 | def __contains__(self, key): | 
|  | 347 | try: | 
|  | 348 | self[key] | 
|  | 349 | except KeyError: | 
|  | 350 | return False | 
|  | 351 | else: | 
|  | 352 | return True | 
|  | 353 |  | 
| Georg Brandl | 60fbf7f | 2008-06-07 17:03:28 +0000 | [diff] [blame] | 354 | def iterkeys(self): | 
|  | 355 | return iter(self) | 
|  | 356 |  | 
|  | 357 | def itervalues(self): | 
|  | 358 | for key in self: | 
|  | 359 | yield self[key] | 
|  | 360 |  | 
|  | 361 | def iteritems(self): | 
|  | 362 | for key in self: | 
|  | 363 | yield (key, self[key]) | 
|  | 364 |  | 
| Guido van Rossum | 64c06e3 | 2007-11-22 00:55:51 +0000 | [diff] [blame] | 365 | def keys(self): | 
| Georg Brandl | 60fbf7f | 2008-06-07 17:03:28 +0000 | [diff] [blame] | 366 | return list(self) | 
| Guido van Rossum | 64c06e3 | 2007-11-22 00:55:51 +0000 | [diff] [blame] | 367 |  | 
|  | 368 | def items(self): | 
| Georg Brandl | 60fbf7f | 2008-06-07 17:03:28 +0000 | [diff] [blame] | 369 | return [(key, self[key]) for key in self] | 
| Guido van Rossum | 64c06e3 | 2007-11-22 00:55:51 +0000 | [diff] [blame] | 370 |  | 
|  | 371 | def values(self): | 
| Georg Brandl | 60fbf7f | 2008-06-07 17:03:28 +0000 | [diff] [blame] | 372 | return [self[key] for key in self] | 
| Guido van Rossum | 64c06e3 | 2007-11-22 00:55:51 +0000 | [diff] [blame] | 373 |  | 
| Nick Coghlan | 48361f5 | 2008-08-11 15:45:58 +0000 | [diff] [blame] | 374 | # Mappings are not hashable by default, but subclasses can change this | 
|  | 375 | __hash__ = None | 
|  | 376 |  | 
| Raymond Hettinger | 45eda64 | 2008-02-06 01:49:00 +0000 | [diff] [blame] | 377 | def __eq__(self, other): | 
| Benjamin Peterson | eb318d3 | 2010-05-21 20:51:45 +0000 | [diff] [blame] | 378 | if not isinstance(other, Mapping): | 
|  | 379 | return NotImplemented | 
|  | 380 | return dict(self.items()) == dict(other.items()) | 
| Raymond Hettinger | 45eda64 | 2008-02-06 01:49:00 +0000 | [diff] [blame] | 381 |  | 
|  | 382 | def __ne__(self, other): | 
|  | 383 | return not (self == other) | 
| Guido van Rossum | 64c06e3 | 2007-11-22 00:55:51 +0000 | [diff] [blame] | 384 |  | 
| Raymond Hettinger | c2bc0d1 | 2008-02-09 01:18:42 +0000 | [diff] [blame] | 385 | class MappingView(Sized): | 
| Guido van Rossum | 64c06e3 | 2007-11-22 00:55:51 +0000 | [diff] [blame] | 386 |  | 
|  | 387 | def __init__(self, mapping): | 
|  | 388 | self._mapping = mapping | 
|  | 389 |  | 
|  | 390 | def __len__(self): | 
|  | 391 | return len(self._mapping) | 
|  | 392 |  | 
| Raymond Hettinger | b31a6d0 | 2009-02-27 08:09:47 +0000 | [diff] [blame] | 393 | def __repr__(self): | 
|  | 394 | return '{0.__class__.__name__}({0._mapping!r})'.format(self) | 
|  | 395 |  | 
| Guido van Rossum | 64c06e3 | 2007-11-22 00:55:51 +0000 | [diff] [blame] | 396 |  | 
|  | 397 | class KeysView(MappingView, Set): | 
|  | 398 |  | 
| Raymond Hettinger | 917bba1 | 2010-08-22 08:01:58 +0000 | [diff] [blame] | 399 | @classmethod | 
|  | 400 | def _from_iterable(self, it): | 
|  | 401 | return set(it) | 
|  | 402 |  | 
| Guido van Rossum | 64c06e3 | 2007-11-22 00:55:51 +0000 | [diff] [blame] | 403 | def __contains__(self, key): | 
|  | 404 | return key in self._mapping | 
|  | 405 |  | 
|  | 406 | def __iter__(self): | 
|  | 407 | for key in self._mapping: | 
|  | 408 | yield key | 
|  | 409 |  | 
| Guido van Rossum | 64c06e3 | 2007-11-22 00:55:51 +0000 | [diff] [blame] | 410 |  | 
|  | 411 | class ItemsView(MappingView, Set): | 
|  | 412 |  | 
| Raymond Hettinger | 917bba1 | 2010-08-22 08:01:58 +0000 | [diff] [blame] | 413 | @classmethod | 
|  | 414 | def _from_iterable(self, it): | 
|  | 415 | return set(it) | 
|  | 416 |  | 
| Guido van Rossum | 64c06e3 | 2007-11-22 00:55:51 +0000 | [diff] [blame] | 417 | def __contains__(self, item): | 
|  | 418 | key, value = item | 
|  | 419 | try: | 
|  | 420 | v = self._mapping[key] | 
|  | 421 | except KeyError: | 
|  | 422 | return False | 
|  | 423 | else: | 
|  | 424 | return v == value | 
|  | 425 |  | 
|  | 426 | def __iter__(self): | 
|  | 427 | for key in self._mapping: | 
|  | 428 | yield (key, self._mapping[key]) | 
|  | 429 |  | 
| Guido van Rossum | 64c06e3 | 2007-11-22 00:55:51 +0000 | [diff] [blame] | 430 |  | 
|  | 431 | class ValuesView(MappingView): | 
|  | 432 |  | 
|  | 433 | def __contains__(self, value): | 
|  | 434 | for key in self._mapping: | 
|  | 435 | if value == self._mapping[key]: | 
|  | 436 | return True | 
|  | 437 | return False | 
|  | 438 |  | 
|  | 439 | def __iter__(self): | 
|  | 440 | for key in self._mapping: | 
|  | 441 | yield self._mapping[key] | 
|  | 442 |  | 
| Guido van Rossum | 64c06e3 | 2007-11-22 00:55:51 +0000 | [diff] [blame] | 443 |  | 
|  | 444 | class MutableMapping(Mapping): | 
|  | 445 |  | 
|  | 446 | @abstractmethod | 
|  | 447 | def __setitem__(self, key, value): | 
|  | 448 | raise KeyError | 
|  | 449 |  | 
|  | 450 | @abstractmethod | 
|  | 451 | def __delitem__(self, key): | 
|  | 452 | raise KeyError | 
|  | 453 |  | 
|  | 454 | __marker = object() | 
|  | 455 |  | 
|  | 456 | def pop(self, key, default=__marker): | 
|  | 457 | try: | 
|  | 458 | value = self[key] | 
|  | 459 | except KeyError: | 
|  | 460 | if default is self.__marker: | 
|  | 461 | raise | 
|  | 462 | return default | 
|  | 463 | else: | 
|  | 464 | del self[key] | 
|  | 465 | return value | 
|  | 466 |  | 
|  | 467 | def popitem(self): | 
|  | 468 | try: | 
|  | 469 | key = next(iter(self)) | 
|  | 470 | except StopIteration: | 
|  | 471 | raise KeyError | 
|  | 472 | value = self[key] | 
|  | 473 | del self[key] | 
|  | 474 | return key, value | 
|  | 475 |  | 
|  | 476 | def clear(self): | 
|  | 477 | try: | 
|  | 478 | while True: | 
|  | 479 | self.popitem() | 
|  | 480 | except KeyError: | 
|  | 481 | pass | 
|  | 482 |  | 
| Mark Dickinson | 42add99 | 2010-07-11 19:17:28 +0000 | [diff] [blame] | 483 | def update(*args, **kwds): | 
|  | 484 | if len(args) > 2: | 
|  | 485 | raise TypeError("update() takes at most 2 positional " | 
|  | 486 | "arguments ({} given)".format(len(args))) | 
|  | 487 | elif not args: | 
|  | 488 | raise TypeError("update() takes at least 1 argument (0 given)") | 
|  | 489 | self = args[0] | 
|  | 490 | other = args[1] if len(args) >= 2 else () | 
|  | 491 |  | 
| Guido van Rossum | 64c06e3 | 2007-11-22 00:55:51 +0000 | [diff] [blame] | 492 | if isinstance(other, Mapping): | 
|  | 493 | for key in other: | 
|  | 494 | self[key] = other[key] | 
|  | 495 | elif hasattr(other, "keys"): | 
|  | 496 | for key in other.keys(): | 
|  | 497 | self[key] = other[key] | 
|  | 498 | else: | 
|  | 499 | for key, value in other: | 
|  | 500 | self[key] = value | 
|  | 501 | for key, value in kwds.items(): | 
|  | 502 | self[key] = value | 
|  | 503 |  | 
| Raymond Hettinger | 45eda64 | 2008-02-06 01:49:00 +0000 | [diff] [blame] | 504 | def setdefault(self, key, default=None): | 
|  | 505 | try: | 
|  | 506 | return self[key] | 
|  | 507 | except KeyError: | 
|  | 508 | self[key] = default | 
|  | 509 | return default | 
|  | 510 |  | 
| Guido van Rossum | 64c06e3 | 2007-11-22 00:55:51 +0000 | [diff] [blame] | 511 | MutableMapping.register(dict) | 
|  | 512 |  | 
|  | 513 |  | 
|  | 514 | ### SEQUENCES ### | 
|  | 515 |  | 
|  | 516 |  | 
| Raymond Hettinger | c2bc0d1 | 2008-02-09 01:18:42 +0000 | [diff] [blame] | 517 | class Sequence(Sized, Iterable, Container): | 
| Guido van Rossum | 64c06e3 | 2007-11-22 00:55:51 +0000 | [diff] [blame] | 518 | """All the operations on a read-only sequence. | 
|  | 519 |  | 
|  | 520 | Concrete subclasses must override __new__ or __init__, | 
|  | 521 | __getitem__, and __len__. | 
|  | 522 | """ | 
|  | 523 |  | 
|  | 524 | @abstractmethod | 
|  | 525 | def __getitem__(self, index): | 
|  | 526 | raise IndexError | 
|  | 527 |  | 
| Guido van Rossum | 64c06e3 | 2007-11-22 00:55:51 +0000 | [diff] [blame] | 528 | def __iter__(self): | 
|  | 529 | i = 0 | 
| Raymond Hettinger | 18a1ffc | 2008-02-08 23:02:27 +0000 | [diff] [blame] | 530 | try: | 
|  | 531 | while True: | 
| Guido van Rossum | 64c06e3 | 2007-11-22 00:55:51 +0000 | [diff] [blame] | 532 | v = self[i] | 
| Raymond Hettinger | 18a1ffc | 2008-02-08 23:02:27 +0000 | [diff] [blame] | 533 | yield v | 
|  | 534 | i += 1 | 
|  | 535 | except IndexError: | 
|  | 536 | return | 
| Guido van Rossum | 64c06e3 | 2007-11-22 00:55:51 +0000 | [diff] [blame] | 537 |  | 
|  | 538 | def __contains__(self, value): | 
|  | 539 | for v in self: | 
|  | 540 | if v == value: | 
|  | 541 | return True | 
|  | 542 | return False | 
|  | 543 |  | 
|  | 544 | def __reversed__(self): | 
|  | 545 | for i in reversed(range(len(self))): | 
|  | 546 | yield self[i] | 
|  | 547 |  | 
|  | 548 | def index(self, value): | 
|  | 549 | for i, v in enumerate(self): | 
|  | 550 | if v == value: | 
|  | 551 | return i | 
|  | 552 | raise ValueError | 
|  | 553 |  | 
|  | 554 | def count(self, value): | 
|  | 555 | return sum(1 for v in self if v == value) | 
|  | 556 |  | 
|  | 557 | Sequence.register(tuple) | 
|  | 558 | Sequence.register(basestring) | 
|  | 559 | Sequence.register(buffer) | 
| Raymond Hettinger | 8c56f88 | 2009-02-24 12:23:23 +0000 | [diff] [blame] | 560 | Sequence.register(xrange) | 
| Guido van Rossum | 64c06e3 | 2007-11-22 00:55:51 +0000 | [diff] [blame] | 561 |  | 
|  | 562 |  | 
|  | 563 | class MutableSequence(Sequence): | 
|  | 564 |  | 
|  | 565 | @abstractmethod | 
|  | 566 | def __setitem__(self, index, value): | 
|  | 567 | raise IndexError | 
|  | 568 |  | 
|  | 569 | @abstractmethod | 
|  | 570 | def __delitem__(self, index): | 
|  | 571 | raise IndexError | 
|  | 572 |  | 
|  | 573 | @abstractmethod | 
|  | 574 | def insert(self, index, value): | 
|  | 575 | raise IndexError | 
|  | 576 |  | 
|  | 577 | def append(self, value): | 
|  | 578 | self.insert(len(self), value) | 
|  | 579 |  | 
|  | 580 | def reverse(self): | 
|  | 581 | n = len(self) | 
|  | 582 | for i in range(n//2): | 
|  | 583 | self[i], self[n-i-1] = self[n-i-1], self[i] | 
|  | 584 |  | 
|  | 585 | def extend(self, values): | 
|  | 586 | for v in values: | 
|  | 587 | self.append(v) | 
|  | 588 |  | 
|  | 589 | def pop(self, index=-1): | 
|  | 590 | v = self[index] | 
|  | 591 | del self[index] | 
|  | 592 | return v | 
|  | 593 |  | 
|  | 594 | def remove(self, value): | 
|  | 595 | del self[self.index(value)] | 
|  | 596 |  | 
|  | 597 | def __iadd__(self, values): | 
|  | 598 | self.extend(values) | 
| Raymond Hettinger | fceb5d4 | 2009-05-18 15:51:59 +0000 | [diff] [blame] | 599 | return self | 
| Guido van Rossum | 64c06e3 | 2007-11-22 00:55:51 +0000 | [diff] [blame] | 600 |  | 
|  | 601 | MutableSequence.register(list) |