Skip to content

gh-148672: Document namespace subpackages inside regular packages#150056

Merged
brettcannon merged 2 commits into
python:mainfrom
Taeknology:gh-148672-document-subpackage-namespaces
Jun 1, 2026
Merged

gh-148672: Document namespace subpackages inside regular packages#150056
brettcannon merged 2 commits into
python:mainfrom
Taeknology:gh-148672-document-subpackage-namespaces

Conversation

@Taeknology
Copy link
Copy Markdown
Contributor

@Taeknology Taeknology commented May 19, 2026

This documents the long-standing behaviour where a subdirectory of a
regular package that does not contain an __init__.py file is imported
as a namespace subpackage of that regular package, per
PEP 420.

The reference docs (Doc/reference/import.rst) currently describe
"Regular packages" and "Namespace packages" as two disjoint categories,
and do not mention that a namespace package can also be nested inside a
regular package. The behaviour is intentional (PEP 420 Specification;
implemented in Lib/importlib/_bootstrap_external.py
FileFinder.find_spec), but is undocumented.

This PR adds:

  1. A short cross-reference paragraph at the end of the "Regular packages"
    section pointing to the namespace package definition.
  2. A paragraph in the "Namespace packages" section explicitly stating
    that namespace packages may also be nested inside a regular package.

Verified locally (Python 3.12.11)

I reproduced the documented behaviour against a CPython interpreter to
make sure the new wording matches what the import system actually does:

$ tree /tmp/test/
/tmp/test/
└── myreg/
    ├── __init__.py        # regular package
    └── empty_sub/         # no __init__.py
        └── deeper/        # no __init__.py

$ python3 -c "
import sys; sys.path.insert(0, '/tmp/test')
import myreg
import myreg.empty_sub
import myreg.empty_sub.deeper
print(repr(myreg))
print(repr(myreg.empty_sub))
print(repr(myreg.empty_sub.deeper))
"
<module 'myreg' from '/tmp/test/myreg/__init__.py'>
<module 'myreg.empty_sub' (namespace) from ['/tmp/test/myreg/empty_sub']>
<module 'myreg.empty_sub.deeper' (namespace) from ['/tmp/test/myreg/empty_sub/deeper']>

The interpreter's own repr labels myreg.empty_sub and
myreg.empty_sub.deeper as (namespace), confirming this is the
intended behaviour and not a bug, which is what the new paragraphs
document.

No code change. No Misc/NEWS.d entry (docs-only).

Fixes #148672

The import system already creates implicit namespace packages for any
subdirectory of a regular package that lacks an ``__init__.py`` file,
per :pep:`420`.  Document this behaviour in Doc/reference/import.rst
so readers do not have to infer it from the PEP and from importlib
internals.
@read-the-docs-community
Copy link
Copy Markdown

read-the-docs-community Bot commented May 19, 2026

Documentation build overview

📚 cpython-previews | 🛠️ Build #32910206 | 📁 Comparing ef2131a against main (517d3d2)

  🔍 Preview build  

41 files changed · ± 41 modified

± Modified

@brettcannon brettcannon added needs backport to 3.13 bugs and security fixes needs backport to 3.14 bugs and security fixes needs backport to 3.15 pre-release feature fixes, bugs and security fixes labels May 29, 2026
@brettcannon brettcannon merged commit 9ba2a89 into python:main Jun 1, 2026
30 checks passed
@github-project-automation github-project-automation Bot moved this from Todo to Done in Docs PRs Jun 1, 2026
@miss-islington-app
Copy link
Copy Markdown

Thanks @Taeknology for the PR, and @brettcannon for merging it 🌮🎉.. I'm working now to backport this PR to: 3.13, 3.14, 3.15.
🐍🍒⛏🤖

@bedevere-app
Copy link
Copy Markdown

bedevere-app Bot commented Jun 1, 2026

GH-150729 is a backport of this pull request to the 3.15 branch.

@bedevere-app bedevere-app Bot removed the needs backport to 3.15 pre-release feature fixes, bugs and security fixes label Jun 1, 2026
@bedevere-app
Copy link
Copy Markdown

bedevere-app Bot commented Jun 1, 2026

GH-150730 is a backport of this pull request to the 3.14 branch.

@bedevere-app bedevere-app Bot removed the needs backport to 3.14 bugs and security fixes label Jun 1, 2026
@bedevere-app
Copy link
Copy Markdown

bedevere-app Bot commented Jun 1, 2026

GH-150731 is a backport of this pull request to the 3.13 branch.

@bedevere-app bedevere-app Bot removed the needs backport to 3.13 bugs and security fixes label Jun 1, 2026
brettcannon pushed a commit that referenced this pull request Jun 1, 2026
…ges (GH-150056) (#150731)

gh-148672: Document namespace subpackages inside regular packages (GH-150056)
(cherry picked from commit 9ba2a89)

Co-authored-by: Taeknology <20297177+Taeknology@users.noreply.github.com>
brettcannon pushed a commit that referenced this pull request Jun 1, 2026
…ges (GH-150056) (#150730)

gh-148672: Document namespace subpackages inside regular packages (GH-150056)
(cherry picked from commit 9ba2a89)

Co-authored-by: Taeknology <20297177+Taeknology@users.noreply.github.com>
brettcannon pushed a commit that referenced this pull request Jun 1, 2026
…ges (GH-150056) (#150729)

gh-148672: Document namespace subpackages inside regular packages (GH-150056)
(cherry picked from commit 9ba2a89)

Co-authored-by: Taeknology <20297177+Taeknology@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

docs Documentation in the Doc dir skip news

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

Document the unexpected importing of sub-namespaces inside normal python packages/namespaces

2 participants