From f5acaf3b9fdf6e8a86e61ac35b64b8c4b0ec1eb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filipe=20La=C3=ADns?= Date: Wed, 26 Jun 2024 07:54:06 +0100 Subject: [PATCH] PEP 739: update fields based on feedback and add JSON Schema (#3851) --- peps/pep-0739.rst | 571 ++++++++++++++---- peps/pep-0739/example.json | 45 ++ .../pep-0739/python-build-info-v1.schema.json | 228 +++++++ 3 files changed, 741 insertions(+), 103 deletions(-) create mode 100644 peps/pep-0739/example.json create mode 100644 peps/pep-0739/python-build-info-v1.schema.json diff --git a/peps/pep-0739.rst b/peps/pep-0739.rst index af9f14ba4..b4c17b7f9 100644 --- a/peps/pep-0739.rst +++ b/peps/pep-0739.rst @@ -32,151 +32,516 @@ Scope This PEP only defines a format. Python implementations may choose to include a build details file as part of their distribution, but they are not required to, -and the specifics of how that file is provided are completely up to them. +and the specifics of how that may happen are out of scope for this PEP. Specification ============= -The standard Python build description format consists of the JSON representation -of a dictionary with the with the following keys. +The specification is defined by the JSON Schema definition provided below, which +is rendered in an human-readable format here. -schema_version --------------- +.. + Rendered with https://gist.github.com/FFY00/eb02d9da2870aae547bc579b7e17a145 -:Type: ``number`` -:Description: Version of the schema to parse the file contents. It SHOULD be - ``1`` for the format described in this document. Future versions - MAY add, remove, or change fields. Versions that only add fields - MAY choose to only increment the schema version by a decimal - point. +.. _spec-start: -language --------- +.. list-table:: + :widths: 25 75 -Subsection with details related to the Python language specification. + * - ``$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** -version -~~~~~~~ +``schema_version`` +------------------ -:Type: ``string`` -:Description: String representation the Python language version — a version - string consisting only of the *major* and *minor* components (Eg. - ``3.13``). +.. list-table:: + :widths: 25 75 -implementation --------------- + * - Type + - ``string`` (constant — ``1``) + * - Description + - Schema version. This is a constant value and MUST be ``1``. + Future iterations of this schema MUST update this value. + * - Required + - **True** -Subsection with details related to Python implementation. This section SHOULD be -equivalent to :py:data:`sys.implementation` on most implementations, but only -the ``name`` and ``version`` keys are actually required to be present. +``base_prefix`` +--------------- -name -~~~~ +.. list-table:: + :widths: 25 75 -:Type: ``string`` -:Description: Lower-case name of the Python implementation. + * - Type + - ``string`` + * - Description + - Base prefix of the Python installation. -version -~~~~~~~ + Either an absolute path, or a relative path to directory where + this file is contained. + * - Examples + - ``/usr``, ``../..``, etc. + * - Required + - **False** -:Type: ``object`` -:Description: Object in the format of :py:data:`sys.version_info`, containing - the implementation version. +``platform`` +------------ -Implementation-specific keys -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +.. list-table:: + :widths: 25 75 -Additionally to the keys defined above, implementations may choose to include -extra keys with extra implementation-specific details. + * - Type + - ``string`` + * - Description + - System platform string. + * - Examples + - - ``linux-x86_64`` + - etc. + * - Required + - **True** -interpreter ------------ +``language`` +------------ +.. list-table:: + :widths: 25 75 -Subsection with details Python interpreter. If the Python installation does not -provide an interpreter, this section will be missing. + * - Type + - ``object`` + * - Description + - Object containing details related to the Python language + specification. -path -~~~~ + In addition to the required keys, implementations may choose to + include extra keys with implementation-specific details. + * - Required + - **True** + * - Additional properties + - **Not allowed** -:Type: ``string`` -:Description: The path to the Python interprer. Either an absolute path, or a - relative path to the directory containing this file, if - applicable. +``language.version`` +~~~~~~~~~~~~~~~~~~~~ -libpython +.. 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. + * - Examples + - ``3.13``, 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`, but only the ``name`` and + ``version`` keys are actually required to be present. + * - 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. + + If the Python installation does not provide an interpreter, 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`` 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 + - ``['d', 't']``, etc. + * - Required + - **True** + +``abi.extension_suffix`` +~~~~~~~~~~~~~~~~~~~~~~~~ + +.. list-table:: + :widths: 25 75 + + * - Type + - ``string`` + * - Description + - Suffix used for extensions built against the current + implementation version. + * - Examples + - - ``.cpython-313-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. + * - Examples + - ``.abi3.so``, etc. + * - Required + - **False** + +``suffixes`` +------------ + +.. list-table:: + :widths: 25 75 + + * - Type + - ``object`` + * - Description + - Valid module suffixes grouped by type. + * - 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. + + If the Python installation does not provide a ``libpython`` + library, 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`` key.. If the Python installation does not + provide a dynamic ``libpython`` library, this entry will be + missing. + * - Examples + - - ``/usr/lib/libpython3.13.so.1.0`` + - ``lib/libpython3.13.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`` key.. If the Python installation does not + provide a static ``libpython`` library, this entry will be + missing. + * - Examples + - - ``/usr/lib/python3.13/config-3.13-x86_64-linux-gnu/libpython3.13.a`` + - ``lib/python3.13/config-3.13-x86_64-linux-gnu/libpython3.13.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? + * - Required + - **False** + +``c_api`` --------- -Subsection with details related to the ``libpython`` library. If the Python -installation does not provide a ``libpython`` library, this section will be -missing. +.. list-table:: + :widths: 25 75 -dynamic -~~~~~~~ + * - Type + - ``object`` + * - Description + - Object containing details related to the Python C API, if + available. -:Type: ``string`` -:Description: The path to the dynamic ``libpython`` library. Either an absolute - path, or a relative path to the directory containing this file, if - applicable. If the Python installation does not provide a dynamic - ``libpython`` library, this entry will be missing. + If the Python implementation does not provide a C API, this + section will be missing. + * - Required + - **False** + * - Additional properties + - **Not allowed** -static -~~~~~~~ +``c_api.headers`` +~~~~~~~~~~~~~~~~~ -:Type: ``string`` -:Description: The path to the static ``libpython`` library. Either an absolute - path, or a relative path to the directory containing this file, if - applicable. If the Python installation does not provide a static - ``libpython`` library, this entry will be missing. +.. list-table:: + :widths: 25 75 -c_api ------ + * - 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`` key.. + * - Examples + - - ``/usr/include/python3.13`` + - ``include/python3.13`` + - etc. + * - Required + - **True** -Subsection with details related to the Python C API, if available. If the Python -implementation does not provide a C API, this section will be missing. +``c_api.pkgconfig_path`` +~~~~~~~~~~~~~~~~~~~~~~~~ -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 directory containing this file, if - applicable. + * - 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`` + key.. + * - 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. + * - Required + - **False** + * - Additional properties + - **Allowed** + + +.. _spec-end: Example ======= -.. code-block:: json +.. literalinclude:: pep-0739/example.json + :language: json + :linenos: - { - "schema_version": 1, - "language": { - "version": "3.13" - }, - "implementation": { - "name": "cpython", - "version": { - "major": 3, - "minor": 13, - "micro": 1, - "releaselevel": "final", - "serial": 0 - }, - "hexversion": 51184112, - "cache_tag": "cpython-313", - "_multiarch": "x86_64-linux-gnu" - }, - "libpython": { - "dynamic": "/usr/lib/libpython3.13.so.1.0", - "static": "/usr/lib/python3.13/config-3.13-x86_64-linux-gnu/libpython3.13.a", - }, - "c_api": { - "headers": "/usr/include/python3.13" - } - } + +JSON Schema +=========== + +.. literalinclude:: pep-0739/python-build-info-v1.schema.json + :language: json + :linenos: Rejected Ideas diff --git a/peps/pep-0739/example.json b/peps/pep-0739/example.json new file mode 100644 index 000000000..13830e913 --- /dev/null +++ b/peps/pep-0739/example.json @@ -0,0 +1,45 @@ +{ + "schema_version": "1", + "base_prefix": "/usr", + "platform": "linux-x86_64", + "language": { + "version": "3.13" + }, + "implementation": { + "name": "cpython", + "version": { + "major": 3, + "minor": 13, + "micro": 1, + "releaselevel": "final", + "serial": 0 + }, + "hexversion": 51184112, + "cache_tag": "cpython-313", + "_multiarch": "x86_64-linux-gnu" + }, + "interpreter": { + "path": "/usr/bin/python" + }, + "abi": { + "flags": ["d", "t"], + "extension_suffix": ".cpython-313-x86_64-linux-gnu.so", + "stable_abi_suffix": ".abi3.so" + }, + "suffixes": { + "source": [".py"], + "bytecode": [".pyc"], + "optimized_bytecode": [".pyc"], + "debug_bytecode": [".pyc"], + "extensions": [".cpython-313-x86_64-linux-gnu.so", ".abi3.so", ".so"] + }, + "libpython": { + "dynamic": "/usr/lib/libpython3.13.so.1.0", + "static": "/usr/lib/python3.13/config-3.13-x86_64-linux-gnu/libpython3.13.a", + "link_to_libpython": true + }, + "c_api": { + "headers": "/usr/include/python3.13", + "pkgconfig_path": "/usr/lib/pkgconfig" + } +} diff --git a/peps/pep-0739/python-build-info-v1.schema.json b/peps/pep-0739/python-build-info-v1.schema.json new file mode 100644 index 000000000..8d8d3497a --- /dev/null +++ b/peps/pep-0739/python-build-info-v1.schema.json @@ -0,0 +1,228 @@ +{ + "$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", + "type": "object", + "title": "Static description file for the build details of Python installations", + "required": [ + "schema_version", + "platform", + "language", + "implementation" + ], + "additionalProperties": false, + "properties": { + "schema_version": { + "type": "string", + "description": "Schema version. This is a constant value and MUST be ``1``. Future iterations of this schema MUST update this value.", + "const": "1" + }, + "base_prefix": { + "type": "string", + "description": "Base prefix of the Python installation.\n\nEither an absolute path, or a relative path to directory where this file is contained.", + "examples": [ + "/usr", + "../.." + ] + }, + "platform": { + "type": "string", + "description": "System platform string.", + "examples": [ + "linux-x86_64" + ] + }, + "language": { + "type": "object", + "description": "Object containing details related to the Python language specification.\n\nIn addition to the required keys, implementations may choose to include extra keys with implementation-specific details.", + "required": [ + "version" + ], + "additionalProperties": false, + "properties": { + "version": { + "type": "string", + "description": "String representation the Python language version — a version string consisting only of the *major* and *minor* components.", + "examples": ["3.13"] + } + } + }, + "implementation": { + "type": "object", + "description": "Object containing details related to Python implementation.\n\nThis section SHOULD be equivalent to :py:data:`sys.implementation`, but only the ``name`` and ``version`` keys are actually required to be present.", + "required": [ + "name", + "version" + ], + "additionalProperties": true, + "properties": { + "name": { + "type": "string", + "description": "Lower-case name of the Python implementation.", + "examples": ["cpython", "pypy"] + }, + "version": { + "type": "object", + "description": "Object in the format of :py:data:`sys.version_info`, containing the implementation version.", + "required": ["major", "minor", "micro", "releaselevel", "serial"], + "additionalProperties": false, + "examples": [ + { + "major": 3, + "minor": 13, + "micro": 1, + "releaselevel": "final", + "serial": 0 + }, + { + "major": 7, + "minor": 3, + "micro": 16, + "releaselevel": "final", + "serial": 0 + } + ], + "properties": { + "major": { + "type": "number" + }, + "minor": { + "type": "number" + }, + "micro": { + "type": "number" + }, + "releaselevel": { + "type": "string", + "enum": ["alpha", "beta", "candidate", "final"] + }, + "serial": { + "type": "number" + } + } + } + } + }, + "interpreter": { + "type": "object", + "description": "Object containing details Python interpreter.\n\nIf the Python installation does not provide an interpreter, this section will be missing.", + "required": [ + "path" + ], + "additionalProperties": false, + "properties": { + "path": { + "type": "string", + "description": "The path to the Python interprer. Either an absolute path, or a relative path to the path defined in the ``base`` key.", + "examples": [ + "/usr/bin/python", + "bin/python" + ] + } + } + }, + "abi": { + "type": "object", + "description": "Object containing details related to ABI.", + "required": [ + "flags", + "extension_suffix" + ], + "additionalProperties": false, + "properties": { + "flags": { + "type": "array", + "description": "Build configuration flags, used to calculate the extension suffix.\n\nThe flags MUST be defined in the order they appear on the extension suffix.", + "additionalProperties": true, + "examples": [ + ["d", "t"] + ] + }, + "extension_suffix": { + "type": "string", + "description": "Suffix used for extensions built against the current implementation version.", + "examples": [ + ".cpython-313-x86_64-linux-gnu.so" + ] + }, + "stable_abi_suffix": { + "type": "string", + "description": "Suffix used for extensions built against the stable ABI.", + "examples": [ + ".abi3.so" + ] + } + } + }, + "suffixes": { + "type": "object", + "description": "Valid module suffixes grouped by type.", + "examples": [ + { + "source": [".py"], + "bytecode": [".pyc"], + "optimized_bytecode": [".pyc"], + "debug_bytecode": [".pyc"], + "extensions": [".cpython-313-x86_64-linux-gnu.so", ".abi3.so", ".so"] + } + ] + }, + "libpython": { + "type": "object", + "description": "Object containing details related to the ``libpython`` library.\n\nIf the Python installation does not provide a ``libpython`` library, this section will be missing.", + "additionalProperties": false, + "properties": { + "dynamic": { + "type": "string", + "description": "The path to the dynamic ``libpython`` library.\n\nEither an absolute path, or a relative path to the path defined in the ``base`` key.. If the Python installation does not provide a dynamic ``libpython`` library, this entry will be missing.", + "examples": [ + "/usr/lib/libpython3.13.so.1.0", + "lib/libpython3.13.so.1.0" + ] + }, + "static": { + "type": "string", + "description": "The path to the static ``libpython`` library.\n\nEither an absolute path, or a relative path to the path defined in the ``base`` key.. If the Python installation does not provide a static ``libpython`` library, this entry will be missing.", + "examples": [ + "/usr/lib/python3.13/config-3.13-x86_64-linux-gnu/libpython3.13.a", + "lib/python3.13/config-3.13-x86_64-linux-gnu/libpython3.13.a" + ] + }, + "link_to_libpython": { + "type": "boolean", + "description": "Should extensions built against a dynamic ``libpython`` link to it?" + } + } + }, + "c_api": { + "type": "object", + "description": "Object containing details related to the Python C API, if available.\n\nIf the Python implementation does not provide a C API, this section will be missing.", + "required": [ + "headers" + ], + "additionalProperties": false, + "properties": { + "headers": { + "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`` key..", + "examples": [ + "/usr/include/python3.13", + "include/python3.13" + ] + }, + "pkgconfig_path": { + "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`` key..", + "examples": [ + "/usr/lib/pkgconfig", + "lib/pkgconfig" + ] + } + } + }, + "arbitrary_data": { + "type": "object", + "description": "Object containing extra arbitrary data.\n\nThis is meant to be used as an escape-hatch, to include any relevant data that is not covered by this specification.", + "additionalProperties": true + } + } +}