Opened 3 weeks ago
Last modified 2 weeks ago
#37384 assigned Bug
Iterating F("pk") can hang
| Reported by: | Jacob Walls | Owned by: | Django Sprints |
|---|---|---|---|
| Component: | Database layer (models, ORM) | Version: | 5.2 |
| Severity: | Normal | Keywords: | |
| Cc: | Simon Charette | Triage Stage: | Accepted |
| Has patch: | no | Needs documentation: | no |
| Needs tests: | no | Patch needs improvement: | no |
| Easy pickings: | no | UI/UX: | no |
Description
#35603 solved one of the two scenarios that could lead to an infinite hang when F() expressions fall back to "old-style" iteration protocols via __getitem__(). It solved it for containment checks by throwing from __contains__. It didn't solve it for iteration, so we encountered an infinite hang in #37291.
When reviewing the fix for #37291, I began to suggest addressing the root cause by throwing an error from F.__iter__() until I realized that it would change the return value of hasattr(expr, "__iter__"). We have several uses in core like that.
What we should do, I think, is set F.__iter__ = None, and then update core (and add release notes) that code should update from:
if hasattr(expr, "__iter__"):
to:
if getattr(expr, "__iter__", None):
...so that the pythonic way of declaring no-iteration can be read statically.
Change History (9)
comment:1 by , 3 weeks ago
| Cc: | added |
|---|
comment:2 by , 3 weeks ago
| Owner: | set to |
|---|---|
| Status: | new → assigned |
comment:3 by , 3 weeks ago
comment:4 by , 3 weeks ago
Good call, TIL that isinstance'ing the simpler container ABCs will check method presence (and not just MRO)!
comment:6 by , 3 weeks ago
| Triage Stage: | Unreviewed → Accepted |
|---|
TIL about __subclasshook__! Thanks both.
comment:7 by , 3 weeks ago
| Owner: | changed from to |
|---|
follow-up: 9 comment:8 by , 2 weeks ago
| Owner: | changed from to |
|---|
@Vaibhav Pant please leave the Django Sprints tickets for sprints or other contribution events. Those are reserved for mentorship opportunities within the community. When re-assigning a ticket to yourself that's assigned to someone else, it should be unmodified for the last 6 months. If it's sooner than that, it can be acceptable to comment, politely asking if they are still working on the issue. Do not reassign it to yourself though until they respond.
comment:9 by , 2 weeks ago
Hi Tim, thanks for explaining, and apologies for the mix-up. I wasn't aware of the guideline about Django Sprints tickets. I'll leave this one for the sprints and look for unassigned tickets instead.
Setting
F.__iter__ = Noneseems like a good way to go about this but I think we should useisinstance(expr, Iterable)instead of thegetattr/hasattrcall?https://docs.python.org/3/library/collections.abc.html#collections.abc.Iterable