Skip to content

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

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

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

Conversation

@XuehaiPan
Copy link
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

codecov bot commented Mar 21, 2026

❌ 1 Tests Failed:

Tests completed Failed Passed Skipped
4 1 3 4
View the top 1 failed test(s) by shortest run time
tests.concurrent.test_subinterpreters::test_import_in_subinterpreters_concurrently
Stack Traces | 1.79s run time
#x1B[0m#x1B[94mdef#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[92mtest_import_in_subinterpreters_concurrently#x1B[39;49;00m():#x1B[90m#x1B[39;49;00m
>       check_script_in_subprocess(#x1B[90m#x1B[39;49;00m
            #x1B[33mf#x1B[39;49;00m#x1B[33m"""#x1B[39;49;00m#x1B[33m#x1B[39;49;00m
    #x1B[33m        from concurrent.futures import InterpreterPoolExecutor, as_completed#x1B[39;49;00m#x1B[33m#x1B[39;49;00m
    #x1B[33m#x1B[39;49;00m
    #x1B[33m        def check_import():#x1B[39;49;00m#x1B[33m#x1B[39;49;00m
    #x1B[33m            import sys#x1B[39;49;00m#x1B[33m#x1B[39;49;00m
    #x1B[33m            import optree#x1B[39;49;00m#x1B[33m#x1B[39;49;00m
    #x1B[33m#x1B[39;49;00m
    #x1B[33m            if optree._C.get_registry_size() != (9 if sys.version_info >= (3, 15) else 8):#x1B[39;49;00m#x1B[33m#x1B[39;49;00m
    #x1B[33m                raise RuntimeError(#x1B[39;49;00m#x1B[33m'#x1B[39;49;00m#x1B[33mregistry size mismatch#x1B[39;49;00m#x1B[33m'#x1B[39;49;00m#x1B[33m)#x1B[39;49;00m#x1B[33m#x1B[39;49;00m
    #x1B[33m            if optree._C.is_current_interpreter_main():#x1B[39;49;00m#x1B[33m#x1B[39;49;00m
    #x1B[33m                raise RuntimeError(#x1B[39;49;00m#x1B[33m'#x1B[39;49;00m#x1B[33mexpected subinterpreter#x1B[39;49;00m#x1B[33m'#x1B[39;49;00m#x1B[33m)#x1B[39;49;00m#x1B[33m#x1B[39;49;00m
    #x1B[33m#x1B[39;49;00m
    #x1B[33m        with InterpreterPoolExecutor(max_workers=#x1B[39;49;00m#x1B[33m{#x1B[39;49;00mNUM_WORKERS#x1B[33m}#x1B[39;49;00m#x1B[33m) as executor:#x1B[39;49;00m#x1B[33m#x1B[39;49;00m
    #x1B[33m            futures = [executor.submit(check_import) for _ in range(#x1B[39;49;00m#x1B[33m{#x1B[39;49;00mNUM_FUTURES#x1B[33m}#x1B[39;49;00m#x1B[33m)]#x1B[39;49;00m#x1B[33m#x1B[39;49;00m
    #x1B[33m            for future in as_completed(futures):#x1B[39;49;00m#x1B[33m#x1B[39;49;00m
    #x1B[33m                future.result()#x1B[39;49;00m#x1B[33m#x1B[39;49;00m
    #x1B[33m        #x1B[39;49;00m#x1B[33m"""#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            output=#x1B[33m'#x1B[39;49;00m#x1B[33m'#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            rerun=NUM_FLAKY_RERUNS,#x1B[90m#x1B[39;49;00m
        )#x1B[90m#x1B[39;49;00m


#x1B[1m#x1B[31mconcurrent/test_subinterpreters.py#x1B[0m:337: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

