[Python-checkins] r54616 - sandbox/trunk/abc/abc.py

guido.van.rossum python-checkins at python.org
Fri Mar 30 17:18:04 CEST 2007


Author: guido.van.rossum
Date: Fri Mar 30 17:18:01 2007
New Revision: 54616

Modified:
   sandbox/trunk/abc/abc.py
Log:
Add abstract class and method feature.  Not used throughout yet.


Modified: sandbox/trunk/abc/abc.py
==============================================================================
--- sandbox/trunk/abc/abc.py	(original)
+++ sandbox/trunk/abc/abc.py	Fri Mar 30 17:18:01 2007
@@ -17,21 +17,60 @@
 import sys
 
 
+def abstractmethod(funcobj):
+  """A decorator indicating abstract methods."""
+  funcobj.__abstractmethod__ = True
+  return funcobj
+
+
+class AbstractClass(type):
+
+  def __new__(mcls, name, bases, namespace):
+    obj = 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)
+    obj.__abstractmethods__ = abstracts
+    return obj
+
+
+class Abstract(metaclass=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 TypeError("Can't instantiate class with abstract methods %s" %
+                      ", ".join(sorted(bad)))
+    return super(Abstract, cls).__new__(cls)
+
+
 ### BASICS ###
 
 
-class Hashable:
+class Hashable(Abstract):
 
   """A hashable has one method, __hash__()."""
 
+  @abstractmethod
   def __hash__(self):
     return 0
 
 
-class Iterable:
+Hashable()
+
+
+class Iterable(Abstract):
 
   """An iterable has one method, __iter__()."""
 
+  @abstractmethod
   def __iter__(self):
     return Iterator()
 
@@ -40,6 +79,7 @@
 
   """An iterator has two methods, __iter__() and next()."""
 
+  @abstractmethod
   def next(self):
     raise StopIteration
 
@@ -47,8 +87,9 @@
     return self
 
 
-class Sizeable:
+class Sizeable(Abstract):
 
+  @abstractmethod
   def __len__(self):
     return 0
 
@@ -56,12 +97,13 @@
 ### SETS ###
 
 
-class BasicSet:
+class BasicSet(Abstract):
 
   # XXX Alternative name: Container? Oracle (as in Delphi's Oracle)?
 
   """A basic set has __contains__() and that's it."""
 
+  @abstractmethod
   def __contains__(self, elem):
     return False
 
@@ -138,7 +180,7 @@
     return frozenset(new)
 
 
-class HashableSet(SizeableSet, HashableSet):
+class HashableSet(SizeableSet, Hashable):
 
   def __hash__(self):
     """The hash value must match __eq__.
@@ -227,7 +269,6 @@
       yield key, self._mapping[key]
 
   def __contains__(self, item):
-    if not isinstance(item, Iterable):
     try:
       key, value = item
     except:


More information about the Python-checkins mailing list