Skip to content

Keep module cache entries present during import reordering - #8948

Draft
youknowdot wants to merge 2 commits into
RustPython:mainfrom
youknowdot:cpython-import-atomic-reorder
Draft

youknowdot wants to merge 2 commits into
RustPython:mainfrom
youknowdot:cpython-import-atomic-reorder

Conversation

@youknowdot

Copy link
Copy Markdown

Summary

Keep exact dict entries in sys.modules present while importlib updates shutdown order. The old pop() / assignment pair exposes a temporary absence to other importing threads. This is independently based on current Python 3.14-targeting main; it does not switch the target or the cached importer callback.

  • Add a private _imp._dict_move_to_end operation for exact dictionaries, with lookup callbacks outside the storage guard and relocation under one write guard
  • Preserve the current value, stored key and hash; invalidate layout caches and retain iterator/compaction bookkeeping
  • Revalidate both matched candidates and previously probed prefixes after reentrant equality callbacks, including nested deletion/compaction and insertion into a visited dummy bucket
  • Use the helper at all four current importlib reorder sites; retain the original pop / assignment behavior for custom mappings, dict subclasses and CPython
  • Add deterministic frozen/source bootstrap regressions and native cache/iterator/compaction tests

Semantic scope

This is a true move rather than a universally equivalent pop / assignment pair. It hashes once, preserves the stored key object, pins one dictionary and lookup key, and makes an already-last entry a no-op. Exact-dict callback side effects that depended on a second hash, key replacement, or rebinding sys.modules between the two Python operations intentionally differ. The custom-mapping fallback preserves those original Python operations and is not atomic.

Deliberate module removal/replacement and whole-map rebinding remain possible; this eliminates the artificial gap caused by shutdown-order maintenance. Identity hits in the first bucket allocate no probe-prefix storage. Pathological reentrant colliding keys can require O(k²) prefix validation and O(k) retained references.

This is a prerequisite for the separately prepared Python 3.15 bootstrap and canonical importer callback migration. It does not claim to fix the pre-existing Python 3.14 hierarchical-import deadlock.

Validation

The standalone release was built from this branch, and its frozen/source bootstrap, private helper, target 3.14 and source-Lib provenance were checked.

  • Native regression snippet and the independently identified false-equality/prefix regression: pass
  • test_importlib test_import test_site test_support test_pkgutil test_dict test_ordered_dict: 2,096 tests run, 131 skipped, no failures
  • Full bounded Python snippets: 469 passed, 13 failures; 10 AF_UNIX sandbox failures, two chown errno differences, and one bounded CPython GC/import stress timeout. The new native regression passes; this is not a green full-snippet claim
  • Fresh workspace Rust tests: 1,348 passed, 18 ignored, including all three new dict_inner::tests::move_to_end_* tests
  • Fresh separate C-API tests: 115 passed, 4 ignored
  • Workspace/C-API Clippy: both passed without warnings
  • Final regression snippet: native RustPython, CPython 3.14.7 and CPython 3.15.0rc2 all pass. Legacy cases remain enabled whenever the bootstrap exposes them; modern load/exec cases always run

Rust/Lib implementation and aggregate checks are at 2e30cbf. The final head only adds the independently rerun snippet availability guard; production source is byte-identical.

A shared-target stale VM test binary was detected because it lacked the new tests. That first aggregate run is discarded as validation. The reported fresh runs rebuilt the affected sources, verified the new test names, and checked the resulting binary provenance. No source content was changed to repair that cache issue.

AI assistance

Implemented, reviewed and tested with OpenAI Codex under the requesting RustPython maintainer's direction. No human code review or maintainer privilege is implied for this account. The runtime does not expose an exact model version; commits use Assisted-by: Codex:model-version-unavailable rather than inventing one.

Add a private exact-dict move primitive and importlib dispatcher so shutdown-order updates never temporarily remove a module. Preserve current values and custom-mapping fallback behavior; validate reentrant equality probe witnesses, invalidate layout caches, and compact moved entries.

Cover all four existing bootstrap reorder sites, including legacy-loader cleanup. Add deterministic trace-window, loader replacement/removal, reentrancy, cache, iterator and compaction regressions. The private native primitive uses true-move semantics; it does not promise arbitrary pop/set callback equivalence.

