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.

Created on 2018-02-24 01:44 by eric.smith, last changed 2022-04-11 14:58 by admin. This issue is now closed.

Pull Requests
URL Status Linked Edit
PR 5891 merged eric.smith, 2018-02-25 18:51
PR 5902 merged miss-islington, 2018-02-26 02:31
Messages (14)
msg312686 - (view) Author: Eric V. Smith (eric.smith) * (Python committer) Date: 2018-02-24 01:44
See https://mail.python.org/pipermail/python-dev/2018-February/152150.html for a discussion. This will remove the @dataclass hash= tri-state parameter, and replace it with an unsafe_hash= boolean-only parameter. From that thread: """ I propose that with @dataclass(unsafe_hash=False) (the default), a __hash__ method is added when the following conditions are true: - frozen=True (not the default) - compare=True (the default) - no __hash__ method is defined in the class If we instead use @dataclass(unsafe_hash=True), a __hash__ will be added regardless of the other flags, but if a __hash__ method is present, an exception is raised. Other values (e.g. unsafe_hash=None) are illegal for this flag. """
msg312688 - (view) Author: Steven D'Aprano (steven.daprano) * (Python committer) Date: 2018-02-24 02:10
This is a truly awful name, there's nothing unsafe about the hash parameter. We rightly hesitate to label *actual* unsafe functions, like eval and exec, with that name. Are we committed to this name?
msg312702 - (view) Author: Eric V. Smith (eric.smith) * (Python committer) Date: 2018-02-24 07:27
That's a quote from Guido. There weren't any better ideas on the python-dev thread.
msg312729 - (view) Author: Guido van Rossum (gvanrossum) * (Python committer) Date: 2018-02-24 16:04
It is important to convey the idea that if you are thinking of using this you are probably doing something fishy. An alternative could be `_hash`, which at least indicates it is not for general use, like `sys._getframe()`.
msg312738 - (view) Author: Eric V. Smith (eric.smith) * (Python committer) Date: 2018-02-24 17:54
Note that this class (from the test suite) will now raise an exception: @dataclass(unsafe_hash=True) class C: i: int def __eq__(self, other): return self.i == other.i That's because it has a __hash__, added when __eq__ is defined. I think we're better off with the rule being: If unsafe_hash=True, raise an exception if __hash__ exists and is not None. Otherwise add __hash__. That's how it used to be with hash=True (in 3.70b1). Or is that what you meant by "but if a __hash__ method is present, an exception is raised"? Notice the word "method", instead of attribute.
msg312763 - (view) Author: Guido van Rossum (gvanrossum) * (Python committer) Date: 2018-02-24 22:26
Sorry, I used imprecise language. What you propose is fine. On Feb 24, 2018 09:54, "Eric V. Smith" <report@bugs.python.org> wrote: > > Eric V. Smith <eric@trueblade.com> added the comment: > > Note that this class (from the test suite) will now raise an exception: > > @dataclass(unsafe_hash=True) > class C: > i: int > def __eq__(self, other): > return self.i == other.i > > That's because it has a __hash__, added when __eq__ is defined. I think > we're better off with the rule being: > > If unsafe_hash=True, raise an exception if __hash__ exists and is not > None. Otherwise add __hash__. > > That's how it used to be with hash=True (in 3.70b1). > > Or is that what you meant by "but if a __hash__ method is present, an > exception is raised"? Notice the word "method", instead of attribute. > > ---------- > > _______________________________________ > Python tracker <report@bugs.python.org> > <https://bugs.python.org/issue32929> > _______________________________________ >
msg312825 - (view) Author: Eric V. Smith (eric.smith) * (Python committer) Date: 2018-02-25 17:25
Here's the simplest way I can describe this, and it's also the table used inside the code. The column "has-explicit-hash?" is trying to answer the question "is there a __hash__ function defined in this class?". It is set to False if either __hash__ is missing, or if __hash__ is None and there's an __eq__ function. I'm assuming that the __hash__ is implicit in the latter case. # Decide if/how we're going to create a hash function. Key is # (unsafe_hash, eq, frozen, does-hash-exist). Value is the action to # take. # Actions: # '': Do nothing. # 'none': Set __hash__ to None. # 'add': Always add a generated __hash__function. # 'exception': Raise an exception. # # +-------------------------------------- unsafe_hash? # | +------------------------------- eq? # | | +------------------------ frozen? # | | | +---------------- has-explicit-hash? # | | | | # | | | | +------- action # | | | | | # v v v v v _hash_action = {(False, False, False, False): (''), (False, False, False, True ): (''), (False, False, True, False): (''), (False, False, True, True ): (''), (False, True, False, False): ('none'), (False, True, False, True ): (''), (False, True, True, False): ('add'), (False, True, True, True ): (''), (True, False, False, False): ('add'), (True, False, False, True ): ('exception'), (True, False, True, False): ('add'), (True, False, True, True ): ('exception'), (True, True, False, False): ('add'), (True, True, False, True ): ('exception'), (True, True, True, False): ('add'), (True, True, True, True ): ('exception'), } PR will be ready as soon as I clean a few things up.
msg312827 - (view) Author: Guido van Rossum (gvanrossum) * (Python committer) Date: 2018-02-25 17:31
I don't know if I'm unique, but I find such a table with 4 Boolean keys hard to understand. I'd rather see it written up as a series of nested 'if' statements.
msg312829 - (view) Author: Eric V. Smith (eric.smith) * (Python committer) Date: 2018-02-25 18:01
if unsafe_hash: # If there's already a __hash__, raise TypeError, otherwise add __hash__. if has_explicit_hash: hash_action = 'exception' else: hash_action = 'add' else: # unsafe_hash is False (the default). if has_explicit_hash: # There's already a __hash__, don't overwrite it. hash_action = '' else: if eq and frozen: # It's frozen and we added __eq__, generate __hash__. hash_action = 'add' elif eq and not frozen: # It's not frozen but has __eq__, make it unhashable. # This is the default if no params to @dataclass. hash_action = 'none' else: # There's no __eq__, use the base class __hash__. hash_action = ''
msg312834 - (view) Author: Eric V. Smith (eric.smith) * (Python committer) Date: 2018-02-25 18:57
I've been focused on getting the code fix in for the next beta release on 2018-02-26, and leaving the possible parameter name change for later. I don't feel strongly about the parameter name. Right now it's unsafe_hash, per Guido's original proposal.
msg312871 - (view) Author: Guido van Rossum (gvanrossum) * (Python committer) Date: 2018-02-26 01:29
@steven.daprano the name was +1'ed by many people in the python-dev discussion as sending the right message. So I'm reluctant to change it. If you can cause a landslide of support for `_hash` there we can change it in b3.
msg312872 - (view) Author: Eric V. Smith (eric.smith) * (Python committer) Date: 2018-02-26 02:30
 New changeset dbf9cff48a4ad0fd58e1c623ce1f36c3dd3d5f38 by Eric V. Smith in branch 'master': bpo-32929: Dataclasses: Change the tri-state hash parameter to the boolean unsafe_hash. (#5891) https://github.com/python/cpython/commit/dbf9cff48a4ad0fd58e1c623ce1f36c3dd3d5f38 
msg312873 - (view) Author: Eric V. Smith (eric.smith) * (Python committer) Date: 2018-02-26 02:33
I'm going to close this. Steven: if you gain support for a parameter name change, please open another issue.
msg312905 - (view) Author: Eric V. Smith (eric.smith) * (Python committer) Date: 2018-02-26 09:43
 New changeset 4cffe2f66b581fa7538f6de884d54a5c7364d8e0 by Eric V. Smith (Miss Islington (bot)) in branch '3.7': bpo-32929: Dataclasses: Change the tri-state hash parameter to the boolean unsafe_hash. (GH-5891) (GH-5902) https://github.com/python/cpython/commit/4cffe2f66b581fa7538f6de884d54a5c7364d8e0 
History
Date User Action Args
2022-04-11 14:58:58adminsetgithub: 77110
2018-02-26 09:43:44eric.smithsetmessages: + msg312905
2018-02-26 02:33:23eric.smithsetstatus: open -> closed
priority: release blocker -> normal
versions: + Python 3.8
messages: + msg312873

resolution: fixed
stage: patch review -> resolved
2018-02-26 02:31:35miss-islingtonsetpull_requests: + pull_request5672
2018-02-26 02:30:20eric.smithsetmessages: + msg312872
2018-02-26 01:29:43gvanrossumsetmessages: + msg312871
2018-02-25 18:57:52eric.smithsetmessages: + msg312834
2018-02-25 18:51:02eric.smithsetkeywords: + patch
stage: patch review
pull_requests: + pull_request5663
2018-02-25 18:01:09eric.smithsetmessages: + msg312829
2018-02-25 17:31:01gvanrossumsetmessages: + msg312827
2018-02-25 17:25:57eric.smithsetmessages: + msg312825
2018-02-24 22:26:57gvanrossumsetmessages: + msg312763
2018-02-24 17:54:31eric.smithsetmessages: + msg312738
2018-02-24 16:04:09gvanrossumsetmessages: + msg312729
2018-02-24 07:27:29eric.smithsetnosy: + gvanrossum
messages: + msg312702
2018-02-24 02:10:55steven.dapranosetnosy: + steven.daprano
messages: + msg312688
2018-02-24 01:44:53eric.smithcreate