[Python-checkins] CVS: python/dist/src/Objects funcobject.c,2.42,2.43

Guido van Rossum gvanrossum@users.sourceforge.net
Mon, 17 Sep 2001 16:46:58 -0700


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

Modified Files:
	funcobject.c 
Log Message:
Rewrite function attributes to use the generic routines properly.
This uses the new "restricted" feature of structmember, and getset
descriptors for some of the type checks.


Index: funcobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/funcobject.c,v
retrieving revision 2.42
retrieving revision 2.43
diff -C2 -d -r2.42 -r2.43
*** funcobject.c	2001/08/29 23:52:31	2.42
--- funcobject.c	2001/09/17 23:46:56	2.43
***************
*** 128,224 ****
  #define OFF(x) offsetof(PyFunctionObject, x)
  
  static struct memberlist func_memberlist[] = {
!         {"func_code",     T_OBJECT,     OFF(func_code)},
!         {"func_globals",  T_OBJECT,     OFF(func_globals),      READONLY},
          {"func_name",     T_OBJECT,     OFF(func_name),         READONLY},
          {"__name__",      T_OBJECT,     OFF(func_name),         READONLY},
-         {"func_closure",  T_OBJECT,     OFF(func_closure),      READONLY},
-         {"func_defaults", T_OBJECT,     OFF(func_defaults)},
-         {"func_doc",      T_OBJECT,     OFF(func_doc)},
-         {"__doc__",       T_OBJECT,     OFF(func_doc)},
-         {"func_dict",     T_OBJECT,     OFF(func_dict)},
-         {"__dict__",      T_OBJECT,     OFF(func_dict)},
          {NULL}  /* Sentinel */
  };
  
  static PyObject *
! func_getattro(PyObject *op, PyObject *name)
  {
! 	char *sname = PyString_AsString(name);
! 	
! 	if (sname[0] != '_' && PyEval_GetRestricted()) {
! 		PyErr_SetString(PyExc_RuntimeError,
! 		  "function attributes not accessible in restricted mode");
  		return NULL;
! 	}
! 	/* If func_dict is being accessed but no attribute has been set
! 	 * yet, then initialize it to the empty dictionary.
! 	 */
! 	if ((!strcmp(sname, "func_dict") || !strcmp(sname, "__dict__"))
! 	     && ((PyFunctionObject*)op)->func_dict == NULL)
! 	{
! 		PyFunctionObject* funcop = (PyFunctionObject*)op;
! 		
! 		funcop->func_dict = PyDict_New();
! 		if (funcop->func_dict == NULL)
  			return NULL;
  	}
! 	return PyObject_GenericGetAttr(op, name);
  }
  
  static int
! func_setattro(PyObject *op, PyObject *name, PyObject *value)
  {
! 	char *sname = PyString_AsString(name);
  
! 	if (PyEval_GetRestricted()) {
! 		PyErr_SetString(PyExc_RuntimeError,
! 		  "function attributes not settable in restricted mode");
  		return -1;
  	}
! 	if (strcmp(sname, "func_code") == 0) {
! 		/* not legal to del f.func_code or to set it to anything
! 		 * other than a code object.
! 		 */
! 		if (value == NULL || !PyCode_Check(value)) {
! 			PyErr_SetString(
! 				PyExc_TypeError,
  				"func_code must be set to a code object");
! 			return -1;
! 		}
  	}
! 	else if (strcmp(sname, "func_defaults") == 0) {
! 		/* legal to del f.func_defaults.  Can only set
! 		 * func_defaults to NULL or a tuple.
! 		 */
! 		if (value == Py_None)
! 			value = NULL;
! 		if (value != NULL && !PyTuple_Check(value)) {
! 			PyErr_SetString(
! 				PyExc_TypeError,
! 				"func_defaults must be set to a tuple object");
! 			return -1;
! 		}
  	}
! 	else if (!strcmp(sname, "func_dict") || !strcmp(sname, "__dict__")) {
! 		/* It is illegal to del f.func_dict.  Can only set
! 		 * func_dict to a dictionary.
! 		 */
! 		if (value == NULL) {
! 			PyErr_SetString(
! 				PyExc_TypeError,
! 				"function's dictionary may not be deleted");
! 			return -1;
! 		}
! 		if (!PyDict_Check(value)) {
! 			PyErr_SetString(
! 				PyExc_TypeError,
! 				"setting function's dictionary to a non-dict");
! 			return -1;
! 		}
  	}
! 	return PyObject_GenericSetAttr(op, name, value);
  }
  
  static void
  func_dealloc(PyFunctionObject *op)
--- 128,270 ----
  #define OFF(x) offsetof(PyFunctionObject, x)
  
+ #define RR ()
+ 
  static struct memberlist func_memberlist[] = {
!         {"func_closure",  T_OBJECT,     OFF(func_closure),
! 	 RESTRICTED|READONLY},
!         {"func_doc",      T_OBJECT,     OFF(func_doc), WRITE_RESTRICTED},
!         {"__doc__",       T_OBJECT,     OFF(func_doc), WRITE_RESTRICTED},
!         {"func_globals",  T_OBJECT,     OFF(func_globals),
! 	 RESTRICTED|READONLY},
          {"func_name",     T_OBJECT,     OFF(func_name),         READONLY},
          {"__name__",      T_OBJECT,     OFF(func_name),         READONLY},
          {NULL}  /* Sentinel */
  };
  
