pypi / multidict
multidict
What changed in multidict 6 to 7, from its official release notes, upgrade guides and advisories. Sources checked 2026-10-21.
7 breaking5 security1 deprecations4 new APIs and options10 performance12 fixes and other
See which of these apply to your code, ranked, in your agent:
npx @unstale/cli initmultidict 731 changes
Breaking changes 6
A str subclass's own lower() is no longer called to compute a key's case-insensitive identity; the identity comes from str.lower().
keys() and iteration yield each distinct key once, spelled as in its first item; items(), values(), and len(d) still include every item.
The build-time requirement is now setuptools >= 77.0 following the metadata and license metadata changes.
The C extension now raises TypeError when an argument is passed both positionally and by name, rather than silently misbehaving or ignoring surplus arguments.
The free-threaded build now requires CPython 3.14 or newer; older free-threaded interpreters fail with a clear compiler error, while GIL builds still support Python 3.10 and newer.
istr is final and can no longer be subclassed on either backend; code that subclassed it must wrap or convert instead.
Security 2
The pair is removed before result construction can run Python code that mutates the multidict, preventing a C-extension use-after-free and a pure-Python length miscount.
On Python 3.10 and 3.11, mutation during value-list allocation is refused with RuntimeError, avoiding a use-after-free.
Deprecations 1
Access emits DeprecationWarning, and the alias is removed from multidict.__all__; it is slated for removal in the next major release.
New APIs and options 4
A public C API lets third-party extensions create, read, and mutate multidicts without going through the Python-level API.
A cimport-able Cython API is available for third-party Cython modules to work with multidicts through the public API.
Provides the include path for the public C API header used by third-party extensions.
C extensions can register watchers to receive multi-value-aware notifications after a MultiDict or CIMultiDict change operation finishes.
Performance 10
Mappings with exact istr keys use a compact table, taking each identity from the key's canonical form and cutting size by about 45%.
Mappings with exact str keys use a compact table without a separate identity or hash per entry; clear() allows compact storage to start again after another key requires the full layout.
Constructing a subclass of CIMultiDict got about 1% cheaper.
The C extension substantially speeds up operations keyed by plain str, including lookups, insertion, construction, extend(), and construction from a dict.
The C extension’s getall() is a little faster for keys with many values because collected values are no longer copied into a larger buffer as they accumulate.
Argument parsing in the C extension is faster for methods taking key, including their all-positional form and keyword arguments.
Constructing a subclass of MultiDict got about 1% cheaper.
The C extension improves lookup, insertion, deletion, iteration, and view-set performance; on free-threaded builds, concurrent mutations and lock-free reads are also faster.
Popping every item from a C-extension mapping now takes linear rather than quadratic time.
Key identity conversion and hashing now happen before the lock is taken, narrowing the critical section in free-threaded builds.
Fixes and other changes 8
The C extension now takes case-sensitivity mode from the instance, so calling MultiDict.__init__ on a CIMultiDict does not make it case-sensitive, and CIMultiDict.__init__ accepts a MultiDict.
Fixed version values being truncated on Windows and 32-bit platforms, and a pure-Python race that could give concurrently mutated multidicts the same version.
Reinitializing a live multidict now installs its new contents and size before releasing old pairs, avoiding lost or leaked finalizer additions and incorrect length.
Python code that reads or mutates a multidict during initialization, updates, merges, deletion, popall, or related operations no longer causes crashes, lost or duplicated pairs, or backend disagreements.
The C extension now propagates MemoryError and KeyboardInterrupt raised by a positional argument's __len__ while estimating update size, matching the pure-Python backend.
Fixed a spurious RuntimeError when garbage collection mutated the multidict while getall() was building its result.
Fixed a data race on the free-threaded C extension by using relaxed atomic loads and stores for the multidict version counter.
Pure-Python MultiDict and CIMultiDict now convert canonical keys to exact str instances without invoking object.__str__() overrides, matching the C extension.
multidict 68 changes
Breaking changes 1
Calls that catch a list shrinking while it is being processed now raise RuntimeError, avoiding reads of freed memory on free-threaded builds.
Security 3
Fixed freed-memory reads while iterating keys that are plain str, including when key conversion runs Python code or suspends a free-threaded critical section.
Fixed a free-threaded use-after-free when lock-free get, item lookup, or membership reads raced with a hash-table resize.
Multidict: Reference leak in CIMultiDict/MultiDict items-view union and subtraction
Fixes and other changes 4
Copying or re-initializing from another multidict now assigns a new version in the C extension, matching the pure Python implementation.
Fixed a free-threaded data race between lock-free reads and freeing a retired hash table.
Fixed free-threaded concurrent writes that could lose a key, and fixed setdefault inserting a duplicate instead of recognizing an in-flight key.
Deferred decrefs until mutations finish, fixing a standard C extension segmentation fault when a value finalizer releases the GIL during mutation.