Assisted-by: Codex:model-version-unavailable
Run legacy-loader cases when the bootstrap exposes that helper, preserving all four 3.14 paths and the two remaining 3.15 paths. Always retain modern load and exec regressions.

Assisted-by: Codex:model-version-unavailable
@coderabbitai

coderabbitai Bot commented Oct 2, 2026

Copy link
Copy Markdown
Contributor

Important

Draft PR not reviewed

Draft PRs are not automatically reviewed by default.

  • Trigger a manual review

To automatically review draft PRs, update your CodeRabbit configuration:

reviews:
  auto_review:
    drafts: true
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Autopilot is currently an internal CodeRabbit preview.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

github-actions Bot commented Oct 2, 2026

Copy link
Copy Markdown
Contributor

📦 Library Dependencies

The following Lib/ modules were modified. Here are their dependencies:

[ ] lib: cpython/Lib/importlib
[ ] test: cpython/Lib/test/test_importlib (TODO: 8)

dependencies:

  • importlib (native: _abc, _adapters, _bootstrap, _bootstrap_external, _collections, _common, _frozen_importlib, _frozen_importlib_external, _functional, _functools, _imp, _io, _itertools, _meta, _text, _warnings, collections.abc, email.message, importlib.abc, importlib.metadata, importlib.readers, itertools, marshal, nt, posix, resources.readers, resources.simple, sys, winreg)
    • io (native: _io, _thread, errno, msvcrt, sys)
    • json (native: _json, decoder, encoder, json.tool, sys)
    • warnings (native: _contextvars, _thread, _warnings, builtins, sys)
    • future, abc, collections, contextlib, csv, email, functools, inspect, operator, os, pathlib, posixpath, re, tempfile, textwrap, threading, tokenize, types, typing, zipfile

dependent tests: (129 tests)

  • importlib: test_asdl_parser test_bdb test_cmd_line_script test_codecs test_compileall test_ctypes test_doctest test_external_inspection test_frozen test_hashlib test_importlib test_inspect test_linecache test_modulefinder test_multiprocessing_main_handling test_pkgutil test_py_compile test_pyclbr test_pydoc test_pyrepl test_reprlib test_runpy test_sundry test_support test_tomllib test_tools test_unittest test_zipfile test_zipimport test_zoneinfo
    • ctypes.util: test_ctypes
    • ensurepip: test_ensurepip test_venv
    • idlelib: test_idle
    • inspect: test_abc test_argparse test_asyncgen test_buffer test_builtin test_clinic test_code test_collections test_coroutines test_decimal test_enum test_functools test_generators test_grammar test_monitoring test_ntpath test_operator test_patma test_posixpath test_signal test_sqlite3 test_traceback test_turtle test_type_annotations test_type_params test_types test_typing test_unittest test_yield_from test_zipimport_support
      • ast: test_ast test_codeop test_compile test_compiler_codegen test_dis test_fstring test_future_stmt test_peepholer test_peg_generator test_site test_ssl test_type_comments test_ucn test_unparse
      • asyncio: test_asyncio test_concurrent_futures test_logging test_os test_pdb test_unittest
      • cmd: test_cmd
      • dataclasses: test__colorize test_copy test_ctypes test_genericalias test_pprint test_regrtest
      • rlcompleter: test_pyrepl test_rlcompleter
      • trace: test_trace
      • xmlrpc.server: test_docxmlrpc test_xmlrpc
    • profile: test_profile
    • py_compile: test_importlib
      • zipfile: test_shutil test_zipapp test_zipfile test_zipfile64
    • sysconfig: test_c_locale_coercion test_cmd_line test_dtrace test_embed test_gc test_launcher test_osx_env test_peg_generator test_posix test_pyexpat test_subprocess test_sys test_sysconfig test_time test_tools test_urllib2net
    • zipfile:
      • shutil: test_bz2 test_filecmp test_glob test_httpservers test_largefile test_sax test_string_literals test_tarfile test_tempfile test_unicode_file
    • zipimport: test_importlib

Legend:

  • [+] path exists in CPython
  • [x] up-to-date, [ ] outdated

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant