mirror of
https://github.com/RustPython/RustPython.git
synced 2026-10-28 10:44:36 +08:00
* Implement _collections.OrderedDict Extracted from #6799: native OrderedDict as a dict subclass, iterator mutation tracking, and mapping-view set operations. * Add OrderedDict, warnings source lines, and socket sendmsg Implement _collections.OrderedDict as a dict subclass with a linked list of insertion-order nodes. Pack struct F/D as native float/double complex pairs, and report unexpected __replace__ field names as a list repr. Register encodings.latin_1 at startup. Reject NUL in input() prompts. Copy non-exact type dicts in mapping order. Fetch warning source lines through _bless_my_loader and unicode splitlines. Keep the last warnings.filters list after deletion. Snapshot sendmsg sequences before converting buffers, parse ancillary ints with __index__, and dispatch AF_CAN by protocol. Store sys.trace and sys.profile on each ThreadSlot so _settraceallthreads/_setprofileallthreads are visible to sys.gettrace/getprofile on other threads. Use <frozen importlib._bootstrap> as frozen importlib co_filename. Keep HEAPTYPE socket objects GC-tracked. Assisted-by: Grok:grok-4.6 * Load marshal via readinto and dump sets in dumps order marshal.load fills a scratch buffer with readinto on a contiguous writable memoryview, and rejects a returned length other than the requested size. set and frozenset dumps write elements in sorted(v, key=marshal.dumps) order. Assisted-by: Grok:grok-4.6 * Add classmethod_descriptor and ABC IS_ABSTRACT flags Give METH_CLASS methods a distinct classmethod_descriptor type. Store Py_TPFLAGS_IS_ABSTRACT from __abstractmethods__ and look up that attribute only in the type's own dict. Expose defaultdict.default_factory as a member descriptor. Inherit bool's unused number slots from int. Mark set and frozenset __contains__ as METH_COEXIST. Parse classmethod, staticmethod, object.__new__, and heap type text signatures. Register interactive source in linecache. Assisted-by: Grok:grok-4.6 * address review: odict reuse, descr call, new wrapper Reuse odict node slots and walk the live list in next_after. Require both | operands to be dicts. Drop the odict iterator on GC clear. Bind classmethod descriptors through descr_get and update IS_ABSTRACT under the type lock. Give odict keys and items sq_contains. Walk tp_new_wrapper past new_wrapper so HEAPTYPE socket subclasses can call socket.__new__. Split FreeBSD Bluetooth protocol constants from Linux values. Assisted-by: Grok:grok-4.6 * Represent chflags bits with bitflagset Assisted-by: Grok:grok-4.6 * Represent access and mode bits with bitflagset Assisted-by: Grok:grok-4.6 * Continue unfinished REPL suites as incomplete input Assisted-by: Grok:grok-4.6 * Add pickle and os.stat inspect signatures Give _pickle.Pickler the clinic constructor text signature and accept fix_imports and buffer_callback as positional-or-keyword. Allow #[pyfunction(text_signature)] and use it so os.stat reports (path, *, dir_fd=None, follow_symlinks=True). Uncomment import _pickle and drop the pickle inspect expectedFailures. Assisted-by: Grok:grok-4.6 * Add Unpickler, dump/load, and lstat signatures Give _pickle Unpickler, dump, dumps, load, and loads clinic text signatures, and os.lstat (path, *, dir_fd=None). Assisted-by: Grok:grok-4.6 * Complete OrderedDict with insertion-order links Move the native OrderedDict into ordered_dict.rs and track order with a linked list of nodes, keeping mapping-view set operations. Assisted-by: Grok:grok-4.6 * address CI: stat casts, HCI_DATA_DIR, passing xfails Compare stat permission bits as Mode so Linux clippy does not flag a u32-to-u32 cast. Export HCI_DATA_DIR with the Bluetooth socket option values. Drop expectedFailure from tests that now pass. Assisted-by: Grok:grok-4.6 * Fix wasm teardown deadlock and bluetooth constants Assisted-by: Grok:grok-4.6 * Clear process-wide eval breaker bits in STW test Assisted-by: Grok:grok-4.6 * Drop exclusive-held panic that tripped wasm clippy Assisted-by: Grok:grok-4.6 * Fix OrderedDict contains and export Windows BDADDR Assisted-by: Grok:grok-4.6 * Add cmp_to_key and hash-once LRU cache _functools.cmp_to_key now returns KeyWrapper. LRU lookups store the key hash on _lru_list_elem so __hash__ is not called again on hits or eviction. Assisted-by: Grok:grok-4.6 * Allow subclass keywords on list, tuple, and float list.__init__ rejects keywords only when tp_new is still list's. tuple/float.__new__ reject them only when tp_init is still the base's. Assisted-by: Grok:grok-4.6 * Fix CI lint, test re-export, and structseq members Drop the duplicate clear_eval_breaker_for_test re-export. Format structseq imports. Expose struct sequence fields as readonly members so assignment raises "readonly attribute". Assisted-by: Grok:grok-4.6 * Allow subclass keywords on itertools and filter Positional-only constructors ignore extra keywords when a subclass has replaced tp_init, matching list/tuple/float. Assisted-by: Grok:grok-4.6 * Remove text_signature derive parameter Drop the string override on #[pyfunction] and #[pyclass]. Signatures are generated from the Rust parameter list only. Restore inspect expectedFailures that depended on the override. Assisted-by: Grok:grok-4.6 * Rename set contains_method to __contains__ Keep a borrowed contains helper for slots and C-API. The coexist pymethod is named __contains__. Assisted-by: Grok:grok-4.6 * Use MonitoringEvent instead of EVENT_* aliases Drop the unused MonitoringEvents bitflags and the EVENT_PY_START style mask constants. Call sites use the enum and .mask(). Assisted-by: Grok:grok-4.6 * Store warnings filters as PyListRef The list already serializes its elements. Drop the extra mutex around the cached list pointer. Assisted-by: Grok:grok-4.6 * Re-export clear_eval_breaker_for_test after rebase Keep the STW test helper visible without bringing back stop_bit_set. Assisted-by: Grok:grok-4.6 * Fix groupby reentrancy and islice arguments Give _grouper its own tgtkey and take currvalue after the key comparison. Accept __index__ on islice bounds, reject step 0, and drain the source up to stop. Assisted-by: Grok:grok-4.6 * SETREF warnings filters, onceregistry, and defaultaction Keep the last list, dict, or str after the module attributes are deleted by swapping the interpreter cache pointer. Do not store a None fallback for _warnings_context. Assisted-by: Grok:grok-4.6 * Iterate OrderedDict inner dict via next_entry &PyDict is not an iterator after the borrowed-ref signature change. Assisted-by: Grok:grok-4.6 * Remove expectedFailure from testBluetoothConstants Linux now exports BTPROTO_HCI and the rest of the set. Assisted-by: Grok:grok-4.6 * Borrow get_filter arguments as PyObject Match the warn_explicit call site that passes borrowed handles after the internal-helper borrow change. Assisted-by: Grok:grok-4.6 * Fix bool slots and SemHandle safety docs Leave unused bool number slots unset so inspect reports __add__ on int. Document SemHandle::from_raw safety. Assisted-by: Grok:grok-4.6 * Keep sendmsg errors and drop duplicate linecache Replace sendmsg iterable TypeError only. Register REPL source in linecache once per compiled input. Assisted-by: Grok:grok-4.6 * Nest REPL parse or-patterns for clippy Assisted-by: Grok:grok-4.6 * Mark pydoc os.stat signature test expectedFailure Assisted-by: Grok:grok-4.6 --------- Co-authored-by: Lee Dogeon <dev.moreal@gmail.com>
368 lines
12 KiB
Python
Vendored
368 lines
12 KiB
Python
Vendored
import signal
|
|
import sys
|
|
import textwrap
|
|
from test import list_tests, support
|
|
from test.support import cpython_only
|
|
from test.support.script_helper import assert_python_failure, assert_python_ok
|
|
import pickle
|
|
import unittest
|
|
|
|
class ListTest(list_tests.CommonTest):
|
|
type2test = list
|
|
|
|
def test_basic(self):
|
|
self.assertEqual(list([]), [])
|
|
l0_3 = [0, 1, 2, 3]
|
|
l0_3_bis = list(l0_3)
|
|
self.assertEqual(l0_3, l0_3_bis)
|
|
self.assertTrue(l0_3 is not l0_3_bis)
|
|
self.assertEqual(list(()), [])
|
|
self.assertEqual(list((0, 1, 2, 3)), [0, 1, 2, 3])
|
|
self.assertEqual(list(''), [])
|
|
self.assertEqual(list('spam'), ['s', 'p', 'a', 'm'])
|
|
self.assertEqual(list(x for x in range(10) if x % 2),
|
|
[1, 3, 5, 7, 9])
|
|
|
|
if sys.maxsize == 0x7fffffff:
|
|
# This test can currently only work on 32-bit machines.
|
|
# XXX If/when PySequence_Length() returns a ssize_t, it should be
|
|
# XXX re-enabled.
|
|
# Verify clearing of bug #556025.
|
|
# This assumes that the max data size (sys.maxint) == max
|
|
# address size this also assumes that the address size is at
|
|
# least 4 bytes with 8 byte addresses, the bug is not well
|
|
# tested
|
|
#
|
|
# Note: This test is expected to SEGV under Cygwin 1.3.12 or
|
|
# earlier due to a newlib bug. See the following mailing list
|
|
# thread for the details:
|
|
|
|
# http://sources.redhat.com/ml/newlib/2002/msg00369.html
|
|
self.assertRaises(MemoryError, list, range(sys.maxsize // 2))
|
|
|
|
# This code used to segfault in Py2.4a3
|
|
x = []
|
|
x.extend(-y for y in x)
|
|
self.assertEqual(x, [])
|
|
|
|
def test_keyword_args(self):
|
|
with self.assertRaisesRegex(TypeError, 'keyword argument'):
|
|
list(sequence=[])
|
|
|
|
def test_keywords_in_subclass(self):
|
|
class subclass(list):
|
|
pass
|
|
u = subclass([1, 2])
|
|
self.assertIs(type(u), subclass)
|
|
self.assertEqual(list(u), [1, 2])
|
|
with self.assertRaises(TypeError):
|
|
subclass(sequence=())
|
|
|
|
class subclass_with_init(list):
|
|
def __init__(self, seq, newarg=None):
|
|
super().__init__(seq)
|
|
self.newarg = newarg
|
|
u = subclass_with_init([1, 2], newarg=3)
|
|
self.assertIs(type(u), subclass_with_init)
|
|
self.assertEqual(list(u), [1, 2])
|
|
self.assertEqual(u.newarg, 3)
|
|
|
|
class subclass_with_new(list):
|
|
def __new__(cls, seq, newarg=None):
|
|
self = super().__new__(cls, seq)
|
|
self.newarg = newarg
|
|
return self
|
|
u = subclass_with_new([1, 2], newarg=3)
|
|
self.assertIs(type(u), subclass_with_new)
|
|
self.assertEqual(list(u), [1, 2])
|
|
self.assertEqual(u.newarg, 3)
|
|
|
|
def test_truth(self):
|
|
super().test_truth()
|
|
self.assertTrue(not [])
|
|
self.assertTrue([42])
|
|
|
|
def test_identity(self):
|
|
self.assertTrue([] is not [])
|
|
|
|
def test_len(self):
|
|
super().test_len()
|
|
self.assertEqual(len([]), 0)
|
|
self.assertEqual(len([0]), 1)
|
|
self.assertEqual(len([0, 1, 2]), 3)
|
|
|
|
def test_overflow(self):
|
|
lst = [4, 5, 6, 7]
|
|
n = int((sys.maxsize*2+2) // len(lst))
|
|
def mul(a, b): return a * b
|
|
def imul(a, b): a *= b
|
|
self.assertRaises((MemoryError, OverflowError), mul, lst, n)
|
|
self.assertRaises((MemoryError, OverflowError), imul, lst, n)
|
|
|
|
def test_empty_slice(self):
|
|
x = []
|
|
x[:] = x
|
|
self.assertEqual(x, [])
|
|
|
|
def test_list_resize_overflow(self):
|
|
# gh-97616: test new_allocated * sizeof(PyObject*) overflow
|
|
# check in list_resize()
|
|
lst = [0] * 65
|
|
del lst[1:]
|
|
self.assertEqual(len(lst), 1)
|
|
|
|
size = sys.maxsize
|
|
with self.assertRaises((MemoryError, OverflowError)):
|
|
lst * size
|
|
with self.assertRaises((MemoryError, OverflowError)):
|
|
lst *= size
|
|
|
|
def test_repr_mutate(self):
|
|
class Obj:
|
|
@staticmethod
|
|
def __repr__():
|
|
try:
|
|
mylist.pop()
|
|
except IndexError:
|
|
pass
|
|
return 'obj'
|
|
|
|
mylist = [Obj() for _ in range(5)]
|
|
self.assertEqual(repr(mylist), '[obj, obj, obj]')
|
|
|
|
def test_repr_large(self):
|
|
# Check the repr of large list objects
|
|
def check(n):
|
|
l = [0] * n
|
|
s = repr(l)
|
|
self.assertEqual(s,
|
|
'[' + ', '.join(['0'] * n) + ']')
|
|
check(10) # check our checking code
|
|
check(1000000)
|
|
|
|
def test_iterator_pickle(self):
|
|
orig = self.type2test([4, 5, 6, 7])
|
|
data = [10, 11, 12, 13, 14, 15]
|
|
for proto in range(pickle.HIGHEST_PROTOCOL + 1):
|
|
# initial iterator
|
|
itorig = iter(orig)
|
|
d = pickle.dumps((itorig, orig), proto)
|
|
it, a = pickle.loads(d)
|
|
a[:] = data
|
|
self.assertEqual(type(it), type(itorig))
|
|
self.assertEqual(list(it), data)
|
|
|
|
# running iterator
|
|
next(itorig)
|
|
d = pickle.dumps((itorig, orig), proto)
|
|
it, a = pickle.loads(d)
|
|
a[:] = data
|
|
self.assertEqual(type(it), type(itorig))
|
|
self.assertEqual(list(it), data[1:])
|
|
|
|
# empty iterator
|
|
for i in range(1, len(orig)):
|
|
next(itorig)
|
|
d = pickle.dumps((itorig, orig), proto)
|
|
it, a = pickle.loads(d)
|
|
a[:] = data
|
|
self.assertEqual(type(it), type(itorig))
|
|
self.assertEqual(list(it), data[len(orig):])
|
|
|
|
# exhausted iterator
|
|
self.assertRaises(StopIteration, next, itorig)
|
|
d = pickle.dumps((itorig, orig), proto)
|
|
it, a = pickle.loads(d)
|
|
a[:] = data
|
|
self.assertEqual(list(it), [])
|
|
|
|
def test_reversed_pickle(self):
|
|
orig = self.type2test([4, 5, 6, 7])
|
|
data = [10, 11, 12, 13, 14, 15]
|
|
for proto in range(pickle.HIGHEST_PROTOCOL + 1):
|
|
# initial iterator
|
|
itorig = reversed(orig)
|
|
d = pickle.dumps((itorig, orig), proto)
|
|
it, a = pickle.loads(d)
|
|
a[:] = data
|
|
self.assertEqual(type(it), type(itorig))
|
|
self.assertEqual(list(it), data[len(orig)-1::-1])
|
|
|
|
# running iterator
|
|
next(itorig)
|
|
d = pickle.dumps((itorig, orig), proto)
|
|
it, a = pickle.loads(d)
|
|
a[:] = data
|
|
self.assertEqual(type(it), type(itorig))
|
|
self.assertEqual(list(it), data[len(orig)-2::-1])
|
|
|
|
# empty iterator
|
|
for i in range(1, len(orig)):
|
|
next(itorig)
|
|
d = pickle.dumps((itorig, orig), proto)
|
|
it, a = pickle.loads(d)
|
|
a[:] = data
|
|
self.assertEqual(type(it), type(itorig))
|
|
self.assertEqual(list(it), [])
|
|
|
|
# exhausted iterator
|
|
self.assertRaises(StopIteration, next, itorig)
|
|
d = pickle.dumps((itorig, orig), proto)
|
|
it, a = pickle.loads(d)
|
|
a[:] = data
|
|
self.assertEqual(list(it), [])
|
|
|
|
def test_step_overflow(self):
|
|
a = [0, 1, 2, 3, 4]
|
|
a[1::sys.maxsize] = [0]
|
|
self.assertEqual(a[3::sys.maxsize], [3])
|
|
|
|
def test_no_comdat_folding(self):
|
|
# Issue 8847: In the PGO build, the MSVC linker's COMDAT folding
|
|
# optimization causes failures in code that relies on distinct
|
|
# function addresses.
|
|
class L(list): pass
|
|
with self.assertRaises(TypeError):
|
|
(3,) + L([1,2])
|
|
|
|
def test_equal_operator_modifying_operand(self):
|
|
# test fix for seg fault reported in bpo-38588 part 2.
|
|
class X:
|
|
def __eq__(self,other) :
|
|
list2.clear()
|
|
return NotImplemented
|
|
|
|
class Y:
|
|
def __eq__(self, other):
|
|
list1.clear()
|
|
return NotImplemented
|
|
|
|
class Z:
|
|
def __eq__(self, other):
|
|
list3.clear()
|
|
return NotImplemented
|
|
|
|
list1 = [X()]
|
|
list2 = [Y()]
|
|
self.assertTrue(list1 == list2)
|
|
|
|
list3 = [Z()]
|
|
list4 = [1]
|
|
self.assertFalse(list3 == list4)
|
|
|
|
def test_lt_operator_modifying_operand(self):
|
|
# See gh-120298
|
|
class evil:
|
|
def __lt__(self, other):
|
|
other.clear()
|
|
return NotImplemented
|
|
|
|
a = [[evil()]]
|
|
with self.assertRaises(TypeError):
|
|
a[0] < a
|
|
|
|
def test_list_index_modifing_operand(self):
|
|
# See gh-120384
|
|
class evil:
|
|
def __init__(self, lst):
|
|
self.lst = lst
|
|
def __iter__(self):
|
|
yield from self.lst
|
|
self.lst.clear()
|
|
|
|
lst = list(range(5))
|
|
operand = evil(lst)
|
|
with self.assertRaises(ValueError):
|
|
lst[::-1] = operand
|
|
|
|
@cpython_only
|
|
def test_preallocation(self):
|
|
iterable = [0] * 10
|
|
iter_size = sys.getsizeof(iterable)
|
|
|
|
self.assertEqual(iter_size, sys.getsizeof(list([0] * 10)))
|
|
self.assertEqual(iter_size, sys.getsizeof(list(range(10))))
|
|
|
|
def test_count_index_remove_crashes(self):
|
|
# bpo-38610: The count(), index(), and remove() methods were not
|
|
# holding strong references to list elements while calling
|
|
# PyObject_RichCompareBool().
|
|
class X:
|
|
def __eq__(self, other):
|
|
lst.clear()
|
|
return NotImplemented
|
|
|
|
lst = [X()]
|
|
with self.assertRaises(ValueError):
|
|
lst.index(lst)
|
|
|
|
class L(list):
|
|
def __eq__(self, other):
|
|
str(other)
|
|
return NotImplemented
|
|
|
|
lst = L([X()])
|
|
lst.count(lst)
|
|
|
|
lst = L([X()])
|
|
with self.assertRaises(ValueError):
|
|
lst.remove(lst)
|
|
|
|
# bpo-39453: list.__contains__ was not holding strong references
|
|
# to list elements while calling PyObject_RichCompareBool().
|
|
lst = [X(), X()]
|
|
3 in lst
|
|
lst = [X(), X()]
|
|
X() in lst
|
|
|
|
def test_tier2_invalidates_iterator(self):
|
|
# GH-121012
|
|
for _ in range(100):
|
|
a = [1, 2, 3]
|
|
it = iter(a)
|
|
for _ in it:
|
|
pass
|
|
a.append(4)
|
|
self.assertEqual(list(it), [])
|
|
|
|
@support.nomemtest
|
|
def test_no_memory(self):
|
|
# gh-118331: Make sure we don't crash if list allocation fails
|
|
code = textwrap.dedent("""
|
|
import _testcapi, sys
|
|
# Prime the freelist
|
|
l = [None]
|
|
del l
|
|
_testcapi.set_nomemory(0)
|
|
l = [None]
|
|
""")
|
|
rc, _, _ = assert_python_failure("-c", code)
|
|
if support.MS_WINDOWS:
|
|
# STATUS_ACCESS_VIOLATION
|
|
self.assertNotEqual(rc, 0xC0000005)
|
|
else:
|
|
self.assertNotEqual(rc, -int(signal.SIGSEGV))
|
|
|
|
def test_deopt_from_append_list(self):
|
|
# gh-132011: it used to crash, because
|
|
# of `CALL_LIST_APPEND` specialization failure.
|
|
code = textwrap.dedent("""
|
|
l = []
|
|
def lappend(l, x, y):
|
|
l.append((x, y))
|
|
for x in range(3):
|
|
lappend(l, None, None)
|
|
try:
|
|
lappend(list, None, None)
|
|
except TypeError:
|
|
pass
|
|
else:
|
|
raise AssertionError
|
|
""")
|
|
|
|
rc, _, _ = assert_python_ok("-c", code)
|
|
self.assertEqual(rc, 0)
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|