New submission from Benjamin Aranguren:
Worked with Alex Martelli at the Google Python Sprint to backport ABC to
2.6.
Added abc.py and test_abc.py to svn trunk.
--
components: Library (Lib)
files: pyABC_backport_to_2_6.patch
messages: 55308
nosy: baranguren
severity: normal
status: open
title: Backport ABC to 2.6
versions: Python 2.6
__
Tracker <[EMAIL PROTECTED]>
<http://bugs.python.org/issue1026>
__Index: Objects/abstract.c
===
--- Objects/abstract.c (revision 57506)
+++ Objects/abstract.c (working copy)
@@ -2275,6 +2275,27 @@
int
PyObject_IsInstance(PyObject *inst, PyObject *cls)
{
+ PyObject *t, *v, *tb;
+ PyObject *checker;
+ PyErr_Fetch(&t, &v, &tb);
+ checker = PyObject_GetAttrString(cls, "__instancecheck__");
+ PyErr_Restore(t, v, tb);
+ if (checker != NULL) {
+ PyObject *res;
+ int ok = -1;
+ if (Py_EnterRecursiveCall(" in __instancecheck__")) {
+ Py_DECREF(checker);
+ return ok;
+ }
+ res = PyObject_CallFunctionObjArgs(checker, inst, NULL);
+ Py_LeaveRecursiveCall();
+ Py_DECREF(checker);
+ if (res != NULL) {
+ ok = PyObject_IsTrue(res);
+ Py_DECREF(res);
+ }
+ return ok;
+ }
return recursive_isinstance(inst, cls, Py_GetRecursionLimit());
}
@@ -2330,6 +2351,25 @@
int
PyObject_IsSubclass(PyObject *derived, PyObject *cls)
{
+ PyObject *t, *v, *tb;
+ PyObject *checker;
+ PyErr_Fetch(&t, &v, &tb);
+ checker = PyObject_GetAttrString(cls, "__subclasscheck__");
+ PyErr_Restore(t, v, tb);
+ if (checker != NULL) {
+ PyObject *res;
+ int ok = -1;
+ if (Py_EnterRecursiveCall(" in __subclasscheck__"))
+ return ok;
+ res = PyObject_CallFunctionObjArgs(checker, derived, NULL);
+ Py_LeaveRecursiveCall();
+ Py_DECREF(checker);
+ if (res != NULL) {
+ ok = PyObject_IsTrue(res);
+ Py_DECREF(res);
+ }
+ return ok;
+ }
return recursive_issubclass(derived, cls, Py_GetRecursionLimit());
}
Index: Lib/abc.py
===
--- Lib/abc.py (revision 0)
+++ Lib/abc.py (revision 0)
@@ -0,0 +1,206 @@
+# Copyright 2007 Google, Inc. All Rights Reserved.
+# Licensed to PSF under a Contributor Agreement.
+
+"""Abstract Base Classes (ABCs) according to PEP 3119."""
+
+
+def abstractmethod(funcobj):
+"""A decorator indicating abstract methods.
+
+Requires that the metaclass is ABCMeta or derived from it. A
+class that has a metaclass derived from ABCMeta 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(metaclass=ABCMeta):
+@abstractmethod
+def my_abstract_method(self, ...):
+...
+"""
+funcobj.__isabstractmethod__ = True
+return funcobj
+
+
+class abstractproperty(property):
+"""A decorator indicating abstract properties.
+
+Requires that the metaclass is ABCMeta or derived from it. A
+class that has a metaclass derived from ABCMeta cannot be
+instantiated unless all of its abstract properties are overridden.
+The abstract properties can be called using any of the the normal
+'super' call mechanisms.
+
+Usage:
+
+class C(metaclass=ABCMeta):
+@abstractproperty
+def my_abstract_property(self):
+...
+
+This defines a read-only property; you can also define a read-write
+abstract property using the 'long' form of property declaration:
+
+class C(metaclass=ABCMeta):
+def getx(self): ...
+def setx(self, value): ...
+x = abstractproperty(getx, setx)
+"""
+__isabstractmethod__ = True
+
+
+class _Abstract(object):
+
+"""Helper class inserted into the bases by ABCMeta (using _fix_bases()).
+
+You should never need to explicitly subclass this class.
+
+There should never be a base class between _Abstract and object.
+"""
+
+def __new__(cls, *args, **kwds):
+am = cls.__dict__.get("__abstractmethods__")
+if am:
+raise TypeError("Can't instantiate abstract class %s "
+"with abstract methods %s" %
+(cls.__name__, ", ".join(sorted(am
+if (args or kwds) and cls.__init__ is object.__init__:
+raise TypeError("Can't pass arguments to __new__ "
+"without overriding __init__")
+return object.__new__(cls)
+
+@classmethod
+def __subclasshook__(cls, subclass):
+"""Abstract