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
reversed() does not work with weakref.proxy of sequences #63558
Comments
When passed a weakref.proxy to a legitimate sequence, reversed() throws a TypeError complaining that its argument isn't a sequence. Perhaps this is the expected behavior, but it's surprising to at least me and the few others I've spoken with about it. |
Attached an attemptive patch. |
Thanks for looking at this. Putting in a special case for weak references isn't the way to go. The problem is that _PyObject_LookupSpecial isn't working well with weakref proxies. A solution for reversed() could be to replace The unfortunate downside is that this would slow down the common cases. Another solution is to patch _PyObject_LookupSpecial to make it smarter with respect to weakref objects or possibly use a fallback to PyObject_GetAttrString when a method isn't found using the speedy lookup. The advantage of fixing _PyObject_LookupSpecial is that it fixes all uses of _PyObject_LookupSpecial not just reversed(). Also, it would keep the current speed benefit for the common case. I'm reassigning to Benjamin because it was his optimized that broke the ability to find the __reversed__ method on a proxy object. Another issue that needs to be looked at is whether PySequence_Check() needs to be made aware of weakref proxies. |
I suppose Benjamin's commit is afd62eb1692e. Claudiu, that doesn't look like the best approach to me. Instead of hardcoding a weakref.proxy check in reversed(), why not implement __reversed__ on weakref.proxy? |
It would also perhaps be practical to have some kind of "proxy mixin" that everyone can re-use to avoid having to reimplement __special__ methods by hand. |
Another possible idea is to introduce a "proxy protocol" (proxy / def PyObject_LookupSpecial(obj, name):
tp = type(obj)
try:
return getattr(tp, name)
except AttributeError:
return getattr(tp.tp_proxy(), name) (not sure that makes sense, I haven't thought very hard about it) |
afd62eb1692e wasn't a matter of speed, but a matter of correctness. Special methods should be looked up on the type on the instance as was done before. |
On 3.10 the reversed_proxy_failure.py script fails with Traceback (most recent call last):
File "/Users/iritkatriel/src/cpython/tmp.py", line 18, in <module>
reversed(weakref.proxy(foo)) # TypeError
AttributeError: 'Foo' object has no attribute '__reversed__' |
This seems to have been fixed:
|
The OP said, a bit ambiguously, that the reproduce raised a "TypeError complaining that its argument isn't a sequence." @Irit, in 2021, you noted that the reproducer failed on 3.10 with TypeError and AttributeError. Did you see this as equivalent to the original claim, verifying the bug, or not? Two months ago you claimed that the bug was fixed because different code runs (in 3.13 or 3.12?). That same code, which fails with just TypeError in 3.8, runs in 3.9. The original reproducer still fails, in 3.13, as it did in 3.10 and 3.9. In 3.8, it failed with just a TypeError. So the conversion of TypeError to Attribute error happened in 3.9, but there is no evidence that anything has changed since then. Is it a bug that the original reproducer still fails, or is it invalid as a bug example? |
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields:
The text was updated successfully, but these errors were encountered: