Irit Katriel <iritkatr...@yahoo.com> added the comment:

This issue only impacts container objects where  the len(repr(o)) is less than 
width. If the length is greater than width, containers are handled by a 
different code path which is covered by a unit test and works correctly.


For this case, indeed it works in Python 2 but not in Python 3. The 
PrettyPrinter._format code has been refactored quite a lot with respect to 
handling of containers.

In both Python 2 and 3 this happens:

PrettyPrinter.pprint([10]) calls
    PrettyPrinter._format([10])  which calls
            PrettyPrinter._repr([10]) which calls
                        MyPrettyPrinter.format([10]) which calls
                            PrettyPrinter.format([10]) which calls
                                    _safe_repr([10])  which calls
                                                _safe_repr(10)
                                                        returns 10
                                        returns [10]
                                returns [10]
                        returns [10]
                returns [10]

But then they diverge - in Python 3 the [10] is returned as the result, but in 
Python 2 there is another piece of code (starting here 
https://github.com/python/cpython/blob/fdda200195f9747e411d3491aae0806bc1fcd919/Lib/pprint.py#L179)
 which overrides this result and recalculates the representation for 
containers. In our case it does:

                since issubclass(type([10]), list):
                        # ignore the [10] calculated above, now call
                        self._format(10) which calls
                                PrettyPrinter._repr(10) which calls
                                        MyPrettyPrinter.format(10)
                                        returns 0xa
                                returns 0xa
                        returns 0xa
                returns [0xa]


This explains the difference between Python 2 and 3. 

As to why the first calculation returns [10] and not [0xa]:
This is because _safe_repr is defined at module scope, so once it is called we 
are no longer on the PrettyPrinter instance, and the format() override is no 
longer accessible.  When _safe_repr needs to recurse on container contents, it 
calls itself.


I think the solution is to make _safe_repr a method of PrettyPrinter, and make 
it call self.format() when it needs to recurse. The default self.format() just 
calls _safe_repr, so when there is no override the result is the same.

The PR's diff looks substantial, but that's mostly due to the indentation of 
_safe_repr code. To make it easier to review, I split it into several commits, 
where the indentation is done in one commit as a noop change. The other commits 
have much smaller diffs.

----------
versions: +Python 3.10, Python 3.8, Python 3.9 -Python 3.5, Python 3.6, Python 
3.7

_______________________________________
Python tracker <rep...@bugs.python.org>
<https://bugs.python.org/issue28850>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com

Reply via email to