![](https://secure.gravatar.com/avatar/de311342220232e618cb27c9936ab9bf.jpg?s=120&d=mm&r=g)
On 03/27/2020 05:21 PM, Ivan Pozdeev via Python-Dev wrote:
On 26.03.2020 19:24, Ethan Furman wrote:
On 03/25/2020 06:53 PM, Ivan Pozdeev via Python-Dev wrote:
A diagnostic is always done by the same algorithm:
1) Identify the exact place in code where the problem manifests itself 2) Examine the state of the program at that moment to find out which if the values are wrong 3) Track the wrong value back to its origin
Seeing an accurate repr() is required for step 2) -- to immediately detect if it's wrong or not.
Before Enum, the repr for socket.AF_UNIX was:
1
Not very useful for debugging.
On the contrary, it's perfect. I know everything I need: it's an integer constant, end of story.
So if it was a 3 you'd still be happy? 1 vs 3 gives you no information as to what the value should be, while blahblah.AF_UNIX vs blahblah.AF_AX25 could point out that that is the wrong value for the function you found it in.
When examining some live object, I would probably see that "1" and won't even need to look anything up to know what I'm dealing with.
If all you care about is the value, then blahblah.AF_UNIX isn't going to hurt you because the repr() displays it: <socket.AF_UNIX: 1>. Hopefully that's immediately recognizable as an Enum, and a `type()` or `isinstance()` will tell you if it's also an `int`. [...]
I would rather search for "AddressFamily" (case-sensitive), and in the entire codebase, not just "*.py".
Yeah, looks like I messed up that example -- I must have switched directories in between the two. The actual results for my simple grep: $ grep AddressFamily *.py socket.py: "has_dualstack_ipv6", "AddressFamily", "SocketKind"] socket.py: 'AddressFamily', socket.py: return _intenum_converter(super().family, AddressFamily) socket.py: addrlist.append((_intenum_converter(af, AddressFamily), So, more useful for finding the source, still not useful for finding other uses.
Long story short, this is a type name and looks like a very distinctive one.
Yup, it's an Enum.
So that search is very likely going to readily find me anything directly related to that type, including its definition, with negligible noise -- however and wherever it's done.
Well, there are less than two dozen lines using your search, but the definition location is non-obvious -- all you see is `AddressFamily` Still, it's something.
I hope this serves as yet another demonstration why knowing the exact type is so crucial.
Not so much in this case -- if it says <socket.AF_UNIX: 1>, then hopefully it's not a far stretch to look in the socket module.
--> help(socket.AF_UNIX) Help on AddressFamily in module socket object:
class AddressFamily(enum.IntEnum) | AddressFamily(value, names=None, *, module=None, qualname=None, type=None, start=1) | | An enumeration. | | ...
Examining repr() of a large number of objects (think dozens to hundreds) vs help() of each of them? I think we have a winner...
Well, the repr in question, whether `socket.*` or `AddressFamily.*`, is still distinctive and still contains the value, the thing you are saying you want.
And help() doesn't even show the value!
I had snipped the output for brevity. Here's the whole thing: Help on AddressFamily in module socket object: class AddressFamily(enum.IntEnum) | AddressFamily(value, names=None, *, module=None, qualname=None, type=None, start=1) | | An enumeration. | | Method resolution order: | AddressFamily | enum.IntEnum | builtins.int | enum.Enum | builtins.object | | Data and other attributes defined here: | | AF_ALG = <socket.AF_ALG: 38> | | AF_APPLETALK = <socket.AF_APPLETALK: 5> | | AF_ASH = <socket.AF_ASH: 18> | | AF_ATMPVC = <socket.AF_ATMPVC: 8> | | AF_ATMSVC = <socket.AF_ATMSVC: 20> | | AF_AX25 = <socket.AF_AX25: 3> | | AF_BLUETOOTH = <socket.AF_BLUETOOTH: 31> | | AF_BRIDGE = <socket.AF_BRIDGE: 7> | | AF_CAN = <socket.AF_CAN: 29> | | AF_ECONET = <socket.AF_ECONET: 19> | | AF_INET = <socket.AF_INET: 2> | | AF_INET6 = <socket.AF_INET6: 10> | | AF_IPX = <socket.AF_IPX: 4> | | AF_IRDA = <socket.AF_IRDA: 23> | | AF_KEY = <socket.AF_KEY: 15> | | AF_LLC = <socket.AF_LLC: 26> | | AF_NETBEUI = <socket.AF_NETBEUI: 13> | | AF_NETLINK = <socket.AF_NETLINK: 16> | | AF_NETROM = <socket.AF_NETROM: 6> | | AF_PACKET = <socket.AF_PACKET: 17> | | AF_PPPOX = <socket.AF_PPPOX: 24> | | AF_QIPCRTR = <socket.AF_QIPCRTR: 42> | | AF_RDS = <socket.AF_RDS: 21> | | AF_ROSE = <socket.AF_ROSE: 11> | | AF_SECURITY = <socket.AF_SECURITY: 14> | | AF_SNA = <socket.AF_SNA: 22> | | AF_TIPC = <socket.AF_TIPC: 30> | | AF_UNIX = <socket.AF_UNIX: 1> | | AF_UNSPEC = <socket.AF_UNSPEC: 0> | | AF_VSOCK = <socket.AF_VSOCK: 40> | | AF_WANPIPE = <socket.AF_WANPIPE: 25> | | AF_X25 = <socket.AF_X25: 9> | | ---------------------------------------------------------------------- | Data descriptors inherited from enum.Enum: | | name | The name of the Enum member. | | value | The value of the Enum member. | | ---------------------------------------------------------------------- | Readonly properties inherited from enum.EnumMeta: | | __members__ | Returns a mapping of member name->value. | | This mapping lists all enum members, including aliases. Note that this | is a read-only view of the internal mapping. You'll note that all the members, and their values, are listed. (They say `socket` instead of `AddressFamily` as I was testing the change.)
You can't be serious suggesting me to do all this extra work (i.e. single-handedly increase diagnostic's labor intensity about 5x -- while problem diagnostic is a key activity during both development and ongoing use) just because someone wishes to playfully ignore an established standard specifically invented to make it unnecessary.
module.function module.class module.attribute are all common access patterns. It should not be a far stretch to see <socket.AF_UNIX: 1> and think to look in the socket module.
Pardon me if I misunderstood you, but I also find the offhand remarks: "adding this and that to your debugging list would also be, um, helpful" -- highly condescending and insulting and showing that you probably don't do much problem diagnostic and don't care at all about anyone who does -- i.e. about software developers and maintainers, your core audience.
I was trying to be humorous -- my apologies. In fact, a large portion of my time is spent debugging. I also recognize Enums when I see them, so they aren't big mysteries to me -- admittedly, I am probably more familiar with Enums and their repr()s than most, but hopefully once you know what they look like they're easy to spot.
All the while yourself being a Python core developer (if your StackOverflow profile is to be believed) -- a spokesperson for the dev team and a shining example of what every Python developer should strive to be.
Well, yes to my Stackoverflow profile being correct, no, I was not made a spokesperson (my opinions are not necessarily shared by any other core developer, nor by the PSF), and do you expect every developer of every open source project to be "shining examples"? Hopefully you were just frustrated, and not serious.
If this is any representation of the prevalent attitude in the core team now, I'm probably wasting my time arguing here as well as supporting Python in general since our values clearly don't match anymore.
Well, my attitude is "ask on python-dev to get wide exposure and feedback to proposed changes since bugs on bpo are not widely seen."
As a reminder, the change under discussion only affects enums created from globally unique constants using the Enum._convert helper utility.
I know. But it sets a precedent of screwing users over with poorly thought cosmetic changes done without thinking of them.
That's offensive. I started this thread precisely because I'm thinking of them. -- ~Ethan~