PEP: 739
Title: Static description file for build details of Python installations
Author: Filipe Laíns <lains@riseup.net>
PEP-Delegate: Paul Moore <p.f.moore@gmail.com>
Discussions-To: https://discuss.python.org/t/pep-739-static-description-file-for-build-details-of-python-installations/44572
Status: Draft
Type: Standards Track
Topic: Packaging
Created: 19-Dec-2023
Python-Version: 3.14


Abstract
========

Introduce a standard format for a static description file with build details
of Python installations.


Rationale
=========

When introspecting a Python installation, running code is often undesirable or
impossible. Having a static description file makes various of Python build
details available without having to run the interpreter.

This is helpful for use-cases such as cross-compilation, Python launchers, etc.


Scope
=====

This PEP defines a format for the description file, and a standard location for
where to place it.


Location
========

When possible, Python installations should install the static description file
inside the standard library directory, with the name ``build-details.json``
(Eg. ``/usr/lib/python3.14/build-details.json``).


.. important::

  Given that there may be technical challenges, Python implementations are not
  required to provide the file if not feasable. In such scenarios, they may
  choose to provide it in a different maner.


.. attention::

  Notwithstanding the standard location specified here, it does not prevent the
  file from **additionally** being provided in another location, and with a
  different name. In fact, the PEP authors expect future PEPs to define
  additional locations to install this file, for better discoverability.


Format
======

The format specification is defined by the JSON Schema definition provided
below, which is rendered in an human-readable format here.

..
    Rendered with https://gist.github.com/FFY00/eb02d9da2870aae547bc579b7e17a145

.. _spec-start:

.. list-table::
    :widths: 25 75

    * - ``$schema``
      - https://json-schema.org/draft/2020-12/schema
    * - ``$id``
      - https://github.com/python/peps/blob/main/peps/pep-0739/python-build-info-v1.schema.json
    * - Title
      - Static description file for the build details of Python
        installations
    * - Type
      - ``object``
    * - Additional properties
      - **Not allowed**

``schema_version``
------------------

.. list-table::
    :widths: 25 75

    * - Type
      - ``string`` (constant — ``1``)
    * - Description
      - Schema version.

        This is a constant value and MUST be ``1``, when using the
        schema described here. Future iterations of this schema MUST
        update this value.
    * - Required
      - **True**

``base_prefix``
---------------

.. list-table::
    :widths: 25 75

    * - Type
      - ``string``
    * - Description
      - Base prefix of the Python installation.

        Either an absolute path, or a relative path to directory where
        this file is contained.
    * - Examples
      - ``/usr``, ``../..``, etc.
    * - Required
      - **False**

``platform``
------------

.. list-table::
    :widths: 25 75

    * - Type
      - ``string``
    * - Description
      - System platform string.

        This field SHOULD be equivalent to ``sysconfig.get_platform()``.
    * - Examples
      - - ``linux-x86_64``
        - etc.
    * - Required
      - **True**

``language``
------------

.. list-table::
    :widths: 25 75

    * - Type
      - ``object``
    * - Description
      - Object containing details related to the Python language
        specification.

        In addition to the required keys, implementations may choose to
        include extra keys with implementation-specific details.
    * - Required
      - **True**
    * - Additional properties
      - **Not allowed**

``language.version``
~~~~~~~~~~~~~~~~~~~~

.. list-table::
    :widths: 25 75

    * - Type
      - ``string``
    * - Description
      - String representation the Python language version — a version
        string consisting only of the *major* and *minor* components.

        This field SHOULD be equivalent to
        ``sysconfig.get_python_version()``.
    * - Examples
      - ``3.14``, etc.
    * - Required
      - **True**

``implementation``
------------------

.. list-table::
    :widths: 25 75

    * - Type
      - ``object``
    * - Description
      - Object containing details related to Python implementation.

        This section SHOULD be equivalent to
        :py:data:`sys.implementation`. It follows specification defined
        in PEP 421, meaning that on top of the required keys,
        implementation-specific keys can also exist, but must be
        prefixed with an underscore.
    * - Required
      - **True**
    * - Additional properties
      - **Allowed**

``implementation.name``
~~~~~~~~~~~~~~~~~~~~~~~

.. list-table::
    :widths: 25 75

    * - Type
      - ``string``
    * - Description
      - Lower-case name of the Python implementation.
    * - Examples
      - ``cpython``, ``pypy``, etc.
    * - Required
      - **True**

``implementation.version``
~~~~~~~~~~~~~~~~~~~~~~~~~~

