FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

UserDict `__getitem__` behavior change between 3.11.1 and 3.12.0b2 · Issue #105524 · python/cpython · GitHub

Repository navigation

UserDict __getitem__ behavior change between 3.11.1 and 3.12.0b2 #105524

Open

Description

I define the following UserDict, that implements nested lookups (d['key.subkey']):

import collections

class DotDict(collections.UserDict):
    def __getitem__(self, key):
        subitem = self.data
        for subkey in key.split("."):
            try:
                subitem = subitem[subkey]
            except KeyError:
                raise KeyError(f"`{key}` not found in configuration") from None
        return subitem

I expect the following to work as it did in Python 3.11, but it does not:

d = DotDict({'one': {'two': 'buckle my shoe'}})
d['one.two']   # works
d.get('one.two')  # does not work

I do not see any release notes indicating that __getitem__ is no longer the correct method to override.

Activity

  1. added
    type-bugAn unexpected behavior, bug, or error
    on Jun 8, 2023
  2. Eclips4 commented on Jun 8, 2023

    Member

    This also reproduced on the current main.
    Seems that in 3.12 and newer versions __getitem__ isn't called in .get

  3. Eclips4 commented on Jun 8, 2023

    Member

    Also, if you define a __contains__ with the same behavior, it will work on 3.12.

    Introduced in #17910
    After some research of this issue, I came to the conclusion that the best solution here would be to add documentation of that.

  4. added
    stdlibStandard Library Python modules in the Lib/ directory
    on Jun 8, 2023
  5. stefanv commented on Jun 28, 2023

    Author

    IUUC, the proposed fix is to change the implementation to the following:

    import collections
    
    class DotDict(collections.UserDict):
        def __getitem__(self, key):
            subitem = self.data
            for subkey in key.split("."):
                try:
                    subitem = subitem[subkey]
                except KeyError:
                    raise KeyError(f"`{key}` not found in configuration") from None
            return subitem
    
        def __contains__(self, key):
            subitem = self.data
            for subkey in key.split("."):
                try:
                    subitem = subitem[subkey]
                except KeyError:
                    return False
            return True

    Not ideal, but it works.

  6. dholth commented on Dec 11, 2023

    Contributor

    This also affects me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

stdlibStandard Library Python modules in the Lib/ directorytype-bugAn unexpected behavior, bug, or error

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions


    Back | FazBrowse Home | New Git URL