python / python/cpython

`PyImport_CreateModuleFromInitfunc()`: wrong `__name__` for submodules, non-ASCII names rejected, inittab name clashes

Đang mở
#157,384 1 bình luận 0 reaction 0 người được giao Xem trên GitHub

Chưa có ai nhận issue này.

interpreter-core topic-C-API type-bug
Ngôn ngữ chính
Python
Star
77.2k
Fork
35.9k
Chỉ số merge pull request
Chỉ số pull request đang chờ

Mô tả

Bug report

Bug description:

Since PyImport_CreateModuleFromInitfunc() was added (in 3.15, gh-116146), I ran into some issues from real world use internally at Meta (with 3.15+, as well as our 3.14 fork, which has this backported). Collected here as a single issue for convenience - let me know if splitting is preferred.

The API is built on the internal create_builtin() helper, and inherits a few inittab behaviors that don't make sense for an explicitly-passed init function.

  1. Single-phase submodules get the short name. The package context is never set while initfunc runs, so a single-phase init that creates its module as sub (what pybind11's PYBIND11_MODULE(sub, m) does) ends up with __name__ == 'sub' while the spec says pkg.sub. The original impl handled that, but it was lost somewhere on the way.
  2. Non-ASCII spec names raise UnicodeEncodeError, even for multi-phase modules, which the dynamic loader accepts.
  3. Names registered in PyImport_Inittab are handled silently. Depending on the state of the builtin, initfunc is ignored, or the module created here replaces the builtin for later imports, or (multi-phase builtin) initfunc's module overwrites the real one in sys.modules. sys and builtins fall in the first bucket.
  4. Undocumented semantics. Single-phase modules are added to sys.modules by the call itself, multi-phase ones aren't. The spec name is the module's identity, so a second call with the same name and a different initfunc returns the cached module and never calls the new function.

The existing test only covers one top-level single-phase and one top-level multi-phase module, so none of this was caught.

AI disclosure: I ran into the first issue in production, used Claude Opus 5 and Fable 5.1 to root cause, which flagged the other issues while investigating. Fable 5.1 prepared the fixes.

Demo output before any fix:

pkg.sub: repr=<module 'sub'> __name__=sub
non-ASCII name: UnicodeEncodeError: 'ascii' codec can't encode character '\xf6'
same name, initfunc B after A: which=A  calls_a=1 calls_b=0
'_random' via custom initfunc, then `import _random`: <module 'same'>  hasattr(Random)=False

Tests demonstrating all of the above: https://github.com/itamaro/cpython/tree/gh-116146-initfunc-tests-only

Plan

One PR each:

  • Set the package context while calling initfunc, like the dynamic loader does (1)
  • Accept non-ASCII names for multi-phase init; single-phase gets the same SystemError as dynamic loading (2)
  • Raise ImportError for names registered in PyImport_Inittab (3)
  • Document the sys.modules and name-identity behavior (4)
CPython versions tested on:

CPython main branch, 3.15

Operating systems tested on:

Linux, macOS

Linked PRs
  • gh-157387
  • gh-157388
  • gh-157389
  • gh-157390
  • gh-157758

Hướng dẫn đóng góp

Mở hướng dẫn đóng góp

Bắt đầu từ đâu

  1. Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
  2. Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
  3. Fork repository và làm thay đổi trên một nhánh.
  4. Mở pull request có tham chiếu số hiệu của issue.

Hướng nghiên cứu

Bắt đầu với PyImport_CreateModuleFromInitfunc(), các bài kiểm thử hiện có cho các module cấp cao nhất một pha và đa pha, cùng nhánh kiểm thử được liên kết gh-116146-initfunc-tests-only. So sánh hành vi của nó với PyImport_Inittab và trình nạp động. Công việc được xem là hoàn tất khi bốn mục trong checklist đã được xử lý, bao gồm ngữ nghĩa về sys.modules và tính đồng nhất của tên được ghi chép; các PR được liên kết gh-157387 đến gh-157390 và gh-157758 cho thấy công việc đã được triển khai.

Do mô hình lập chỉ mục viết ra từ nội dung của issue.

Đánh giá

Công nghệ
python
Lĩnh vực
backend
Loại issue
Lỗi
Độ khó
4/5
Thời gian dự kiến
3-5 ngày
Mức độ hoạt động
Đình trệ
Độ rõ ràng
Khá rõ ràng
Mức phù hợp với người mới
25/100

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.