[Types-sig] Re: PRE-PROPOSAL: Python Interfaces

Barry A. Warsaw bwarsaw@cnri.reston.va.us (Barry A. Warsaw)
Mon, 30 Nov 1998 22:44:59 -0500 (EST)


>>>>> "TP" == Tim Peters <tim_one@email.msn.com> writes:

    TP> 7/16'ths of me too, but I believe the groundrules for the
    TP> Scarecrow Proposal include "no language changes".  That leaves
    TP> manual, or at best semi-automated, convention for now.  In a
    TP> Python2 world, I doubt it would be more of an insanely
    TP> protracted battle than usual <wink> to get a "defer" keyword
    TP> added, provided it worked out in practice by hand first.

    TP> Given "def push(self, thing): defer" we could peek at the
    TP> bytecode today, note the senseless LOAD_GLOBAL of "defer", and
    TP> simply rewrite the user's code for them <cackle>.

An easy change for Python 1.6 would be to add something like
NotImplementedError to exceptions.py and a defer() builtin function.
The latter has some potential for existing code breakage, but since
user definitions of that attribute will silently override the builtin
one, it's probably minimal.  That might get us far enough along for
1.6 to play while leaving open a `defer' keyword later.

So trivial to implement, I've attached a patch set (against my hacked
1.5.2 -- watch for fuzz factor).  Extremely minimally tested.  Here's
what it looks like:

-------------------- snip snip --------------------
Python 1.5.2b1 (#101, Nov 30 1998, 22:33:15) [C] on sunos5
Copyright 1991-1995 Stichting Mathematisch Centrum, Amsterdam
>>> defer()
Traceback (innermost last):
  File "<stdin>", line 1, in ?
NotImplementedError: Implementation expected in derived class
>>> defer(1)
Traceback (innermost last):
  File "<stdin>", line 1, in ?
TypeError: function requires exactly 0 arguments; 1 given
>>> class A:
... 	def doit(self): defer()
... 
>>> class B(A):
... 	def doit(self): print 'done!'
... 
>>> a = A()
>>> b = B()
>>> a.doit()
Traceback (innermost last):
  File "<stdin>", line 1, in ?
  File "<stdin>", line 2, in doit
NotImplementedError: Implementation expected in derived class
>>> b.doit()
done!
>>> try: a.doit()
... except NotImplementedError: pass
... 
>>> 
-------------------- snip snip --------------------
Index: bltinmodule.c
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Python/bltinmodule.c,v
retrieving revision 2.129
diff -c -r2.129 bltinmodule.c
*** bltinmodule.c	1998/10/01 15:33:12	2.129
--- bltinmodule.c	1998/12/01 03:32:47
***************
*** 981,986 ****
--- 963,988 ----
  
  
  static PyObject *
+ builtin_defer(self, args)
+ 	PyObject *self;
+ 	PyObject *args;
+ {
+ 	if (!PyArg_ParseTuple(args, ""))
+ 		return NULL;
+ 	PyErr_SetString(PyExc_NotImplementedError,
+ 			"Implementation expected in derived class");
+ 	return NULL;
+ }
+ 
+ 
+ static char defer_doc[] =
+ "defer()\n\
+ \n\
+ Raise a NotImplementedError unconditionally.  This is used in the body\n\
+ of `abstract' method definitions.";
+ 
+ 
+ static PyObject *
  builtin_hash(self, args)
  	PyObject *self;
  	PyObject *args;
***************
*** 1887,1892 ****
--- 1931,1937 ----
  #ifndef WITHOUT_COMPLEX
  	{"complex",	builtin_complex, 1, complex_doc},
  #endif
+ 	{"defer",       builtin_defer, 1, defer_doc},
  	{"delattr",	builtin_delattr, 1, delattr_doc},
  	{"dir",		builtin_dir, 1, dir_doc},
  	{"divmod",	builtin_divmod, 1, divmod_doc},
***************
*** 1954,1959 ****
--- 1999,2005 ----
  PyObject *PyExc_NameError;
  PyObject *PyExc_OverflowError;
  PyObject *PyExc_RuntimeError;
+ PyObject *PyExc_NotImplementedError;
  PyObject *PyExc_SyntaxError;
  PyObject *PyExc_SystemError;
  PyObject *PyExc_SystemExit;
***************
*** 1989,1994 ****
--- 2035,2041 ----
  	{"NameError",          &PyExc_NameError,          1},
  	{"OverflowError",      &PyExc_OverflowError,      1},
  	{"RuntimeError",       &PyExc_RuntimeError,       1},
+ 	{"NotImplementedError",&PyExc_NotImplementedError,1},
  	{"SyntaxError",        &PyExc_SyntaxError,        1},
  	{"SystemError",        &PyExc_SystemError,        1},
  	{"SystemExit",         &PyExc_SystemExit,         1},
Index: exceptions.py
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Lib/exceptions.py,v
retrieving revision 1.11
diff -c -r1.11 exceptions.py
*** exceptions.py	1998/09/25 22:43:21	1.11
--- exceptions.py	1998/12/01 03:26:46
***************
*** 33,38 ****
--- 33,41 ----
        |
        +-- EOFError
        +-- RuntimeError
+       |    |
+       |    +-- NotImplementedError
+       |
        +-- NameError
        +-- AttributeError
        +-- SyntaxError
***************
*** 128,133 ****
--- 131,139 ----
      pass
  
  class RuntimeError(StandardError):
+     pass
+ 
+ class NotImplementedError(RuntimeError):
      pass
  
  class SystemError(StandardError):
Index: pyerrors.h
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Include/pyerrors.h,v
retrieving revision 2.30
diff -c -r2.30 pyerrors.h
*** pyerrors.h	1998/07/23 15:57:34	2.30
--- pyerrors.h	1998/12/01 03:32:26
***************
*** 73,78 ****
--- 73,79 ----
  extern DL_IMPORT(PyObject *) PyExc_NameError;
  extern DL_IMPORT(PyObject *) PyExc_OverflowError;
  extern DL_IMPORT(PyObject *) PyExc_RuntimeError;
+ extern DL_IMPORT(PyObject *) PyExc_NotImplementedError;
  extern DL_IMPORT(PyObject *) PyExc_SyntaxError;
  extern DL_IMPORT(PyObject *) PyExc_SystemError;
  extern DL_IMPORT(PyObject *) PyExc_SystemExit;