[Python-checkins] CVS: python/dist/src/Python ceval.c,2.219,2.220 getargs.c,2.51,2.52

Ka-Ping Yee ping@users.sourceforge.net
Mon, 15 Jan 2001 14:14:18 -0800


Update of /cvsroot/python/python/dist/src/Python
In directory usw-pr-cvs1:/tmp/cvs-serv31281/Python

Modified Files:
	ceval.c getargs.c 
Log Message:
This patch makes sure that the function name always appears in the error
message, and tries to make the messages more consistent and helpful when
the wrong number of arguments or duplicate keyword arguments are supplied.
Comes with more tests for test_extcall.py and and an update to an error
message in test/output/test_pyexpat.


Index: ceval.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Python/ceval.c,v
retrieving revision 2.219
retrieving revision 2.220
diff -C2 -r2.219 -r2.220
*** ceval.c	2001/01/12 16:24:03	2.219
--- ceval.c	2001/01/15 22:14:16	2.220
***************
*** 49,54 ****
  static PyObject *do_call(PyObject *, PyObject ***, int, int);
  static PyObject *ext_do_call(PyObject *, PyObject ***, int, int, int);
! static PyObject *update_keyword_args(PyObject *, int, PyObject ***);
! static PyObject *update_star_args(int, int, PyObject *,	PyObject ***);
  static PyObject *load_args(PyObject ***, int);
  #define CALL_FLAG_VAR 1
--- 49,54 ----
  static PyObject *do_call(PyObject *, PyObject ***, int, int);
  static PyObject *ext_do_call(PyObject *, PyObject ***, int, int, int);
! static PyObject *update_keyword_args(PyObject *, int, PyObject ***, PyObject *);
! static PyObject *update_star_args(int, int, PyObject *, PyObject ***);
  static PyObject *load_args(PyObject ***, int);
  #define CALL_FLAG_VAR 1
***************
*** 452,459 ****
  			if (!(co->co_flags & CO_VARARGS)) {
  				PyErr_Format(PyExc_TypeError,
! 				    "too many arguments to %s(); "
! 				    "expected %d, got %d",
  				    PyString_AsString(co->co_name),
! 				    co->co_argcount, argcount);
  				goto fail;
  			}
--- 452,463 ----
  			if (!(co->co_flags & CO_VARARGS)) {
  				PyErr_Format(PyExc_TypeError,
! 				    "%.200s() takes %s %d "
! 				    "%sargument%s (%d given)",
  				    PyString_AsString(co->co_name),
! 				    defcount ? "at most" : "exactly",
! 				    co->co_argcount,
! 				    kwcount ? "non-keyword " : "",
! 				    co->co_argcount == 1 ? "" : "s",
! 				    argcount);
  				goto fail;
  			}
***************
*** 481,486 ****
  			int j;
  			if (keyword == NULL || !PyString_Check(keyword)) {
! 				PyErr_SetString(PyExc_TypeError,
! 						"keywords must be strings");
  				goto fail;
  			}
--- 485,491 ----
  			int j;
  			if (keyword == NULL || !PyString_Check(keyword)) {
! 				PyErr_Format(PyExc_TypeError,
! 				    "%.200s() keywords must be strings",
! 				    PyString_AsString(co->co_name));
  				goto fail;
  			}
***************
*** 509,516 ****
  				if (GETLOCAL(j) != NULL) {
  					PyErr_Format(PyExc_TypeError, 
! 					     "keyword parameter '%.400s' "
! 					     "redefined in call to %.200s()",
! 					     PyString_AsString(keyword),
! 					     PyString_AsString(co->co_name));
  					goto fail;
  				}
--- 514,522 ----
  				if (GETLOCAL(j) != NULL) {
  					PyErr_Format(PyExc_TypeError, 
! 					     "%.200s() got multiple "
! 					     "values for keyword "
! 					     "argument '%.400s'",
! 					     PyString_AsString(co->co_name),
! 					     PyString_AsString(keyword));
  					goto fail;
  				}
***************
*** 524,531 ****
  				if (GETLOCAL(i) == NULL) {
  					PyErr_Format(PyExc_TypeError,
! 					    "not enough arguments to "
! 					    "%.200s(); expected %d, got %d",
  					    PyString_AsString(co->co_name),
! 					    m, i);
  					goto fail;
  				}
