Skip to content

feat: add built-in frozendict support for Python 3.15+#274

Open
XuehaiPan wants to merge 11 commits intometaopt:mainfrom
XuehaiPan:frozendict
Open

feat: add built-in frozendict support for Python 3.15+#274
XuehaiPan wants to merge 11 commits intometaopt:mainfrom
XuehaiPan:frozendict

Conversation

@XuehaiPan
Copy link
Copy Markdown
Member

@XuehaiPan XuehaiPan commented Mar 21, 2026

Description

Register frozendict (PEP 814, Python 3.15.0a7+) as a built-in PyTree node type with key-sorted traversal, matching the behavior of dict and collections.defaultdict. The dict_insertion_ordered context manager also affects frozendict.

Also improves the empty deque representation: deque() instead of deque([]).

Motivation and Context

Python 3.15 introduces frozendict as a built-in immutable mapping type (PEP 814). As a fundamental container type, it should be supported as a built-in PyTree node — just like dict, OrderedDict, and defaultdict.

  • I have raised an issue to propose this change (required for new features and bug fixes)

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds core functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation (update in the documentation)

Implemented Tasks

  • C++ PyTreeKind::FrozenDict enum and PyFrozenDictTypeObject macro (guarded by PY_VERSION_HEX >= 0x030F00A7)
  • All treespec switch statements updated (flatten, unflatten, serialize, hash, compare, traverse, construct, paths, accessors, entries)
  • Python registry with sorted and insertion-ordered flatten/unflatten functions
  • treespec_frozendict() constructor, STANDARD_DICT_TYPES expansion, PyTree[T] type union
  • optree.treespec.frozendict namespace alias
  • README (linked to PEP 814), Sphinx docs, and spelling wordlist
  • Test data extended (3 frozendict entries in TREES fixture, subinterpreter test tree, registry size checks)
  • Empty deque repr improvement

Checklist

  • I have read the CONTRIBUTION guide. (required)
  • My change requires a change to the documentation.
  • I have updated the tests accordingly. (required for a bug fix or a new feature)
  • I have updated the documentation accordingly.
  • I have reformatted the code using make format. (required)
  • I have checked the code using make lint. (required)
  • I have ensured make test pass. (required)

@XuehaiPan XuehaiPan self-assigned this Mar 21, 2026
@XuehaiPan XuehaiPan added enhancement New feature or request cxx Something related to the CXX source code python Something related to the Python source code labels Mar 21, 2026
@codecov
Copy link
Copy Markdown

codecov bot commented Mar 21, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (7d80015) to head (0faccef).

Additional details and impacted files
@@            Coverage Diff            @@
##              main      #274   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files           15        15           
  Lines         1565      1611   +46     
  Branches       207       218   +11     
