Try this: if (PyInstance_Check(obj)) { bound_method = PyObject_GetAttr(obj, str__format__); if (!bound_method) return NULL; <call it passing only the format string> Py_DECREF(bound_method); return <whatever the call returned> } else { do it the py3k way; }
On Feb 13, 2008 5:31 PM, Eric Smith <[EMAIL PROTECTED]> wrote: > [slight mailer problem, this might show up as a dupe. sorry] > Guido van Rossum wrote: > > On Feb 13, 2008 2:57 PM, Eric Smith <[EMAIL PROTECTED]> wrote: > >> Guido van Rossum wrote: > >>> On Feb 13, 2008 2:20 PM, Eric Smith <[EMAIL PROTECTED]> wrote: > >>>> Nick Coghlan wrote: > >>>>> However, the source code for cPickle may provide some ideas (when it > >>>>> looks up _reduce__/__getstate__/etc). > >>>> Those do look promising. Thanks! > >>> Or look in classobject.c itself; e.g. instance_str(). > >> It uses a static helper function instance_getattr(), which while it > >> looks like what I want, I can't get to. > > > > Well, it just implements PyObject_GetAttr for classic class instances... > > > >> So I've come up with the following. I haven't checked for leaks yet, > >> but at least it appears to do what I want, for both classic and > >> new-style classes. I'm still porting over test cases from 3.0, so I'm > >> not convinced this is correct, yet. > >> > >> /* Check for a __format__ method. */ > >> meth = PyObject_GetAttr(value, str__format__); > >> if (meth) > >> result = PyObject_CallFunctionObjArgs(meth, spec, NULL); > >> else { > > > > You'd need PyErr_Clear() here the way this is written. > > Okay. > > > But the > > following call is redundant -- if that _PyType_Lookup() call finds > > something, PyObject_GetAttr() will have found that too (or something > > else). > > > >> meth = _PyType_Lookup(Py_TYPE(value), str__format__); > >> if (meth) > >> result = PyObject_CallFunctionObjArgs(meth, value, spec, NULL); > >> else { > >> PyErr_Format(PyExc_TypeError, > >> "Type %.100s doesn't define __format__", > >> Py_TYPE(value)->tp_name); > >> goto done; > >> } > >> } > > Yes, but what's the "or something else", and is it the right thing? Are > you saying I should call _PyType_Lookup first? But that's how I > started: if I do it that way, I can't override __format__ in a classic > class. As the code stands (PyObject_GetAttr then _PyType_Lookup), it's > definitely true that _PyType_Lookup will succeed when PyObject_GetAttr > will have failed. > > Or should the logic be: > if is-new-style-class(Py_TYPE(value)): > lookup method with _PyType_Lookup(Py_TYPE(value)) > else: > lookup method with PyObject_GetAttr(value) > > And if so, how to test for "is-new-style-class"? > > Sorry to be wasting your time, but I'm don't understand all of the > issues trying to support both new and classic classes in C. I think > I'll get the rest of PEP 3101 working, then come back to this issue. > It's pretty well contained. I'll spend some time understanding > classobject.c's implementation. It just seems like it shouldn't be this > hard to call a method (if it exists), given an instance. > > I think my confusion leads to this problem (if in fact it's a problem): > >>> format(object, '') > Traceback (most recent call last): > File "<stdin>", line 1, in <module> > TypeError: __format__() takes exactly 1 argument (0 given) > >>> format(object(), '') > '<object object at 0x307408>' > >>> ^D > > Which works in the py3k branch. > > > Since PyObject_GetAttr() sets an AttributeError exception already, I > > question the benefit of setting a different exception. > > Agreed. > > > > _______________________________________________ > Python-Dev mailing list > Python-Dev@python.org > http://mail.python.org/mailman/listinfo/python-dev > Unsubscribe: > http://mail.python.org/mailman/options/python-dev/guido%40python.org > -- --Guido van Rossum (home page: http://www.python.org/~guido/) _______________________________________________ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com