55
66#define TP_DESCR_GET (t ) ((t)->tp_descr_get)
77
8-
98PyObject *
109PyMethod_Function (PyObject * im )
1110{
@@ -68,12 +67,12 @@ PyMethod_New(PyObject *func, PyObject *self)
6867
6968/* im_func and im_self are stored in the PyMethod object */
7069
71- #define OFF (x ) offsetof(PyMethodObject, x)
70+ #define MO_OFF (x ) offsetof(PyMethodObject, x)
7271
7372static PyMemberDef method_memberlist [] = {
74- {"__func__" , T_OBJECT , OFF (im_func ), READONLY |RESTRICTED ,
73+ {"__func__" , T_OBJECT , MO_OFF (im_func ), READONLY |RESTRICTED ,
7574 "the function (or other callable) implementing a method" },
76- {"__self__" , T_OBJECT , OFF (im_self ), READONLY |RESTRICTED ,
75+ {"__self__" , T_OBJECT , MO_OFF (im_self ), READONLY |RESTRICTED ,
7776 "the instance to which a method is bound" },
7877 {NULL } /* Sentinel */
7978};
@@ -131,15 +130,15 @@ method_getattro(PyObject *obj, PyObject *name)
131130PyDoc_STRVAR (method_doc ,
132131"method(function, instance)\n\
133132\n\
134- Create an instance method object." );
133+ Create a bound instance method object." );
135134
136135static PyObject *
137136method_new (PyTypeObject * type , PyObject * args , PyObject * kw )
138137{
139138 PyObject * func ;
140139 PyObject * self ;
141140
142- if (!_PyArg_NoKeywords ("instancemethod " , kw ))
141+ if (!_PyArg_NoKeywords ("method " , kw ))
143142 return NULL ;
144143 if (!PyArg_UnpackTuple (args , "method" , 2 , 2 ,
145144 & func , & self ))
@@ -351,7 +350,7 @@ PyTypeObject PyMethod_Type = {
351350 (traverseproc )method_traverse , /* tp_traverse */
352351 0 , /* tp_clear */
353352 method_richcompare , /* tp_richcompare */
354- offsetof(PyMethodObject , im_weakreflist ), /* tp_weaklistoffset */
353+ offsetof(PyMethodObject , im_weakreflist ), /* tp_weaklistoffset */
355354 0 , /* tp_iter */
356355 0 , /* tp_iternext */
357356 0 , /* tp_methods */
@@ -378,3 +377,245 @@ PyMethod_Fini(void)
378377 PyObject_GC_Del (im );
379378 }
380379}
380+
381+ /* ------------------------------------------------------------------------
382+ * instance method
383+ */
384+
385+ PyObject *
386+ PyInstanceMethod_New (PyObject * func ) {
387+ PyInstanceMethodObject * method ;
388+ method = PyObject_GC_New (PyInstanceMethodObject ,
389+ & PyInstanceMethod_Type );
390+ if (method == NULL ) return NULL ;
391+ Py_INCREF (func );
392+ method -> func = func ;
393+ _PyObject_GC_TRACK (method );
394+ return (PyObject * )method ;
395+ }
396+
397+ PyObject *
398+ PyInstanceMethod_Function (PyObject * im )
399+ {
400+ if (!PyInstanceMethod_Check (im )) {
401+ PyErr_BadInternalCall ();
402+ return NULL ;
403+ }
404+ return PyInstanceMethod_GET_FUNCTION (im );
405+ }
406+
407+ #define IMO_OFF (x ) offsetof(PyInstanceMethodObject, x)
408+
409+ static PyMemberDef instancemethod_memberlist [] = {
410+ {"__func__" , T_OBJECT , IMO_OFF (func ), READONLY |RESTRICTED ,
411+ "the function (or other callable) implementing a method" },
412+ {NULL } /* Sentinel */
413+ };
414+
415+ static PyObject *
416+ instancemethod_get_doc (PyObject * self , void * context )
417+ {
418+ static PyObject * docstr ;
419+ if (docstr == NULL ) {
420+ docstr = PyUnicode_InternFromString ("__doc__" );
421+ if (docstr == NULL )
422+ return NULL ;
423+ }
424+ return PyObject_GetAttr (PyInstanceMethod_GET_FUNCTION (self ), docstr );
425+ }
426+
427+ static PyGetSetDef instancemethod_getset [] = {
428+ {"__doc__" , (getter )instancemethod_get_doc , NULL , NULL },
429+ {0 }
430+ };
431+
432+ static PyObject *
433+ instancemethod_getattro (PyObject * self , PyObject * name )
434+ {
435+ PyTypeObject * tp = self -> ob_type ;
436+ PyObject * descr = NULL ;
437+
438+ if (tp -> tp_dict == NULL ) {
439+ if (PyType_Ready (tp ) < 0 )
440+ return NULL ;
441+ }
442+ descr = _PyType_Lookup (tp , name );
443+
444+ if (descr != NULL ) {
445+ descrgetfunc f = TP_DESCR_GET (descr -> ob_type );
446+ if (f != NULL )
447+ return f (descr , self , (PyObject * )self -> ob_type );
448+ else {
449+ Py_INCREF (descr );
450+ return descr ;
451+ }
452+ }
453+
454+ return PyObject_GetAttr (PyInstanceMethod_GET_FUNCTION (self ), name );
455+ }
456+
457+ static void
458+ instancemethod_dealloc (PyObject * self ) {
459+ _PyObject_GC_UNTRACK (self );
460+ Py_DECREF (PyInstanceMethod_GET_FUNCTION (self ));
461+ PyObject_GC_Del (self );
462+ }
463+
464+ static int
465+ instancemethod_traverse (PyObject * self , visitproc visit , void * arg ) {
466+ Py_VISIT (PyInstanceMethod_GET_FUNCTION (self ));
467+ return 0 ;
468+ }
469+
470+ static PyObject *
471+ instancemethod_call (PyObject * self , PyObject * arg , PyObject * kw )
472+ {
473+ return PyObject_Call (PyMethod_GET_FUNCTION (self ), arg , kw );
474+ }
475+
476+ static PyObject *
477+ instancemethod_descr_get (PyObject * descr , PyObject * obj , PyObject * type ) {
478+ register PyObject * func = PyInstanceMethod_GET_FUNCTION (descr );
479+ if (obj == NULL )
480+ return func ;
481+ else
482+ return PyMethod_New (func , obj );
483+ }
484+
485+ static PyObject *
486+ instancemethod_richcompare (PyObject * self , PyObject * other , int op )
487+ {
488+ PyInstanceMethodObject * a , * b ;
489+ PyObject * res ;
490+ int eq ;
491+
492+ if ((op != Py_EQ && op != Py_NE ) ||
493+ !PyInstanceMethod_Check (self ) ||
494+ !PyInstanceMethod_Check (other ))
495+ {
496+ Py_INCREF (Py_NotImplemented );
497+ return Py_NotImplemented ;
498+ }
499+ a = (PyInstanceMethodObject * )self ;
500+ b = (PyInstanceMethodObject * )other ;
501+ eq = PyObject_RichCompareBool (a -> func , b -> func , Py_EQ );
502+ if (eq < 0 )
503+ return NULL ;
504+ if (op == Py_EQ )
505+ res = eq ? Py_True : Py_False ;
506+ else
507+ res = eq ? Py_False : Py_True ;
508+ Py_INCREF (res );
509+ return res ;
510+ }
511+
512+ static PyObject *
513+ instancemethod_repr (PyObject * self )
514+ {
515+ PyObject * func = PyInstanceMethod_Function (self );
516+ PyObject * funcname = NULL , * result = NULL ;
517+ char * defname = "?" ;
518+
519+ if (func == NULL ) {
520+ PyErr_BadInternalCall ();
521+ return NULL ;
522+ }
523+
524+ funcname = PyObject_GetAttrString (func , "__name__" );
525+ if (funcname == NULL ) {
526+ if (!PyErr_ExceptionMatches (PyExc_AttributeError ))
527+ return NULL ;
528+ PyErr_Clear ();
529+ }
530+ else if (!PyUnicode_Check (funcname )) {
531+ Py_DECREF (funcname );
532+ funcname = NULL ;
533+ }
534+
535+ result = PyUnicode_FromFormat ("<instancemethod %V at %p>" ,
536+ funcname , defname , self );
537+
538+ Py_XDECREF (funcname );
539+ return result ;
540+ }
541+
542+ /*
543+ static long
544+ instancemethod_hash(PyObject *self)
545+ {
546+ long x, y;
547+ x = (long)self;
548+ y = PyObject_Hash(PyInstanceMethod_GET_FUNCTION(self));
549+ if (y == -1)
550+ return -1;
551+ x = x ^ y;
552+ if (x == -1)
553+ x = -2;
554+ return x;
555+ }
556+ */
557+
558+ PyDoc_STRVAR (instancemethod_doc ,
559+ "instancemethod(function)\n\
560+ \n\
561+ Bind a function to a class." );
562+
563+ static PyObject *
564+ instancemethod_new (PyTypeObject * type , PyObject * args , PyObject * kw )
565+ {
566+ PyObject * func ;
567+
568+ if (!_PyArg_NoKeywords ("instancemethod" , kw ))
569+ return NULL ;
570+ if (!PyArg_UnpackTuple (args , "instancemethod" , 1 , 1 , & func ))
571+ return NULL ;
572+ if (!PyCallable_Check (func )) {
573+ PyErr_SetString (PyExc_TypeError ,
574+ "first argument must be callable" );
575+ return NULL ;
576+ }
577+
578+ return PyInstanceMethod_New (func );
579+ }
580+
581+ PyTypeObject PyInstanceMethod_Type = {
582+ PyVarObject_HEAD_INIT (& PyType_Type , 0 )
583+ "instancemethod" , /* tp_name */
584+ sizeof (PyInstanceMethodObject ), /* tp_basicsize */
585+ 0 , /* tp_itemsize */
586+ instancemethod_dealloc , /* tp_dealloc */
587+ 0 , /* tp_print */
588+ 0 , /* tp_getattr */
589+ 0 , /* tp_setattr */
590+ 0 , /* tp_compare */
591+ (reprfunc )instancemethod_repr , /* tp_repr */
592+ 0 , /* tp_as_number */
593+ 0 , /* tp_as_sequence */
594+ 0 , /* tp_as_mapping */
595+ 0 , /*(hashfunc)instancemethod_hash, tp_hash */
596+ instancemethod_call , /* tp_call */
597+ 0 , /* tp_str */
598+ instancemethod_getattro , /* tp_getattro */
599+ PyObject_GenericSetAttr , /* tp_setattro */
600+ 0 , /* tp_as_buffer */
601+ Py_TPFLAGS_DEFAULT
602+ | Py_TPFLAGS_HAVE_GC , /* tp_flags */
603+ instancemethod_doc , /* tp_doc */
604+ instancemethod_traverse , /* tp_traverse */
605+ 0 , /* tp_clear */
606+ instancemethod_richcompare , /* tp_richcompare */
607+ 0 , /* tp_weaklistoffset */
608+ 0 , /* tp_iter */
609+ 0 , /* tp_iternext */
610+ 0 , /* tp_methods */
611+ instancemethod_memberlist , /* tp_members */
612+ instancemethod_getset , /* tp_getset */
613+ 0 , /* tp_base */
614+ 0 , /* tp_dict */
615+ instancemethod_descr_get , /* tp_descr_get */
616+ 0 , /* tp_descr_set */
617+ 0 , /* tp_dictoffset */
618+ 0 , /* tp_init */
619+ 0 , /* tp_alloc */
620+ instancemethod_new , /* tp_new */
621+ };
0 commit comments