=========================================
+ Hits          1565      1611   +46     
Flag Coverage Δ
unittests 100.00% <100.00%> (ø)
unittests-cp310-Linux 100.00% <100.00%> (ø)
unittests-cp310-Windows 100.00% <100.00%> (ø)
unittests-cp310-macOS 100.00% <100.00%> (ø)
unittests-cp311-Linux 100.00% <100.00%> (ø)
unittests-cp311-Windows 100.00% <100.00%> (ø)
unittests-cp311-macOS 100.00% <100.00%> (ø)
unittests-cp312-Linux 100.00% <100.00%> (ø)
unittests-cp312-Windows 100.00% <100.00%> (ø)
unittests-cp312-macOS 100.00% <100.00%> (ø)
unittests-cp313-Linux 100.00% <100.00%> (ø)
unittests-cp313-Windows 100.00% <100.00%> (ø)
unittests-cp313-macOS 100.00% <100.00%> (ø)
unittests-cp313t-Linux 100.00% <100.00%> (ø)
unittests-cp313t-Windows 100.00% <100.00%> (ø)
unittests-cp313t-macOS 100.00% <100.00%> (ø)
unittests-cp314-Linux 100.00% <100.00%> (ø)
unittests-cp314-Windows 100.00% <100.00%> (ø)
unittests-cp314-macOS 100.00% <100.00%> (ø)
unittests-cp314t-Linux 100.00% <100.00%> (ø)
unittests-cp314t-Windows 100.00% <100.00%> (ø)
unittests-cp314t-macOS 100.00% <100.00%> (ø)
unittests-cp315-Linux 100.00% <100.00%> (?)
unittests-cp315-Windows 100.00% <100.00%> (?)
unittests-cp315-macOS 100.00% <100.00%> (?)
unittests-cp315t-Linux 100.00% <100.00%> (?)
unittests-cp315t-Windows 100.00% <100.00%> (?)
unittests-cp315t-macOS 100.00% <100.00%> (?)
unittests-cp39-Linux 100.00% <100.00%> (ø)
unittests-cp39-Windows 100.00% <100.00%> (ø)
unittests-cp39-macOS 100.00% <100.00%> (ø)
unittests-pp311-Linux 100.00% <100.00%> (ø)
unittests-pp311-Windows 100.00% <100.00%> (ø)
unittests-pp311-macOS 100.00% <100.00%> (ø)
unittests-pydebug 100.00% <100.00%> (ø)
unittests-pydebug-cp310d-Linux 100.00% <100.00%> (ø)
unittests-pydebug-cp310d-Windows 100.00% <100.00%> (ø)
unittests-pydebug-cp310d-macOS 100.00% <100.00%> (ø)
unittests-pydebug-cp311d-Linux 100.00% <100.00%> (ø)
unittests-pydebug-cp311d-Windows 100.00% <100.00%> (ø)
unittests-pydebug-cp311d-macOS 100.00% <100.00%> (ø)
unittests-pydebug-cp312d-Linux 100.00% <100.00%> (ø)
unittests-pydebug-cp312d-Windows 100.00% <100.00%> (ø)
unittests-pydebug-cp312d-macOS 100.00% <100.00%> (ø)
unittests-pydebug-cp313d-Linux 100.00% <100.00%> (ø)
unittests-pydebug-cp313d-Windows 100.00% <100.00%> (ø)
unittests-pydebug-cp313d-macOS 100.00% <100.00%> (ø)
unittests-pydebug-cp313td-Linux 100.00% <100.00%> (ø)
unittests-pydebug-cp313td-Windows 100.00% <100.00%> (ø)
unittests-pydebug-cp313td-macOS 100.00% <100.00%> (ø)
unittests-pydebug-cp314d-Linux 100.00% <100.00%> (ø)
unittests-pydebug-cp314d-Windows 100.00% <100.00%> (ø)
unittests-pydebug-cp314d-macOS 100.00% <100.00%> (ø)
unittests-pydebug-cp314td-Linux 100.00% <100.00%> (ø)
unittests-pydebug-cp314td-Windows 100.00% <100.00%> (ø)
unittests-pydebug-cp314td-macOS 100.00% <100.00%> (ø)
unittests-pydebug-cp315d-Linux 100.00% <100.00%> (?)
unittests-pydebug-cp315d-Windows 97.84% <39.13%> (?)
unittests-pydebug-cp315d-macOS 100.00% <100.00%> (?)
unittests-pydebug-cp315td-Linux 100.00% <100.00%> (?)
unittests-pydebug-cp315td-Windows 97.84% <39.13%> (?)
unittests-pydebug-cp315td-macOS 100.00% <100.00%> (?)
unittests-pydebug-cp39d-Linux 100.00% <100.00%> (ø)
unittests-pydebug-cp39d-Windows 100.00% <100.00%> (ø)
unittests-pydebug-cp39d-macOS 100.00% <100.00%> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Register `frozendict` (Python 3.15.0a7+) as a built-in PyTree node type
with key-sorted traversal, matching the behavior of `dict` and
`collections.defaultdict`. The `dict_insertion_ordered` context manager
also affects `frozendict`.

Changes across 29 files:
- C++ enum `PyTreeKind::FrozenDict` and `PyFrozenDictTypeObject` macro
  (guarded by `PY_VERSION_HEX >= 0x030F00A7`)
- All treespec switch statements updated (flatten, unflatten, serialize,
  hash, compare, traverse, construct, paths, accessors, entries)
- Python registry with sorted and insertion-ordered flatten/unflatten
- `treespec_frozendict()` constructor, `STANDARD_DICT_TYPES` expansion,
  `PyTree[T]` type union update
- `optree.treespec.frozendict` namespace alias
- README, Sphinx docs, and spelling wordlist
- Test data extended (3 frozendict entries in TREES fixture),
  subinterpreter test tree includes frozendict, registry size checks
- Minor: empty deque repr improved (`deque()` instead of `deque([])`)
Sphinx autodoc/autosummary imports symbols during the reading phase
regardless of ``.. only::`` directives, causing import errors on
Python < 3.15 where ``treespec_frozendict`` does not exist. Remove the
entries for now with TODO comments to add them back when building with
Python 3.15+.
@XuehaiPan XuehaiPan force-pushed the frozendict branch 2 times, most recently from ab50f0d to 3d9da38 Compare April 1, 2026 14:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cxx Something related to the CXX source code enhancement New feature or request python Something related to the Python source code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant