From d766c5320109a22f53656160ae54feb68c2e3e37 Mon Sep 17 00:00:00 2001 From: Brett Cannon Date: Thu, 28 Aug 2025 14:59:40 -0700 Subject: [PATCH 1/2] PEP 794: Differentiate between public and private import names Also explicitly allow for an empty `Import-Name` to signal there are no import names provided by a distribution file. --- peps/pep-0794.rst | 54 ++++++++++++++++++++++++++++++++++------------- 1 file changed, 39 insertions(+), 15 deletions(-) diff --git a/peps/pep-0794.rst b/peps/pep-0794.rst index ba1dbf4248f..5f4fbc0ac8e 100644 --- a/peps/pep-0794.rst +++ b/peps/pep-0794.rst @@ -17,9 +17,9 @@ This PEP proposes extending the core metadata specification for Python packaging to include two new, repeatable fields named ``Import-Name`` and ``Import-Namespace`` to record the import names that a project provides once installed. New keys named ``import-names`` and ``import-namespaces`` will be -added to the ``[project]`` table in ``pyproject.toml`` for providing the values -for the new core metadata fields. This also leads to the introduction of core -metadata version 2.5. +added to the ``[project]`` table in :file:`pyproject.toml` for providing the +values for the new core metadata fields. This also leads to the introduction of +core metadata version 2.5. Motivation @@ -74,9 +74,19 @@ projects to only have to check a single file's core metadata to get all possible import names instead of checking all the released files. This also means one does not need to worry if a file is missing when reading the core metadata or one can work solely from an sdist if the metadata is provided. As -well, it simplifies having ``project.import-names`` and ``project.import-namespaces`` -keys in ``pyproject.toml`` by having it be consistent for the entire project -version and not unique per released file for the same version. +well, it simplifies having ``project.import-names`` and +``project.import-namespaces`` keys in :file:`pyproject.toml` by having it be +consistent for the entire project version and not unique per released file for +the same version. + +A distribution file containing modules and packages can have any combination of +public and private APIs at the module/package level. Distribution files can also +contain no modules or packages of any kind. Being able to distinguish between +the situations all have various tool uses that could be beneficial to users. For +instance, knowing all import names regardless of whether they are public or +private helps detect clashes at install time. But knowing what is explicitly +public or private allows tools such as editors to not suggest private import +names as part of auto-complete. This PEP is not overly strict on what to (not) list in the proposed metadata on purpose. Having build back-ends verify that a project is accurately following @@ -111,12 +121,17 @@ Because this PEP introduces a new field to the core metadata, it bumps the latest core metadata version to 2.5. The ``Import-Name`` and ``Import-Namespace`` fields are "multiple uses" fields. -Each entry of both fields MUST be a valid import name. The names specified MUST -be importable when the project is installed on *some* platform for the same -version of the project (e.g. the metadata MUST be consistent across all sdists -and wheels for a project release). This does imply that the information isn't -specific to the distribution artifact it is found in, but to the release -version the distribution artifact belongs to. +Each entry of both fields MUST be a valid import name or can be empty in the +case of ``Import-Name``. Any names specified MUST be importable when the project +is installed on *some* platform for the same version of the project (e.g. the +metadata MUST be consistent across all sdists and wheels for a project release). +This does imply that the information isn't specific to the distribution artifact +it is found in, but to the release version the distribution artifact belongs to. + +An import name MAY be followed by a semi-colon and the term "private" (e.g. +``; private``). This signals to tools that the import name is not part of the +public API for the project. Any number of spaces surrounding the ``;`` is +allowed. ``Import-Name`` lists import names which a project, when installed, would *exclusively* provide (i.e. if two projects were installed with the same import @@ -142,7 +157,9 @@ name should also be listed appropriately in ``Import-Namespace`` and/or ``project.import-names = ["spam"]``. A project that lists ``spam.bacon.eggs`` would also need to account for ``spam`` and ``spam.bacon`` appropriately in ``import-names`` and ``import-namespaces``. Listing all names acts as a check -that the intent of the import names is as expected. +that the intent of the import names is as expected. As well, projects SHOULD +list all import names, public or private, using the ``; private`` modifier +as appropriate. If a project lists the same name in both ``Import-Name`` and ``Import-Namespace``, then tools MUST raise an error due to ambiguity; this also @@ -168,6 +185,13 @@ Projects MAY set ``import-names`` or ``import-namespaces`` -- as well as import name of the project to explicitly declare that the project's name is also the import name. +Projects MAY set ``import-names`` an empty array and not set +``import-namespaces`` at all in a :file:`pyproject.toml` file (e.g. +``import-names = []``). To match this, projects MAY have an empty +``Import-Name`` field in their metadata. This represents a project with NO +import names, public or private (i.e. there are no Python modules of any kind +in the distribution file). + Examples -------- @@ -225,8 +249,8 @@ projects provide for importing. If their project name matches the module or package name their project provides they don't have to do anything. If there is a difference, though, they should record all the import names their project provides, using the shortest names possible. If any of the names are implicit -namespaces, those go into ``project.import-namespaces`` in ``pyproject.toml``, -otherwise the name goes into ``project.import-names``. +namespaces, those go into ``project.import-namespaces`` in +:file:`pyproject.toml`, otherwise the name goes into ``project.import-names``. Users of projects don't necessarily need to know about this new metadata. While they may be exposed to it via tooling, the details of where that data From 94fb11aa5af963b3a79a4bcdc4b194d8b4372d24 Mon Sep 17 00:00:00 2001 From: Brett Cannon Date: Thu, 28 Aug 2025 15:02:32 -0700 Subject: [PATCH 2/2] Very minor touch-up --- peps/pep-0794.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/peps/pep-0794.rst b/peps/pep-0794.rst index 5f4fbc0ac8e..748c20eb36e 100644 --- a/peps/pep-0794.rst +++ b/peps/pep-0794.rst @@ -128,7 +128,7 @@ metadata MUST be consistent across all sdists and wheels for a project release). This does imply that the information isn't specific to the distribution artifact it is found in, but to the release version the distribution artifact belongs to. -An import name MAY be followed by a semi-colon and the term "private" (e.g. +An import name MAY be followed by a semicolon and the term "private" (e.g. ``; private``). This signals to tools that the import name is not part of the public API for the project. Any number of spaces surrounding the ``;`` is allowed. @@ -175,7 +175,7 @@ a project has an entry in ``Import-Name`` that overlaps with another project's Projects MAY leave ``Import-Name`` and ``Import-Namespace`` out of the core metadata for a project. In that instance, tools SHOULD assume that when the core metadata is 2.5 or newer, the normalized project name, when converted to -an import name, would be an entry in ``Import-Name`` (i.e. ``-`` substituted for +an import name, would be an entry in ``Import-Name`` (i.e. ``-`` replaced with ``_`` in the normalized project name). This is deemed reasonable as this will only occur for projects that make a new release once their build back-end supports core metadata 2.5 or newer as proposed by this PEP.