Add __repr__ for QColor?

RoadrunnerWMC roadrunnerwmc at gmail.com
Wed Apr 5 02:17:57 BST 2023


For what it's worth, I'd also like this. The core geometry classes (QPoint,
QRect, QLine, etc. and their float versions) have custom reprs, and I've
definitely been bitten by wrongly assuming that QColor has one when
debugging in the past.

That said, it should use the same syntax as those other classes, instead of
what QGIS's monkeypatch does:

>>> from PyQt6 import QtCore, QtGui, QtWidgets
> >>> app = QtWidgets.QApplication([])
> >>>
> >>> QtCore.QPoint(1, 2)
> PyQt6.QtCore.QPoint(1, 2)
> >>> QtCore.QRectF(1, 2, 3, 4)
> PyQt6.QtCore.QRectF(1.0, 2.0, 3.0, 4.0)
> >>>
> >>> QtGui.QColor(1, 2, 3, 4)

<PyQt6.QtGui.QColor object at 0x7fad4120b840>

>>>

>>> # Showing *hypothetical* new QColor reprs from here on.

>>>

>>> QtGui.QColor(1, 2, 3, 4)
> PyQt6.QtGui.QColor(1, 2, 3, 4)
> >>> # since alpha defaults to 255, perhaps it could be omitted if it has
> that value:
> >>> QtGui.QColor(1, 2, 3, 255)
> PyQt6.QtGui.QColor(1, 2, 3)


Returning "a string that would yield an object with the same value when
passed to eval()" is good style
<https://docs.python.org/3/library/functions.html#repr>, so this output
format makes sense.

There's a problem, though: showing the components as 8-bit integers would
be misleading, since QColor uses higher precision (16-bit integers)
internally:

>>> QtGui.QColor.fromRgbF(0.5, 0.5, 0.5)
> PyQt6.QtGui.QColor(128, 128, 128)
> >>> QtGui.QColor.fromRgbF(0.5, 0.5, 0.501)
> PyQt6.QtGui.QColor(128, 128, 128)
> >>> QtGui.QColor.fromRgbF(0.5, 0.5, 0.5) == QtGui.QColor.fromRgbF(0.5,
> 0.5, 0.5)
> True
> >>> QtGui.QColor.fromRgbF(0.5, 0.5, 0.5) == QtGui.QColor.fromRgbF(0.5,
> 0.5, 0.501)
> False


As a debugging aid, this would arguably be worse than no repr at all, in
some cases.

The float constructor lets you specify more accurate values, but since the
components aren't *stored* as floats, the rounding makes it kind of gross:

>>> QtGui.QColor.fromRgbF(0.5, 0.5, 0.501)
> PyQt6.QtGui.QColor.fromRgbF(0.5000076293945312, 0.5000076293945312,
> 0.5009994506835938)
>

You could use the constructor that takes 16-bit integers:

>>> QtGui.QColor.fromRgbF(0.5, 0.5, 0.501)
> PyQt6.QtGui.QColor.fromRgba64(32768, 32768, 32833)


But that's kind of hard to read at a glance, which is not great given that
this is supposed to help with debugging.

I think what I'd do, personally, is have it dynamically choose which way to
repr itself based on whether all the channels match what Qt would choose
for 8-bit input values (aka channel * 0x101):

>>> QtGui.QColor.fromRgba64(32382, 32639, 32896)
> PyQt6.QtGui.QColor(126, 127, 128)
> >>> QtGui.QColor.fromRgba64(32382, 32639, 32897)
> PyQt6.QtGui.QColor.fromRgba64(32382, 32639, 32897)


Shrug. Just my two cents, I guess :)

On Tue, Apr 4, 2023 at 5:40 PM Nyall Dawson <nyall.dawson at gmail.com> wrote:

> Hi list!
>
> I'm wondering if it would be possible to add a __repr__ for the QColor
> class. PyQt doesn't set one itself, but it's VERY useful for debugging
> purposes.
>
> Downstream we patch one in using this approach:
>
> https://github.com/qgis/QGIS/blob/574d1ea47b921ff9733f75b577e38034bae74793/python/PyQt/PyQt5/QtGui.py#L27
>
> Would you consider adding a similar repr to PyQt itself?
>
> Many thanks!
> Nyall
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://www.riverbankcomputing.com/pipermail/pyqt/attachments/20230404/a4283d75/attachment.htm>


More information about the PyQt mailing list