.. list-table::
    :widths: 25 75

    * - Type
      - ``object``
    * - Description
      - Object in the format of :py:data:`sys.version_info`, containing
        the implementation version.
    * - Examples
      - - ``{'major': 3, 'minor': 13, 'micro': 1, 'releaselevel': 'final', 'serial': 0}``
        - ``{'major': 7, 'minor': 3, 'micro': 16, 'releaselevel': 'final', 'serial': 0}``
        - etc.
    * - Required
      - **True**
    * - Additional properties
      - **Not allowed**

``implementation.version.major``
++++++++++++++++++++++++++++++++

.. list-table::
    :widths: 25 75

    * - Type
      - ``number``
    * - Required
      - **True**

``implementation.version.minor``
++++++++++++++++++++++++++++++++

.. list-table::
    :widths: 25 75

    * - Type
      - ``number``
    * - Required
      - **True**

``implementation.version.micro``
++++++++++++++++++++++++++++++++

.. list-table::
    :widths: 25 75

    * - Type
      - ``number``
    * - Required
      - **True**

``implementation.version.releaselevel``
+++++++++++++++++++++++++++++++++++++++

.. list-table::
    :widths: 25 75

    * - Type
      - ``string`` (enum — ``alpha``, ``beta``, ``candidate``, ``final``)
    * - Required
      - **True**

``implementation.version.serial``
+++++++++++++++++++++++++++++++++

.. list-table::
    :widths: 25 75

    * - Type
      - ``number``
    * - Required
      - **True**

``interpreter``
---------------

.. list-table::
    :widths: 25 75

    * - Type
      - ``object``
    * - Description
      - Object containing details Python interpreter.

        This section MUST be present if the Python installation provides
        an interpreter binary, otherwise this section will be missing.
    * - Required
      - **False**
    * - Additional properties
      - **Not allowed**

``interpreter.path``
~~~~~~~~~~~~~~~~~~~~

.. list-table::
    :widths: 25 75

    * - Type
      - ``string``
    * - Description
      - The path to the Python interprer. Either an absolute path, or a
        relative path to the path defined in the ``base_prefix`` key.
    * - Examples
      - - ``/usr/bin/python``
        - ``bin/python``
        - etc.
    * - Required
      - **True**

``abi``
-------

.. list-table::
    :widths: 25 75

    * - Type
      - ``object``
    * - Description
      - Object containing details related to ABI.
    * - Required
      - **False**
    * - Additional properties
      - **Not allowed**

``abi.flags``
~~~~~~~~~~~~~

.. list-table::
    :widths: 25 75

    * - Type
      - ``array``
    * - Description
      - Build configuration flags, used to calculate the extension
        suffix.

        The flags MUST be defined in the order they appear on the
        extension suffix.
    * - Examples
      - ``['t', 'd']``, etc.
    * - Required
      - **True**

``abi.extension_suffix``
~~~~~~~~~~~~~~~~~~~~~~~~

.. list-table::
    :widths: 25 75

    * - Type
      - ``string``
    * - Description
      - Suffix used for extensions built against the current
        implementation version.

        This field MUST be present if the Python implementation supports
        extensions, otherwise this entry will be missing.
    * - Examples
      - - ``.cpython-314-x86_64-linux-gnu.so``
        - etc.
    * - Required
      - **True**

``abi.stable_abi_suffix``
~~~~~~~~~~~~~~~~~~~~~~~~~

.. list-table::
    :widths: 25 75

    * - Type
      - ``string``
    * - Description
      - Suffix used for extensions built against the stable ABI.

        This field MUST be present if the Python implementation has a
        stable ABI extension suffix, otherwise this entry will be
        missing.
    * - Examples
      - ``.abi3.so``, etc.
    * - Required
      - **False**

``suffixes``
------------

.. list-table::
    :widths: 25 75

    * - Type
      - ``object``
    * - Description
      - Valid module suffixes grouped by type.

        This section SHOULD be equivalent to the
        ``importlib.machinery.*_SUFFIXES`` attributes, if the
        implementation provides such suffixes. However, if the Python
        implementation does not provide suffixes of the kind specified
        by any of the attributes, the equivalent sub-section is not
        required to be present. Additionally, if a Python implementation
        provides extension kinds other than the ones listed on
        ``importlib.machinery`` module, they MAY add a sub-section for
        them.
    * - Examples
      - - ``{'source': ['.py'], 'bytecode': ['.pyc'], 'optimized_bytecode': ['.pyc'], 'debug_bytecode': ['.pyc'], 'extensions': ['.cpython-313-x86_64-linux-gnu.so', '.abi3.so', '.so']}``
        - etc.
    * - Required
      - **False**
    * - Additional properties
      - **Allowed**

