This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Author taleinat
Recipients epaine, gpolo, serhiy.storchaka, taleinat
Date 2020-09-28.08:14:05
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1601280847.44.0.93197701009.issue41851@roundup.psfhosted.org>
In-reply-to
Content
> > I also think using [.equal] wouldn't add anything

> I disagree and will stand by this one!

Please do note that the full quote was "I also think using it wouldn't add anything, and would be less clear, compared to font1.actual() == font2.actual()".

> I think it would be helpful to have a convenience method to check if two fonts represent the same thing that is displayed to the user.

More convenient than font1.actual() == font2.actual() ?

Since this will be used rather rarely, IMO the more significant problem is discoverability - I've done a *lot* of work with Tkinter and had never heard of the .actual() method. However, adding another comparison method won't help with that by itself.

> I am reluctant to touch __eq__. Any ideas?

You wrote that "Checking to see if the fonts are the same Tk object is also very helpful (in other, granted fewer, contexts)": Could you elaborate on that?

I still think we should consider overriding __eq__. But I need to check how consistent Tktinter is regarding __eq__ checking whether two objects have the same name.


[goes to check the docs, code, and do some interactive investigation...]


Okay, so the Font class's .name attribute is just a name the user gives to a certain font configuration, which is supposed to be unique. Our docs are pretty clear about this:

"The Font class represents a named font. Font instances are given unique names and can be specified by their family, size, and style configuration. Named fonts are Tk's method of creating and identifying fonts as a single object, rather than specifying a font by its attributes with each occurrence." So in this case, tkinter is letting a particularly confusing Tk detail show through.

Note that providing a name isn't required, and how confusing the result is when not providing font names:

>>> Font(family='DejaVu Sans', size=12) == Font(family='DejaVu Sans', size=12)
False

Also, if you happen to try to create a font with a name which has already been used:

>>> Font(name='default font', family='DejaVu Sans', size=12)
<tkinter.font.Font object at 0x7f96ebbf5e60>
>>> Font(name='default font', family='DejaVu Sans', size=12)
Traceback [...]
_tkinter.TclError: named font "default font" already exists

One can avoid this error by passing exists=True, but using that when the font doesn't exist raises an exception:

>>> Font(name='other font', family='DejaVu Sans', size=10, exists=True)
Traceback [...]
_tkinter.TclError: named font other font does not already exist


My point is: Using named fonts in tkinter seems incredibly annoying. Using fonts without names seems to work better. But without using names, font comparison is meaningless.

It seems to me that we could change __eq__ to:
1. Keep the current behavior if both font objects have explicitly set names or if their automatically generated names are equal (i.e. `self is other`).
2. Otherwise, compare the the results of calling their .actual() methods.

This would require adding a simple internal flag in __init__ to remember whether the name was set explicitly, since __init__ sets a unique name if not provided with one.



P.S. The "name" constructor parameter is confusing! Here even Terry J. Reedy got it wrong in IDLE font configuration dialog's code:
https://github.com/python/cpython/blob/d9ab95ff1fe81efdf70e545d536d9f6927d1ba81/Lib/idlelib/config.py#L745)
History
Date User Action Args
2020-09-28 08:14:07taleinatsetrecipients: + taleinat, gpolo, serhiy.storchaka, epaine
2020-09-28 08:14:07taleinatsetmessageid: <1601280847.44.0.93197701009.issue41851@roundup.psfhosted.org>
2020-09-28 08:14:07taleinatlinkissue41851 messages
2020-09-28 08:14:05taleinatcreate