--- 530,541 ----
  				if (GETLOCAL(i) == NULL) {
  					PyErr_Format(PyExc_TypeError,
! 					    "%.200s() takes %s %d "
! 					    "%sargument%s (%d given)",
  					    PyString_AsString(co->co_name),
! 					    ((co->co_flags & CO_VARARGS) ||
! 					     defcount) ? "at least"
! 						       : "exactly",
! 					    m, kwcount ? "non-keyword " : "",
! 					    m == 1 ? "" : "s", i);
  					goto fail;
  				}
***************
*** 547,552 ****
  		if (argcount > 0 || kwcount > 0) {
  			PyErr_Format(PyExc_TypeError,
! 				     "%.200s() expected no arguments",
! 				     PyString_AsString(co->co_name));
  			goto fail;
  		}
--- 557,563 ----
  		if (argcount > 0 || kwcount > 0) {
  			PyErr_Format(PyExc_TypeError,
! 				     "%.200s() takes no arguments (%d given)",
! 				     PyString_AsString(co->co_name),
! 				     argcount + kwcount);
  			goto fail;
  		}
***************
*** 2670,2675 ****
  				  (((PyInstanceObject *)self)->in_class),
  					  class))) {
! 		PyErr_SetString(PyExc_TypeError,
! 	"unbound method must be called with instance as first argument");
  			return NULL;
  		}
--- 2681,2690 ----
  				  (((PyInstanceObject *)self)->in_class),
  					  class))) {
!                 PyObject* fn = ((PyFunctionObject*) func)->func_name;
! 		PyErr_Format(PyExc_TypeError,
!                              "unbound method %s%smust be "
!                              "called with instance as first argument",
!                              fn ? PyString_AsString(fn) : "",
!                              fn ? "() " : "");
  			return NULL;
  		}
***************
*** 2794,2798 ****
  
  static PyObject *
