[Python-checkins] python/dist/src/Modules functionalmodule.c, 1.1, 1.2

rhettinger at users.sourceforge.net rhettinger at users.sourceforge.net
Tue Mar 8 07:14:53 CET 2005


Update of /cvsroot/python/python/dist/src/Modules
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv23159/Modules

Modified Files:
	functionalmodule.c 
Log Message:
Make functional.partial() more closely match the spec by emulating
some useful features of regular functions:

* Made weak referencable.
* Allow attribute access so a user can set __name__, __doc__, etc.



Index: functionalmodule.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Modules/functionalmodule.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- functionalmodule.c	28 Feb 2005 19:39:43 -0000	1.1
+++ functionalmodule.c	8 Mar 2005 06:14:51 -0000	1.2
@@ -16,6 +16,8 @@
 	PyObject *fn;
 	PyObject *args;
 	PyObject *kw;
+	PyObject *dict;
+	PyObject *weakreflist; /* List of weak references */
 } partialobject;
 
 static PyTypeObject partial_type;
@@ -63,6 +65,9 @@
 		Py_INCREF(Py_None);
 	}
 
+	pto->weakreflist = NULL;
+	pto->dict = NULL;
+
 	return (PyObject *)pto;
 }
 
@@ -70,9 +75,12 @@
 partial_dealloc(partialobject *pto)
 {
 	PyObject_GC_UnTrack(pto);
+	if (pto->weakreflist != NULL)
+		PyObject_ClearWeakRefs((PyObject *) pto);
 	Py_XDECREF(pto->fn);
 	Py_XDECREF(pto->args);
 	Py_XDECREF(pto->kw);
+	Py_XDECREF(pto->dict);
 	pto->ob_type->tp_free(pto);
 }
 
@@ -128,6 +136,7 @@
 	Py_VISIT(pto->fn);
 	Py_VISIT(pto->args);
 	Py_VISIT(pto->kw);
+	Py_VISIT(pto->dict);
 	return 0;
 }
 
@@ -146,6 +155,47 @@
 	{NULL}  /* Sentinel */
 };
 
+static PyObject *
+partial_get_dict(partialobject *pto)
+{
+	if (pto->dict == NULL) {
+		pto->dict = PyDict_New();
+		if (pto->dict == NULL)
+			return NULL;
+	}
+	Py_INCREF(pto->dict);
+	return pto->dict;
+}
+
+static int
+partial_set_dict(partialobject *pto, PyObject *value)
+{
+	PyObject *tmp;
+
+	/* It is illegal to del p.__dict__ */
+	if (value == NULL) {
+		PyErr_SetString(PyExc_TypeError,
+				"a partial object's dictionary may not be deleted");
+		return -1;
+	}
+	/* Can only set __dict__ to a dictionary */
+	if (!PyDict_Check(value)) {
+		PyErr_SetString(PyExc_TypeError,
+				"setting partial object's dictionary to a non-dict");
+		return -1;
+	}
+	tmp = pto->dict;
+	Py_INCREF(value);
+	pto->dict = value;
+	Py_XDECREF(tmp);
+	return 0;
+}
+
+static PyGetSetDef partail_getsetlist[] = {
+	{"__dict__", (getter)partial_get_dict, (setter)partial_set_dict},
+	{NULL} /* Sentinel */
+};
+
 static PyTypeObject partial_type = {
 	PyObject_HEAD_INIT(NULL)
 	0,				/* ob_size */
@@ -166,25 +216,25 @@
 	(ternaryfunc)partial_call,	/* tp_call */
 	0,				/* tp_str */
 	PyObject_GenericGetAttr,	/* tp_getattro */
-	0,				/* tp_setattro */
+	PyObject_GenericSetAttr,	/* tp_setattro */
 	0,				/* tp_as_buffer */
 	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
-		Py_TPFLAGS_BASETYPE,	/* tp_flags */
+		Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_WEAKREFS,	/* tp_flags */
 	partial_doc,			/* tp_doc */
 	(traverseproc)partial_traverse,	/* tp_traverse */
 	0,				/* tp_clear */
 	0,				/* tp_richcompare */
-	0,				/* tp_weaklistoffset */
+	offsetof(partialobject, weakreflist),	/* tp_weaklistoffset */
 	0,				/* tp_iter */
 	0,				/* tp_iternext */
 	0,				/* tp_methods */
 	partial_memberlist,		/* tp_members */
-	0,				/* tp_getset */
+	partail_getsetlist,		/* tp_getset */
 	0,				/* tp_base */
 	0,				/* tp_dict */
 	0,				/* tp_descr_get */
 	0,				/* tp_descr_set */
-	0,				/* tp_dictoffset */
+	offsetof(partialobject, dict),	/* tp_dictoffset */
 	0,				/* tp_init */
 	0,				/* tp_alloc */
 	partial_new,			/* tp_new */



More information about the Python-checkins mailing list