classification
Title: Dataclasses: frozen should not be inherited for non-dataclass derived classes
Type: behavior Stage: resolved
Components: Library (Lib) Versions: Python 3.8, Python 3.7
process
Status: closed Resolution: fixed
Dependencies: Superseder:
Assigned To: eric.smith Nosy List: eric.smith, rhettinger
Priority: normal Keywords: patch

Created on 2018-02-25 22:23 by eric.smith, last changed 2018-03-19 01:04 by eric.smith. This issue is now closed.

Pull Requests
URL Status Linked Edit
PR 6147 merged eric.smith, 2018-03-18 21:29
PR 6148 merged miss-islington, 2018-03-19 00:41
Messages (5)
msg312866 - (view) Author: Eric V. Smith (eric.smith) * (Python committer) Date: 2018-02-25 22:23
Reported by Raymond Hettinger:

When working on the docs for dataclasses, something unexpected came up.  If a dataclass is specified to be frozen, that characteristic is inherited by subclasses which prevents them from assigning additional attributes:

    >>> @dataclass(frozen=True)
    class D:
            x: int = 10

    >>> class S(D):
            pass

    >>> s = S()
    >>> s.cached = True
    Traceback (most recent call last):
      File "<pyshell#49>", line 1, in <module>
        s.cached = True
      File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/dataclasses.py", line 448, in _frozen_setattr
        raise FrozenInstanceError(f'cannot assign to field {name!r}')
    dataclasses.FrozenInstanceError: cannot assign to field 'cached'

Other immutable classes in Python don't behave the same way:


    >>> class T(tuple):
            pass

    >>> t = T([10, 20, 30])
    >>> t.cached = True

    >>> class F(frozenset):
            pass

    >>> f = F([10, 20, 30])
    >>> f.cached = True

    >>> class B(bytes):
            pass

    >>> b = B()
    >>> b.cached = True


Raymond
msg312867 - (view) Author: Eric V. Smith (eric.smith) * (Python committer) Date: 2018-02-25 22:29
A related issue is that dataclasses derived from frozen dataclasses are automatically "promoted" to being frozen.

>>> @dataclass(frozen=True)
... class A:
...     i: int
...
>>> @dataclass
... class B(A):
...     j: int
...
>>> b = B(1, 2)
>>> b.j = 3
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\home\eric\local\python\cpython\lib\dataclasses.py", line 452, in _frozen_setattr
    raise FrozenInstanceError(f'cannot assign to field {name!r}')
dataclasses.FrozenInstanceError: cannot assign to field 'j'

If this can't be addressed before 3.7, maybe it should be an error to declare B as non-frozen and then we can properly fix it in a future release.
msg313075 - (view) Author: Eric V. Smith (eric.smith) * (Python committer) Date: 2018-02-28 23:22
See https://mail.python.org/pipermail/python-dev/2018-February/152320.html for a discussion.
msg314070 - (view) Author: Eric V. Smith (eric.smith) * (Python committer) Date: 2018-03-19 00:40
New changeset f199bc655eb50c28e94010714629b376bbbd077b by Eric V. Smith in branch 'master':
bpo-32953: Dataclasses: frozen should not be inherited for non-dataclass derived classes (#6147)
https://github.com/python/cpython/commit/f199bc655eb50c28e94010714629b376bbbd077b
msg314071 - (view) Author: Eric V. Smith (eric.smith) * (Python committer) Date: 2018-03-19 01:03
New changeset 45648312e540cda3b10109b6a808cbf6955c84eb by Eric V. Smith (Miss Islington (bot)) in branch '3.7':
bpo-32953: Dataclasses: frozen should not be inherited for non-dataclass derived classes (GH-6147) (GH-6148)
https://github.com/python/cpython/commit/45648312e540cda3b10109b6a808cbf6955c84eb
History
Date User Action Args
2018-03-19 01:04:16eric.smithsetstatus: open -> closed
resolution: fixed
stage: patch review -> resolved
2018-03-19 01:03:39eric.smithsetmessages: + msg314071
2018-03-19 00:41:52miss-islingtonsetpull_requests: + pull_request5906
2018-03-19 00:40:37eric.smithsetmessages: + msg314070
2018-03-18 21:29:19eric.smithsetkeywords: + patch
stage: patch review
pull_requests: + pull_request5905
2018-02-28 23:22:05eric.smithsetmessages: + msg313075
title: Dataclasses: frozen should not be inherited -> Dataclasses: frozen should not be inherited for non-dataclass derived classes
2018-02-25 22:29:23eric.smithsetmessages: + msg312867
2018-02-25 22:23:51eric.smithcreate