Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(1)

Delta Between Two Patch Sets: Lib/_collections_abc.py

Issue 25958: Implicit ABCs have no means of "anti-registration"
Left Patch Set: Created 4 years, 1 month ago
Right Patch Set: Created 3 years, 6 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « Doc/reference/datamodel.rst ('k') | Lib/test/test_augassign.py » ('j') | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
1 # Copyright 2007 Google, Inc. All Rights Reserved. 1 # Copyright 2007 Google, Inc. All Rights Reserved.
2 # Licensed to PSF under a Contributor Agreement. 2 # Licensed to PSF under a Contributor Agreement.
3 3
4 """Abstract Base Classes (ABCs) for collections, according to PEP 3119. 4 """Abstract Base Classes (ABCs) for collections, according to PEP 3119.
5 5
6 Unit tests are in test_collections. 6 Unit tests are in test_collections.
7 """ 7 """
8 8
9 from abc import ABCMeta, abstractmethod 9 from abc import ABCMeta, abstractmethod
10 import sys 10 import sys
11 11
12 __all__ = ["Awaitable", "Coroutine", "AsyncIterable", "AsyncIterator", 12 __all__ = ["Awaitable", "Coroutine", "AsyncIterable", "AsyncIterator",
13 "Hashable", "Iterable", "Iterator", "Generator", 13 "Hashable", "Iterable", "Iterator", "Generator", "Reversible",
14 "Sized", "Container", "Reversible", "Callable", 14 "Sized", "Container", "Callable",
15 "Set", "MutableSet", 15 "Set", "MutableSet",
16 "Mapping", "MutableMapping", 16 "Mapping", "MutableMapping",
17 "MappingView", "KeysView", "ItemsView", "ValuesView", 17 "MappingView", "KeysView", "ItemsView", "ValuesView",
18 "Sequence", "MutableSequence", 18 "Sequence", "MutableSequence",
19 "ByteString", 19 "ByteString",
20 ] 20 ]
21 21
22 # This module has been renamed from collections.abc to _collections_abc to 22 # This module has been renamed from collections.abc to _collections_abc to
23 # speed up interpreter startup. Some of the types such as MutableMapping are 23 # speed up interpreter startup. Some of the types such as MutableMapping are
24 # required early but collections module imports a lot of other modules. 24 # required early but collections module imports a lot of other modules.
(...skipping 30 matching lines...) Expand all
55 ## coroutine ## 55 ## coroutine ##
56 async def _coro(): pass 56 async def _coro(): pass
57 _coro = _coro() 57 _coro = _coro()
58 coroutine = type(_coro) 58 coroutine = type(_coro)
59 _coro.close() # Prevent ResourceWarning 59 _coro.close() # Prevent ResourceWarning
60 del _coro 60 del _coro
61 61
62 62
63 ### ONE-TRICK PONIES ### 63 ### ONE-TRICK PONIES ###
64 64
65 def _check_methods(C, *methods): 65 def _check_methods(C, *methods):
storchaka 2016/01/05 21:48:04 FYI, there is a separate issue for introducing suc
66 mro = C.__mro__ 66 mro = C.__mro__
67 for method in methods: 67 for method in methods:
68 for B in mro: 68 for B in mro:
69 if method in B.__dict__: 69 if method in B.__dict__:
70 if B.__dict__[method] is None: 70 if B.__dict__[method] is None:
71 return NotImplemented 71 return NotImplemented
72 break 72 break
73 else: 73 else:
74 return NotImplemented 74 return NotImplemented
75 return True 75 return True
76 76
77 class Hashable(metaclass=ABCMeta): 77 class Hashable(metaclass=ABCMeta):
78 78
79 __slots__ = () 79 __slots__ = ()
80 80
81 @abstractmethod 81 @abstractmethod
82 def __hash__(self): 82 def __hash__(self):
83 return 0 83 return 0
84 84
85 @classmethod 85 @classmethod
86 def __subclasshook__(cls, C): 86 def __subclasshook__(cls, C):
87 print(cls)
gvanrossum 2016/01/05 20:55:20 Delete this.
storchaka 2016/01/05 21:48:04 Forgotten debugging print.
88 if cls is Hashable: 87 if cls is Hashable:
89 return _check_methods(C, "__hash__") 88 return _check_methods(C, "__hash__")
90 return NotImplemented 89 return NotImplemented
91 90
92 91
93 class Awaitable(metaclass=ABCMeta): 92 class Awaitable(metaclass=ABCMeta):
94 93
95 __slots__ = () 94 __slots__ = ()
96 95
97 @abstractmethod 96 @abstractmethod
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
147 146
148 147
149 Coroutine.register(coroutine) 148 Coroutine.register(coroutine)
150 149
151 150
152 class AsyncIterable(metaclass=ABCMeta): 151 class AsyncIterable(metaclass=ABCMeta):
153 152
154 __slots__ = () 153 __slots__ = ()
155 154
156 @abstractmethod 155 @abstractmethod
157 async def __aiter__(self): 156 def __aiter__(self):
158 return AsyncIterator() 157 return AsyncIterator()
159 158
160 @classmethod 159 @classmethod
161 def __subclasshook__(cls, C): 160 def __subclasshook__(cls, C):
162 if cls is AsyncIterable: 161 if cls is AsyncIterable:
163 return _check_methods(C, "__aiter__") 162 return _check_methods(C, "__aiter__")
164 return NotImplemented 163 return NotImplemented
165 164
166 165
167 class AsyncIterator(AsyncIterable): 166 class AsyncIterator(AsyncIterable):
168 167
169 __slots__ = () 168 __slots__ = ()
170 169
171 @abstractmethod 170 @abstractmethod
172 async def __anext__(self): 171 async def __anext__(self):
173 """Return the next item or raise StopAsyncIteration when exhausted.""" 172 """Return the next item or raise StopAsyncIteration when exhausted."""
174 raise StopAsyncIteration 173 raise StopAsyncIteration
175 174
176 async def __aiter__(self): 175 def __aiter__(self):
177 return self 176 return self
178 177
179 @classmethod 178 @classmethod
180 def __subclasshook__(cls, C): 179 def __subclasshook__(cls, C):
181 if cls is AsyncIterator: 180 if cls is AsyncIterator:
182 return _check_methods(C, "__anext__", "__aiter__") 181 return _check_methods(C, "__anext__", "__aiter__")
183 return NotImplemented 182 return NotImplemented
184 183
185 184
186 class Iterable(metaclass=ABCMeta): 185 class Iterable(metaclass=ABCMeta):
(...skipping 20 matching lines...) Expand all
207 def __next__(self): 206 def __next__(self):
208 'Return the next item from the iterator. When exhausted, raise StopItera tion' 207 'Return the next item from the iterator. When exhausted, raise StopItera tion'
209 raise StopIteration 208 raise StopIteration
210 209
211 def __iter__(self): 210 def __iter__(self):
212 return self 211 return self
213 212
214 @classmethod 213 @classmethod
215 def __subclasshook__(cls, C): 214 def __subclasshook__(cls, C):
216 if cls is Iterator: 215 if cls is Iterator:
217 return _check_methods(C, "__next__", "__iter__") 216 return _check_methods(C, '__iter__', '__next__')
218 return NotImplemented 217 return NotImplemented
219 218
220 Iterator.register(bytes_iterator) 219 Iterator.register(bytes_iterator)
221 Iterator.register(bytearray_iterator) 220 Iterator.register(bytearray_iterator)
222 #Iterator.register(callable_iterator) 221 #Iterator.register(callable_iterator)
223 Iterator.register(dict_keyiterator) 222 Iterator.register(dict_keyiterator)
224 Iterator.register(dict_valueiterator) 223 Iterator.register(dict_valueiterator)
225 Iterator.register(dict_itemiterator) 224 Iterator.register(dict_itemiterator)
226 Iterator.register(list_iterator) 225 Iterator.register(list_iterator)
227 Iterator.register(list_reverseiterator) 226 Iterator.register(list_reverseiterator)
228 Iterator.register(range_iterator) 227 Iterator.register(range_iterator)
229 Iterator.register(set_iterator) 228 Iterator.register(set_iterator)
230 Iterator.register(str_iterator) 229 Iterator.register(str_iterator)
231 Iterator.register(tuple_iterator) 230 Iterator.register(tuple_iterator)
232 Iterator.register(zip_iterator) 231 Iterator.register(zip_iterator)
233 232
234 233
234 class Reversible(Iterable):
235
236 __slots__ = ()
237
238 @abstractmethod
239 def __reversed__(self):
240 while False:
241 yield None
242
243 @classmethod
244 def __subclasshook__(cls, C):
245 if cls is Reversible:
246 return _check_methods(C, "__reversed__", "__iter__")
247 return NotImplemented
248
249
235 class Generator(Iterator): 250 class Generator(Iterator):
236 251
237 __slots__ = () 252 __slots__ = ()
238 253
239 def __next__(self): 254 def __next__(self):
240 """Return the next item from the generator. 255 """Return the next item from the generator.
241 When exhausted, raise StopIteration. 256 When exhausted, raise StopIteration.
242 """ 257 """
243 return self.send(None) 258 return self.send(None)
244 259
(...skipping 27 matching lines...) Expand all
272 else: 287 else:
273 raise RuntimeError("generator ignored GeneratorExit") 288 raise RuntimeError("generator ignored GeneratorExit")
274 289
275 @classmethod 290 @classmethod
276 def __subclasshook__(cls, C): 291 def __subclasshook__(cls, C):
277 if cls is Generator: 292 if cls is Generator:
278 return _check_methods(C, '__iter__', '__next__', 293 return _check_methods(C, '__iter__', '__next__',
279 'send', 'throw', 'close') 294 'send', 'throw', 'close')
280 return NotImplemented 295 return NotImplemented
281 296
282
283 Generator.register(generator) 297 Generator.register(generator)
284 298
285 299
286 class Sized(metaclass=ABCMeta): 300 class Sized(metaclass=ABCMeta):
287 301
288 __slots__ = () 302 __slots__ = ()
289 303
290 @abstractmethod 304 @abstractmethod
291 def __len__(self): 305 def __len__(self):
292 return 0 306 return 0
(...skipping 25 matching lines...) Expand all
318 __slots__ = () 332 __slots__ = ()
319 333
320 @abstractmethod 334 @abstractmethod
321 def __call__(self, *args, **kwds): 335 def __call__(self, *args, **kwds):
322 return False 336 return False
323 337
324 @classmethod 338 @classmethod
325 def __subclasshook__(cls, C): 339 def __subclasshook__(cls, C):
326 if cls is Callable: 340 if cls is Callable:
327 return _check_methods(C, "__call__") 341 return _check_methods(C, "__call__")
328 return NotImplemented
329
330
331 class Reversible(Iterable):
332
333 __slots__ = ()
334
335 @abstractmethod
336 def __reversed__(self):
337 while False:
338 yield None
339
340 @classmethod
341 def __subclasshook__(cls, C):
storchaka 2016/01/05 21:48:04 Since Reversible is Iterable subclass, shouldn't R
342 if cls is Reversible:
343 return _check_methods(C, "__reversed__")
344 return NotImplemented 342 return NotImplemented
345 343
346 344
347 ### SETS ### 345 ### SETS ###
348 346
349 347
350 class Set(Sized, Iterable, Container): 348 class Set(Sized, Iterable, Container):
351 349
352 """A set is a finite, iterable container. 350 """A set is a finite, iterable container.
353 351
(...skipping 310 matching lines...) Expand 10 before | Expand all | Expand 10 after
664 def _from_iterable(self, it): 662 def _from_iterable(self, it):
665 return set(it) 663 return set(it)
666 664
667 def __contains__(self, item): 665 def __contains__(self, item):
668 key, value = item 666 key, value = item
669 try: 667 try:
670 v = self._mapping[key] 668 v = self._mapping[key]
671 except KeyError: 669 except KeyError:
672 return False 670 return False
673 else: 671 else:
674 return v == value 672 return v is value or v == value
675 673
676 def __iter__(self): 674 def __iter__(self):
677 for key in self._mapping: 675 for key in self._mapping:
678 yield (key, self._mapping[key]) 676 yield (key, self._mapping[key])
679 677
680 ItemsView.register(dict_items) 678 ItemsView.register(dict_items)
681 679
682 680
683 class ValuesView(MappingView): 681 class ValuesView(MappingView):
684 682
685 __slots__ = () 683 __slots__ = ()
686 684
687 def __contains__(self, value): 685 def __contains__(self, value):
688 for key in self._mapping: 686 for key in self._mapping:
689 if value == self._mapping[key]: 687 v = self._mapping[key]
688 if v is value or v == value:
690 return True 689 return True
691 return False 690 return False
692 691
693 def __iter__(self): 692 def __iter__(self):
694 for key in self._mapping: 693 for key in self._mapping:
695 yield self._mapping[key] 694 yield self._mapping[key]
696 695
697 ValuesView.register(dict_values) 696 ValuesView.register(dict_values)
698 697
699 698
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
814 try: 813 try:
815 while True: 814 while True:
816 v = self[i] 815 v = self[i]
817 yield v 816 yield v
818 i += 1 817 i += 1
819 except IndexError: 818 except IndexError:
820 return 819 return
821 820
822 def __contains__(self, value): 821 def __contains__(self, value):
823 for v in self: 822 for v in self:
824 if v == value: 823 if v is value or v == value:
825 return True 824 return True
826 return False 825 return False
827 826
828 def __reversed__(self): 827 def __reversed__(self):
829 for i in reversed(range(len(self))): 828 for i in reversed(range(len(self))):
830 yield self[i] 829 yield self[i]
831 830
832 def index(self, value, start=0, stop=None): 831 def index(self, value, start=0, stop=None):
833 '''S.index(value, [start, [stop]]) -> integer -- return first index of v alue. 832 '''S.index(value, [start, [stop]]) -> integer -- return first index of v alue.
834 Raises ValueError if the value is not present. 833 Raises ValueError if the value is not present.
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
931 Raise ValueError if the value is not present. 930 Raise ValueError if the value is not present.
932 ''' 931 '''
933 del self[self.index(value)] 932 del self[self.index(value)]
934 933
935 def __iadd__(self, values): 934 def __iadd__(self, values):
936 self.extend(values) 935 self.extend(values)
937 return self 936 return self
938 937
939 MutableSequence.register(list) 938 MutableSequence.register(list)
940 MutableSequence.register(bytearray) # Multiply inheriting, see ByteString 939 MutableSequence.register(bytearray) # Multiply inheriting, see ByteString
LEFTRIGHT

RSS Feeds Recent Issues | This issue
This is Rietveld 894c83f36cb7+