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

UserDict __getitem__ behavior change between 3.11.1 and 3.12.0b2 #105524

Open
stefanv opened this issue Jun 8, 2023 · 4 comments
Open

UserDict __getitem__ behavior change between 3.11.1 and 3.12.0b2 #105524

stefanv opened this issue Jun 8, 2023 · 4 comments
Assignees
Labels
stdlib Python modules in the Lib dir type-bug An unexpected behavior, bug, or error

Comments

@stefanv
Copy link

stefanv commented Jun 8, 2023

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.

@stefanv stefanv added the type-bug An unexpected behavior, bug, or error label Jun 8, 2023
@Eclips4
Copy link
Member

Eclips4 commented Jun 8, 2023

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

@Eclips4
Copy link
Member

Eclips4 commented Jun 8, 2023

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.

@AlexWaygood AlexWaygood added the stdlib Python modules in the Lib dir label Jun 8, 2023
@stefanv
Copy link
Author

stefanv commented Jun 28, 2023

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.

@dholth
Copy link
Contributor

dholth commented Dec 11, 2023

This also affects me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
stdlib Python modules in the Lib dir type-bug An unexpected behavior, bug, or error
Projects
None yet
Development

No branches or pull requests

5 participants