Opened 2 years ago

Last modified 2 years ago

#26287 new New feature

SimpleLazyObject doesn't implement __radd__

Reported by: Keryn Knight Owned by: nobody
Component: Utilities Version: master
Severity: Normal Keywords:
Cc: django@…, debanshuk2007@… Triage Stage: Accepted
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

Technically, there's a whole bunch of magic methods it doesn't implement, compared to a complete proxy implementation, like that of wrapt.ObjectProxy, but __radd__ being missing is the one that's biting me at the moment.

As far as I can tell, the implementation can't just be

__radd__ = new_method_proxy(operator.radd)

because that doesn't exist, which is rubbish.

__radd__ = new_method_proxy(operator.attrgetter("__radd__"))

also won't work because types may not have that attr, and attrgetter doesn't supress the exception (correctly)

The minimal implementation I've found that works for me is:

    def __radd__(self, other):
        if self._wrapped is empty:
            self._setup()
        return other + self._wrapped

Change History (6)

comment:1 Changed 2 years ago by Tim Graham

Could you please give some sample code with your use case?

comment:2 Changed 2 years ago by Keryn Knight

In a boiled-down nutshell:

def lazy_consumer():
    # something more complex, obviously.
    return [1, 3, 5]
consumer = SimpleLazyObject(lazy_consumer)

# inside third party code ...
def some_func(param):
    third_party_code = [...]
    # then, through parameter passing, my value is provided to be used.
    # param is at  this point, `consumer`
    third_party_code_plus_mine = third_party_code + param

which ultimately yields:

TypeError: unsupported operand type(s) for +: 'list' and 'SimpleLazyObject'

comment:3 Changed 2 years ago by Tim Graham

Triage Stage: UnreviewedAccepted

Seems okay, although I'm not an expert on the SimpleLazyObject class.

comment:4 in reply to:  2 Changed 2 years ago by Attila Tovt

Replying to kezabelle:

def lazy_consumer():
    # something more complex, obviously.
    return [1, 3, 5]
consumer = SimpleLazyObject(lazy_consumer)

If you know what is the resulting type or possible resulting types of your expression, I think you better use django.utils.functional.lazy which will provide all the necessary methods.

comment:5 in reply to:  description Changed 2 years ago by Debanshu Kundu

Replying to kezabelle:

As far as I can tell, the implementation can't just be

__radd__ = new_method_proxy(operator.radd)

because that doesn't exist, which is rubbish.

__radd__ = new_method_proxy(operator.attrgetter("__radd__"))

also won't work because types may not have that attr, and attrgetter doesn't supress the exception (correctly)

Wouldn't the following code work?

    __add__ = new_method_proxy(operator.add)
    __radd__ = new_method_proxy(lambda a, b: operator.add(b, a))

I have tested this and it seems to work as excepted.

comment:6 Changed 2 years ago by Debanshu Kundu

Cc: debanshuk2007@… added
Note: See TracTickets for help on using tickets.
Back to Top