Files
RustPython/extra_tests/snippets/stdlib_functools.py
Alok Pandey f90a5cf650 Fix del obj.__dict__ to match CPython behavior (fixes #5355) (#7568)
* Fix del obj.__dict__ to match CPython behavior (issue #5355)

* Address CodeRabbit concerns: fix GC clearing and improve thread safety of lazy __dict__ recreation

* Fix del obj.__dict__: improve GC safety, implement lazy re-creation in setattr, and enable passing CPython tests

* Restore expectedFailure for test_has_inline_values

* Fix ObjExt::new call site to include has_dict parameter

* Remove stray test.py to avoid CI syntax errors

* Remove debug txt files and clean test_class.py comments

* Delete Lib/test/test_class.py

* Restore test_class.py with correct changes (remove expectedFailure, no deletion)

* Fix clippy warnings: remove unused into_inner, collapse nested if-let

* Fix rustfmt formatting and ruff PEP 8 E302 blank line

* Align __dict__ error messages and ensure safety for function/partial objects

* Fix compilation errors: change &self to &Py<Self> in __dict__ methods

* Fix compilation errors: resolve borrow-after-move and replace transpose on PySetterValue

- type.rs: Replace invalid .transpose() on PySetterValue with explicit
  match on Assign/Delete variants in subtype_set_dict
- function.rs: Fix borrow-after-move in set___dict__ by capturing class
  name before downcast; use as_object() for instance_dict/set_dict calls
- _functools.rs: Same borrow-after-move fix and as_object() calls for
  PyPartial's __dict__ getter/setter

* Fix compilation errors: resolve borrow-after-move and replace transpose on PySetterValue

* Fix snippet formatting and mark test_remote as expected failure

* Fix test_remote by removing HAS_DICT flag from function type

* Fix lint formatting error

* Remove unnecessary print statement in test_del_dict

* Fix trailing newlines in snippet test

* Trigger CI

* Align __dict__ generic setter behavior

* Move __dict__ deletion tests to relevant snippets

---------

Co-authored-by: Jeong, YunWon <jeong@youknowone.org>
2026-04-30 02:09:16 +00:00

100 lines
2.2 KiB
Python

from functools import partial, reduce
from testutils import assert_raises
class Squares:
def __init__(self, max):
self.max = max
self.sofar = []
def __len__(self):
return len(self.sofar)
def __getitem__(self, i):
if not 0 <= i < self.max:
raise IndexError
n = len(self.sofar)
while n <= i:
self.sofar.append(n * n)
n += 1
return self.sofar[i]
def add(a, b):
return a + b
assert reduce(add, ["a", "b", "c"]) == "abc"
assert reduce(add, ["a", "b", "c"], str(42)) == "42abc"
assert reduce(add, [["a", "c"], [], ["d", "w"]], []) == ["a", "c", "d", "w"]
assert reduce(add, [["a", "c"], [], ["d", "w"]], []) == ["a", "c", "d", "w"]
assert reduce(lambda x, y: x * y, range(2, 21), 1) == 2432902008176640000
assert reduce(add, Squares(10)) == 285
assert reduce(add, Squares(10), 0) == 285
assert reduce(add, Squares(0), 0) == 0
assert reduce(42, "1") == "1"
assert reduce(42, "", "1") == "1"
with assert_raises(TypeError):
reduce()
with assert_raises(TypeError):
reduce(42, 42)
with assert_raises(TypeError):
reduce(42, 42, 42)
class TestFailingIter:
def __iter__(self):
raise RuntimeError
with assert_raises(RuntimeError):
reduce(add, TestFailingIter())
assert reduce(add, [], None) == None
assert reduce(add, [], 42) == 42
class BadSeq:
def __getitem__(self, index):
raise ValueError
with assert_raises(ValueError):
reduce(42, BadSeq())
# Test reduce()'s use of iterators.
class SequenceClass:
def __init__(self, n):
self.n = n
def __getitem__(self, i):
if 0 <= i < self.n:
return i
else:
raise IndexError
assert reduce(add, SequenceClass(5)) == 10
assert reduce(add, SequenceClass(5), 42) == 52
with assert_raises(TypeError):
reduce(add, SequenceClass(0))
assert reduce(add, SequenceClass(0), 42) == 42
assert reduce(add, SequenceClass(1)) == 0
assert reduce(add, SequenceClass(1), 42) == 42
d = {"one": 1, "two": 2, "three": 3}
assert reduce(add, d) == "".join(d.keys())
p = partial(add)
try:
del p.__dict__
assert False, "TypeError expected for partial dict deletion"
except TypeError:
pass