Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 12 additions & 10 deletions .github/workflows/upgrade-pylib.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
5 changes: 1 addition & 4 deletions Lib/collections/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
19 changes: 16 additions & 3 deletions Lib/test/test_collections.py
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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):
Expand Down Expand Up @@ -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)])
Expand Down