Opened 10 years ago
Closed 4 years ago
#26287 closed New feature (fixed)
SimpleLazyObject doesn't implement __radd__
| Reported by: | Keryn Knight | Owned by: | Theofilos Alexiou |
|---|---|---|---|
| Component: | Utilities | Version: | dev |
| Severity: | Normal | Keywords: | |
| Cc: | django@…, debanshuk2007@… | Triage Stage: | Ready for checkin |
| Has patch: | yes | 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 (11)
comment:1 by , 10 years ago
follow-up: 4 comment:2 by , 10 years ago
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 by , 10 years ago
| Triage Stage: | Unreviewed → Accepted |
|---|
Seems okay, although I'm not an expert on the SimpleLazyObject class.
comment:4 by , 10 years ago
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 by , 9 years ago
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 by , 9 years ago
| Cc: | added |
|---|
comment:7 by , 4 years ago
| Owner: | changed from to |
|---|---|
| Status: | new → assigned |
comment:8 by , 4 years ago
| Has patch: | set |
|---|---|
| Triage Stage: | Accepted → Ready for checkin |
PR here: https://github.com/django/django/pull/15400. Tried the suggestion by @Debanshu Kundu and it seems to work.
comment:9 by , 4 years ago
| Triage Stage: | Ready for checkin → Accepted |
|---|
RFC should be set by reviewer, see docs.
comment:10 by , 4 years ago
| Triage Stage: | Accepted → Ready for checkin |
|---|
Could you please give some sample code with your use case?