mirror of
https://github.com/RustPython/RustPython.git
synced 2026-10-28 10:44:36 +08:00
Traverse references held by operator callables (#9044)
Extract attrgetter, itemgetter and methodcaller GC traversal from #8954. Add four bounded reference-cycle cases to the existing operator snippet, including a non-dotted str subclass retained by attrgetter. Assisted-by: OpenAI Codex:model identifier unavailable
This commit is contained in:
1 parent
9c8b745bfe
commit
7c9a0e32b3
2 files changed
+31
-3
No files matched your search
@@ -351,7 +351,7 @@ mod _operator {
|
||||
}
|
||||
|
||||
#[pyattr]
|
||||
#[pyclass(name = "attrgetter", module = "operator")]
|
||||
#[pyclass(name = "attrgetter", module = "operator", traverse)]
|
||||
#[derive(Debug, PyPayload)]
|
||||
struct PyAttrGetter {
|
||||
attrs: Vec<PyStrRef>,
|
||||
@@ -470,7 +470,7 @@ mod _operator {
|
||||
}
|
||||
|
||||
#[pyattr]
|
||||
#[pyclass(name = "itemgetter", module = "operator")]
|
||||
#[pyclass(name = "itemgetter", module = "operator", traverse)]
|
||||
#[derive(Debug, PyPayload)]
|
||||
struct PyItemGetter {
|
||||
items: Vec<PyObjectRef>,
|
||||
@@ -556,7 +556,7 @@ mod _operator {
|
||||
}
|
||||
|
||||
#[pyattr]
|
||||
#[pyclass(name = "methodcaller", module = "operator")]
|
||||
#[pyclass(name = "methodcaller", module = "operator", traverse)]
|
||||
#[derive(Debug, PyPayload)]
|
||||
struct PyMethodCaller {
|
||||
name: PyUtf8StrRef,
|
||||
|
||||
@@ -3,3 +3,31 @@ import _operator
|
||||
assert _operator._compare_digest("abcdef", "abcdef")
|
||||
assert not _operator._compare_digest("abcdef", "abc")
|
||||
assert not _operator._compare_digest("abc", "abcdef")
|
||||
|
||||
|
||||
def check_operator_reference_cycles():
|
||||
import gc
|
||||
import weakref
|
||||
|
||||
class Holder:
|
||||
pass
|
||||
|
||||
class Name(str):
|
||||
pass
|
||||
|
||||
for make, make_payload in (
|
||||
(_operator.itemgetter, Holder),
|
||||
(lambda value: _operator.methodcaller("method", value), Holder),
|
||||
(lambda value: _operator.methodcaller("method", value=value), Holder),
|
||||
(_operator.attrgetter, lambda: Name("attribute")),
|
||||
):
|
||||
payload = make_payload()
|
||||
wrapper = make(payload)
|
||||
payload.wrapper = wrapper
|
||||
reference = weakref.ref(payload)
|
||||
del wrapper, payload
|
||||
gc.collect()
|
||||
assert reference() is None
|
||||
|
||||
|
||||
check_operator_reference_cycles()
|
||||
Reference in new issue
Block a user