script = 'from concurrent.futures import InterpreterPoolExecutor, as_completed\n\ndef check_import():\n    import sys\n    impo... [executor.submit(check_import) for _ in range(32)]\n    for future in as_completed(futures):\n        future.result()'

    #x1B[0m#x1B[94mdef#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[92mcheck_script_in_subprocess#x1B[39;49;00m(#x1B[90m#x1B[39;49;00m
        script,#x1B[90m#x1B[39;49;00m
        /,#x1B[90m#x1B[39;49;00m
        *,#x1B[90m#x1B[39;49;00m
        output,#x1B[90m#x1B[39;49;00m
        timeout=#x1B[94m120.0#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
        cwd=TEST_ROOT,#x1B[90m#x1B[39;49;00m
        env=#x1B[94mNone#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
        rerun=#x1B[94m1#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
    ):#x1B[90m#x1B[39;49;00m
        script = textwrap.dedent(script).strip()#x1B[90m#x1B[39;49;00m
        result = #x1B[33m'#x1B[39;49;00m#x1B[33m'#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        #x1B[94mfor#x1B[39;49;00m _ #x1B[95min#x1B[39;49;00m #x1B[96mrange#x1B[39;49;00m(rerun):#x1B[90m#x1B[39;49;00m
            #x1B[94mtry#x1B[39;49;00m:#x1B[90m#x1B[39;49;00m
                result = subprocess.check_output(#x1B[90m#x1B[39;49;00m
                    [sys.executable, #x1B[33m'#x1B[39;49;00m#x1B[33m-u#x1B[39;49;00m#x1B[33m'#x1B[39;49;00m, #x1B[33m'#x1B[39;49;00m#x1B[33m-X#x1B[39;49;00m#x1B[33m'#x1B[39;49;00m, #x1B[33m'#x1B[39;49;00m#x1B[33mdev#x1B[39;49;00m#x1B[33m'#x1B[39;49;00m, #x1B[33m'#x1B[39;49;00m#x1B[33m-Walways#x1B[39;49;00m#x1B[33m'#x1B[39;49;00m, #x1B[33m'#x1B[39;49;00m#x1B[33m-Werror#x1B[39;49;00m#x1B[33m'#x1B[39;49;00m, #x1B[33m'#x1B[39;49;00m#x1B[33m-c#x1B[39;49;00m#x1B[33m'#x1B[39;49;00m, script],#x1B[90m#x1B[39;49;00m
                    stderr=subprocess.STDOUT,#x1B[90m#x1B[39;49;00m
                    text=#x1B[94mTrue#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
                    encoding=#x1B[33m'#x1B[39;49;00m#x1B[33mutf-8#x1B[39;49;00m#x1B[33m'#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
                    timeout=timeout,#x1B[90m#x1B[39;49;00m
                    cwd=cwd,#x1B[90m#x1B[39;49;00m
                    env={#x1B[90m#x1B[39;49;00m
                        key: value#x1B[90m#x1B[39;49;00m
                        #x1B[94mfor#x1B[39;49;00m key, value #x1B[95min#x1B[39;49;00m (env #x1B[94mif#x1B[39;49;00m env #x1B[95mis#x1B[39;49;00m #x1B[95mnot#x1B[39;49;00m #x1B[94mNone#x1B[39;49;00m #x1B[94melse#x1B[39;49;00m os.environ).items()#x1B[90m#x1B[39;49;00m
                        #x1B[94mif#x1B[39;49;00m (#x1B[90m#x1B[39;49;00m
                            #x1B[95mnot#x1B[39;49;00m key.startswith((#x1B[33m'#x1B[39;49;00m#x1B[33mPYTHON#x1B[39;49;00m#x1B[33m'#x1B[39;49;00m, #x1B[33m'#x1B[39;49;00m#x1B[33mPYTEST#x1B[39;49;00m#x1B[33m'#x1B[39;49;00m, #x1B[33m'#x1B[39;49;00m#x1B[33mCOV_#x1B[39;49;00m#x1B[33m'#x1B[39;49;00m))#x1B[90m#x1B[39;49;00m
                            #x1B[95mor#x1B[39;49;00m key #x1B[95min#x1B[39;49;00m (#x1B[33m'#x1B[39;49;00m#x1B[33mPYTHON_GIL#x1B[39;49;00m#x1B[33m'#x1B[39;49;00m, #x1B[33m'#x1B[39;49;00m#x1B[33mPYTHONDEVMODE#x1B[39;49;00m#x1B[33m'#x1B[39;49;00m, #x1B[33m'#x1B[39;49;00m#x1B[33mPYTHONHASHSEED#x1B[39;49;00m#x1B[33m'#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
                        )#x1B[90m#x1B[39;49;00m
                    },#x1B[90m#x1B[39;49;00m
                )#x1B[90m#x1B[39;49;00m
            #x1B[94mexcept#x1B[39;49;00m subprocess.CalledProcessError #x1B[94mas#x1B[39;49;00m ex:#x1B[90m#x1B[39;49;00m