+ static int
+ restricted(void)
+ {
+ 	if (!PyEval_GetRestricted())
+ 		return 0;
+ 	PyErr_SetString(PyExc_RuntimeError,
+ 		"function attributes not accessible in restricted mode");
+ 	return 1;
+ }
+ 
  static PyObject *
! func_get_dict(PyFunctionObject *op)
  {
! 	if (restricted())
  		return NULL;
! 	if (op->func_dict == NULL) {
! 		op->func_dict = PyDict_New();
! 		if (op->func_dict == NULL)
  			return NULL;
  	}
! 	Py_INCREF(op->func_dict);
! 	return op->func_dict;
  }
  
  static int
! func_set_dict(PyFunctionObject *op, PyObject *value)
  {
! 	PyObject *tmp;
  
! 	if (restricted())
! 		return -1;
! 	/* It is illegal to del f.func_dict */
! 	if (value == NULL) {
! 		PyErr_SetString(PyExc_TypeError,
! 				"function's dictionary may not be deleted");
  		return -1;
  	}
! 	/* Can only set func_dict to a dictionary */
! 	if (!PyDict_Check(value)) {
! 		PyErr_SetString(PyExc_TypeError,
! 				"setting function's dictionary to a non-dict");
! 		return -1;
! 	}
! 	tmp = op->func_dict;
! 	Py_INCREF(value);
! 	op->func_dict = value;
! 	Py_XDECREF(tmp);
! 	return 0;
! }
! 
! static PyObject *
! func_get_code(PyFunctionObject *op)
! {
! 	if (restricted())
! 		return NULL;
! 	Py_INCREF(op->func_code);
! 	return op->func_code;
! }
! 
! static int
! func_set_code(PyFunctionObject *op, PyObject *value)
! {
! 	PyObject *tmp;
! 
! 	if (restricted())
! 		return -1;
! 	/* Not legal to del f.func_code or to set it to anything
! 	 * other than a code object. */
! 	if (value == NULL || !PyCode_Check(value)) {
! 		PyErr_SetString(PyExc_TypeError,
  				"func_code must be set to a code object");
! 		return -1;
  	}
! 	tmp = op->func_code;
! 	Py_INCREF(value);
! 	op->func_code = value;
! 	Py_DECREF(tmp);
! 	return 0;
! }
! 
! static PyObject *
! func_get_defaults(PyFunctionObject *op)
! {
! 	if (restricted())
! 		return NULL;
! 	if (op->func_defaults == NULL) {
! 		Py_INCREF(Py_None);
! 		return Py_None;
  	}
! 	Py_INCREF(op->func_defaults);
! 	return op->func_defaults;
! }
! 
! static int
! func_set_defaults(PyFunctionObject *op, PyObject *value)
! {
! 	PyObject *tmp;
! 
! 	if (restricted())
! 		return -1;
! 	/* Legal to del f.func_defaults.
! 	 * Can only set func_defaults to NULL or a tuple. */
! 	if (value == Py_None)
! 		value = NULL;
! 	if (value != NULL && !PyTuple_Check(value)) {
! 		PyErr_SetString(PyExc_TypeError,
! 				"func_defaults must be set to a tuple object");
! 		return -1;
  	}
! 	tmp = op->func_defaults;
! 	Py_XINCREF(value);
! 	op->func_defaults = value;
! 	Py_XDECREF(tmp);
! 	return 0;
  }
  
+ static struct getsetlist func_getsetlist[] = {
+         {"func_code", (getter)func_get_code, (setter)func_set_code},
+         {"func_defaults", (getter)func_get_defaults,
+ 	 (setter)func_set_defaults},
+ 	{"func_dict", (getter)func_get_dict, (setter)func_set_dict},
+ 	{"__dict__", (getter)func_get_dict, (setter)func_set_dict},
+ 	{NULL} /* Sentinel */
+ };
+ 
  static void
  func_dealloc(PyFunctionObject *op)
***************
*** 366,371 ****
  	function_call,				/* tp_call */
  	0,					/* tp_str */
! 	func_getattro,				/* tp_getattro */
! 	func_setattro,				/* tp_setattro */
  	0,					/* tp_as_buffer */
  	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
--- 412,417 ----
  	function_call,				/* tp_call */
  	0,					/* tp_str */
! 	PyObject_GenericGetAttr,		/* tp_getattro */
! 	PyObject_GenericSetAttr,		/* tp_setattro */
  	0,					/* tp_as_buffer */
  	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
***************
*** 379,383 ****
  	0,					/* tp_methods */
  	func_memberlist,			/* tp_members */
! 	0,					/* tp_getset */
  	0,					/* tp_base */
  	0,					/* tp_dict */
--- 425,429 ----
  	0,					/* tp_methods */
  	func_memberlist,			/* tp_members */
! 	func_getsetlist,			/* tp_getset */
  	0,					/* tp_base */
  	0,					/* tp_dict */