PyObject __repr__, __str__ and toString

Jeff Allen <[email protected]>
Newsgroups gmane.comp.lang.jython.devel
Message-ID <[email protected]>
We're discussing this in a couple of places already, but I wanted to ask 
here in case there are old hands subscribed who can shed any light.

http://bugs.jython.org/issue2719

https://github.com/jythontools/jython/pull/126

PyObject.java contains some comments I've never understood and have had 
difficulty following 
(https://hg.python.org/jython/file/tip/src/org/python/core/PyObject.java#l218). 
It seems advice only relevant to those who extend PyObject, which is 
mostly us. And we certainly don't follow it in PyObjectDerived which 
contains the mechanism by which Python authors override __str__ and 
where toString delegates to __repr__.

Generally, the plain dunder methods in Jython correspond to tp_* slots 
in CPython, and methods with a name like int___add__ to which they 
delegate are the implementation functions. Overriding __add__ to call 
int___add__ is equivalent to the action in CPython of placing a function 
pointer in a tp-slot. At present, __str__ and __repr__ do not follow 
this convention: __str__ defaults to __repr__ by this mechanism, as 
expected. However, we tell people not to override these methods, but to 
define the result of either by overriding Object.toString. No real clue 
there what to do if they should give different results. Moreover, we 
expose (the non-final) Java PyObject.__repr__ as Python object.__str__, 
and something we call object_toString as object.__repr__. The logic of 
this cross-wiring is not explained, except that there will be a stack 
overflow if you don't. But why is this the right way to solve that problem?

To me the obvious pattern is something like:

 1. __str__ calls final object___str__, which is exposed as object.__str__ .
 2. object___str__ calls __repr__
 3. __repr__ calls final object___repr__, which is exposed as
    object.__repr__ .
 4. toString calls __str__ and we discourage overriding it because
    that's what __str__ is for in Python objects.

Then in PyObjectDerived we do not override toString, but as normal all 
slot functions do their look-up for exposed versions and toString 
continues to call __str__. I think this defuses the stack overflow in a 
natural way, but if it doesn't, we look for some other solution than the 
one we have now.

I notice that in CPython, these slots are wrapped with a little more 
logic (e.g. 
https://github.com/python/cpython/blob/2.7/Objects/object.c#L453), 
whereas in Jython we tend to call __str__ and so on directly. This may 
also be part of the right solution for us: to be investigated.

Jeff

-- 
Jeff Allen
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.