@@ -16,6 +16,8 @@ typedef struct {
1616 PyObject * fn ;
1717 PyObject * args ;
1818 PyObject * kw ;
19+ PyObject * dict ;
20+ PyObject * weakreflist ; /* List of weak references */
1921} partialobject ;
2022
2123static PyTypeObject partial_type ;
@@ -63,16 +65,22 @@ partial_new(PyTypeObject *type, PyObject *args, PyObject *kw)
6365 Py_INCREF (Py_None );
6466 }
6567
68+ pto -> weakreflist = NULL ;
69+ pto -> dict = NULL ;
70+
6671 return (PyObject * )pto ;
6772}
6873
6974static void
7075partial_dealloc (partialobject * pto )
7176{
7277 PyObject_GC_UnTrack (pto );
78+ if (pto -> weakreflist != NULL )
79+ PyObject_ClearWeakRefs ((PyObject * ) pto );
7380 Py_XDECREF (pto -> fn );
7481 Py_XDECREF (pto -> args );
7582 Py_XDECREF (pto -> kw );
83+ Py_XDECREF (pto -> dict );
7684 pto -> ob_type -> tp_free (pto );
7785}
7886
@@ -128,6 +136,7 @@ partial_traverse(partialobject *pto, visitproc visit, void *arg)
128136 Py_VISIT (pto -> fn );
129137 Py_VISIT (pto -> args );
130138 Py_VISIT (pto -> kw );
139+ Py_VISIT (pto -> dict );
131140 return 0 ;
132141}
133142
@@ -146,6 +155,47 @@ static PyMemberDef partial_memberlist[] = {
146155 {NULL } /* Sentinel */
147156};
148157
158+ static PyObject *
159+ partial_get_dict (partialobject * pto )
160+ {
161+ if (pto -> dict == NULL ) {
162+ pto -> dict = PyDict_New ();
163+ if (pto -> dict == NULL )
164+ return NULL ;
165+ }
166+ Py_INCREF (pto -> dict );
167+ return pto -> dict ;
168+ }
169+
170+ static int
171+ partial_set_dict (partialobject * pto , PyObject * value )
172+ {
173+ PyObject * tmp ;
174+
175+ /* It is illegal to del p.__dict__ */
176+ if (value == NULL ) {
177+ PyErr_SetString (PyExc_TypeError ,
178+ "a partial object's dictionary may not be deleted" );
179+ return -1 ;
180+ }
181+ /* Can only set __dict__ to a dictionary */
182+ if (!PyDict_Check (value )) {
183+ PyErr_SetString (PyExc_TypeError ,
184+ "setting partial object's dictionary to a non-dict" );
185+ return -1 ;
186+ }
187+ tmp = pto -> dict ;
188+ Py_INCREF (value );
189+ pto -> dict = value ;
190+ Py_XDECREF (tmp );
191+ return 0 ;
192+ }
193+
194+ static PyGetSetDef partail_getsetlist [] = {
195+ {"__dict__" , (getter )partial_get_dict , (setter )partial_set_dict },
196+ {NULL } /* Sentinel */
197+ };
198+
149199static PyTypeObject partial_type = {
150200 PyObject_HEAD_INIT (NULL )
151201 0 , /* ob_size */
@@ -166,25 +216,25 @@ static PyTypeObject partial_type = {
166216 (ternaryfunc )partial_call , /* tp_call */
167217 0 , /* tp_str */
168218 PyObject_GenericGetAttr , /* tp_getattro */
169- 0 , /* tp_setattro */
219+ PyObject_GenericSetAttr , /* tp_setattro */
170220 0 , /* tp_as_buffer */
171221 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
172- Py_TPFLAGS_BASETYPE , /* tp_flags */
222+ Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_WEAKREFS , /* tp_flags */
173223 partial_doc , /* tp_doc */
174224 (traverseproc )partial_traverse , /* tp_traverse */
175225 0 , /* tp_clear */
176226 0 , /* tp_richcompare */
177- 0 , /* tp_weaklistoffset */
227+ offsetof( partialobject , weakreflist ), /* tp_weaklistoffset */
178228 0 , /* tp_iter */
179229 0 , /* tp_iternext */
180230 0 , /* tp_methods */
181231 partial_memberlist , /* tp_members */
182- 0 , /* tp_getset */
232+ partail_getsetlist , /* tp_getset */
183233 0 , /* tp_base */
184234 0 , /* tp_dict */
185235 0 , /* tp_descr_get */
186236 0 , /* tp_descr_set */
187- 0 , /* tp_dictoffset */
237+ offsetof( partialobject , dict ), /* tp_dictoffset */
188238 0 , /* tp_init */
189239 0 , /* tp_alloc */
190240 partial_new , /* tp_new */
0 commit comments