[Python-checkins] r54639 - sandbox/trunk/abc/abc.py
guido.van.rossum
python-checkins at python.org
Sat Mar 31 22:31:05 CEST 2007
Author: guido.van.rossum
Date: Sat Mar 31 22:31:05 2007
New Revision: 54639
Modified:
sandbox/trunk/abc/abc.py
Log:
Reindent using 4-space indents.
Modified: sandbox/trunk/abc/abc.py
==============================================================================
--- sandbox/trunk/abc/abc.py (original)
+++ sandbox/trunk/abc/abc.py Sat Mar 31 22:31:05 2007
@@ -18,82 +18,82 @@
def abstractmethod(funcobj):
- """A decorator indicating abstract methods.
+ """A decorator indicating abstract methods.
- Requires that the class (directly or indirectly) derives from
- Abstract, and that the metaclass is AbstractClass or derived from it
- (deriving from Abstract ensure this). A class deriving from
- Abstract cannot be instantiated unless all of its abstract methods
- are overridden. The abstract methods can be called using any of the
- the normal 'super' call mechanisms.
-
- Usage:
-
- class C(Abstract):
- @abstractmethod
- def my_abstract_method(self, ...):
- ...
-
- When combining this with other decorators, this should come last:
-
- class C(Abstract):
- @classmethod
- @abstractmethod
- def my_abstract_class_method(self, ...):
- ...
- """
- funcobj.__abstractmethod__ = True
- return funcobj
+ Requires that the class (directly or indirectly) derives from
+ Abstract, and that the metaclass is AbstractClass or derived from it
+ (deriving from Abstract ensure this). A class deriving from
+ Abstract cannot be instantiated unless all of its abstract methods
+ are overridden. The abstract methods can be called using any of the
+ the normal 'super' call mechanisms.
+
+ Usage:
+
+ class C(Abstract):
+ @abstractmethod
+ def my_abstract_method(self, ...):
+ ...
+
+ When combining this with other decorators, this should come last:
+
+ class C(Abstract):
+ @classmethod
+ @abstractmethod
+ def my_abstract_class_method(self, ...):
+ ...
+ """
+ funcobj.__abstractmethod__ = True
+ return funcobj
class AbstractClass(type):
- """Metaclass to support the abstractmethod decorator."""
+ """Metaclass to support the abstractmethod decorator."""
- def __new__(mcls, name, bases, namespace):
- cls = super(AbstractClass, mcls).__new__(mcls, name, bases, namespace)
- abstracts = set()
- for base in bases:
- abstracts.update(getattr(base, "__abstractmethods__", set()))
- for name, value in namespace.items():
- if getattr(value, "__abstractmethod__", False):
- abstracts.add(name)
- cls.__abstractmethods__ = abstracts
- return cls
+ def __new__(mcls, name, bases, namespace):
+ cls = super(AbstractClass, mcls).__new__(mcls, name, bases, namespace)
+ abstracts = set()
+ for base in bases:
+ abstracts.update(getattr(base, "__abstractmethods__", set()))
+ for name, value in namespace.items():
+ if getattr(value, "__abstractmethod__", False):
+ abstracts.add(name)
+ cls.__abstractmethods__ = abstracts
+ return cls
class AbstractInstantiationError(TypeError):
- """Exception raised when an abstract class is instantiated."""
+ """Exception raised when an abstract class is instantiated."""
- def __init__(self, abstract_methods):
- TypeError.__init__(self)
- self.abstract_methods = abstract_methods
-
- def __str__(self):
- msg = ", ".join(sorted(self.abstract_methods))
- return "Can't instantiate class with abstract method(s) %s" % msg
+ def __init__(self, abstract_methods):
+ TypeError.__init__(self)
+ self.abstract_methods = abstract_methods
+
+ def __str__(self):
+ msg = ", ".join(sorted(self.abstract_methods))
+ return "Can't instantiate class with abstract method(s) %s" % msg
- def __repr__(self):
- return "AbstractInstantiationError(%r)" % (self.abstract_methods,)
+ def __repr__(self):
+ return "AbstractInstantiationError(%r)" % (self.abstract_methods,)
class Abstract(metaclass=AbstractClass):
- """Base class to support the abstractmethod decorator.
+ """Base class to support the abstractmethod decorator.
- This implicitly sets the metaclass to AbstractClass.
- """
+ This implicitly sets the metaclass to AbstractClass.
+ """
- def __new__(cls):
- bad = set()
- for name in cls.__abstractmethods__:
- value = getattr(cls, name, None)
- if getattr(value, "__abstractmethod__", False):
- bad.add(name)
- if bad:
- raise AbstractInstantiationError(bad)
- return super(Abstract, cls).__new__(cls)
+ def __new__(cls):
+ bad = set()
+ for name in cls.__abstractmethods__:
+ value = getattr(cls, name, None)
+ if getattr(value, "__abstractmethod__", False):
+ bad.add(name)
+ if bad:
+ raise AbstractInstantiationError(bad)
+ return super(Abstract, cls).__new__(cls)
### BASICS ###
@@ -101,39 +101,39 @@
class Hashable(Abstract):
- """A hashable has one method, __hash__()."""
+ """A hashable has one method, __hash__()."""
- @abstractmethod
- def __hash__(self):
- return 0
+ @abstractmethod
+ def __hash__(self):
+ return 0
class Iterable(Abstract):
- """An iterable has one method, __iter__()."""
+ """An iterable has one method, __iter__()."""
- @abstractmethod
- def __iter__(self):
- return Iterator()
+ @abstractmethod
+ def __iter__(self):
+ return Iterator()
class Iterator(Iterable):
- """An iterator has two methods, __iter__() and next()."""
+ """An iterator has two methods, __iter__() and next()."""
- @abstractmethod
- def next(self):
- raise StopIteration
+ @abstractmethod
+ def next(self):
+ raise StopIteration
- def __iter__(self):
- return self
+ def __iter__(self):
+ return self
class Sizeable(Abstract):
- @abstractmethod
- def __len__(self):
- return 0
+ @abstractmethod
+ def __len__(self):
+ return 0
### SETS ###
@@ -141,101 +141,101 @@
class BasicSet(Abstract):
- # XXX Alternative name: Container? Oracle (as in Delphi's Oracle)?
+ # XXX Alternative name: Container? Oracle (as in Delphi's Oracle)?
- """A basic set has __contains__() and that's it."""
+ """A basic set has __contains__() and that's it."""
- @abstractmethod
- def __contains__(self, elem):
- return False
+ @abstractmethod
+ def __contains__(self, elem):
+ return False
class IterableSet(BasicSet, Iterable):
- """An iterable set is a basic set that is also iterable.
+ """An iterable set is a basic set that is also iterable.
- It may not have a length though; it may be infinite!
+ It may not have a length though; it may be infinite!
- XXX Do we care about potentially infinite sets, or sets of
- indeterminate size?
- """
+ XXX Do we care about potentially infinite sets, or sets of
+ indeterminate size?
+ """
class SizeableSet(IterableSet, Sizeable):
- """A sizeable set is an iterable set that has a finite, known size.
+ """A sizeable set is an iterable set that has a finite, known size.
- This enables a generic implementation of equality and ordering based
- on set inclusion.
+ This enables a generic implementation of equality and ordering based
+ on set inclusion.
- I don't see a use case for a non-iterable set that has a size.
+ I don't see a use case for a non-iterable set that has a size.
- The idea here is that 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, SizeableSet):
- return NotImplemented
- if len(self) > len(other):
- return False
- for elem in self:
- if elem not in other:
- return False
- return True
+ The idea here is that all you have to do is redefine __le__ and then
+ the other operations will automatically follow suit.
+ """
- def __lt__(self, other):
- if not isinstance(other, SizeableSet):
- return NotImplemented
- return len(self) < len(other) and self.__le__(other)
-
- def __eq__(self, other):
- if not isinstance(other, SizeableSet):
- return NotImplemented
- return len(self) == len(other) and self.__le__(other)
-
- # XXX Should we define __ge__ and __gt__ too?
-
- # XXX The following implementations of &, |, ^, - return frozen sets
- # because we have to pick a concrete type. They are allowed to
- # return any subclass of SizeableSet (but SizeableSet is not a
- # concrete implementation).
-
- def __and__(self, other):
- new = set(self)
- new.intersection_update(other)
- return frozenset(new)
-
- def __or__(self, other):
- new = set(self)
- new.update(other)
- return frozenset(new)
-
- def __xor__(self, other):
- new = set(self)
- new.symmetric_difference_update(other)
- return frozenset(new)
-
- def __sub__(self, other):
- new = set(self)
- new.difference_update(other)
- return frozenset(new)
+ def __le__(self, other):
+ if not isinstance(other, SizeableSet):
+ 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, SizeableSet):
+ return NotImplemented
+ return len(self) < len(other) and self.__le__(other)
+
+ def __eq__(self, other):
+ if not isinstance(other, SizeableSet):
+ return NotImplemented
+ return len(self) == len(other) and self.__le__(other)
+
+ # XXX Should we define __ge__ and __gt__ too?
+
+ # XXX The following implementations of &, |, ^, - return frozen sets
+ # because we have to pick a concrete type. They are allowed to
+ # return any subclass of SizeableSet (but SizeableSet is not a
+ # concrete implementation).
+
+ def __and__(self, other):
+ new = set(self)
+ new.intersection_update(other)
+ return frozenset(new)
+
+ def __or__(self, other):
+ new = set(self)
+ new.update(other)
+ return frozenset(new)
+
+ def __xor__(self, other):
+ new = set(self)
+ new.symmetric_difference_update(other)
+ return frozenset(new)
+
+ def __sub__(self, other):
+ new = set(self)
+ new.difference_update(other)
+ return frozenset(new)
class HashableSet(SizeableSet, Hashable):
- def __hash__(self):
- """The hash value must match __eq__.
+ def __hash__(self):
+ """The hash value must match __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 just XOR the hash of the elements.
- """
- h = 0
- for elem in self:
- h ^= hash(elem)
- return h
+ 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 just XOR the hash of the elements.
+ """
+ h = 0
+ for elem in self:
+ h ^= hash(elem)
+ return h
# class set(SizeableSet)
@@ -247,157 +247,157 @@
class BasicMapping(Abstract):
- # XXX derive from (BasicSet)?
+ # XXX derive from (BasicSet)?
- """A basic mapping has __getitem__(), __contains__() and get().
+ """A basic mapping has __getitem__(), __contains__() and get().
- The idea is that you only need to override __getitem__().
+ The idea is that you only need to override __getitem__().
- Other dict methods are not supported.
- """
+ Other dict methods are not supported.
+ """
- @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]
- return True
- except KeyError:
- return False
+ @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]
+ return True
+ except KeyError:
+ return False
class IterableMapping(BasicMapping, Iterable):
- def keys(self):
- return KeysView(self)
+ def keys(self):
+ return KeysView(self)
- def items(self):
- return ItemsView(self)
+ def items(self):
+ return ItemsView(self)
- def values(self):
- return ValuesView(self)
+ def values(self):
+ return ValuesView(self)
class _MappingView:
- def __init__(self, mapping):
- self._mapping = mapping
+ def __init__(self, mapping):
+ self._mapping = mapping
class KeysView(_MappingView, BasicSet):
- def __iter__(self):
- for key in self._mapping:
- yield key
+ def __iter__(self):
+ for key in self._mapping:
+ yield key
- def __contains__(self, key):
- return key in self._mapping
+ def __contains__(self, key):
+ return key in self._mapping
class ItemsView(_MappingView, BasicSet):
- def __iter__(self):
- for key in self._mapping:
- yield key, self._mapping[key]
-
- def __contains__(self, item):
- try:
- key, value = item
- except:
- return False
- try:
- val = self._mapping[key]
- except KeyError:
- return False
- return value == val
+ def __iter__(self):
+ for key in self._mapping:
+ yield key, self._mapping[key]
+
+ def __contains__(self, item):
+ try:
+ key, value = item
+ except:
+ return False
+ try:
+ val = self._mapping[key]
+ except KeyError:
+ return False
+ return value == val
class ValuesView(_MappingView):
- # Note: does not derive from BasicSet, and does not implement __contains__!
+ # Note: does not derive from BasicSet, and does not implement __contains__!
- def __iter__(self):
- for key in self._mapping:
- yield self._mapping[key]
+ def __iter__(self):
+ for key in self._mapping:
+ yield self._mapping[key]
class SizeableMapping(IterableMapping, Sizeable):
- def keys(self):
- return SizeableKeysView(self)
+ def keys(self):
+ return SizeableKeysView(self)
- def items(self):
- return SizeableItemsView(self)
+ def items(self):
+ return SizeableItemsView(self)
- def values(self):
- return SizeableValuesView(self)
+ def values(self):
+ return SizeableValuesView(self)
- def __eq__(self, other):
- if not isinstance(other, SizeableMapping):
- return NotImplemented
- if len(other) != len(self):
- return False
- # XXX Or: for key, value1 in self.items(): ?
- for key in self:
- value1 = self[key]
- try:
- value2 = other[key]
- except KeyError:
- return False
- if value1 != value2:
- return False
- return True
+ def __eq__(self, other):
+ if not isinstance(other, SizeableMapping):
+ return NotImplemented
+ if len(other) != len(self):
+ return False
+ # XXX Or: for key, value1 in self.items(): ?
+ for key in self:
+ value1 = self[key]
+ try:
+ value2 = other[key]
+ except KeyError:
+ return False
+ if value1 != value2:
+ return False
+ return True
class _SizeableMappingView(_MappingView, Sizeable):
- def __len__(self):
- return len(self._mapping)
+ def __len__(self):
+ return len(self._mapping)
class SizeableKeysView(_SizeableMappingView, KeysView, SizeableSet):
- pass
+ pass
class SizeableItemsView(_SizeableMappingView, ItemsView, SizeableSet):
- pass
+ pass
class SizeableValuesView(_SizeableMappingView, ValuesView):
- def __eq__(self, other):
- if not (isinstance(other, Sizeable) and isinstance(other, Iterable)):
- return NotImplemented
- if len(self) != len(other):
- return False
- # XXX This is slow. Sometimes this could be optimized, but these
- # are the semantics: we can't depend on the values to be hashable
- # or comparable.
- o_values = list(other)
- for value in self:
- for i, o_value in enumerate(o_values):
- if value == o_value:
- del o_values[i]
- break
- else:
- return False
- assert not o_values # self must have mutated somehow
- return True
-
- def __contains__(self, value):
- # This is slow, but these are the semantics.
- for elem in self:
- if elem == value:
+ def __eq__(self, other):
+ if not (isinstance(other, Sizeable) and isinstance(other, Iterable)):
+ return NotImplemented
+ if len(self) != len(other):
+ return False
+ # XXX This is slow. Sometimes this could be optimized, but these
+ # are the semantics: we can't depend on the values to be hashable
+ # or comparable.
+ o_values = list(other)
+ for value in self:
+ for i, o_value in enumerate(o_values):
+ if value == o_value:
+ del o_values[i]
+ break
+ else:
+ return False
+ assert not o_values # self must have mutated somehow
return True
- return False
+
+ def __contains__(self, value):
+ # This is slow, but these are the semantics.
+ for elem in self:
+ if elem == value:
+ return True
+ return False
### SEQUENCES ###
@@ -405,142 +405,142 @@
class Sequence(Sizeable, Iterable):
- """A minimal sequence.
+ """A minimal sequence.
- I'm not bothering with an unsized version; I don't see a use case.
+ I'm not bothering with an unsized version; I don't see a use case.
- Concrete subclasses must override __new__ or __init__, __getitem__,
- and __len__; they might want to override __add__ and __mul__. The
- constructor signature is expected to support a single argument
- giving an iterable providing the elements.
- """
-
- def __index(self, i):
- # Internal helper to raise TypeError for non-integer(-castable) values
- if not isinstance(i, int):
- if not hasattr(i, "__index__"):
- raise TypeError
- i = i.__index__()
- if not isinstance(i, int):
- raise TypeError
- return i
-
- @abstractmethod
- def __getitem__(self, index):
- if isinstance(index, slice):
- return self.__getslice(index)
- index = self.__index(index)
- raise IndexError
-
- def __getslice(self, slc):
- # XXX Would be nice to make this generally available?
- start, stop, step = slc.start, slc.stop, slc.step
- for index in start, stop, step:
- if index is not None:
- self.__index(index)
- if step is None:
- step = 1
- if step == 0:
- raise ValueError
- if step < 0:
- if start is None:
- start = len(self) - 1
- if stop is None:
- stop = -1
- else:
- if start is None:
- start = 0
- if stop is None:
- stop = len(self)
- return self.__class__(self[i] for i in range(start, stop, step))
-
- @abstractmethod
- def __len__(self):
- return 0
-
- def __iter__(self):
- i = 0
- while i < len(self):
- yield self[i]
- i += 1
-
- def __reversed__(self):
- i = len(self)
- while i > 0:
- i -= 1
- yield self[i]
-
- def index(self, value):
- for i, elem in enumerate(self):
- if elem == value:
- return i
- raise ValueError
+ Concrete subclasses must override __new__ or __init__, __getitem__,
+ and __len__; they might want to override __add__ and __mul__. The
+ constructor signature is expected to support a single argument
+ giving an iterable providing the elements.
+ """
- def count(self, value):
- return sum(1 for elem in self if elem == value)
+ def __index(self, i):
+ # Internal helper to raise TypeError for non-integer(-castable) values
+ if not isinstance(i, int):
+ if not hasattr(i, "__index__"):
+ raise TypeError
+ i = i.__index__()
+ if not isinstance(i, int):
+ raise TypeError
+ return i
- def __add__(self, other):
- if not isinstance(other, Sequence):
- return NotImplemented
- return self.__class__(elem for seq in (self, other) for elem in seq)
-
- def __mul__(self, repeat):
- # XXX Looks like we need an ABC to indicate integer-ness...
- if not isinstance(repeat, int) and not hasattr(repeat, "__index__"):
- return NotImplemented
- repeat = self.__index(repeat)
- return self.__class__(elem for i in range(repeat) for elem in self)
-
- def __eq__(self, other):
- if not isinstance(other, Sequence):
- return NotImplemented
- if len(self) != len(other):
- return False
- for a, b in zip(self, other):
- if a == b:
- continue
- return False
- return len(self) == len(other)
-
- def __lt__(self, other):
- if not isinstance(other, Sequence):
- return NotImplemented
- for a, b in zip(self, other):
- if a == b:
- continue
- return a < b
- return len(self) < len(other)
-
- def __le__(self, other):
- if not isinstance(other, Sequence):
- return NotImplemented
- for a, b in zip(self, other):
- if a == b:
- continue
- return a < b
- return len(self) <= len(other)
+ @abstractmethod
+ def __getitem__(self, index):
+ if isinstance(index, slice):
+ return self.__getslice(index)
+ index = self.__index(index)
+ raise IndexError
+
+ def __getslice(self, slc):
+ # XXX Would be nice to make this generally available?
+ start, stop, step = slc.start, slc.stop, slc.step
+ for index in start, stop, step:
+ if index is not None:
+ self.__index(index)
+ if step is None:
+ step = 1
+ if step == 0:
+ raise ValueError
+ if step < 0:
+ if start is None:
+ start = len(self) - 1
+ if stop is None:
+ stop = -1
+ else:
+ if start is None:
+ start = 0
+ if stop is None:
+ stop = len(self)
+ return self.__class__(self[i] for i in range(start, stop, step))
+
+ @abstractmethod
+ def __len__(self):
+ return 0
+
+ def __iter__(self):
+ i = 0
+ while i < len(self):
+ yield self[i]
+ i += 1
+
+ def __reversed__(self):
+ i = len(self)
+ while i > 0:
+ i -= 1
+ yield self[i]
+
+ def index(self, value):
+ for i, elem in enumerate(self):
+ if elem == value:
+ return i
+ raise ValueError
+
+ def count(self, value):
+ return sum(1 for elem in self if elem == value)
+
+ def __add__(self, other):
+ if not isinstance(other, Sequence):
+ return NotImplemented
+ return self.__class__(elem for seq in (self, other) for elem in seq)
+
+ def __mul__(self, repeat):
+ # XXX Looks like we need an ABC to indicate integer-ness...
+ if not isinstance(repeat, int) and not hasattr(repeat, "__index__"):
+ return NotImplemented
+ repeat = self.__index(repeat)
+ return self.__class__(elem for i in range(repeat) for elem in self)
+
+ def __eq__(self, other):
+ if not isinstance(other, Sequence):
+ return NotImplemented
+ if len(self) != len(other):
+ return False
+ for a, b in zip(self, other):
+ if a == b:
+ continue
+ return False
+ return len(self) == len(other)
+
+ def __lt__(self, other):
+ if not isinstance(other, Sequence):
+ return NotImplemented
+ for a, b in zip(self, other):
+ if a == b:
+ continue
+ return a < b
+ return len(self) < len(other)
+
+ def __le__(self, other):
+ if not isinstance(other, Sequence):
+ return NotImplemented
+ for a, b in zip(self, other):
+ if a == b:
+ continue
+ return a < b
+ return len(self) <= len(other)
class HashableSequence(Sequence, Hashable):
- def __hash__(self):
- """The hash value must match __eq__.
+ def __hash__(self):
+ """The hash value must match __eq__.
- Since we want sequences to be equal iff their elements are equal
- (regardless of the sequence type), this algorithm is (XXX
- hopefully) identical to tuple.__hash__().
- """
- mask = sys.maxint*2 + 1
- mult = 1000003
- h = 0x345678
- n = len(self)
- for i, elem in enumerate(self):
- h = ((h ^ hash(elem)) * mult) & mask
- mult = (mult + (82520 - 2 + 2*(n-i))) & mask
- h += 97531
- h &= mask
- if h > sys.maxint:
- h -= mask + 1
- if h == -1:
- h = -2
- return h
+ Since we want sequences to be equal iff their elements are equal
+ (regardless of the sequence type), this algorithm is (XXX
+ hopefully) identical to tuple.__hash__().
+ """
+ mask = sys.maxint*2 + 1
+ mult = 1000003
+ h = 0x345678
+ n = len(self)
+ for i, elem in enumerate(self):
+ h = ((h ^ hash(elem)) * mult) & mask
+ mult = (mult + (82520 - 2 + 2*(n-i))) & mask
+ h += 97531
+ h &= mask
+ if h > sys.maxint:
+ h -= mask + 1
+ if h == -1:
+ h = -2
+ return h
More information about the Python-checkins
mailing list