diff --git a/.github/workflows/upgrade-pylib.md b/.github/workflows/upgrade-pylib.md index 75a7f694641..c2e82d94828 100644 --- a/.github/workflows/upgrade-pylib.md +++ b/.github/workflows/upgrade-pylib.md @@ -72,21 +72,23 @@ else fi ``` -## Step 2: Pick a module to upgrade +## Step 2: Determine module name -If the user provided a module name via `${{ github.event.inputs.name }}`, use **exactly** that module. Skip the selection logic below and go directly to Step 3. - -If NO module name was provided, run the todo script to auto-pick one: +Run this script to determine the module name: ```bash -python3 scripts/update_lib todo +MODULE_NAME="${{ github.event.inputs.name }}" +if [ -z "$MODULE_NAME" ]; then + echo "No module specified, running todo to find one..." + python3 scripts/update_lib todo + echo "Pick one module from the list above that is marked [ ], has no unmet deps, and has a small Δ number." + echo "Do NOT pick: opcode, datetime, random, hashlib, tokenize, pdb, _pyrepl, concurrent, asyncio, multiprocessing, ctypes, idlelib, tkinter, shutil, tarfile, email, unittest" +else + echo "Module specified by user: $MODULE_NAME" +fi ``` -From the output, pick **one** module that: -- Is marked `[ ]` (not yet up-to-date) -- Has `[no deps]` or `[0/N deps]` (all dependencies are satisfied) -- Has a small diff count (`Δ` number) — prefer modules with smaller diffs for reliability -- Is NOT one of these complex modules: `opcode`, `datetime`, `collections`, `random`, `hashlib`, `tokenize`, `pdb`, `_pyrepl`, `concurrent`, `asyncio`, `multiprocessing`, `ctypes`, `idlelib`, `tkinter`, `shutil`, `tarfile`, `email`, `unittest` +If the script printed "Module specified by user: ...", use that exact name. If it printed the todo list, pick one suitable module from it. ## Step 3: Run the upgrade diff --git a/Lib/collections/__init__.py b/Lib/collections/__init__.py index db36248c4ff..3d3bbd7a39a 100644 --- a/Lib/collections/__init__.py +++ b/Lib/collections/__init__.py @@ -57,10 +57,7 @@ try: from _collections import defaultdict except ImportError: - # FIXME: try to implement defaultdict in collections.rs rather than in Python - # I (coolreader18) couldn't figure out some class stuff with __new__ and - # __init__ and __missing__ and subclassing built-in types from Rust, so I went - # with this instead. + # TODO: RUSTPYTHON - implement defaultdict in Rust from ._defaultdict import defaultdict heapq = None # Lazily imported diff --git a/Lib/test/test_collections.py b/Lib/test/test_collections.py index b68305dd7aa..0ed51c9f1d8 100644 --- a/Lib/test/test_collections.py +++ b/Lib/test/test_collections.py @@ -262,7 +262,7 @@ def __contains__(self, key): d = c.new_child(b=20, c=30) self.assertEqual(d.maps, [{'b': 20, 'c': 30}, {'a': 1, 'b': 2}]) - @unittest.expectedFailure # TODO: RUSTPYTHON + @unittest.expectedFailure # TODO: RUSTPYTHON def test_union_operators(self): cm1 = ChainMap(dict(a=1, b=2), dict(c=3, d=4)) cm2 = ChainMap(dict(a=10, e=5), dict(b=20, d=4)) @@ -1957,7 +1957,7 @@ class X(ByteString): pass # No metaclass conflict class Z(ByteString, Awaitable): pass - @unittest.expectedFailure # TODO: RUSTPYTHON; Need to implement __buffer__ and __release_buffer__ (https://docs.python.org/3.13/reference/datamodel.html#emulating-buffer-types) + @unittest.expectedFailure # TODO: RUSTPYTHON; Need to implement __buffer__ and __release_buffer__ (https://docs.python.org/3.13/reference/datamodel.html#emulating-buffer-types) def test_Buffer(self): for sample in [bytes, bytearray, memoryview]: self.assertIsInstance(sample(b"x"), Buffer) @@ -2029,7 +2029,7 @@ def insert(self, index, value): self.assertEqual(len(mss), len(mss2)) self.assertEqual(list(mss), list(mss2)) - @unittest.expectedFailure # TODO: RUSTPYTHON + @unittest.expectedFailure # TODO: RUSTPYTHON def test_illegal_patma_flags(self): with self.assertRaises(TypeError): class Both(Collection): @@ -2121,6 +2121,19 @@ def test_basics(self): self.assertEqual(c.setdefault('e', 5), 5) self.assertEqual(c['e'], 5) + def test_update_reentrant_add_clears_counter(self): + c = Counter() + key = object() + + class Evil(int): + def __add__(self, other): + c.clear() + return NotImplemented + + c[key] = Evil() + c.update([key]) + self.assertEqual(c[key], 1) + def test_init(self): self.assertEqual(list(Counter(self=42).items()), [('self', 42)]) self.assertEqual(list(Counter(iterable=42).items()), [('iterable', 42)])