``libpython``
-------------

.. list-table::
    :widths: 25 75

    * - Type
      - ``object``
    * - Description
      - Object containing details related to the ``libpython`` library.

        This section MUST by present if Python installation provides a
        ``libpython`` library, otherwise this section will be missing.
    * - Required
      - **False**
    * - Additional properties
      - **Not allowed**

``libpython.dynamic``
~~~~~~~~~~~~~~~~~~~~~

.. list-table::
    :widths: 25 75

    * - Type
      - ``string``
    * - Description
      - The path to the dynamic ``libpython`` library. Either an
        absolute path, or a relative path to the path defined in the
        ``base_prefix`` key.

        This field MUST be present if the Python installation provides a
        dynamic ``libpython`` library, otherwise this entry will be
        missing.
    * - Examples
      - - ``/usr/lib/libpython3.14.so.1.0``
        - ``lib/libpython3.14.so.1.0``
        - etc.
    * - Required
      - **False**

``libpython.static``
~~~~~~~~~~~~~~~~~~~~

.. list-table::
    :widths: 25 75

    * - Type
      - ``string``
    * - Description
      - The path to the static ``libpython`` library. Either an absolute
        path, or a relative path to the path defined in the
        ``base_prefix`` key.

        This field MUST be present if the Python installation provides a
        static ``libpython`` library, otherwise this entry will be
        missing.
    * - Examples
      - - ``/usr/lib/python3.14/config-3.14-x86_64-linux-gnu/libpython3.14.a``
        - ``lib/python3.14/config-3.14-x86_64-linux-gnu/libpython3.14.a``
        - etc.
    * - Required
      - **False**

``libpython.link_to_libpython``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

.. list-table::
    :widths: 25 75

    * - Type
      - ``boolean``
    * - Description
      - Should extensions built against a dynamic ``libpython`` link to
        it?

        This field MUST be present if the Python installation provides a
        dynamic ``libpython`` library, otherwise this entry will be
        missing.
    * - Required
      - **False**

``c_api``
---------

.. list-table::
    :widths: 25 75

    * - Type
      - ``object``
    * - Description
      - Object containing details related to the Python C API, if
        available.

        This section MUST be present if the Python implementation
        provides a C API, otherwise this section will be missing.
    * - Required
      - **False**
    * - Additional properties
      - **Not allowed**

``c_api.headers``
~~~~~~~~~~~~~~~~~

.. list-table::
    :widths: 25 75

    * - Type
      - ``string``
    * - Description
      - The path to the C API headers. Either an absolute path, or a
        relative path to the path defined in the ``base_prefix`` key.
    * - Examples
      - - ``/usr/include/python3.14``
        - ``include/python3.14``
        - etc.
    * - Required
      - **True**

``c_api.pkgconfig_path``
~~~~~~~~~~~~~~~~~~~~~~~~

.. list-table::
    :widths: 25 75

    * - Type
      - ``string``
    * - Description
      - The path to the pkg-config definition files. Either an absolute
        path, or a relative path to the path defined in the
        ``base_prefix`` key.

        This field MUST be present if the Python implementation provides
        pkg-config definition files for the C API, otherwise this
        section will be missing.
    * - Examples
      - - ``/usr/lib/pkgconfig``
        - ``lib/pkgconfig``
        - etc.
    * - Required
      - **False**

``arbitrary_data``
------------------

.. list-table::
    :widths: 25 75

    * - Type
      - ``object``
    * - Description
      - Object containing extra arbitrary data.

        This is meant to be used as an escape-hatch, to include any
        relevant data that is not covered by this specification.
        Implamentations may choose what data to provide in this section.
    * - Required
      - **False**
    * - Additional properties
      - **Allowed**


.. _spec-end:


Example
=======


.. literalinclude:: pep-0739/example.json
   :language: json
   :linenos:


JSON Schema
===========

.. literalinclude:: pep-0739/python-build-info-v1.schema.json
   :language: json
   :linenos:


Rejected Ideas
==============

Having a larger scope
---------------------

One of the main requests in the discussion of this PEP was the inclusion of
other kind of information, such as the ``site-packages`` path. It is the opinion
of the PEP authors that information regarding the Python environment should be
provided by a separate file, creating the a clear separation between the build
details, which should be immutable across any interpreter instance, and details
that can change, such as environment details.


Copyright
=========

This document is placed in the public domain or under the
CC0-1.0-Universal license, whichever is more permissive.
