docs/limitations/collections.md
collections moduledeque, namedtuple, defaultdict, and Counter are implemented and
feature-complete against CPython 3.14 apart from the divergences below. The
exact supported surface is pinned by the custom typeshed stub
(crates/monty-typeshed/custom/collections/__init__.pyi) and
crates/monty/tests/collections.rs. defaultdict and Counter are exposed as
the type objects themselves (like deque), so type(d) is defaultdict and
isinstance(c, Counter) hold.
OrderedDict, ChainMap, UserDict, UserList, UserString, and the
collections.abc submodule. Importing one raises
ImportError: cannot import name 'OrderedDict' from 'collections' (unknown location) (or AttributeError
as an attribute); import collections.abc raises ModuleNotFoundError. The
narrowed typeshed stub makes from collections import OrderedDict a type error
too, rather than something that type-checks and then fails at runtime.
dequed * 1.5 raises TypeError: unsupported operand type(s) for *: 'collections.deque' and 'float', where CPython
says can't multiply sequence by non-int of type 'float'. Shared with list.[2**63, 2**64) are accepted where CPython rejects them:
Monty's repeat count is a usize, CPython's a C ssize_t. Only observable
for a bounded deque, whose result truncates to maxlen: deque([1, 2], maxlen=2) * 2**63 yields
deque([1, 2], maxlen=2) in Monty but OverflowError
in CPython. 2**64 or more raises OverflowError in both.list, so the maxlen bound and the
deque-ness are lost; sending it back yields a list. (Same as
defaultdict/Counter, which arrive as plain dicts.)enumerate/zip/map/
filter/reversed: those are eager (see builtins.md), so
the deque is fully read before the loop body runs. for x in d and explicit
iter()/next() detect it exactly as CPython does.d += <any iterable> works (it is extend), even though list's += still
accepts only another list.extend/extendleft/+= append each item as the source yields it, so an
iterator raising part-way leaves the earlier items in place, as in CPython.
But map/filter/zip/enumerate are eager (see
builtins.md), so d += map(f, xs) with a raising f raises
before the extend begins and appends nothing, where CPython appends whatever
was yielded first.del d[i] and subclassing (class Q(deque)) both fail at compile time: the
del statement and class inheritance are unimplemented Monty-wide (see
language.md / classes.md), not deque limitations.
namedtupleField-name validation matches CPython's messages exactly; see
namedtuple.md for the tuple-inherited surface and its
divergences. repr(Point) is <class 'Point'> where CPython gives
<class '__main__.Point'>, the repo-wide unqualified-class-name pattern.
defaultdictdefault_factory cannot call an external or os function; a
missing-key access then raises NotImplementedError. Plain factories (int,
list, lambda, ordinary functions) work. This applies to every callback
Monty invokes mid-expression (the key= of sorted/min/max, map,
filter, __repr__), not just defaultdict.dict: the default_factory is a
function and cannot cross, so sending the dict back yields a plain dict.Counterelements() returns a list, not CPython's lazy iterator. The values and
order match, but the whole sequence is built up front, so a very large count
can hit the memory limit where CPython would stream.dict.c &= [list] (a non-mapping) subscripts other[elem] like
CPython and raises TypeError, but with Monty's list-index wording (list indices must be integers, not 'str' vs
CPython's ... or slices, not str).
Mapping operands (c &= {'a': 1}) match CPython exactly, including the
KeyError for a key missing from a plain dict.deque and defaultdict are C types, so CPython qualifies them
(collections.deque) in repr(T) and in every type-naming error message
(unsupported operand type(s), object is not callable, object has no attribute) while __name__ stays bare
('deque'); Monty matches both
surfaces.
Counter is a Python-level class, so CPython gives the bare name everywhere
except repr(Counter), which is <class 'collections.Counter'> where Monty
writes <class 'Counter'>. Everywhere else — __name__, the cannot use ...
unhashable clause, other type-naming errors — the bare name matches.