Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

dataclasses.field does not preserve empty metadata object #80141

Closed
chrahunt mannequin opened this issue Feb 11, 2019 · 4 comments
Closed

dataclasses.field does not preserve empty metadata object #80141

chrahunt mannequin opened this issue Feb 11, 2019 · 4 comments
Assignees
Labels
3.7 (EOL) end of life 3.8 only security fixes stdlib Python modules in the Lib dir type-bug An unexpected behavior, bug, or error

Comments

@chrahunt
Copy link
Mannequin

chrahunt mannequin commented Feb 11, 2019

BPO 35960
Nosy @ericvsmith, @chrahunt
PRs
  • bpo-35960: Fix dataclasses.field throwing away empty metadata.  #11815
  • bpo-35960: Fix dataclasses.field throwing away empty metadata.  #11815
  • bpo-35960: Fix dataclasses.field throwing away empty metadata.  #11815
  • [3.7] bpo-35960: Fix dataclasses.field throwing away empty metadata. (GH-11815) #11826
  • Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.

    Show more details

    GitHub fields:

    assignee = 'https://github.com/ericvsmith'
    closed_at = <Date 2019-02-12.12:12:47.164>
    created_at = <Date 2019-02-11.01:06:54.108>
    labels = ['3.7', '3.8', 'type-bug', 'library']
    title = 'dataclasses.field does not preserve empty metadata object'
    updated_at = <Date 2019-02-12.12:12:47.163>
    user = 'https://github.com/chrahunt'

    bugs.python.org fields:

    activity = <Date 2019-02-12.12:12:47.163>
    actor = 'eric.smith'
    assignee = 'eric.smith'
    closed = True
    closed_date = <Date 2019-02-12.12:12:47.164>
    closer = 'eric.smith'
    components = ['Library (Lib)']
    creation = <Date 2019-02-11.01:06:54.108>
    creator = 'chrahunt'
    dependencies = []
    files = []
    hgrepos = []
    issue_num = 35960
    keywords = ['patch', 'patch', 'patch']
    message_count = 4.0
    messages = ['335184', '335296', '335297', '335298']
    nosy_count = 2.0
    nosy_names = ['eric.smith', 'chrahunt']
    pr_nums = ['11815', '11815', '11815', '11826']
    priority = 'normal'
    resolution = 'fixed'
    stage = 'resolved'
    status = 'closed'
    superseder = None
    type = 'behavior'
    url = 'https://bugs.python.org/issue35960'
    versions = ['Python 3.7', 'Python 3.8']

    @chrahunt
    Copy link
    Mannequin Author

    chrahunt mannequin commented Feb 11, 2019

    The metadata argument to dataclasses.field is not preserved in the resulting Field.metadata attribute if the argument is a mapping with length 0.

    The docs for dataclasses.field state:

    metadata: This can be a mapping or None. None is treated as an empty dict. This value is wrapped in MappingProxyType() to make it read-only, and exposed on the Field object.

    The docs for MappingProxyType() state:

    Read-only proxy of a mapping. It provides a dynamic view on the mapping’s entries, which means that when the mapping changes, the view reflects these changes.

    I assumed that the mapping provided could be updated after class initialization and the changes would reflect in the field's metadata attribute. Indeed this is the case when the mapping is non-empty, but not when the mapping is initially empty.

    For example:

        $ python
        Python 3.8.0a1+ (heads/master:9db56fb8fa, Feb 10 2019, 19:54:10)
        [GCC 7.3.0] on linux
        Type "help", "copyright", "credits" or "license" for more information.
        >>> from dataclasses import field
        >>> d = {}
        >>> v = field(metadata=d)
        >>> d['i'] = 1
        >>> v.metadata
        mappingproxy({})
        >>> v = field(metadata=d)
        >>> v.metadata
        mappingproxy({'i': 1})
        >>> d['j'] = 2
        >>> v.metadata
        mappingproxy({'i': 1, 'j': 2})

    In my case I have a LazyDict into which I was trying to save partial(callback, field). I could not have the field before it was initialized so I tried:

        d = {}
        member: T = field(metadata=d)
        d['key'] = partial(callback, field)

    and it failed same as above.

    As a workaround, one can set a dummy value in the mapping prior to calling dataclasses.field and then remove/overwrite it afterwards.

    @chrahunt chrahunt mannequin added 3.7 (EOL) end of life 3.8 only security fixes stdlib Python modules in the Lib dir type-bug An unexpected behavior, bug, or error labels Feb 11, 2019
    @ericvsmith ericvsmith self-assigned this Feb 11, 2019
    @ericvsmith
    Copy link
    Member

    New changeset b01786c by Eric V. Smith (Christopher Hunt) in branch 'master':
    bpo-35960: Fix dataclasses.field throwing away empty metadata. (GH-11815)
    b01786c

    @ericvsmith
    Copy link
    Member

    New changeset 0a834c1 by Eric V. Smith (Miss Islington (bot)) in branch '3.7':
    bpo-35960: Fix dataclasses.field throwing away empty metadata. (GH-11815) (GH-11826)
    0a834c1

    @ericvsmith
    Copy link
    Member

    Thanks for the patch!

    @ezio-melotti ezio-melotti transferred this issue from another repository Apr 10, 2022
    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
    Labels
    3.7 (EOL) end of life 3.8 only security fixes stdlib Python modules in the Lib dir type-bug An unexpected behavior, bug, or error
    Projects
    None yet
    Development

    No branches or pull requests

    1 participant