! update_keyword_args(PyObject *orig_kwdict, int nk, PyObject ***pp_stack)
  {
  	PyObject *kwdict = NULL;
--- 2809,2814 ----
  
  static PyObject *
! update_keyword_args(PyObject *orig_kwdict, int nk, PyObject ***pp_stack,
!                     PyObject *func)
  {
  	PyObject *kwdict = NULL;
***************
*** 2810,2817 ****
  		PyObject *key = EXT_POP(*pp_stack);
  		if (PyDict_GetItem(kwdict, key) != NULL) {
! 			PyErr_Format(PyExc_TypeError, 
! 				     "keyword parameter '%.400s' "
! 				     "redefined in function call",
! 				     PyString_AsString(key));
  			Py_DECREF(key);
  			Py_DECREF(value);
--- 2826,2835 ----
  		PyObject *key = EXT_POP(*pp_stack);
  		if (PyDict_GetItem(kwdict, key) != NULL) {
!                         PyObject* fn = ((PyFunctionObject*) func)->func_name;
!                         PyErr_Format(PyExc_TypeError, 
!                                      "%.200s%s got multiple values "
!                                      "for keyword argument '%.400s'",
!                                      fn ? PyString_AsString(fn) : "function",
!                                      fn ? "()" : "", PyString_AsString(key));
  			Py_DECREF(key);
  			Py_DECREF(value);
***************
*** 2878,2882 ****
  
  	if (nk > 0) {
! 		kwdict = update_keyword_args(NULL, nk, pp_stack);
  		if (kwdict == NULL)
  			goto call_fail;
--- 2896,2900 ----
  
  	if (nk > 0) {
! 		kwdict = update_keyword_args(NULL, nk, pp_stack, func);
  		if (kwdict == NULL)
  			goto call_fail;
***************
*** 2904,2909 ****
  		kwdict = EXT_POP(*pp_stack);
  		if (!(kwdict && PyDict_Check(kwdict))) {
! 			PyErr_SetString(PyExc_TypeError,
! 					"** argument must be a dictionary");
  			goto ext_call_fail;
  		}
--- 2922,2930 ----
  		kwdict = EXT_POP(*pp_stack);
  		if (!(kwdict && PyDict_Check(kwdict))) {
!                         PyObject* fn = ((PyFunctionObject*) func)->func_name;
! 			PyErr_Format(PyExc_TypeError,
!                             "%s%s argument after ** must be a dictionary",
!                             fn ? PyString_AsString(fn) : "function",
!                             fn ? "()" : "");
  			goto ext_call_fail;
  		}
***************
*** 2916,2921 ****
  			if (t == NULL) {
  			    if (PyErr_ExceptionMatches(PyExc_TypeError)) {
! 				PyErr_SetString(PyExc_TypeError,
! 					"* argument must be a sequence");
  			    }
  				goto ext_call_fail;
--- 2937,2946 ----
  			if (t == NULL) {
  			    if (PyErr_ExceptionMatches(PyExc_TypeError)) {
!                                 PyObject* fn =
!                                     ((PyFunctionObject*) func)->func_name;
! 				PyErr_Format(PyExc_TypeError,
!                                     "%s%s argument after * must be a sequence",
!                                     fn ? PyString_AsString(fn) : "function",
!                                     fn ? "()" : "");
  			    }
  				goto ext_call_fail;
***************
*** 2927,2931 ****
  	}
  	if (nk > 0) {
! 		kwdict = update_keyword_args(kwdict, nk, pp_stack);
  		if (kwdict == NULL)
  			goto ext_call_fail;
--- 2952,2956 ----
  	}
  	if (nk > 0) {
! 		kwdict = update_keyword_args(kwdict, nk, pp_stack, func);
  		if (kwdict == NULL)
  			goto ext_call_fail;

Index: getargs.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Python/getargs.c,v
retrieving revision 2.51
retrieving revision 2.52
diff -C2 -r2.51 -r2.52
*** getargs.c	2000/12/11 20:01:55	2.51
--- getargs.c	2001/01/15 22:14:16	2.52
***************
*** 131,136 ****
  			if (args == NULL)
  				return 1;
! 			sprintf(msgbuf, "%s requires no arguments",
! 				fname==NULL ? "function" : fname);
  			PyErr_SetString(PyExc_TypeError, msgbuf);
  			return 0;
--- 131,137 ----
  			if (args == NULL)
  				return 1;
! 			sprintf(msgbuf, "%s%s takes no arguments",
! 				fname==NULL ? "function" : fname,
! 				fname==NULL ? "" : "()");
  			PyErr_SetString(PyExc_TypeError, msgbuf);
  			return 0;
***************
*** 139,144 ****
  			if (args == NULL) {
  				sprintf(msgbuf,
! 					"%s requires at least one argument",
! 					fname==NULL ? "function" : fname);
  				PyErr_SetString(PyExc_TypeError, msgbuf);
  				return 0;
--- 140,146 ----
  			if (args == NULL) {
  				sprintf(msgbuf,
! 					"%s%s takes at least one argument",
! 					fname==NULL ? "function" : fname,
! 					fname==NULL ? "" : "()");
  				PyErr_SetString(PyExc_TypeError, msgbuf);
  				return 0;
***************
*** 168,173 ****
  		if (message == NULL) {
  			sprintf(msgbuf,
! 				"%s requires %s %d argument%s; %d given",
  				fname==NULL ? "function" : fname,
  				min==max ? "exactly"
  				         : len < min ? "at least" : "at most",
--- 170,176 ----
  		if (message == NULL) {
  			sprintf(msgbuf,
! 				"%s%s takes %s %d argument%s (%d given)",
  				fname==NULL ? "function" : fname,
+ 				fname==NULL ? "" : "()",
  				min==max ? "exactly"
  				         : len < min ? "at least" : "at most",
***************
*** 214,233 ****
  	if (PyErr_Occurred())
  		return;
- 	if (iarg == 0 && message == NULL)
- 		message = msg;
  	else if (message == NULL) {
  		if (fname != NULL) {
! 			sprintf(p, "%s, ", fname);
  			p += strlen(p);
  		}
! 		sprintf(p, "argument %d", iarg);
! 		i = 0;
! 		p += strlen(p);
! 		while (levels[i] > 0) {
! 			sprintf(p, ", item %d", levels[i]-1);
  			p += strlen(p);
- 			i++;
  		}
! 		sprintf(p, ": expected %s found", msg);
  		message = buf;
  	}
--- 217,240 ----
  	if (PyErr_Occurred())
  		return;
  	else if (message == NULL) {
  		if (fname != NULL) {
! 			sprintf(p, "%s() ", fname);
  			p += strlen(p);
  		}
! 		if (iarg != 0) {
! 			sprintf(p, "argument %d", iarg);
! 			i = 0;
! 			p += strlen(p);
! 			while (levels[i] > 0) {
! 				sprintf(p, ", item %d", levels[i]-1);
! 				p += strlen(p);
! 				i++;
! 			}
! 		}
! 		else {
! 			sprintf(p, "argument");
  			p += strlen(p);
  		}
! 		sprintf(p, " %s", msg);
  		message = buf;
  	}
***************
*** 248,255 ****
        *levels is a 0-terminated list of item numbers,
        *msgbuf contains an error message, whose format is:
!          "<typename1>, <typename2>", where:
              <typename1> is the name of the expected type, and
              <typename2> is the name of the actual type,
-          (so you can surround it by "expected ... found"),
        and msgbuf is returned.
  */
--- 255,261 ----
        *levels is a 0-terminated list of item numbers,
        *msgbuf contains an error message, whose format is:
!          "must be <typename1>, not <typename2>", where:
              <typename1> is the name of the expected type, and
              <typename2> is the name of the actual type,
        and msgbuf is returned.
  */
***************
*** 282,289 ****
  	}
  	
! 	if (!PySequence_Check(arg)) {
  		levels[0] = 0;
  		sprintf(msgbuf,
! 			toplevel ? "%d arguments, %s" : "%d-sequence, %s",
  			n, arg == Py_None ? "None" : arg->ob_type->tp_name);
  		return msgbuf;
--- 288,296 ----
  	}
  	
! 	if (!PySequence_Check(arg) || PyString_Check(arg)) {
  		levels[0] = 0;
  		sprintf(msgbuf,
! 			toplevel ? "expected %d arguments, not %s" :
! 				   "must be %d-item sequence, not %s",
  			n, arg == Py_None ? "None" : arg->ob_type->tp_name);
  		return msgbuf;
***************
*** 293,301 ****
  		levels[0] = 0;
  		sprintf(msgbuf,
! 		    toplevel ? "%d arguments, %d" : "%d-sequence, %d-sequence",
! 		    n, i);
  		return msgbuf;
  	}
! 	
  	format = *p_format;
  	for (i = 0; i < n; i++) {
--- 300,309 ----
  		levels[0] = 0;
  		sprintf(msgbuf,
! 			toplevel ? "expected %d arguments, not %d" :
! 				   "must be sequence of length %d, not %d",
! 			n, i);
  		return msgbuf;
  	}
! 
  	format = *p_format;
  	for (i = 0; i < n; i++) {
***************
*** 311,315 ****
  		}
  	}
! 	
  	*p_format = format;
  	return NULL;
--- 319,323 ----
  		}
  	}
! 
  	*p_format = format;
  	return NULL;
***************
*** 344,348 ****
  
  /* Convert a non-tuple argument.  Adds to convertsimple1 functionality
!    by appending ", <actual argument type>" to error message. */
  
  static char *
--- 352,356 ----
  
  /* Convert a non-tuple argument.  Adds to convertsimple1 functionality
!    by formatting messages as "must be <desired type>, not <actual type>". */
  
  static char *
***************
*** 351,355 ****
  	char *msg = convertsimple1(arg, p_format, p_va);
  	if (msg != NULL) {
! 		sprintf(msgbuf, "%.50s, %.50s", msg,
  			arg == Py_None ? "None" : arg->ob_type->tp_name);
  		msg = msgbuf;
--- 359,363 ----
  	char *msg = convertsimple1(arg, p_format, p_va);
  	if (msg != NULL) {
! 		sprintf(msgbuf, "must be %.50s, not %.50s", msg,
  			arg == Py_None ? "None" : arg->ob_type->tp_name);
  		msg = msgbuf;
***************
*** 1064,1069 ****
  		if (message == NULL) {
  			sprintf(msgbuf,
! 				"%s requires %s %d argument%s; %d given",
  				fname==NULL ? "function" : fname,
  				min==max ? "exactly"
  				         : len < min ? "at least" : "at most",
--- 1072,1078 ----
  		if (message == NULL) {
  			sprintf(msgbuf,
! 				"%s%s takes %s %d argument%s (%d given)",
  				fname==NULL ? "function" : fname,
+ 				fname==NULL ? "" : "()",
  				min==max ? "exactly"
  				         : len < min ? "at least" : "at most",