>               #x1B[94mraise#x1B[39;49;00m CalledProcessError(ex.returncode, ex.cmd, ex.output, ex.stderr) #x1B[94mfrom#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[94mNone#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31mE               helpers.CalledProcessError: Command '['.../hostedtoolcache/Python/3.15.0-alpha..../x64/bin/python', '-u', '-X', 'dev', '-Walways', '-Werror', '-c', "from concurrent.futures import InterpreterPoolExecutor, as_completed\n\ndef check_import():\n    import sys\n    import optree\n\n    if optree._C.get_registry_size() != (9 if sys.version_info >= (3, 15) else 8):\n        raise RuntimeError('registry size mismatch')\n    if optree._C.is_current_interpreter_main():\n        raise RuntimeError('expected subinterpreter')\n\nwith InterpreterPoolExecutor(max_workers=8) as executor:\n    futures = [executor.submit(check_import) for _ in range(32)]\n    for future in as_completed(futures):\n        future.result()"]' died with <Signals.SIGSEGV: 11>.#x1B[0m
#x1B[1m#x1B[31mE               Output:#x1B[0m
#x1B[1m#x1B[31mE               Fatal Python error: Segmentation fault#x1B[0m
#x1B[1m#x1B[31mE               #x1B[0m
#x1B[1m#x1B[31mE               Current thread 0x00007f23c6ffe6c0 [InterpreterPool] (most recent call first):#x1B[0m
#x1B[1m#x1B[31mE               #x1B[0m
#x1B[1m#x1B[31mE               Thread 0x00007f23b1ffd6c0 [InterpreterPool] (most recent call first):#x1B[0m
#x1B[1m#x1B[31mE                 File ".../hostedtoolcache/Python/3.15.0-alpha..../x64/lib/python3.15................................................/concurrent/interpreters/__init__.py", line 220 in _call#x1B[0m
#x1B[1m#x1B[31mE                 File ".../hostedtoolcache/Python/3.15.0-alpha..../x64/lib/python3.15................................................/concurrent/interpreters/__init__.py", line 238 in call#x1B[0m
#x1B[1m#x1B[31mE                 File ".../hostedtoolcache/Python/3.15.0-alpha..../x64/lib/python3.15......................../concurrent/futures/interpreter.py", line 84 in run#x1B[0m
#x1B[1m#x1B[31mE                 File ".../hostedtoolcache/Python/3.15.0-alpha..../x64/lib/python3.15................................................/concurrent/futures/thread.py", line 86 in run#x1B[0m
#x1B[1m#x1B[31mE                 File ".../hostedtoolcache/Python/3.15.0-alpha..../x64/lib/python3.15................................................/concurrent/futures/thread.py", line 119 in _worker#x1B[0m
#x1B[1m#x1B[31mE                 File ".../hostedtoolcache/Python/3.15.0-alpha..../x64/lib/python3.15/threading.py", line 1017 in run#x1B[0m
#x1B[1m#x1B[31mE                 File ".../hostedtoolcache/Python/3.15.0-alpha..../x64/lib/python3.15/threading.py", line 1075 in _bootstrap_inner#x1B[0m
#x1B[1m#x1B[31mE                 File ".../hostedtoolcache/Python/3.15.0-alpha..../x64/lib/python3.15/threading.py", line 1037 in _bootstrap#x1B[0m
#x1B[1m#x1B[31mE               #x1B[0m
#x1B[1m#x1B[31mE               Thread 0x00007f23b2ffe6c0 [InterpreterPool] (most recent call first):#x1B[0m
#x1B[1m#x1B[31mE                 File ".../hostedtoolcache/Python/3.15.0-alpha..../x64/lib/python3.15................................................/concurrent/interpreters/__init__.py", line 220 in _call#x1B[0m
#x1B[1m#x1B[31mE                 File ".../hostedtoolcache/Python/3.15.0-alpha..../x64/lib/python3.15................................................/concurrent/interpreters/__init__.py", line 238 in call#x1B[0m
#x1B[1m#x1B[31mE                 File ".../hostedtoolcache/Python/3.15.0-alpha..../x64/lib/python3.15......................../concurrent/futures/interpreter.py", line 84 in run#x1B[0m
#x1B[1m#x1B[31mE                 File ".../hostedtoolcache/Python/3.15.0-alpha..../x64/lib/python3.15................................................/concurrent/futures/thread.py", line 86 in run#x1B[0m
#x1B[1m#x1B[31mE                 File ".../hostedtoolcache/Python/3.15.0-alpha..../x64/lib/python3.15................................................/concurrent/futures/thread.py", line 119 in _worker#x1B[0m
#x1B[1m#x1B[31mE                 File ".../hostedtoolcache/Python/3.15.0-alpha..../x64/lib/python3.15/threading.py", line 1017 in run#x1B[0m
#x1B[1m#x1B[31mE                 File ".../hostedtoolcache/Python/3.15.0-alpha..../x64/lib/python3.15/threading.py", line 1075 in _bootstrap_inner#x1B[0m
#x1B[1m#x1B[31mE                 File ".../hostedtoolcache/Python/3.15.0-alpha..../x64/lib/python3.15/threading.py", line 1037 in _bootstrap#x1B[0m
#x1B[1m#x1B[31mE               #x1B[0m
#x1B[1m#x1B[31mE               Thread 0x00007f23b3fff6c0 [InterpreterPool] (most recent call first):#x1B[0m
#x1B[1m#x1B[31mE                 File ".../hostedtoolcache/Python/3.15.0-alpha..../x64/lib/python3.15................................................/concurrent/interpreters/__init__.py", line 220 in _call#x1B[0m
#x1B[1m#x1B[31mE                 File ".../hostedtoolcache/Python/3.15.0-alpha..../x64/lib/python3.15................................................/concurrent/interpreters/__init__.py", line 238 in call#x1B[0m
#x1B[1m#x1B[31mE                 File ".../hostedtoolcache/Python/3.15.0-alpha..../x64/lib/python3.15......................../concurrent/futures/interpreter.py", line 84 in run#x1B[0m
#x1B[1m#x1B[31mE                 File ".../hostedtoolcache/Python/3.15.0-alpha..../x64/lib/python3.15................................................/concurrent/futures/thread.py", line 86 in run#x1B[0m
#x1B[1m#x1B[31mE                 File ".../hostedtoolcache/Python/3.15.0-alpha..../x64/lib/python3.15................................................/concurrent/futures/thread.py", line 119 in _worker#x1B[0m
#x1B[1m#x1B[31mE                 File ".../hostedtoolcache/Python/3.15.0-alpha..../x64/lib/python3.15/threading.py", line 1017 in run#x1B[0m
#x1B[1m#x1B[31mE                 File ".../hostedtoolcache/Python/3.15.0-alpha..../x64/lib/python3.15/threading.py", line 1075 in _bootstrap_inner#x1B[0m
#x1B[1m#x1B[31mE                 File ".../hostedtoolcache/Python/3.15.0-alpha..../x64/lib/python3.15/threading.py", line 1037 in _bootstrap#x1B[0m
#x1B[1m#x1B[31mE               #x1B[0m
#x1B[1m#x1B[31mE               Thread 0x00007f23c5ffd6c0 [InterpreterPool] (most recent call first):#x1B[0m
#x1B[1m#x1B[31mE                 File ".../hostedtoolcache/Python/3.15.0-alpha..../x64/lib/python3.15................................................/concurrent/interpreters/__init__.py", line 220 in _call#x1B[0m
#x1B[1m#x1B[31mE                 File ".../hostedtoolcache/Python/3.15.0-alpha..../x64/lib/python3.15................................................/concurrent/interpreters/__init__.py", line 238 in call#x1B[0m
#x1B[1m#x1B[31mE                 File ".../hostedtoolcache/Python/3.15.0-alpha..../x64/lib/python3.15......................../concurrent/futures/interpreter.py", line 84 in run#x1B[0m
#x1B[1m#x1B[31mE                 File ".../hostedtoolcache/Python/3.15.0-alpha..../x64/lib/python3.15................................................/concurrent/futures/thread.py", line 86 in run#x1B[0m
#x1B[1m#x1B[31mE                 File ".../hostedtoolcache/Python/3.15.0-alpha..../x64/lib/python3.15................................................/concurrent/futures/thread.py", line 119 in _worker#x1B[0m
#x1B[1m#x1B[31mE                 File ".../hostedtoolcache/Python/3.15.0-alpha..../x64/lib/python3.15/threading.py", line 1017 in run#x1B[0m
#x1B[1m#x1B[31mE                 File ".../hostedtoolcache/Python/3.15.0-alpha..../x64/lib/python3.15/threading.py", line 1075 in _bootstrap_inner#x1B[0m
#x1B[1m#x1B[31mE                 File ".../hostedtoolcache/Python/3.15.0-alpha..../x64/lib/python3.15/threading.py", line 1037 in _bootstrap#x1B[0m
#x1B[1m#x1B[31mE               #x1B[0m
#x1B[1m#x1B[31mE               Thread 0x00007f23c6ffe6c0 [InterpreterPool] (most recent call first):#x1B[0m
#x1B[1m#x1B[31mE                 File ".../hostedtoolcache/Python/3.15.0-alpha..../x64/lib/python3.15................................................/concurrent/interpreters/__init__.py", line 220 in _call#x1B[0m
#x1B[1m#x1B[31mE                 File ".../hostedtoolcache/Python/3.15.0-alpha..../x64/lib/python3.15................................................/concurrent/interpreters/__init__.py", line 238 in call#x1B[0m
#x1B[1m#x1B[31mE                 File ".../hostedtoolcache/Python/3.15.0-alpha..../x64/lib/python3.15......................../concurrent/futures/interpreter.py", line 84 in run#x1B[0m
#x1B[1m#x1B[31mE                 File ".../hostedtoolcache/Python/3.15.0-alpha..../x64/lib/python3.15................................................/concurrent/futures/thread.py", line 86 in run#x1B[0m
#x1B[1m#x1B[31mE                 File ".../hostedtoolcache/Python/3.15.0-alpha..../x64/lib/python3.15................................................/concurrent/futures/thread.py", line 119 in _worker#x1B[0m
#x1B[1m#x1B[31mE                 File ".../hostedtoolcache/Python/3.15.0-alpha..../x64/lib/python3.15/threading.py", line 1017 in run#x1B[0m
#x1B[1m#x1B[31mE                 File ".../hostedtoolcache/Python/3.15.0-alpha..../x64/lib/python3.15/threading.py", line 1075 in _bootstrap_inner#x1B[0m
#x1B[1m#x1B[31mE                 File ".../hostedtoolcache/Python/3.15.0-alpha..../x64/lib/python3.15/threading.py", line 1037 in _bootstrap#x1B[0m
#x1B[1m#x1B[31mE               #x1B[0m
#x1B[1m#x1B[31mE               Thread 0x00007f23c7fff6c0 [InterpreterPool] (most recent call first):#x1B[0m
#x1B[1m#x1B[31mE                 File ".../hostedtoolcache/Python/3.15.0-alpha..../x64/lib/python3.15................................................/concurrent/interpreters/__init__.py", line 220 in _call#x1B[0m
#x1B[1m#x1B[31mE                 File ".../hostedtoolcache/Python/3.15.0-alpha..../x64/lib/python3.15................................................/concurrent/interpreters/__init__.py", line 238 in call#x1B[0m
#x1B[1m#x1B[31mE                 File ".../hostedtoolcache/Python/3.15.0-alpha..../x64/lib/python3.15......................../concurrent/futures/interpreter.py", line 84 in run#x1B[0m
#x1B[1m#x1B[31mE                 File ".../hostedtoolcache/Python/3.15.0-alpha..../x64/lib/python3.15................................................/concurrent/futures/thread.py", line 86 in run#x1B[0m
#x1B[1m#x1B[31mE                 File ".../hostedtoolcache/Python/3.15.0-alpha..../x64/lib/python3.15................................................/concurrent/futures/thread.py", line 119 in _worker#x1B[0m
#x1B[1m#x1B[31mE                 File ".../hostedtoolcache/Python/3.15.0-alpha..../x64/lib/python3.15/threading.py", line 1017 in run#x1B[0m
#x1B[1m#x1B[31mE                 File ".../hostedtoolcache/Python/3.15.0-alpha..../x64/lib/python3.15/threading.py", line 1075 in _bootstrap_inner#x1B[0m
#x1B[1m#x1B[31mE                 File ".../hostedtoolcache/Python/3.15.0-alpha..../x64/lib/python3.15/threading.py", line 1037 in _bootstrap#x1B[0m
#x1B[1m#x1B[31mE               #x1B[0m
#x1B[1m#x1B[31mE               Thread 0x00007f23cdd526c0 [InterpreterPool] (most recent call first):#x1B[0m
#x1B[1m#x1B[31mE                 File ".../hostedtoolcache/Python/3.15.0-alpha..../x64/lib/python3.15................................................/concurrent/interpreters/__init__.py", line 220 in _call#x1B[0m
#x1B[1m#x1B[31mE                 File ".../hostedtoolcache/Python/3.15.0-alpha..../x64/lib/python3.15................................................/concurrent/interpreters/__init__.py", line 238 in call#x1B[0m
#x1B[1m#x1B[31mE                 File ".../hostedtoolcache/Python/3.15.0-alpha..../x64/lib/python3.15......................../concurrent/futures/interpreter.py", line 84 in run#x1B[0m
#x1B[1m#x1B[31mE                 File ".../hostedtoolcache/Python/3.15.0-alpha..../x64/lib/python3.15................................................/concurrent/futures/thread.py", line 86 in run#x1B[0m
#x1B[1m#x1B[31mE                 File ".../hostedtoolcache/Python/3.15.0-alpha..../x64/lib/python3.15................................................/concurrent/futures/thread.py", line 119 in _worker#x1B[0m
#x1B[1m#x1B[31mE                 File ".../hostedtoolcache/Python/3.15.0-alpha..../x64/lib/python3.15/threading.py", line 1017 in run#x1B[0m
#x1B[1m#x1B[31mE                 File ".../hostedtoolcache/Python/3.15.0-alpha..../x64/lib/python3.15/threading.py", line 1075 in _bootstrap_inner#x1B[0m
#x1B[1m#x1B[31mE                 File ".../hostedtoolcache/Python/3.15.0-alpha..../x64/lib/python3.15/threading.py", line 1037 in _bootstrap#x1B[0m
#x1B[1m#x1B[31mE               #x1B[0m
#x1B[1m#x1B[31mE               Thread 0x00007f23cedcc6c0 [InterpreterPool] (most recent call first):#x1B[0m
#x1B[1m#x1B[31mE                 File ".../hostedtoolcache/Python/3.15.0-alpha..../x64/lib/python3.15................................................/concurrent/interpreters/__init__.py", line 220 in _call#x1B[0m
#x1B[1m#x1B[31mE                 File ".../hostedtoolcache/Python/3.15.0-alpha..../x64/lib/python3.15................................................/concurrent/interpreters/__init__.py", line 238 in call#x1B[0m
#x1B[1m#x1B[31mE                 File ".../hostedtoolcache/Python/3.15.0-alpha..../x64/lib/python3.15......................../concurrent/futures/interpreter.py", line 84 in run#x1B[0m
#x1B[1m#x1B[31mE                 File ".../hostedtoolcache/Python/3.15.0-alpha..../x64/lib/python3.15................................................/concurrent/futures/thread.py", line 86 in run#x1B[0m
#x1B[1m#x1B[31mE                 File ".../hostedtoolcache/Python/3.15.0-alpha..../x64/lib/python3.15................................................/concurrent/futures/thread.py", line 119 in _worker#x1B[0m
#x1B[1m#x1B[31mE                 File ".../hostedtoolcache/Python/3.15.0-alpha..../x64/lib/python3.15/threading.py", line 1017 in run#x1B[0m
#x1B[1m#x1B[31mE                 File ".../hostedtoolcache/Python/3.15.0-alpha..../x64/lib/python3.15/threading.py", line 1075 in _bootstrap_inner#x1B[0m
#x1B[1m#x1B[31mE                 File ".../hostedtoolcache/Python/3.15.0-alpha..../x64/lib/python3.15/threading.py", line 1037 in _bootstrap#x1B[0m
#x1B[1m#x1B[31mE               #x1B[0m
#x1B[1m#x1B[31mE               Thread 0x00007f23d008cb80 [python] (most recent call first):#x1B[0m
#x1B[1m#x1B[31mE                 File ".../hostedtoolcache/Python/3.15.0-alpha..../x64/lib/python3.15/threading.py", line 362 in wait#x1B[0m
#x1B[1m#x1B[31mE                 File ".../hostedtoolcache/Python/3.15.0-alpha..../x64/lib/python3.15/threading.py", line 663 in wait#x1B[0m
#x1B[1m#x1B[31mE                 File ".../hostedtoolcache/Python/3.15.0-alpha..../x64/lib/python3.15.../concurrent/futures/_base.py", line 237 in as_completed#x1B[0m
#x1B[1m#x1B[31mE                 File "<string>", line 14 in <module>#x1B[0m
#x1B[1m#x1B[31mE               #x1B[0m
#x1B[1m#x1B[31mE               Current thread's C stack trace (most recent call first):#x1B[0m
#x1B[1m#x1B[31mE                 Binary file ".../hostedtoolcache/Python/3.15.0-alpha..../x64/lib/libpython3.15.so.1.0", at _Py_DumpStack+0x47 [0x7f23cfb8358d]#x1B[0m
#x1B[1m#x1B[31mE                 Binary file ".../hostedtoolcache/Python/3.15.0-alpha..../x64/lib/libpython3.15.so.1.0", at +0x1916f0 [0x7f23cfb916f0]#x1B[0m
#x1B[1m#x1B[31mE                 Binary file ".../lib/x86_64-linux-gnu/libc.so.6", at +0x45330 [0x7f23cf645330]#x1B[0m
#x1B[1m#x1B[31mE                 Binary file ".../optree/optree/_C.cpython-315-x86_64-linux-gnu.so", at +0x5273b [0x7f23a313f73b]#x1B[0m
#x1B[1m#x1B[31mE                 Binary file ".../optree/optree/_C.cpython-315-x86_64-linux-gnu.so", at +0x54d4b [0x7f23a3141d4b]#x1B[0m
#x1B[1m#x1B[31mE                 Binary file ".../optree/optree/_C.cpython-315-x86_64-linux-gnu.so", at PyInit__C+0x49 [0x7f23a310d0b0]#x1B[0m
#x1B[1m#x1B[31mE                 Binary file ".../hostedtoolcache/Python/3.15.0-alpha..../x64/lib/libpython3.15.so.1.0", at +0x3186d4 [0x7f23cfd186d4]#x1B[0m
#x1B[1m#x1B[31mE                 Binary file ".../hostedtoolcache/Python/3.15.0-alpha..../x64/lib/libpython3.15.so.1.0", at +0x31645d [0x7f23cfd1645d]#x1B[0m
#x1B[1m#x1B[31mE                 Binary file ".../hostedtoolcache/Python/3.15.0-alpha..../x64/lib/libpython3.15.so.1.0", at +0x317ab9 [0x7f23cfd17ab9]#x1B[0m
#x1B[1m#x1B[31mE                 Binary file ".../hostedtoolcache/Python/3.15.0-alpha..../x64/lib/libpython3.15.so.1.0", at _PyEval_EvalFrameDefault+0x40cb [0x7f23cfc5a1fb]#x1B[0m
#x1B[1m#x1B[31mE                 Binary file ".../hostedtoolcache/Python/3.15.0-alpha..../x64/lib/libpython3.15.so.1.0", at +0x255122 [0x7f23cfc55122]#x1B[0m
#x1B[1m#x1B[31mE                 Binary file ".../hostedtoolcache/Python/3.15.0-alpha..../x64/lib/libpython3.15.so.1.0", at +0x1e9764 [0x7f23cfbe9764]#x1B[0m
#x1B[1m#x1B[31mE                 Binary file ".../hostedtoolcache/Python/3.15.0-alpha..../x64/lib/libpython3.15.so.1.0", at PyObject_CallMethodObjArgs+0x108 [0x7f23cfbeaa78]#x1B[0m
#x1B[1m#x1B[31mE                 Binary file ".../hostedtoolcache/Python/3.15.0-alpha..../x64/lib/libpython3.15.so.1.0", at +0x316b6a [0x7f23cfd16b6a]#x1B[0m
#x1B[1m#x1B[31mE                 Binary file ".../hostedtoolcache/Python/3.15.0-alpha..../x64/lib/libpython3.15.so.1.0", at PyImport_ImportModuleLevelObject+0x2d7 [0x7f23cfc79057]#x1B[0m
#x1B[1m#x1B[31mE                 Binary file ".../hostedtoolcache/Python/3.15.0-alpha..../x64/lib/libpython3.15.so.1.0", at _PyEval_ImportName+0x7b [0x7f23cfd002bb]#x1B[0m
#x1B[1m#x1B[31mE                 Binary file ".../hostedtoolcache/Python/3.15.0-alpha..../x64/lib/libpython3.15.so.1.0", at _PyEval_EvalFrameDefault+0x89b4 [0x7f23cfc5eae4]#x1B[0m
#x1B[1m#x1B[31mE                 Binary file ".../hostedtoolcache/Python/3.15.0-alpha..../x64/lib/libpython3.15.so.1.0", at +0x255122 [0x7f23cfc55122]#x1B[0m
#x1B[1m#x1B[31mE                 Binary file ".../hostedtoolcache/Python/3.15.0-alpha..../x64/lib/libpython3.15.so.1.0", at PyEval_EvalCode+0xca [0x7f23cfd0011a]#x1B[0m
#x1B[1m#x1B[31mE                 Binary file ".../hostedtoolcache/Python/3.15.0-alpha..../x64/lib/libpython3.15.so.1.0", at +0x2fe52f [0x7f23cfcfe52f]#x1B[0m
#x1B[1m#x1B[31mE                 Binary file ".../hostedtoolcache/Python/3.15.0-alpha..../x64/lib/libpython3.15.so.1.0", at _PyEval_EvalFrameDefault+0x40cb [0x7f23cfc5a1fb]#x1B[0m
#x1B[1m#x1B[31mE                 Binary file ".../hostedtoolcache/Python/3.15.0-alpha..../x64/lib/libpython3.15.so.1.0", at +0x255122 [0x7f23cfc55122]#x1B[0m
#x1B[1m#x1B[31mE                 Binary file ".../hostedtoolcache/Python/3.15.0-alpha..../x64/lib/libpython3.15.so.1.0", at +0x1e9764 [0x7f23cfbe9764]#x1B[0m
#x1B[1m#x1B[31mE                 Binary file ".../hostedtoolcache/Python/3.15.0-alpha..../x64/lib/libpython3.15.so.1.0", at PyObject_CallMethodObjArgs+0x108 [0x7f23cfbeaa78]#x1B[0m
#x1B[1m#x1B[31mE                 Binary file ".../hostedtoolcache/Python/3.15.0-alpha..../x64/lib/libpython3.15.so.1.0", at +0x316b6a [0x7f23cfd16b6a]#x1B[0m
#x1B[1m#x1B[31mE                 Binary file ".../hostedtoolcache/Python/3.15.0-alpha..../x64/lib/libpython3.15.so.1.0", at PyImport_ImportModuleLevelObject+0x2d7 [0x7f23cfc79057]#x1B[0m
#x1B[1m#x1B[31mE                 Binary file ".../hostedtoolcache/Python/3.15.0-alpha..../x64/lib/libpython3.15.so.1.0", at +0x25343f [0x7f23cfc5343f]#x1B[0m
#x1B[1m#x1B[31mE                 Binary file ".../hostedtoolcache/Python/3.15.0-alpha..../x64/lib/libpython3.15.so.1.0", at _PyEval_EvalFrameDefault+0x40cb [0x7f23cfc5a1fb]#x1B[0m
#x1B[1m#x1B[31mE                 Binary file ".../hostedtoolcache/Python/3.15.0-alpha..../x64/lib/libpython3.15.so.1.0", at +0x255122 [0x7f23cfc55122]#x1B[0m
#x1B[1m#x1B[31mE                 Binary file ".../hostedtoolcache/Python/3.15.0-alpha..../x64/lib/libpython3.15.so.1.0", at +0x1e9764 [0x7f23cfbe9764]#x1B[0m
#x1B[1m#x1B[31mE                 Binary file ".../hostedtoolcache/Python/3.15.0-alpha..../x64/lib/libpython3.15.so.1.0", at PyObject_CallMethodObjArgs+0x108 [0x7f23cfbeaa78]#x1B[0m
#x1B[1m#x1B[31mE                 Binary file ".../hostedtoolcache/Python/3.15.0-alpha..../x64/lib/libpython3.15.so.1.0", at PyImport_ImportModuleLevelObject+0x4b8 [0x7f23cfc79238]#x1B[0m
#x1B[1m#x1B[31mE                 <truncated rest of calls>#x1B[0m

_          = 4
cwd        = PosixPath('.../optree/optree/tests')
env        = None
output     = ''
rerun      = 16
result     = ''
script     = 'from concurrent.futures import InterpreterPoolExecutor, as_completed\n\ndef check_import():\n    import sys\n    impo... [executor.submit(check_import) for _ in range(32)]\n    for future in as_completed(futures):\n        future.result()'
timeout    = 120.0

#x1B[1m#x1B[31mhelpers.py#x1B[0m:205: CalledProcessError

To view more test analytics, go to the Test Analytics Dashboard
📋 Got 3 mins? Take this short survey to help us improve Test Analytics.

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+.
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