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

patch does not correctly restore state on objects without __dict__ #126886

Open
c00w opened this issue Nov 15, 2024 · 5 comments
Open

patch does not correctly restore state on objects without __dict__ #126886

c00w opened this issue Nov 15, 2024 · 5 comments
Labels
stdlib Python modules in the Lib dir type-bug An unexpected behavior, bug, or error

Comments

@c00w
Copy link

c00w commented Nov 15, 2024

Bug report

Bug description:

from unittest.mock import patch
class Proxy(object):
    config = {}
    def __getattr__(self, name):
        return self.config[name]
    def __setattr__(self, name, value):
        if name == 'config':
            object.__setattr__(self, name, value)
            return
        self.config[name] = value
    def __delattr__(self, name):
        self.config[name] = 'DEFAULT'

p = Proxy()
p.a = True
print(p.a)
with patch('__main__.p.a', False):
    print(p.a)
print(p.a)

Expected

True
False
True

Actual

True
False
DEFAULT

Note that this is a relatively niche issue, but for example in a config system (i.e. pytorch/pytorch#140779), if you don't want to have a delete work, (i.e. have it set it back to a default value), the code in

if not self.create and (not hasattr(self.target, self.attribute) or
will call delattr, and then not call setattr, because it still has the attr.

Possible fixes:
If delattr throws (maybe NotImplementederror), call setattr instead (this is nice and explicit + removes the hacky workaround I have to do).

If the value after it's been deleted doesn't equal the original value, reassign it? (this might require objects to be comparable, not sure if that is already an issue here).

Either way I wanted to see if there was any interest in fixing this, and if anyone saw a solution that seemed reasonable enough.

CPython versions tested on:

3.12

Operating systems tested on:

Linux

@c00w c00w added the type-bug An unexpected behavior, bug, or error label Nov 15, 2024
@bhagwant4040

This comment was marked as off-topic.

@c00w
Copy link
Author

c00w commented Nov 15, 2024

Except we're not a proxy class. In particular it makes no logical sense to delete these configs. Making delattr throw on all calls probably makes more sense for the usecase, then defining it to either reset to default, or to allow deletion.

@picnixz picnixz added the stdlib Python modules in the Lib dir label Nov 15, 2024
@ZeroIntensity
Copy link
Member

@bhagwant4040 Don't use LLMs to help with issues--they're not particularly helpful. If you want to help triage issues, see the devguide :)

@c00w
Copy link
Author

c00w commented Nov 19, 2024

@picnixz - No pressure, but curious if patches would be welcome here, or if the risk of breakage is high enough that pateches are unlikely to be accepted :).

@picnixz
Copy link
Contributor

picnixz commented Nov 27, 2024

The issue I see here is that the object being patched has custom special setters and deleters.

The current library seems to special case some attributes so it's already a bit fragile. Ideally I would also have expected the original value to be set (via some setattr, possibly suppressing AttributeError raised by custom setattr) but this may break some code out there though I don't know how much.

I think users expect the patch to restore the old value even if you have custom __delattr__. But I don't have an immediate and generic fix for this one. There are many other cases where you create dictlike objects for configuration with default values.

By the way, from a OOP PoV, I wouldn't have changed __delattr__ but rather returned DEFAULT in __getattr__ instead. I don't think __delattr__ should be responsible for setting a default value but that is a matter of personal taste.

Now, before opening a PR, I think this should be discussed on https://discuss.python.org/c/ideas/6.

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
Status: Todo
Development

No branches or pull requests

4 participants