From 86cd1f48caf454ee9c3205bf900395bfff089bde Mon Sep 17 00:00:00 2001 From: "Jonathan J. Helmus" Date: Tue, 25 Aug 2026 12:04:07 -0500 Subject: [PATCH 1/2] convert docs to markdown and build using mkdocs --- .gitignore | 1 + docs/Makefile | 23 +- docs/building.md | 164 ++++++++ docs/building.rst | 152 -------- docs/conf.py | 10 - docs/distributions.md | 704 +++++++++++++++++++++++++++++++++++ docs/distributions.rst | 622 ------------------------------- docs/{index.rst => index.md} | 36 +- docs/quirks.md | 229 ++++++++++++ docs/quirks.rst | 238 ------------ docs/running.md | 403 ++++++++++++++++++++ docs/running.rst | 379 ------------------- docs/status.md | 342 +++++++++++++++++ docs/status.rst | 283 -------------- docs/stylesheets/extra.css | 65 ++++ docs/technotes.md | 156 ++++++++ docs/technotes.rst | 168 --------- mkdocs.yml | 75 ++++ pyproject.toml | 4 + uv.lock | 222 +++++++++++ 20 files changed, 2381 insertions(+), 1895 deletions(-) create mode 100644 docs/building.md delete mode 100644 docs/building.rst delete mode 100644 docs/conf.py create mode 100644 docs/distributions.md delete mode 100644 docs/distributions.rst rename docs/{index.rst => index.md} (65%) create mode 100644 docs/quirks.md delete mode 100644 docs/quirks.rst create mode 100644 docs/running.md delete mode 100644 docs/running.rst create mode 100644 docs/status.md delete mode 100644 docs/status.rst create mode 100644 docs/stylesheets/extra.css create mode 100644 docs/technotes.md delete mode 100644 docs/technotes.rst create mode 100644 mkdocs.yml diff --git a/.gitignore b/.gitignore index b6d4a84ab..3f87e54e2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ .idea/ build/ docs/_build/ +site/ dist/ target/ venv/ diff --git a/docs/Makefile b/docs/Makefile index d4bb2cbb9..7bc57ee54 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -1,20 +1,7 @@ -# Minimal makefile for Sphinx documentation -# +.PHONY: html serve -# You can set these variables from the command line, and also -# from the environment for the first two. -SPHINXOPTS ?= -SPHINXBUILD ?= sphinx-build -SOURCEDIR = . -BUILDDIR = _build +html: + uv run --group docs mkdocs build --strict --config-file ../mkdocs.yml -# Put it first so that "make" without argument is like "make help". -help: - @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) - -.PHONY: help Makefile - -# Catch-all target: route all unknown targets to Sphinx using the new -# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). -%: Makefile - @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) +serve: + uv run --group docs mkdocs serve --config-file ../mkdocs.yml diff --git a/docs/building.md b/docs/building.md new file mode 100644 index 000000000..a879abf7e --- /dev/null +++ b/docs/building.md @@ -0,0 +1,164 @@ + + +# Building + +A Python distribution can be built on a Linux, macOS, or Windows host. +Regardless of the operating system, [uv](https://docs.astral.sh/uv/) +must be installed. Additional operating system requirements are outlined +in the following sections. + +Regardless of the host, to build a Python distribution: + +``` +$ uv run --no-dev build.py +``` + +On Linux and macOS, `./build.py` can also be used; it uses +`uv run --no-dev` via its shebang. + +To build a different version of Python: + +``` +$ uv run --no-dev build.py --python cpython-3.14 +``` + +Various build options can be specified: + +``` +# With profile-guided optimizations (generated code should be faster) +$ uv run --no-dev build.py --options pgo +# Produce a debug build. +$ uv run --no-dev build.py --options debug +# Produce a free-threaded build without extra optimizations +$ uv run --no-dev build.py --options freethreaded+noopt +``` + +Different platforms support different build options. +`uv run --no-dev build.py --help` will show the available build options +and other usage information. + +## Linux + +The host system must be x86-64 or aarch64. The execution environment must +have access to a Docker daemon (all build operations are performed in +Docker containers for isolation from the host system). Docker Buildx must +be installed and available as `docker buildx`. + +`build.py` accepts a `--target-triple` argument to support building +for non-native targets (i.e., cross-compiling). + +This option can be used to build for musl libc: + +``` +$ ./build.py --target-triple x86_64-unknown-linux-musl +``` + +Or on an x86-64 host for different architectures: + +``` +$ ./build.py --target-triple armv7-unknown-linux-gnueabi +$ ./build.py --target-triple armv7-unknown-linux-gnueabihf +$ ./build.py --target-triple ppc64le-unknown-linux-gnu +$ ./build.py --target-triple riscv64-unknown-linux-gnu +$ ./build.py --target-triple s390x-unknown-linux-gnu +``` + +### Jessie image package authentication + +The `build`, `gcc`, and `rust` Dockerfiles include +`cpython-unix/base.Dockerfile`. These amd64 images use Debian Jessie +for build compatibility. Cross-compilation targets also use the `gcc` +image for toolchain builds. + +Building these images requires Docker Buildx with support for Dockerfile +1.6's `ADD --checksum` instruction. + +The base Dockerfile pins the SHA-256 digests of the three archived +`Packages.gz` indexes because Jessie's archive signing keys have expired. +Docker fetches them over HTTPS and verifies their digests before APT uses +them. APT then verifies downloaded packages against the hashes in these +fixed indexes. `trusted=yes` permits this separate trust root; +`apt-get update` is blocked to prevent replacing the pinned indexes with +unauthenticated metadata. + +The pinned base image lacks both `apt-transport-https` and +`ca-certificates`. Their bootstrap download uses HTTP, authenticated by +the pinned package hashes. Once they are installed, subsequent package +downloads use HTTPS with certificate verification. + +The index digests come from the SHA256 sections of the archived +[Jessie Release](https://snapshot.debian.org/archive/debian/20230322T152120Z/dists/jessie/Release), +[Jessie updates Release](https://snapshot.debian.org/archive/debian/20230322T152120Z/dists/jessie-updates/Release), and +[Jessie security Release](https://snapshot.debian.org/archive/debian-security/20230322T152120Z/dists/jessie/updates/Release) +files. The corresponding archive key fingerprints in the digest-pinned +base image are `126C0D24BD8A2942CC7DF8AC7638D0442B90D010` +for Jessie and Jessie updates, and +`D21169141CECD440F2EB8DDA9D6D8F6BC857C906` for Jessie security. Any change +to the snapshot or index digests requires independently authenticating the +replacement metadata. + +## macOS + +The Xcode command-line tools must be installed. +`/usr/bin/clang` must exist. + +macOS SDK headers must be installed. If you see errors such as `stdio.h` +not being found, try running `xcode-select --install` to install them. +Verify they are installed by running `xcrun --show-sdk-path`. It should +print something like +`/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk` +on modern versions of macOS. + +The `--target-triple` argument can be used to build for an Intel Mac on +an arm64 (Apple Silicon) host: + +``` +$ ./build.py --target-triple x86_64-apple-darwin +``` + +Additionally, an arm64 macOS host can be used to build Linux aarch64 and x86-64 +targets using Docker: + +``` +$ ./build.py --target-triple aarch64-unknown-linux-gnu +$ ./build.py --target-triple x86_64-unknown-linux-gnu +``` + +The `APPLE_SDK_PATH` environment variable is recognized as the path +to the Apple SDK to use. If not defined, the build will attempt to find +an SDK by running `xcrun --show-sdk-path`. + +`aarch64-apple-darwin` builds require a macOS 11.0+ SDK. +It should be possible to build for `aarch64-apple-darwin` from +an Intel 10.15 machine (as long as the 11.0+ SDK is used). + +## Windows + +Visual Studio 2022 (or later) is required. For `x86_64-pc-windows-msvc` +targets, use Visual Studio 2026 when building CPython 3.15 or newer. The +`i686-pc-windows-msvc` and `aarch64-pc-windows-msvc` targets continue +to use Visual Studio 2022. +A compatible Windows SDK is required (10.0.26100.0 as of CPython 3.10). +A `git.exe` must be on `PATH` (to clone `libffi` from source). +Cygwin must be installed with the `autoconf`, `automake`, `libtool`, +and `make` packages, which are required to build `libffi`. + +Building can be done from the `x64 Native Tools Command Prompt`, by calling +the vcvars batch file, or by adjusting the `PATH` and environment variables. + +You will need to specify the path to `sh.exe` from Cygwin: + +``` +$ uv run --no-dev build.py --sh c:\cygwin\bin\sh.exe +``` + +When using a version of Visual Studio other than 2022, the version must +be specified with the `--vs` option. For example, to build CPython 3.15 +with Visual Studio 2026: + +``` +$ uv run --no-dev build.py --sh c:\cygwin\bin\sh.exe --vs 2026 --python cpython-3.15 +``` + +To build a 32-bit x86 binary, simply use an +`x86 Native Tools Command Prompt` instead of `x64`. diff --git a/docs/building.rst b/docs/building.rst deleted file mode 100644 index 5ea5ba9a0..000000000 --- a/docs/building.rst +++ /dev/null @@ -1,152 +0,0 @@ -.. _building: - -======== -Building -======== - -A Python distribution can be built on a Linux, macOS, or Windows host. -Regardless of the operating system, `uv `_ -must be installed. Additional operating system requirements are outlined -in the following sections. - -Regardless of the host, to build a Python distribution:: - - $ uv run --no-dev build.py - -On Linux and macOS, ``./build.py`` can also be used; it uses -``uv run --no-dev`` via its shebang. - -To build a different version of Python:: - - $ uv run --no-dev build.py --python cpython-3.14 - -Various build options can be specified:: - - # With profile-guided optimizations (generated code should be faster) - $ uv run --no-dev build.py --options pgo - # Produce a debug build. - $ uv run --no-dev build.py --options debug - # Produce a free-threaded build without extra optimizations - $ uv run --no-dev build.py --options freethreaded+noopt - -Different platforms support different build options. -``uv run --no-dev build.py --help`` will show the available build options -and other usage information. - -Linux -===== - -The host system must be x86-64 or aarch64. The execution environment must -have access to a Docker daemon (all build operations are performed in -Docker containers for isolation from the host system). Docker Buildx must -be installed and available as ``docker buildx``. - -``build.py`` accepts a ``--target-triple`` argument to support building -for non-native targets (i.e., cross-compiling). - -This option can be used to build for musl libc:: - - $ ./build.py --target-triple x86_64-unknown-linux-musl - -Or on an x86-64 host for different architectures:: - - $ ./build.py --target-triple armv7-unknown-linux-gnueabi - $ ./build.py --target-triple armv7-unknown-linux-gnueabihf - $ ./build.py --target-triple ppc64le-unknown-linux-gnu - $ ./build.py --target-triple riscv64-unknown-linux-gnu - $ ./build.py --target-triple s390x-unknown-linux-gnu - -Jessie image package authentication ------------------------------------ - -The ``build``, ``gcc``, and ``rust`` Dockerfiles include -``cpython-unix/base.Dockerfile``. These amd64 images use Debian Jessie -for build compatibility. Cross-compilation targets also use the ``gcc`` -image for toolchain builds. - -Building these images requires Docker Buildx with support for Dockerfile -1.6's ``ADD --checksum`` instruction. - -The base Dockerfile pins the SHA-256 digests of the three archived -``Packages.gz`` indexes because Jessie's archive signing keys have expired. -Docker fetches them over HTTPS and verifies their digests before APT uses -them. APT then verifies downloaded packages against the hashes in these -fixed indexes. ``trusted=yes`` permits this separate trust root; -``apt-get update`` is blocked to prevent replacing the pinned indexes with -unauthenticated metadata. - -The pinned base image lacks both ``apt-transport-https`` and -``ca-certificates``. Their bootstrap download uses HTTP, authenticated by -the pinned package hashes. Once they are installed, subsequent package -downloads use HTTPS with certificate verification. - -The index digests come from the SHA256 sections of the archived -`Jessie Release `_, -`Jessie updates Release `_, and -`Jessie security Release `_ -files. The corresponding archive key fingerprints in the digest-pinned -base image are ``126C0D24BD8A2942CC7DF8AC7638D0442B90D010`` -for Jessie and Jessie updates, and -``D21169141CECD440F2EB8DDA9D6D8F6BC857C906`` for Jessie security. Any change -to the snapshot or index digests requires independently authenticating the -replacement metadata. - -macOS -===== - -The Xcode command-line tools must be installed. -``/usr/bin/clang`` must exist. - -macOS SDK headers must be installed. If you see errors such as ``stdio.h`` -not being found, try running ``xcode-select --install`` to install them. -Verify they are installed by running ``xcrun --show-sdk-path``. It should -print something like -``/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk`` -on modern versions of macOS. - -The ``--target-triple`` argument can be used to build for an Intel Mac on -an arm64 (Apple Silicon) host:: - - $ ./build.py --target-triple x86_64-apple-darwin - -Additionally, an arm64 macOS host can be used to build Linux aarch64 and x86-64 -targets using Docker:: - - $ ./build.py --target-triple aarch64-unknown-linux-gnu - $ ./build.py --target-triple x86_64-unknown-linux-gnu - -The ``APPLE_SDK_PATH`` environment variable is recognized as the path -to the Apple SDK to use. If not defined, the build will attempt to find -an SDK by running ``xcrun --show-sdk-path``. - -``aarch64-apple-darwin`` builds require a macOS 11.0+ SDK. -It should be possible to build for ``aarch64-apple-darwin`` from -an Intel 10.15 machine (as long as the 11.0+ SDK is used). - -Windows -======= - -Visual Studio 2022 (or later) is required. For ``x86_64-pc-windows-msvc`` -targets, use Visual Studio 2026 when building CPython 3.15 or newer. The -``i686-pc-windows-msvc`` and ``aarch64-pc-windows-msvc`` targets continue -to use Visual Studio 2022. -A compatible Windows SDK is required (10.0.26100.0 as of CPython 3.10). -A ``git.exe`` must be on ``PATH`` (to clone ``libffi`` from source). -Cygwin must be installed with the ``autoconf``, ``automake``, ``libtool``, -and ``make`` packages, which are required to build ``libffi``. - -Building can be done from the ``x64 Native Tools Command Prompt``, by calling -the vcvars batch file, or by adjusting the ``PATH`` and environment variables. - -You will need to specify the path to ``sh.exe`` from Cygwin:: - - $ uv run --no-dev build.py --sh c:\cygwin\bin\sh.exe - -When using a version of Visual Studio other than 2022, the version must -be specified with the ``--vs`` option. For example, to build CPython 3.15 -with Visual Studio 2026:: - - $ uv run --no-dev build.py --sh c:\cygwin\bin\sh.exe --vs 2026 --python cpython-3.15 - -To build a 32-bit x86 binary, simply use an -``x86 Native Tools Command Prompt`` instead of ``x64``. diff --git a/docs/conf.py b/docs/conf.py deleted file mode 100644 index c15f06b85..000000000 --- a/docs/conf.py +++ /dev/null @@ -1,10 +0,0 @@ -release = "" -project = "python-build-standalone" -copyright = "2020, Gregory Szorc" -author = "Gregory Szorc" -extensions = [] -templates_path = ["_templates"] -exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"] -html_theme = "alabaster" -html_static_path = ["_static"] -master_doc = "index" diff --git a/docs/distributions.md b/docs/distributions.md new file mode 100644 index 000000000..e5e67c830 --- /dev/null +++ b/docs/distributions.md @@ -0,0 +1,704 @@ + + +# Distribution Archives + +This project produces tarball archives containing Python distributions. + +## Full Archive + +The canonical output of this project's build system are `.tar.zst` +(zstandard compressed tarballs) files. + +All files within the tar are prefixed with `python/`. + +Within the `python/` directory are the following well-known paths: + +PYTHON.json + +: Machine readable file describing this Python distribution. + + See the `PYTHON.json File` section for the format of this file. + +By convention, the `build/` directory contains artifacts from building +this distribution (object files, libraries, etc) and the `install/` directory +contains a working, self-contained Python installation of this distribution. +The `PYTHON.json` file should be read to determine where specific entities +are located within the archive. + +### PYTHON.json File + +The `PYTHON.json` file describes the Python distribution in a machine +readable manner. This file is meant to be opened by downstream consumers +of this distribution so that they may learn things about the distribution +without having to resort to heuristics. + +The file contains a JSON map. This map has the following keys: + +version + +: Version number of the file format. Currently `8`. + +target_triple + +: A target triple defining the platform and architecture of the machine + that binaries target. We use Rust's set of defined targets for values. + Run `rustup target list` to see potential values. + + Example values are `x86_64-unknown-linux-gnu`, + `x86_64-unknown-linux-musl`, `x86_64-pc-windows-msvc`, + and `x86_64-apple-darwin`. + + (Version 5 or above only.) + +optimizations + +: String indicating what optimization profile has been applied to the + build. + + Known values include `debug`, `noopt`, `pgo`, `lto`, and + `pgo+lto`. + + (Deprecated in version 8 in favor of `build_options`.) + +build_options + +: String indicating what build options were used. Options are separated + by a `+`. + + Known values include `debug`, `noopt`, `pgo`, `lto`, `static`, + and `freethreaded`. + + (Version 8 or above only.) + +os + +: Target operating system for the distribution. e.g. `linux`, `macos`, + or `windows`. + + (Deprecated in version 5 in favor of `target_triple`.) + +arch + +: Target architecture for the distribution. e.g. `x86` (32-bit) or + `x86_64` (64-bit). + + (Deprecated in version 5 in favor of `target_triple`.) + +python_tag + +: The PEP 425 *Python Tag* value. e.g. `cp313`. + + (Version 5 or above only.) + +python_abi_tag + +: The PEP 425 *ABI Tag* value. e.g. `cp313m`. + + This may be null if the distribution's platform doesn't expose the concept + of an ABI tag. + + (Version 5 or above only.) + +python_platform_tag + +: The PEP 425 *Platform Tag* value. e.g. `linux_x86_64`. + + (Version 5 or above only.) + +python_flavor + +: Type of Python distribution. e.g. `cpython`. + + (Deprecated in version 5 in favor of PEP 425 tags.) + +python_implementation_cache_tag + +: Tag used by import machinery to derive filenames for bytecode files. + + This is the value exposed by `sys.implementation.cache_tag` + + (Version 5 or above only.) + +python_implementation_hex_version + +: Hexadecimal expression of implementation version. + + This is the value exposed by `sys.implementation.hexversion`. + + (Version 5 or above only.) + +python_implementation_name + +: Name of Python implementation. + + This is the value exposed by `sys.implementation.name`. + + (Version 5 or above only.) + +python_implementation_version + +: Array of version components of Python implementation. + + This is the value exposed by `sys.implementation.version`. + + Unlike `sys.implementation.version`, all elements are strings, + not a mix of numbers and strings. + + (Version 5 or above only.) + +python_version + +: Version of Python distribution. e.g. `3.13.0`. + +python_major_minor_version + +: `X.Y` version string consisting of Python major and minor version. + + (Version 5 or above only.) + +python_paths + +: Mapping of `sysconfig` path names to paths in the distribution. + + Keys are values like `stdlib` and `include`. Values are relative + paths within the distribution. + + See + for the meaning of keys. + + (Version 5 or above only.) + +python_paths_abstract + +: Mapping of `sysconfig` path names with placeholder values. + + See + for the meaning of keys. + + This is equivalent to calling `sysconfig.get_paths(expand=False)`. + + (Version 6 or above only.) + +python_config_vars + +: Mapping of string configuration names to string values. + + This is equivalent to `sysconfig.get_config_vars()` with all values + normalized to strings. + + Many configuration values may represent state as it existed in the + build environment and aren't appropriate for the run-time environment + on a different system. + + (Version 6 or above only.) + +python_exe + +: Relative path to main Python interpreter executable. + +python_include + +: Relative path to include path for Python headers. If this path is on + the compiler's include path, `#include ` should work. + + (Deprecated in version 5 in favor of `python_paths`.) + +python_stdlib + +: Relative path to Python's standard library (where `.py` and resource + files are located). + + (Deprecated in version 5 in favor of `python_paths`.) + +python_stdlib_platform_config + +: Relative path to a `config-` directory in the standard + library containing files used to embed Python in a binary. + + This is a standard directory present in POSIX Python installations + and is not specific to this project. + + The key may be absent if no platform config directory exists. + + (Version 5 or above only.) + +python_stdlib_test_packages + +: Array of strings of Python packages that define tests. (Version 4 or above + only.) + +python_suffixes + +: A map defining file suffixes for various Python file types. Each entry + in the map is an array of strings. + + The map has the following keys. + + `bytecode` + + : Suffixes for bytecode modules. Corresponds to + `importlib.machinery.BYTECODE_SUFFIXES`. e.g. `[".pyc"]`. + + `debug_bytecode` + + : Suffixes for debug bytecode modules. Corresponds to + `importlib.machinery.DEBUG_BYTECODE_SUFFIXES`. e.g. `[".pyc"]`. + + `extension` + + : Suffixes for extension modules. Corresponds to + `importlib.machinery.EXTENSION_SUFFIXES`. e.g. + `[".cpython-313-x86_64-linux-gnu.so", ".abi3.so", ".so"]`. + + `optimized_bytecode` + + : Suffixes for optimized bytecode modules. Corresponds to + `importlib.machinery.OPTIMIZED_BYTECODE_SUFFIXES`. e.g. + `[".pyc"]`. + + `source` + + : Suffixes for source modules. Corresponds to + `importlib.machinery.SOURCE_SUFFIXES`. e.g. `[".py"]`. + + (Version 5 or above only.) + +python_bytecode_magic_number + +: Magic number to use for bytecode files, expressed as a hexadecimal + string. + + (Version 5 or above only.) + +libpython_link_mode + +: How `libpython` is linked. Values can be one of the following: + + `static` + + : Statically linked. + + `shared` + + : Dynamically linked. (A `libpythonXY` shared library will be part + of the distribution.) + + (Version 5 or above only.) + +link_mode + +: Alias of `libpython_link_mode`. + + (Version 4 or above only. Deprecated in version 5.) + +python_symbol_visibility + +: Defines how Python symbols are defined in binaries. + + `global-default` + + : (UNIX only.) Symbols are defined as *global* and have *default* + binding, making them visible outside their defining component. + + `dllexport` + + : (Windows only.) Symbols are exported via `__declspec(dllexport)`, + making them visible to external libraries. + + (Version 5 or above only.) + +python_extension_module_loading + +: Defines support for loading Python extension modules. + + The value is an array of strings denoting support for various + loading mechanisms. + + Note that downstream consumers reconstructing a new binary from + object files or a static library can alter support depending on + how that binary is linked. + + The special values are as follows. + + `builtin` + + : Supports loading of *builtin* extension modules compiled into + the binary. (This should always be present.) + + `shared-library` + + : Supports loading of extension modules defined as shared + libraries. e.g. from `.so` or `.pyd` files. + + (Version 5 or above only.) + +apple_sdk_canonical_name + +: Optional canonical name of Apple SDK used to build. + + Should only be present for target triples with `apple` in them. + + The canonical name can be used to find a copy of this SDK on another + machine. + + (Version 7 or above only.) + +apple_sdk_platform + +: Optional name of the platform of the Apple SDK used to build. + + Should only be present for target triples with `apple` in them. + + e.g. `macosx` + + (Version 7 or above only.) + +apple_sdk_version + +: Optional version of the Apple SDK used to build. + + Should only be present for target triples with `apple` in them. + + If relinking build artifacts, ideally this exact SDK version is used. + Newer versions will likely work. Older versions or Clang toolchains + associated with older versions may not. + + (Version 7 or above only.) + +apple_sdk_deployment_target + +: Optional version of the Apple SDK deployment target used to build. + + This effectively establishes a minimum version of the target operating + system this binary is purportedly compatible with. + + (Version 7 or above only.) + +crt_features + +: Describes C Runtime features/requirements for binaries. + + The value is an array of strings denoting various properties. + + The special string values are as follows. + + `glibc-dynamic` + + : Binaries link dynamically against glibc. + + `glibc-max-symbol-version:N` + + : Denotes the max symbol version seen in glibc versioned symbols. + + This effectively advertises the oldest version of glibc that + binaries support and indirectly advertises the oldest Linux + distributions binaries can run on. + + `static` + + : Binaries link the CRT statically. + + `vcruntime:N` + + : Binaries link against the Microsoft Visual C++ Redistributable Runtime, + version `N`. `N` is a string like `140`, which denotes the + version component in a `vcruntimeXYZ.dll` file. + + `libSystem` + + : Binaries link against `libSystem.B.dylib`, which is the mega + library backing a lot of systems-level functionality in macOS. + + (Version 5 or above only.) + +run_tests + +: The path to a Python script to run the test harness for this + distribution. + + (Version 5 or above only.) + +build_info + +: A map describing build configuration and artifacts for this distribution. + + See the `build_info Data` section below. + +licenses + +: > Array of strings containing the license shortname identifiers from the + > SPDX license list () for the Python distribution. + + (Version 2 or above only.) + +license_path + +: Path to a text file containing the license for this Python distribution. + + (Version 2 or above only.) + +tcl_library_path + +: Relative path to location of tcl library files. The path should be a + directory tree containing tcl files to support the tkinter extension. + This will include a subset of the library files provided by the tcl + and tk packages. + + This points to the root directory containing tcl resources. Actual + tcl resources are in sub-directories underneath, as identified by + `tcl_library_paths`. + + (Version 3 or above only.) + +tcl_library_paths + +: Array of relative paths holding tcl library files relative to + `tcl_library_path`. + + Because `tcl_library_path` can be shared with other resources + (e.g. on UNIX the path is typically `install/lib`, which holds + system libraries as well), distributions may advertise the list + of directories under `tcl_library_path` actually containing + tcl resources. + + (Version 5 or above only.) + +### build_info Data + +The `build_info` key in the `PYTHON.json` file describes build artifacts +in the Python distribution. The primary goal of the data is to give downstream +distribution consumers enough details to integrate build artifacts into their +own build systems. This includes the ability to produce a Python binary with a +custom set of built-in extension modules. + +This map has the following keys: + +core + +: A map describing the core Python distribution (essentially `libpython`). + + objs + + : An array of paths to object files constituting the Python core distribution. + + Core object files are typically object files that are linked together to + create libpython. + + links + + : An array of linking requirement maps. (See below for data format.) + + shared_lib + + : Path to a shared library representing `libpython`. May not be defined. + (Version 4 or above only.) + + static_lib + + : Path to a static library representing `libpython`. May not be defined. + (Version 4 or above only.) + + inittab_object + + : Path to object file defining `_PyImport_Inittab`, which defines + built-in extension modules. + + (Version 5 or above only.) + + inittab_source + + : Path to source code file that defines `_PyImport_Inittab`. On + CPython, this will point to a `config.c` file. + + (Version 5 or above only.) + + inittab_cflags + + : Array of strings constituting compiler flags to use when compiling + `inittab_source`. + + (Version 5 or above only.) + +extensions + +: A map of extension names to an array of maps describing candidate extensions. + + Extensions are non-core/non-essential parts of the Python distribution that + are frequently built as standalone entities. + + Names in this map denote the name of the extension module. + + Values are arrays of maps. Each map represents a potential candidate + providing the extension. There is frequently only a single extension + candidate. Multiple candidates can occur if there are e.g. varying + libraries an extension can be linked against to supply underlying + functionality. + + Each map has the following keys: + + in_core + + : Boolean indicating if this extension is defined by the core distribution. + + If true, object files should be in the `['core']['objs']` array, not the + `objs` array in this map. + + Downstream consumers should key off this value to determine how to + assemble this extension's code into a new distribution. + + This field was introduced to support Windows, where CPython's Visual + Studio project files define various extensions as part of the project + providing libpython. This is in contrast to make-based builds, where + the `Modules/Setup.*` files treat each extension as separate entities. + + init_fn + + : The name of the extension module initialization function for this + extension. + + The string value may be `NULL`, which may need special handling by + consumers. + + licenses + + : Array of strings containing the license shortname identifiers from the + SPDX license list (). + + If this field is missing, licenses are unknown. Empty array denotes no known + licenses. + + The license applies to additional libraries needed by this extension, not + the extension itself, as extensions should be licensed the same as the + Python distribution. + + (Version 2 or above only.) + + license_path + + : Paths to text files containing the licenses for this extension. + + (Version 2 or above only.) + + license_public_domain + + : Bool indicating that the license for the extension is in the public + domain. + + There is no SPDX identifier for public domain. And we want to be explicit + about something being in the public domain because of the legal implications. + + (Version 2 or above only.) + + links + + : An array of linking requirement maps. (See below for data format.) + + objs + + : An array of paths to object files constituting this extension module. + + required + + : Boolean indicating if this extension is required to initialize the Python + interpreter. + + shared_lib + + : The path to a shared library defining this extension module. May not + be defined. (Version 4 or above only.) + + static_lib + + : The path to a static library defining this extension module. May not + be defined. + + variant + + : String describing this extension variant. Downstream consumers can key off + this value to choose an appropriate extension variant when there are + multiple options. + +object_file_format + +: Denotes the data format for object files. Can be one of the following + values. + + `elf` + + : Standard object file format for Linux. + + `llvm-bitcode:N` + + : Files are LLVM bitcode produced with LLVM version `N`. e.g. + `llvm-bitcode:10.0.0`. + + This variant is typically seen for builds using LTO. + + `coff` + + : Standard object file format for Windows. + + `mach-o` + + : Standard object file format for macOS. + + (Version 5 or newer only.) + +Each entry in a `links` array is a map with the following keys: + +name + +: Name of the library being linked against. + +path_static + +: Path to the static version of this library, if available in the + distribution. + +path_dynamic + +: Path to the dynamic version of this library, if available in the + distribution. + +framework + +: Denotes that the link target is a macOS framework. + +system + +: Denotes that the link target is a system library. + + System libraries are typically passed into the linker by name only and + found using default library search paths. + +## Install Only Archive + +At release time, this project produces tar files containing just the +Python installation, without the `PYTHON.json` or build files from +the full `.tar.zst` archives. These are referred to as *install only* +archives. + +An *install only* archive is created by taking a `.tar.zst` and +rewriting `python/install/*` to `python/*`. All files not under +`python/install/*` are not carried forward to the *install only* +archive. + +For each Python version, target, and threading variant, the fastest +available build is selected for the *install only* archive. Builds are +generally preferred in the following order: `pgo+lto`, `pgo`, +`lto`, `noopt`. + +An *install only stripped* archive is also available. This archive is +equivalent to *install only*, but without debug symbols, which results in a +smaller download and on-disk footprint. + +For CPython 3.13 and newer, *install only* and *install only stripped* +archives are created separately for the GIL-enabled and free-threaded +variants. Free-threaded archives include `freethreaded` in the filename. + +For musl targets, *install only* archives use dynamically linked builds. +Fully static musl builds are only available as *full* archives with +`+static` in their build options. + +For maximum compatibility, *install only* and *install only stripped* +archives use gzip compression. diff --git a/docs/distributions.rst b/docs/distributions.rst deleted file mode 100644 index 5d73e7417..000000000 --- a/docs/distributions.rst +++ /dev/null @@ -1,622 +0,0 @@ -.. _distributions: - -===================== -Distribution Archives -===================== - -This project produces tarball archives containing Python distributions. - -Full Archive -============ - -The canonical output of this project's build system are ``.tar.zst`` -(zstandard compressed tarballs) files. - -All files within the tar are prefixed with ``python/``. - -Within the ``python/`` directory are the following well-known paths: - -PYTHON.json - Machine readable file describing this Python distribution. - - See the ``PYTHON.json File`` section for the format of this file. - -By convention, the ``build/`` directory contains artifacts from building -this distribution (object files, libraries, etc) and the ``install/`` directory -contains a working, self-contained Python installation of this distribution. -The ``PYTHON.json`` file should be read to determine where specific entities -are located within the archive. - -PYTHON.json File ----------------- - -The ``PYTHON.json`` file describes the Python distribution in a machine -readable manner. This file is meant to be opened by downstream consumers -of this distribution so that they may learn things about the distribution -without having to resort to heuristics. - -The file contains a JSON map. This map has the following keys: - -version - Version number of the file format. Currently ``8``. - -target_triple - A target triple defining the platform and architecture of the machine - that binaries target. We use Rust's set of defined targets for values. - Run ``rustup target list`` to see potential values. - - Example values are ``x86_64-unknown-linux-gnu``, - ``x86_64-unknown-linux-musl``, ``x86_64-pc-windows-msvc``, - and ``x86_64-apple-darwin``. - - (Version 5 or above only.) - -optimizations - String indicating what optimization profile has been applied to the - build. - - Known values include ``debug``, ``noopt``, ``pgo``, ``lto``, and - ``pgo+lto``. - - (Deprecated in version 8 in favor of ``build_options``.) - -build_options - String indicating what build options were used. Options are separated - by a ``+``. - - Known values include ``debug``, ``noopt``, ``pgo``, ``lto``, ``static``, - and ``freethreaded``. - - (Version 8 or above only.) - -os - Target operating system for the distribution. e.g. ``linux``, ``macos``, - or ``windows``. - - (Deprecated in version 5 in favor of ``target_triple``.) - -arch - Target architecture for the distribution. e.g. ``x86`` (32-bit) or - ``x86_64`` (64-bit). - - (Deprecated in version 5 in favor of ``target_triple``.) - -python_tag - The PEP 425 *Python Tag* value. e.g. ``cp313``. - - (Version 5 or above only.) - -python_abi_tag - The PEP 425 *ABI Tag* value. e.g. ``cp313m``. - - This may be null if the distribution's platform doesn't expose the concept - of an ABI tag. - - (Version 5 or above only.) - -python_platform_tag - The PEP 425 *Platform Tag* value. e.g. ``linux_x86_64``. - - (Version 5 or above only.) - -python_flavor - Type of Python distribution. e.g. ``cpython``. - - (Deprecated in version 5 in favor of PEP 425 tags.) - -python_implementation_cache_tag - Tag used by import machinery to derive filenames for bytecode files. - - This is the value exposed by ``sys.implementation.cache_tag`` - - (Version 5 or above only.) - -python_implementation_hex_version - Hexadecimal expression of implementation version. - - This is the value exposed by ``sys.implementation.hexversion``. - - (Version 5 or above only.) - -python_implementation_name - Name of Python implementation. - - This is the value exposed by ``sys.implementation.name``. - - (Version 5 or above only.) - -python_implementation_version - Array of version components of Python implementation. - - This is the value exposed by ``sys.implementation.version``. - - Unlike ``sys.implementation.version``, all elements are strings, - not a mix of numbers and strings. - - (Version 5 or above only.) - -python_version - Version of Python distribution. e.g. ``3.13.0``. - -python_major_minor_version - ``X.Y`` version string consisting of Python major and minor version. - - (Version 5 or above only.) - -python_paths - Mapping of ``sysconfig`` path names to paths in the distribution. - - Keys are values like ``stdlib`` and ``include``. Values are relative - paths within the distribution. - - See https://docs.python.org/3/library/sysconfig.html#installation-paths - for the meaning of keys. - - (Version 5 or above only.) - -python_paths_abstract - Mapping of ``sysconfig`` path names with placeholder values. - - See https://docs.python.org/3/library/sysconfig.html#installation-paths - for the meaning of keys. - - This is equivalent to calling ``sysconfig.get_paths(expand=False)``. - - (Version 6 or above only.) - -python_config_vars - Mapping of string configuration names to string values. - - This is equivalent to ``sysconfig.get_config_vars()`` with all values - normalized to strings. - - Many configuration values may represent state as it existed in the - build environment and aren't appropriate for the run-time environment - on a different system. - - (Version 6 or above only.) - -python_exe - Relative path to main Python interpreter executable. - -python_include - Relative path to include path for Python headers. If this path is on - the compiler's include path, ``#include `` should work. - - (Deprecated in version 5 in favor of ``python_paths``.) - -python_stdlib - Relative path to Python's standard library (where ``.py`` and resource - files are located). - - (Deprecated in version 5 in favor of ``python_paths``.) - -python_stdlib_platform_config - Relative path to a ``config-`` directory in the standard - library containing files used to embed Python in a binary. - - This is a standard directory present in POSIX Python installations - and is not specific to this project. - - The key may be absent if no platform config directory exists. - - (Version 5 or above only.) - -python_stdlib_test_packages - Array of strings of Python packages that define tests. (Version 4 or above - only.) - -python_suffixes - A map defining file suffixes for various Python file types. Each entry - in the map is an array of strings. - - The map has the following keys. - - ``bytecode`` - Suffixes for bytecode modules. Corresponds to - ``importlib.machinery.BYTECODE_SUFFIXES``. e.g. ``[".pyc"]``. - - ``debug_bytecode`` - Suffixes for debug bytecode modules. Corresponds to - ``importlib.machinery.DEBUG_BYTECODE_SUFFIXES``. e.g. ``[".pyc"]``. - - ``extension`` - Suffixes for extension modules. Corresponds to - ``importlib.machinery.EXTENSION_SUFFIXES``. e.g. - ``[".cpython-313-x86_64-linux-gnu.so", ".abi3.so", ".so"]``. - - ``optimized_bytecode`` - Suffixes for optimized bytecode modules. Corresponds to - ``importlib.machinery.OPTIMIZED_BYTECODE_SUFFIXES``. e.g. - ``[".pyc"]``. - - ``source`` - Suffixes for source modules. Corresponds to - ``importlib.machinery.SOURCE_SUFFIXES``. e.g. ``[".py"]``. - - (Version 5 or above only.) - -python_bytecode_magic_number - Magic number to use for bytecode files, expressed as a hexadecimal - string. - - (Version 5 or above only.) - -libpython_link_mode - How `libpython` is linked. Values can be one of the following: - - `static` - Statically linked. - - `shared` - Dynamically linked. (A `libpythonXY` shared library will be part - of the distribution.) - - (Version 5 or above only.) - -link_mode - Alias of ``libpython_link_mode``. - - (Version 4 or above only. Deprecated in version 5.) - -python_symbol_visibility - Defines how Python symbols are defined in binaries. - - ``global-default`` - (UNIX only.) Symbols are defined as *global* and have *default* - binding, making them visible outside their defining component. - - ``dllexport`` - (Windows only.) Symbols are exported via ``__declspec(dllexport)``, - making them visible to external libraries. - - (Version 5 or above only.) - -python_extension_module_loading - Defines support for loading Python extension modules. - - The value is an array of strings denoting support for various - loading mechanisms. - - Note that downstream consumers reconstructing a new binary from - object files or a static library can alter support depending on - how that binary is linked. - - The special values are as follows. - - ``builtin`` - Supports loading of *builtin* extension modules compiled into - the binary. (This should always be present.) - - ``shared-library`` - Supports loading of extension modules defined as shared - libraries. e.g. from ``.so`` or ``.pyd`` files. - - (Version 5 or above only.) - -apple_sdk_canonical_name - Optional canonical name of Apple SDK used to build. - - Should only be present for target triples with ``apple`` in them. - - The canonical name can be used to find a copy of this SDK on another - machine. - - (Version 7 or above only.) - -apple_sdk_platform - Optional name of the platform of the Apple SDK used to build. - - Should only be present for target triples with ``apple`` in them. - - e.g. ``macosx`` - - (Version 7 or above only.) - -apple_sdk_version - Optional version of the Apple SDK used to build. - - Should only be present for target triples with ``apple`` in them. - - If relinking build artifacts, ideally this exact SDK version is used. - Newer versions will likely work. Older versions or Clang toolchains - associated with older versions may not. - - (Version 7 or above only.) - -apple_sdk_deployment_target - Optional version of the Apple SDK deployment target used to build. - - This effectively establishes a minimum version of the target operating - system this binary is purportedly compatible with. - - (Version 7 or above only.) - -crt_features - Describes C Runtime features/requirements for binaries. - - The value is an array of strings denoting various properties. - - The special string values are as follows. - - ``glibc-dynamic`` - Binaries link dynamically against glibc. - - ``glibc-max-symbol-version:N`` - Denotes the max symbol version seen in glibc versioned symbols. - - This effectively advertises the oldest version of glibc that - binaries support and indirectly advertises the oldest Linux - distributions binaries can run on. - - ``static`` - Binaries link the CRT statically. - - ``vcruntime:N`` - Binaries link against the Microsoft Visual C++ Redistributable Runtime, - version ``N``. ``N`` is a string like ``140``, which denotes the - version component in a ``vcruntimeXYZ.dll`` file. - - ``libSystem`` - Binaries link against ``libSystem.B.dylib``, which is the mega - library backing a lot of systems-level functionality in macOS. - - (Version 5 or above only.) - -run_tests - The path to a Python script to run the test harness for this - distribution. - - (Version 5 or above only.) - -build_info - A map describing build configuration and artifacts for this distribution. - - See the ``build_info Data`` section below. - -licenses - Array of strings containing the license shortname identifiers from the - SPDX license list (https://spdx.org/licenses/) for the Python distribution. - - (Version 2 or above only.) - -license_path - Path to a text file containing the license for this Python distribution. - - (Version 2 or above only.) - -tcl_library_path - Relative path to location of tcl library files. The path should be a - directory tree containing tcl files to support the tkinter extension. - This will include a subset of the library files provided by the tcl - and tk packages. - - This points to the root directory containing tcl resources. Actual - tcl resources are in sub-directories underneath, as identified by - ``tcl_library_paths``. - - (Version 3 or above only.) - -tcl_library_paths - Array of relative paths holding tcl library files relative to - ``tcl_library_path``. - - Because ``tcl_library_path`` can be shared with other resources - (e.g. on UNIX the path is typically ``install/lib``, which holds - system libraries as well), distributions may advertise the list - of directories under ``tcl_library_path`` actually containing - tcl resources. - - (Version 5 or above only.) - -build_info Data ---------------- - -The ``build_info`` key in the ``PYTHON.json`` file describes build artifacts -in the Python distribution. The primary goal of the data is to give downstream -distribution consumers enough details to integrate build artifacts into their -own build systems. This includes the ability to produce a Python binary with a -custom set of built-in extension modules. - -This map has the following keys: - -core - A map describing the core Python distribution (essentially `libpython`). - - objs - An array of paths to object files constituting the Python core distribution. - - Core object files are typically object files that are linked together to - create libpython. - - links - An array of linking requirement maps. (See below for data format.) - - shared_lib - Path to a shared library representing `libpython`. May not be defined. - (Version 4 or above only.) - - static_lib - Path to a static library representing `libpython`. May not be defined. - (Version 4 or above only.) - - inittab_object - Path to object file defining ``_PyImport_Inittab``, which defines - built-in extension modules. - - (Version 5 or above only.) - - inittab_source - Path to source code file that defines ``_PyImport_Inittab``. On - CPython, this will point to a ``config.c`` file. - - (Version 5 or above only.) - - inittab_cflags - Array of strings constituting compiler flags to use when compiling - ``inittab_source``. - - (Version 5 or above only.) - -extensions - A map of extension names to an array of maps describing candidate extensions. - - Extensions are non-core/non-essential parts of the Python distribution that - are frequently built as standalone entities. - - Names in this map denote the name of the extension module. - - Values are arrays of maps. Each map represents a potential candidate - providing the extension. There is frequently only a single extension - candidate. Multiple candidates can occur if there are e.g. varying - libraries an extension can be linked against to supply underlying - functionality. - - Each map has the following keys: - - in_core - Boolean indicating if this extension is defined by the core distribution. - - If true, object files should be in the ``['core']['objs']`` array, not the - ``objs`` array in this map. - - Downstream consumers should key off this value to determine how to - assemble this extension's code into a new distribution. - - This field was introduced to support Windows, where CPython's Visual - Studio project files define various extensions as part of the project - providing libpython. This is in contrast to make-based builds, where - the ``Modules/Setup.*`` files treat each extension as separate entities. - - init_fn - The name of the extension module initialization function for this - extension. - - The string value may be ``NULL``, which may need special handling by - consumers. - - licenses - Array of strings containing the license shortname identifiers from the - SPDX license list (https://spdx.org/licenses/). - - If this field is missing, licenses are unknown. Empty array denotes no known - licenses. - - The license applies to additional libraries needed by this extension, not - the extension itself, as extensions should be licensed the same as the - Python distribution. - - (Version 2 or above only.) - - license_path - Paths to text files containing the licenses for this extension. - - (Version 2 or above only.) - - license_public_domain - Bool indicating that the license for the extension is in the public - domain. - - There is no SPDX identifier for public domain. And we want to be explicit - about something being in the public domain because of the legal implications. - - (Version 2 or above only.) - - links - An array of linking requirement maps. (See below for data format.) - - objs - An array of paths to object files constituting this extension module. - - required - Boolean indicating if this extension is required to initialize the Python - interpreter. - - shared_lib - The path to a shared library defining this extension module. May not - be defined. (Version 4 or above only.) - - static_lib - The path to a static library defining this extension module. May not - be defined. - - variant - String describing this extension variant. Downstream consumers can key off - this value to choose an appropriate extension variant when there are - multiple options. - -object_file_format - Denotes the data format for object files. Can be one of the following - values. - - ``elf`` - Standard object file format for Linux. - - ``llvm-bitcode:N`` - Files are LLVM bitcode produced with LLVM version ``N``. e.g. - ``llvm-bitcode:10.0.0``. - - This variant is typically seen for builds using LTO. - - ``coff`` - Standard object file format for Windows. - - ``mach-o`` - Standard object file format for macOS. - - (Version 5 or newer only.) - -Each entry in a ``links`` array is a map with the following keys: - -name - Name of the library being linked against. - -path_static - Path to the static version of this library, if available in the - distribution. - -path_dynamic - Path to the dynamic version of this library, if available in the - distribution. - -framework - Denotes that the link target is a macOS framework. - -system - Denotes that the link target is a system library. - - System libraries are typically passed into the linker by name only and - found using default library search paths. - -Install Only Archive -==================== - -At release time, this project produces tar files containing just the -Python installation, without the ``PYTHON.json`` or build files from -the full ``.tar.zst`` archives. These are referred to as *install only* -archives. - -An *install only* archive is created by taking a ``.tar.zst`` and -rewriting ``python/install/*`` to ``python/*``. All files not under -``python/install/*`` are not carried forward to the *install only* -archive. - -For each Python version, target, and threading variant, the fastest -available build is selected for the *install only* archive. Builds are -generally preferred in the following order: ``pgo+lto``, ``pgo``, -``lto``, ``noopt``. - -An *install only stripped* archive is also available. This archive is -equivalent to *install only*, but without debug symbols, which results in a -smaller download and on-disk footprint. - -For CPython 3.13 and newer, *install only* and *install only stripped* -archives are created separately for the GIL-enabled and free-threaded -variants. Free-threaded archives include ``freethreaded`` in the filename. - -For musl targets, *install only* archives use dynamically linked builds. -Fully static musl builds are only available as *full* archives with -``+static`` in their build options. - -For maximum compatibility, *install only* and *install only stripped* -archives use gzip compression. diff --git a/docs/index.rst b/docs/index.md similarity index 65% rename from docs/index.rst rename to docs/index.md index 0a5460f4c..599ae868f 100644 --- a/docs/index.rst +++ b/docs/index.md @@ -1,5 +1,4 @@ -Python Standalone Builds -======================== +# Python Standalone Builds This project produces self-contained, highly portable, high-performance Python distributions. These Python distributions contain a fully usable, @@ -19,30 +18,17 @@ BOLT post-link binary optimization. Together, these techniques improve runtime performance while preserving portability. The most common method of using these distributions is with -`uv `_. +[uv](https://docs.astral.sh/uv/). -To run a particular distribution using ``uv``:: +To run a particular distribution using `uv`: - uvx --managed-python python +``` +uvx --managed-python python +``` -A Python version or another specifier can be included:: +A Python version or another specifier can be included: - uvx --managed-python python@3.13 - uvx --managed-python python@3.14+freethreaded - -.. toctree:: - :maxdepth: 2 - :caption: Contents: - - running - building - quirks - technotes - distributions - status - -Indices and tables -================== - -* :ref:`genindex` -* :ref:`search` +``` +uvx --managed-python python@3.13 +uvx --managed-python python@3.14+freethreaded +``` diff --git a/docs/quirks.md b/docs/quirks.md new file mode 100644 index 000000000..eac2f24f2 --- /dev/null +++ b/docs/quirks.md @@ -0,0 +1,229 @@ + + +# Behavior Quirks + +While these Python distributions are intended to be broadly compatible +with the Python ecosystem, there are a few known behavior quirks that +affect specific environments, packages, or use cases. + + + +## If special keys do not work in the Python REPL + +If you attempt to run `python` and the backspace key doesn't +erase characters or the arrow keys don't work as expected, this +is because the executable can't find the *terminfo database*. + +If this happens, the Python REPL will print the following warning +message on startup: + +``` +Cannot read termcap database; +using dumb terminal settings. +``` + +When you type a special key like the backspace key, this is +registered as a key press. There is special software (typically +`readline` or `libedit`) that most interactive programs use +that intercepts these special key presses and converts them into +special behavior, such as moving the cursor back instead of +forward. But because computer environments are different, +there needs to be some definition of how these special +behaviors are performed. This is the *terminfo database*. + +When `readline` and `libedit` are compiled, there is +typically a hard-coded set of search locations for the +*terminfo database* baked into the built library. And when +you build a program (like Python) locally, you link against +`readline` or `libedit` and get these default locations +*for free*. + +These Python distributions compile and use their own version of +`libedit` to avoid a dependency on what is (or isn't) installed on +your system. This means that they do not use your system-provided +libraries for reading the *terminfo database*. This version of +`libedit` is configured to look for in locations that should work for +most OSes (specifically, `/usr/share/terminfo` on macOS, and +`/etc/terminfo`, `/lib/terminfo`, and `/usr/share/terminfo` on +Linux, which should cover all major Linux distributions), but it is +possible that your environment has it somewhere else. If your OS stores +the *terminfo database* in an uncommon location, you can set the +`TERMINFO_DIRS` environment variable so that `libedit` can find it. + +For instance, you may need to do something like: + +> \$ TERMINFO_DIRS=/uncommon/place/terminfo install/bin/python3.10 + +If you are running on a relatively standard OS and this does not work +out of the box, please file a bug report so we can add the location of +the *terminfo database* to the build. + +For convenience, a relatively recent copy of the terminfo database +is distributed in the `share/terminfo` directory (`../../share/terminfo` +relative to the `bin/python3` executable) in Linux distributions. Note +that ncurses and derived libraries don't know how to find this directory +since they are configured to use absolute paths to the terminfo database +and the absolute path of the Python distribution is obviously not known +at build time! So actually using this bundled terminfo database will +require custom code setting `TERMINFO_DIRS` before +ncurses/libedit/readline are loaded. + + + +## No tix on UNIX + +Tix is an old widget library for Tcl/Tk. Python previously had a wrapper +for it in `tkinter.tix`, but it was deprecated in Python 3.6 (the +recommendation is to use `tkinter.ttk`) and removed in Python 3.13. + +The macOS and Linux distributions from this project do not build and +ship Tix, even for Python versions 3.12 and below. + +We had previously attempted to ship Tix support on Linux, but it was +broken and nobody reported an issue about it. The macOS distributions +from this project never shipped support for Tix. The official Python.org +macOS installers and Apple's build of Python do not ship support for +Tix, either, so this project behaves similarly to those distributions. + + + +## No `pip.exe` on Windows + +The Windows distributions have `pip` installed however no `Scripts/pip.exe`, +`Scripts/pip3.exe`, and `Scripts/pipX.Y.exe` files are provided because +the way these executables are built isn't portable. (It might be possible to +change how these are built to make them portable.) + +To use pip, run `python.exe -m pip`. (It is generally a best practice to +invoke pip via `python -m pip` on all platforms so you can be explicit +about the `python` executable that pip uses.) + + + +## Linking Static Library on macOS + +Python 3.10+ makes use of the `__builtin_available()` compiler feature. +This functionality requires a symbol from `libclang_rt`, which may not +be linked by default. Failure to link against `libclang_rt` could result +in a linker error due to an undefined symbol `___isOSVersionAtLeast`. + +To work around this linker failure, link against the static library +`libclang_rt..a` present in the Clang installation. e.g. +`libclang_rt.osx.a`. You can find this library by invoking +`clang --print-search-dirs` and looking in the `lib/darwin` directory +under the printed `libraries` directory. An example path is +`/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/12.0.0/lib/darwin/libclang_rt.osx.a`. + +A copy of the `libclang_rt..a` from the Clang used to build +the distribution is included in the archive. However, it isn't annotated +in `PYTHON.json` because we're unsure if using the file with another +build/version of Clang is supported. Use at your own risk. + +See and + for more on this topic. + + + +## Use of `libedit` on Linux + +Python 3.10+ Linux distributions link against `libedit` (as opposed to +`readline`) by default, as `libedit` is supported on 3.10+ outside of +macOS. + +Most Python builds on Linux will link against `readline` because `readline` +is the dominant library on Linux. + +Some functionality may behave subtly differently as a result of our choice +to link `libedit` by default. (We choose `libedit` by default to +avoid GPL licensing requirements of `readline`.) + + + +## References to Build-Time Paths + +The built Python distribution captures some absolute paths and other +build-time configuration in a handful of files: + +- In a `_sysconfigdata_*.py` file in the standard library. e.g. + `lib/python3.10/_sysconfigdata__linux_x86_64-linux-gnu.py`. +- In a `Makefile` under a `config-*` directory in the standard library. + e.g. `lib/python3.10/config-3.10-x86_64-linux-gnu/Makefile`. +- In python-build-standalone's metadata file `PYTHON.json` (mostly + reflected values from `_sysconfigdata_*.py`). + +Each of these serves a different use case. But the general theme is various +aspects of the Python distribution attempt to capture how Python was built. +The most common use of these values is to facilitate compiling or linking +other software against this Python build. For example, the `_sysconfigdata*` +module is loaded by the [sysconfig](https://docs.python.org/3/library/sysconfig.html) +module. `sysconfig` in turn is used by packaging tools like `setuptools` +and `pip` to figure out how to invoke a compiler for e.g. compiling C +extensions from source. + +When installed by [uv](https://docs.astral.sh/uv/), these absolute +paths are fixed up to point to the actual location on your system where +the distribution was installed, so **this quirk generally does not +affect uv users**. The third-party tool [sysconfigpatcher](https://github.com/bluss/sysconfigpatcher) also does this and might +be helpful to use or reference if you are installing these distributions +on your own. + +In particular, you may see references to our install-time paths on the +build infrastructure, e.g., `/build` and `/install` on Linux, a +particular SDK in `/Applications/Xcode.app` on macOS, and temporary +directories on Windows. + +Also, Python reports the compiler and flags in use, just in case it is +needed to make binary-compatible extensions. On Linux, for instance, we +use our own builds of Clang and potentially some flags (warnings, +optimizations, locations of the build environment) that do not work or +apply in other environments. We try to configure Python to remove +unneeded flags and absolute paths to files in the build environment. +references to build-time paths. Python's `sysconfig` system requires +listing a compiler, so we leave it set to `clang` without the absolute +path, but you should be able to use another compiler like `gcc` to +compile extensions, too. + +If there is a build time normalization that you think should be performed to +make distributions more portable, please file a GitHub issue. + + + + + + + +## Former quirks + +The following quirks were previously listed on this page but have since +been resolved. + +- "Static Linking of musl libc Prevents Extension Module Library + Loading": Starting with the 20250311 release, the default musl + distributions are dynamically linked by default, so extension modules + should work properly. Note that these now require a system-wide + installation of the musl C library. (This is present by default on + musl-based OSes like Alpine, and many glibc-based distros have a + `musl` package you can safely co-install with glibc, too.) If you + specifically need a statically-linked binary, variants with the + `+static` build option are available, but these retain the quirk + that compiled extension modules (e.g., `musllinux` wheels) cannot be + loaded. +- "Missing `libcrypt.so.1`": The 20230507 release and earlier required + the system library `libcrypt.so.1`, which stopped being shipped by + default in several Linux distributions around 2022. Starting with the + 20230726 release, this dependency is now only needed by the deprecated + `crypt` module, which only exists on Python 3.12 and lower. If you + still need this module, your OS may offer a `libxcrypt` package to + provide this library. Alternatively, there are suggestions in [What's + New in Python 3.13][what's new in python 3.13] about third-party replacements for the `crypt` + module. +- "Static Linking of `libX11` / Incompatibility with PyQt on Linux": + The 20220318 release and earlier exported dynamic symbols for the + internal, statically-linked build of `libX11` and other libraries. + These would cause conflicts and potential crashes when using + third-party extension modules such as PyQt that load an actual shared + `libX11` library (usually provided by your OS). Starting with the + 20220502 release, symbols from internal dependencies are no longer + exported. + +[what's new in python 3.13]: https://docs.python.org/3/whatsnew/3.13.html#whatsnew313-pep594 diff --git a/docs/quirks.rst b/docs/quirks.rst deleted file mode 100644 index 1259f23ef..000000000 --- a/docs/quirks.rst +++ /dev/null @@ -1,238 +0,0 @@ -.. _quirks: - -=============== -Behavior Quirks -=============== - -While these Python distributions are intended to be broadly compatible -with the Python ecosystem, there are a few known behavior quirks that -affect specific environments, packages, or use cases. - -.. _quirk_backspace_key: - -If special keys do not work in the Python REPL -============================================== - -If you attempt to run ``python`` and the backspace key doesn't -erase characters or the arrow keys don't work as expected, this -is because the executable can't find the *terminfo database*. - -If this happens, the Python REPL will print the following warning -message on startup:: - - Cannot read termcap database; - using dumb terminal settings. - -When you type a special key like the backspace key, this is -registered as a key press. There is special software (typically -``readline`` or ``libedit``) that most interactive programs use -that intercepts these special key presses and converts them into -special behavior, such as moving the cursor back instead of -forward. But because computer environments are different, -there needs to be some definition of how these special -behaviors are performed. This is the *terminfo database*. - -When ``readline`` and ``libedit`` are compiled, there is -typically a hard-coded set of search locations for the -*terminfo database* baked into the built library. And when -you build a program (like Python) locally, you link against -``readline`` or ``libedit`` and get these default locations -*for free*. - -These Python distributions compile and use their own version of -``libedit`` to avoid a dependency on what is (or isn't) installed on -your system. This means that they do not use your system-provided -libraries for reading the *terminfo database*. This version of -``libedit`` is configured to look for in locations that should work for -most OSes (specifically, ``/usr/share/terminfo`` on macOS, and -``/etc/terminfo``, ``/lib/terminfo``, and ``/usr/share/terminfo`` on -Linux, which should cover all major Linux distributions), but it is -possible that your environment has it somewhere else. If your OS stores -the *terminfo database* in an uncommon location, you can set the -``TERMINFO_DIRS`` environment variable so that ``libedit`` can find it. - -For instance, you may need to do something like: - - $ TERMINFO_DIRS=/uncommon/place/terminfo install/bin/python3.10 - -If you are running on a relatively standard OS and this does not work -out of the box, please file a bug report so we can add the location of -the *terminfo database* to the build. - -For convenience, a relatively recent copy of the terminfo database -is distributed in the ``share/terminfo`` directory (``../../share/terminfo`` -relative to the ``bin/python3`` executable) in Linux distributions. Note -that ncurses and derived libraries don't know how to find this directory -since they are configured to use absolute paths to the terminfo database -and the absolute path of the Python distribution is obviously not known -at build time! So actually using this bundled terminfo database will -require custom code setting ``TERMINFO_DIRS`` before -ncurses/libedit/readline are loaded. - -.. _quirk_macos_no_tix: - -No tix on UNIX -============== - -Tix is an old widget library for Tcl/Tk. Python previously had a wrapper -for it in ``tkinter.tix``, but it was deprecated in Python 3.6 (the -recommendation is to use ``tkinter.ttk``) and removed in Python 3.13. - -The macOS and Linux distributions from this project do not build and -ship Tix, even for Python versions 3.12 and below. - -We had previously attempted to ship Tix support on Linux, but it was -broken and nobody reported an issue about it. The macOS distributions -from this project never shipped support for Tix. The official Python.org -macOS installers and Apple's build of Python do not ship support for -Tix, either, so this project behaves similarly to those distributions. - -.. _quirk_windows_no_pip: - -No ``pip.exe`` on Windows -========================= - -The Windows distributions have ``pip`` installed however no ``Scripts/pip.exe``, -``Scripts/pip3.exe``, and ``Scripts/pipX.Y.exe`` files are provided because -the way these executables are built isn't portable. (It might be possible to -change how these are built to make them portable.) - -To use pip, run ``python.exe -m pip``. (It is generally a best practice to -invoke pip via ``python -m pip`` on all platforms so you can be explicit -about the ``python`` executable that pip uses.) - -.. _quirk_macos_linking: - -Linking Static Library on macOS -=============================== - -Python 3.10+ makes use of the ``__builtin_available()`` compiler feature. -This functionality requires a symbol from ``libclang_rt``, which may not -be linked by default. Failure to link against ``libclang_rt`` could result -in a linker error due to an undefined symbol ``___isOSVersionAtLeast``. - -To work around this linker failure, link against the static library -``libclang_rt..a`` present in the Clang installation. e.g. -``libclang_rt.osx.a``. You can find this library by invoking -``clang --print-search-dirs`` and looking in the ``lib/darwin`` directory -under the printed ``libraries`` directory. An example path is -``/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/12.0.0/lib/darwin/libclang_rt.osx.a``. - -A copy of the ``libclang_rt..a`` from the Clang used to build -the distribution is included in the archive. However, it isn't annotated -in ``PYTHON.json`` because we're unsure if using the file with another -build/version of Clang is supported. Use at your own risk. - -See https://jonnyzzz.com/blog/2018/06/05/link-error-2/ and -https://jonnyzzz.com/blog/2018/06/13/link-error-3/ for more on this topic. - -.. _quirk_linux_libedit: - -Use of ``libedit`` on Linux -=========================== - -Python 3.10+ Linux distributions link against ``libedit`` (as opposed to -``readline``) by default, as ``libedit`` is supported on 3.10+ outside of -macOS. - -Most Python builds on Linux will link against ``readline`` because ``readline`` -is the dominant library on Linux. - -Some functionality may behave subtly differently as a result of our choice -to link ``libedit`` by default. (We choose ``libedit`` by default to -avoid GPL licensing requirements of ``readline``.) - - -.. _quirk_references_to_build_paths: - -References to Build-Time Paths -============================== - -The built Python distribution captures some absolute paths and other -build-time configuration in a handful of files: - -* In a ``_sysconfigdata_*.py`` file in the standard library. e.g. - ``lib/python3.10/_sysconfigdata__linux_x86_64-linux-gnu.py``. -* In a ``Makefile`` under a ``config-*`` directory in the standard library. - e.g. ``lib/python3.10/config-3.10-x86_64-linux-gnu/Makefile``. -* In python-build-standalone's metadata file ``PYTHON.json`` (mostly - reflected values from ``_sysconfigdata_*.py``). - -Each of these serves a different use case. But the general theme is various -aspects of the Python distribution attempt to capture how Python was built. -The most common use of these values is to facilitate compiling or linking -other software against this Python build. For example, the ``_sysconfigdata*`` -module is loaded by the `sysconfig `_ -module. ``sysconfig`` in turn is used by packaging tools like ``setuptools`` -and ``pip`` to figure out how to invoke a compiler for e.g. compiling C -extensions from source. - -When installed by `uv `_, these absolute -paths are fixed up to point to the actual location on your system where -the distribution was installed, so **this quirk generally does not -affect uv users**. The third-party tool `sysconfigpatcher -`_ also does this and might -be helpful to use or reference if you are installing these distributions -on your own. - -In particular, you may see references to our install-time paths on the -build infrastructure, e.g., ``/build`` and ``/install`` on Linux, a -particular SDK in ``/Applications/Xcode.app`` on macOS, and temporary -directories on Windows. - -Also, Python reports the compiler and flags in use, just in case it is -needed to make binary-compatible extensions. On Linux, for instance, we -use our own builds of Clang and potentially some flags (warnings, -optimizations, locations of the build environment) that do not work or -apply in other environments. We try to configure Python to remove -unneeded flags and absolute paths to files in the build environment. -references to build-time paths. Python's ``sysconfig`` system requires -listing a compiler, so we leave it set to ``clang`` without the absolute -path, but you should be able to use another compiler like ``gcc`` to -compile extensions, too. - -If there is a build time normalization that you think should be performed to -make distributions more portable, please file a GitHub issue. - -.. _quirk_former: -.. _quirk_missing_libcrypt: -.. _quirk_linux_libx11: - -Former quirks -============= - -The following quirks were previously listed on this page but have since -been resolved. - -* "Static Linking of musl libc Prevents Extension Module Library - Loading": Starting with the 20250311 release, the default musl - distributions are dynamically linked by default, so extension modules - should work properly. Note that these now require a system-wide - installation of the musl C library. (This is present by default on - musl-based OSes like Alpine, and many glibc-based distros have a - ``musl`` package you can safely co-install with glibc, too.) If you - specifically need a statically-linked binary, variants with the - ``+static`` build option are available, but these retain the quirk - that compiled extension modules (e.g., ``musllinux`` wheels) cannot be - loaded. - -* "Missing ``libcrypt.so.1``": The 20230507 release and earlier required - the system library ``libcrypt.so.1``, which stopped being shipped by - default in several Linux distributions around 2022. Starting with the - 20230726 release, this dependency is now only needed by the deprecated - ``crypt`` module, which only exists on Python 3.12 and lower. If you - still need this module, your OS may offer a ``libxcrypt`` package to - provide this library. Alternatively, there are suggestions in `What's - New in Python 3.13`_ about third-party replacements for the ``crypt`` - module. - -* "Static Linking of ``libX11`` / Incompatibility with PyQt on Linux": - The 20220318 release and earlier exported dynamic symbols for the - internal, statically-linked build of ``libX11`` and other libraries. - These would cause conflicts and potential crashes when using - third-party extension modules such as PyQt that load an actual shared - ``libX11`` library (usually provided by your OS). Starting with the - 20220502 release, symbols from internal dependencies are no longer - exported. - -.. _What's New in Python 3.13: https://docs.python.org/3/whatsnew/3.13.html#whatsnew313-pep594 diff --git a/docs/running.md b/docs/running.md new file mode 100644 index 000000000..664172db1 --- /dev/null +++ b/docs/running.md @@ -0,0 +1,403 @@ + + +# Running Distributions + +## Using uv + +The most common method of using the prebuilt distributions from this +project is with [uv](https://docs.astral.sh/uv/). By default, uv will +download, install, and use an appropriate distribution if the system does +not provide a compatible Python installation that uv can discover. These +downloaded distributions are referred to as *managed* Python installations, +as compared to *system* Python installations. You can configure uv to +always use a *managed* Python installation, for example by using the +`--managed-python` flag. + +To run a particular distribution using `uv`: + +``` +uvx --managed-python python +``` + +A Python version or another specifier can be included: + +``` +uvx --managed-python python@3.13 +uvx --managed-python python@3.14+freethreaded +``` + +The uv documentation on +[installing Python](https://docs.astral.sh/uv/guides/install-python/) +and [Python versions](https://docs.astral.sh/uv/concepts/python-versions/) +provides more information and examples. + +## Obtaining Distributions + +Prebuilt distributions are published as releases on GitHub at +. +Simply go to that page and find the latest release along with +its release notes. + +Machines can find the latest release by querying the GitHub releases +API. Alternatively, a JSON file publishing metadata about the latest +release can be fetched from +. +The JSON format is simple and hopefully self-descriptive. + +Published distributions vary by their: + +- Python version +- Target machine architecture +- Build configuration +- Archive flavor + +The Python version is hopefully pretty obvious. + +The target machine architecture defines the CPU type and operating +system the distribution runs on. We use LLVM target triples. +Distributions are produced for the following target triples: + +`aarch64-apple-darwin` + +: macOS ARM CPUs, i.e., Apple Silicon. + +`x86_64-apple-darwin` + +: macOS Intel CPUs. + +`x86_64-pc-windows-msvc` + +: Windows 64-bit Intel/AMD CPUs. + +`i686-pc-windows-msvc` + +: Windows 32-bit Intel/AMD CPUs. + +`aarch64-pc-windows-msvc` + +: Windows 64-bit ARM CPUs. Available for CPython 3.11 and newer. + +`x86_64-unknown-linux-gnu` + +: Linux 64-bit Intel/AMD CPUs linking against GNU libc. + +`x86_64-unknown-linux-musl` + +: Linux 64-bit Intel/AMD CPUs linking against musl libc. + + Distributions are provided that dynamically link musl or are fully static + (`+static`). Dynamically linked distributions require musl to be installed + on the host. Fully static distributions have no shared library dependencies, + but cannot load Python `.so` extensions. + +`aarch64-unknown-linux-*` + +: Similar to above except targeting Linux on ARM64 CPUs. Distributions + are provided for GNU libc, musl, and static musl. + + For example, this target supports AWS Graviton EC2 instances. Many + Linux ARM devices are also `aarch64`. + +`x86_64_v2-*` + +: Targets 64-bit Intel/AMD CPUs approximately newer than + [Nehalem]() + (released in 2008). + + Binaries will have SSE3, SSE4, and other CPU instructions added after the + \~initial x86-64 CPUs were launched in 2003. + + Binaries will crash if you attempt to run them on an older CPU not + supporting the newer instructions. + +`x86_64_v3-*` + +: Targets 64-bit Intel/AMD CPUs approximately newer than + [Haswell]() + (released in 2013) and + [Excavator]() + (released in 2015). + + Binaries will have AVX, AVX2, MOVBE and other newer CPU instructions. + + Binaries will crash if you attempt to run them on an older CPU not + supporting the newer instructions. + + Most x86-64 CPUs manufactured after 2013 (Intel) or 2015 (AMD) support + this microarchitecture level. An exception is Intel Atom P processors, + which Intel released in 2020 but did not include AVX. + +`x86_64_v4-*` + +: Targets 64-bit Intel/AMD CPUs with some AVX-512 instructions. + + Requires Intel CPUs manufactured after ~2017. But many Intel CPUs don't + have AVX-512. + +The `x86_64_v2`, `x86_64_v3`, and `x86_64_v4` binaries usually crash +on startup when run on an incompatible CPU. We don't recommend running the +`x86_64_v4` builds in production because they likely don't yield a reliable +performance benefit. Unless you are executing these binaries on a CPU older +than ~2008 or ~2013, we recommend running the `x86_64_v2` or `x86_64_v3` +binaries, as these should be slightly faster since they take advantage +of more modern CPU instructions which are more efficient. But if you want +maximum portability, stick with the baseline `x86_64` builds. + +`armv7-unknown-linux-gnueabi` + +: Linux 32-bit ARM CPUs without hardware floating-point instructions, + linking against GNU libc. + + This is an uncommon platform. In most cases, the hardware floating-point + target should be used. These distributions can be used on Debian's + `armel` port. + +`armv7-unknown-linux-gnueabihf` + +: Linux 32-bit ARM CPUs with hardware floating-point instructions, + linking against GNU libc. + + This is a common 32-bit ARM platform. Raspberry Pi model 2 and later + can use these distributions on many 32-bit Linux distributions. + +`ppc64le-unknown-linux-gnu` + +: Linux 64-bit POWER8+ CPUs linking against GNU libc. + +`riscv64-unknown-linux-gnu` + +: Linux 64-bit RISC-V CPUs linking against GNU libc. + +`s390x-unknown-linux-gnu` + +: Linux 64-bit IBM Z (s390x) CPUs linking against GNU libc. + +We recommend using the `*-unknown-linux-gnu` builds on Linux, since they +are able to load compiled Python extensions. The non-static +`*-unknown-linux-musl` builds should be used on musl-based Linux +distributions like Alpine Linux. If you don't need to load compiled +extensions not provided by the standard library, or you are willing to +compile and link third-party extensions into a custom binary, the static +`*-unknown-linux-musl` builds should work just fine. + +The build configuration denotes how Python and its dependencies were built. +Common configurations include: + +`pgo+lto` + +: Profile-guided optimization and link-time optimization. **These should be + the fastest distributions since they have the most build-time + optimizations.** + +`pgo` + +: Profile-guided optimization. + + Starting with CPython 3.12, BOLT is also applied alongside traditional + PGO on platforms supporting BOLT. (Currently just Linux x86-64.) + +`lto` + +: Link-time optimization. + +`noopt` + +: A regular optimized build without PGO or LTO. + +`debug` + +: A debug build. No optimizations. + +`freethreaded` + +: A free-threaded build, available for CPython 3.13 and newer. This + option is combined with an optimization option, such as + `freethreaded+pgo+lto` or `freethreaded+lto`. + +`static` + +: A fully static musl build. Has no shared library dependencies and + cannot load dynamically linked Python extensions. + +The archive flavor denotes the content in the archive. See +[Distribution Archives](distributions.md#distributions) for more. + +Casual users will likely want to use the `install_only` archive, as most +users do not need the build artifacts present in the `full` archive. +The `install_only` archive does not include the optimization options in +its filename. For each Python version, target, and threading variant, +it uses the fastest available build configuration. + +An `install_only_stripped` archive is also available. This archive is +equivalent to `install_only`, but without debug symbols, which results +in a smaller download and on-disk footprint. For CPython 3.13 and newer, +free-threaded archives are identified by `freethreaded` in the filename. + +Fully static musl builds are only available as `full` archives with +`+static` in their build options. The `install_only` and +`install_only_stripped` musl archives use dynamically linked builds. + +## Extracting Distributions + +Distributions are defined as zstandard or gzip compressed tarballs. + +Modern versions of `tar` support zstandard and you can extract +like any normal archive: + +``` +$ tar -axvf path/to/distribution.tar.zstd +``` + +(The `-a` argument tells tar to guess the compression format by +the file extension.) + +If your `tar` doesn't support `-a` (e.g. the default macOS `tar`), +try: + +``` +$ tar xvf path/to/distribution.tar.zstd +``` + +If you do not have `tar`, you can install and use the `zstd` +tool (typically available via a `zstd` or `zstandard` system +package): + +``` +$ zstd -d path/to/distribution.tar.zstd +$ tar -xvf path/to/distribution.tar +``` + +If you want to extract the distribution with Python, use the +`zstandard` Python package: + +```python +import tarfile +import zstandard + +with open("path/to/distribution.tar.zstd", "rb") as ifh: + dctx = zstandard.ZstdDecompressor() + with dctx.stream_reader(ifh) as reader: + with tarfile.open(mode="r|", fileobj=reader) as tf: + tf.extractall("path/to/output/directory") +``` + +## Runtime Requirements + +### Linux + +The produced Linux binaries have minimal references to shared +libraries and thus can be executed on most Linux systems. + +Distributions linked against glibc may reference the following shared +libraries: + +- linux-vdso.so.1 +- libpthread.so.0 +- libdl.so.2 (required by ctypes extension) +- libutil.so.1 +- librt.so.1 +- libm.so.6 +- libc.so.6 +- ld-linux-x86-64.so.2 + +On Python 3.12 and earlier, the deprecated `crypt` module additionally +requires `libcrypt.so.1`. + +The minimum glibc version required for most targets is 2.17. This should make +binaries compatible with the following Linux distributions: + +- Fedora 21+ +- RHEL/CentOS 7+ +- openSUSE 13.2+ +- Debian 8+ (Jessie) +- Ubuntu 14.04+ + +For the `riscv64-unknown-linux-gnu` target, the minimum glibc version is +2.28. + +Distributions linked against musl do not depend on glibc. By default, musl +distributions are dynamically linked and require musl to be installed on the +host. Fully static distributions use the `+static` build option and have +no shared library dependencies, but cannot load dynamically linked Python +extension modules. + +### Windows + +Windows distributions model the requirements of the official Python +distributions: + +- CPython 3.14 and newer: Windows 10 or newer. +- CPython 3.13 and earlier: Windows 8.1 or newer. + +Windows Server support follows the corresponding CPython release's +upstream platform policy. + +## Extra Python Software + +Python installations have some additional software pre-installed: + +- [pip](https://pypi.org/project/pip/) +- [setuptools](https://pypi.org/project/setuptools/) (for Python 3.11 and older) + +The intent of the pre-installed software is to facilitate end-user +package installation without having to first bootstrap a packaging +tool via an insecure installation technique (such as `curl | sh` +patterns). + +## Licensing + +Python and its various dependencies are governed by varied software use +licenses. This impacts the rights and requirements of downstream consumers. + +Most licenses are fairly permissive. Notable exceptions to this are GDBM and +readline, which are both licensed under GPL Version 3. + +We build CPython against libedit - as opposed to readline - to avoid this +GPL dependency. This requires patches on CPython < 3.10. Distribution releases +before 2023 may link against readline and are therefore subject to the GPL. + +We globally disable the `_gdbm` extension module to avoid linking against +GDBM and introducing a GPL dependency. Distribution releases before 2023 may +link against GDBM and be subject to the GPL. + +**It is important to understand the licensing requirements when integrating +the output of this project into derived works.** To help with this, the +JSON document describing the Python distribution contains licensing metadata +and the archive contains copies of license texts. + +## Reconsuming Build Artifacts + +Produced Python distributions contain object files and libraries for the +built Python and its dependencies. It is possible for downstream consumers +to take these build artifacts and link them into a new binary. + +Reconsuming the build artifacts this way can be a bit fragile due to +incompatibilities between the host that generated them and the target that +is consuming them. + +To ensure optimal compatibility, it is highly recommended to use the same +toolchain for all operations. + +This is often harder than it sounds. For example, if these build artifacts +were to be combined into a Rust binary, the version of LLVM that the Rust +compiler itself was built against can matter. As a concrete example, the +Rust 1.31 compiler will produce LLVM intrinsics that vary from intrinsics +that would be produced with LLVM/Clang 7. At linking time, you would get +errors like the following: + +``` +Intrinsic has incorrect argument type! +void (i8*, i8, i64, i1)* @llvm.memset.p0i8.i64 +``` + +The distributions that contain object files are useful for +embedding Python in a larger binary. See the +[PyOxidizer](https://github.com/indygreg/PyOxidizer) sister project +for such a downstream repackager. + +Some users of these distributions might be better served by the +[PyOxy](https://pyoxidizer.readthedocs.io/en/latest/pyoxy.html) +sister project. PyOxy takes these Python distributions and adds Rust code +to enhance the functionality of the Python interpreter. The official +PyOxy release binaries are single-file executables providing +a full-featured Python interpreter. diff --git a/docs/running.rst b/docs/running.rst deleted file mode 100644 index 897dd7964..000000000 --- a/docs/running.rst +++ /dev/null @@ -1,379 +0,0 @@ -.. _running: - -===================== -Running Distributions -===================== - -Using uv -======== - -The most common method of using the prebuilt distributions from this -project is with `uv `_. By default, uv will -download, install, and use an appropriate distribution if the system does -not provide a compatible Python installation that uv can discover. These -downloaded distributions are referred to as *managed* Python installations, -as compared to *system* Python installations. You can configure uv to -always use a *managed* Python installation, for example by using the -``--managed-python`` flag. - -To run a particular distribution using ``uv``:: - - uvx --managed-python python - -A Python version or another specifier can be included:: - - uvx --managed-python python@3.13 - uvx --managed-python python@3.14+freethreaded - -The uv documentation on -`installing Python `_ -and `Python versions `_ -provides more information and examples. - -Obtaining Distributions -======================= - -Prebuilt distributions are published as releases on GitHub at -https://github.com/astral-sh/python-build-standalone/releases. -Simply go to that page and find the latest release along with -its release notes. - -Machines can find the latest release by querying the GitHub releases -API. Alternatively, a JSON file publishing metadata about the latest -release can be fetched from -https://raw.githubusercontent.com/astral-sh/python-build-standalone/latest-release/latest-release.json. -The JSON format is simple and hopefully self-descriptive. - -Published distributions vary by their: - -* Python version -* Target machine architecture -* Build configuration -* Archive flavor - -The Python version is hopefully pretty obvious. - -The target machine architecture defines the CPU type and operating -system the distribution runs on. We use LLVM target triples. -Distributions are produced for the following target triples: - -``aarch64-apple-darwin`` - macOS ARM CPUs, i.e., Apple Silicon. - -``x86_64-apple-darwin`` - macOS Intel CPUs. - -``x86_64-pc-windows-msvc`` - Windows 64-bit Intel/AMD CPUs. - -``i686-pc-windows-msvc`` - Windows 32-bit Intel/AMD CPUs. - -``aarch64-pc-windows-msvc`` - Windows 64-bit ARM CPUs. Available for CPython 3.11 and newer. - -``x86_64-unknown-linux-gnu`` - Linux 64-bit Intel/AMD CPUs linking against GNU libc. - -``x86_64-unknown-linux-musl`` - Linux 64-bit Intel/AMD CPUs linking against musl libc. - - Distributions are provided that dynamically link musl or are fully static - (``+static``). Dynamically linked distributions require musl to be installed - on the host. Fully static distributions have no shared library dependencies, - but cannot load Python ``.so`` extensions. - -``aarch64-unknown-linux-*`` - Similar to above except targeting Linux on ARM64 CPUs. Distributions - are provided for GNU libc, musl, and static musl. - - For example, this target supports AWS Graviton EC2 instances. Many - Linux ARM devices are also ``aarch64``. - -``x86_64_v2-*`` - Targets 64-bit Intel/AMD CPUs approximately newer than - `Nehalem `_ - (released in 2008). - - Binaries will have SSE3, SSE4, and other CPU instructions added after the - ~initial x86-64 CPUs were launched in 2003. - - Binaries will crash if you attempt to run them on an older CPU not - supporting the newer instructions. - -``x86_64_v3-*`` - Targets 64-bit Intel/AMD CPUs approximately newer than - `Haswell `_ - (released in 2013) and - `Excavator `_ - (released in 2015). - - Binaries will have AVX, AVX2, MOVBE and other newer CPU instructions. - - Binaries will crash if you attempt to run them on an older CPU not - supporting the newer instructions. - - Most x86-64 CPUs manufactured after 2013 (Intel) or 2015 (AMD) support - this microarchitecture level. An exception is Intel Atom P processors, - which Intel released in 2020 but did not include AVX. - -``x86_64_v4-*`` - Targets 64-bit Intel/AMD CPUs with some AVX-512 instructions. - - Requires Intel CPUs manufactured after ~2017. But many Intel CPUs don't - have AVX-512. - -The ``x86_64_v2``, ``x86_64_v3``, and ``x86_64_v4`` binaries usually crash -on startup when run on an incompatible CPU. We don't recommend running the -``x86_64_v4`` builds in production because they likely don't yield a reliable -performance benefit. Unless you are executing these binaries on a CPU older -than ~2008 or ~2013, we recommend running the ``x86_64_v2`` or ``x86_64_v3`` -binaries, as these should be slightly faster since they take advantage -of more modern CPU instructions which are more efficient. But if you want -maximum portability, stick with the baseline ``x86_64`` builds. - -``armv7-unknown-linux-gnueabi`` - Linux 32-bit ARM CPUs without hardware floating-point instructions, - linking against GNU libc. - - This is an uncommon platform. In most cases, the hardware floating-point - target should be used. These distributions can be used on Debian's - ``armel`` port. - -``armv7-unknown-linux-gnueabihf`` - Linux 32-bit ARM CPUs with hardware floating-point instructions, - linking against GNU libc. - - This is a common 32-bit ARM platform. Raspberry Pi model 2 and later - can use these distributions on many 32-bit Linux distributions. - -``ppc64le-unknown-linux-gnu`` - Linux 64-bit POWER8+ CPUs linking against GNU libc. - -``riscv64-unknown-linux-gnu`` - Linux 64-bit RISC-V CPUs linking against GNU libc. - -``s390x-unknown-linux-gnu`` - Linux 64-bit IBM Z (s390x) CPUs linking against GNU libc. - -We recommend using the ``*-unknown-linux-gnu`` builds on Linux, since they -are able to load compiled Python extensions. The non-static -``*-unknown-linux-musl`` builds should be used on musl-based Linux -distributions like Alpine Linux. If you don't need to load compiled -extensions not provided by the standard library, or you are willing to -compile and link third-party extensions into a custom binary, the static -``*-unknown-linux-musl`` builds should work just fine. - -The build configuration denotes how Python and its dependencies were built. -Common configurations include: - -``pgo+lto`` - Profile-guided optimization and link-time optimization. **These should be - the fastest distributions since they have the most build-time - optimizations.** - -``pgo`` - Profile-guided optimization. - - Starting with CPython 3.12, BOLT is also applied alongside traditional - PGO on platforms supporting BOLT. (Currently just Linux x86-64.) - -``lto`` - Link-time optimization. - -``noopt`` - A regular optimized build without PGO or LTO. - -``debug`` - A debug build. No optimizations. - -``freethreaded`` - A free-threaded build, available for CPython 3.13 and newer. This - option is combined with an optimization option, such as - ``freethreaded+pgo+lto`` or ``freethreaded+lto``. - -``static`` - A fully static musl build. Has no shared library dependencies and - cannot load dynamically linked Python extensions. - -The archive flavor denotes the content in the archive. See -:ref:`distributions` for more. - -Casual users will likely want to use the ``install_only`` archive, as most -users do not need the build artifacts present in the ``full`` archive. -The ``install_only`` archive does not include the optimization options in -its filename. For each Python version, target, and threading variant, -it uses the fastest available build configuration. - -An ``install_only_stripped`` archive is also available. This archive is -equivalent to ``install_only``, but without debug symbols, which results -in a smaller download and on-disk footprint. For CPython 3.13 and newer, -free-threaded archives are identified by ``freethreaded`` in the filename. - -Fully static musl builds are only available as ``full`` archives with -``+static`` in their build options. The ``install_only`` and -``install_only_stripped`` musl archives use dynamically linked builds. - -Extracting Distributions -======================== - -Distributions are defined as zstandard or gzip compressed tarballs. - -Modern versions of ``tar`` support zstandard and you can extract -like any normal archive:: - - $ tar -axvf path/to/distribution.tar.zstd - -(The ``-a`` argument tells tar to guess the compression format by -the file extension.) - -If your ``tar`` doesn't support ``-a`` (e.g. the default macOS ``tar``), -try:: - - $ tar xvf path/to/distribution.tar.zstd - -If you do not have ``tar``, you can install and use the ``zstd`` -tool (typically available via a ``zstd`` or ``zstandard`` system -package):: - - $ zstd -d path/to/distribution.tar.zstd - $ tar -xvf path/to/distribution.tar - -If you want to extract the distribution with Python, use the -``zstandard`` Python package: - -.. code-block:: python - - import tarfile - import zstandard - - with open("path/to/distribution.tar.zstd", "rb") as ifh: - dctx = zstandard.ZstdDecompressor() - with dctx.stream_reader(ifh) as reader: - with tarfile.open(mode="r|", fileobj=reader) as tf: - tf.extractall("path/to/output/directory") - -Runtime Requirements -==================== - -Linux ------ - -The produced Linux binaries have minimal references to shared -libraries and thus can be executed on most Linux systems. - -Distributions linked against glibc may reference the following shared -libraries: - -* linux-vdso.so.1 -* libpthread.so.0 -* libdl.so.2 (required by ctypes extension) -* libutil.so.1 -* librt.so.1 -* libm.so.6 -* libc.so.6 -* ld-linux-x86-64.so.2 - -On Python 3.12 and earlier, the deprecated ``crypt`` module additionally -requires ``libcrypt.so.1``. - -The minimum glibc version required for most targets is 2.17. This should make -binaries compatible with the following Linux distributions: - -* Fedora 21+ -* RHEL/CentOS 7+ -* openSUSE 13.2+ -* Debian 8+ (Jessie) -* Ubuntu 14.04+ - -For the ``riscv64-unknown-linux-gnu`` target, the minimum glibc version is -2.28. - -Distributions linked against musl do not depend on glibc. By default, musl -distributions are dynamically linked and require musl to be installed on the -host. Fully static distributions use the ``+static`` build option and have -no shared library dependencies, but cannot load dynamically linked Python -extension modules. - -Windows -------- - -Windows distributions model the requirements of the official Python -distributions: - -* CPython 3.14 and newer: Windows 10 or newer. -* CPython 3.13 and earlier: Windows 8.1 or newer. - -Windows Server support follows the corresponding CPython release's -upstream platform policy. - -Extra Python Software -===================== - -Python installations have some additional software pre-installed: - -* `pip `_ -* `setuptools `_ (for Python 3.11 and older) - -The intent of the pre-installed software is to facilitate end-user -package installation without having to first bootstrap a packaging -tool via an insecure installation technique (such as `curl | sh` -patterns). - -Licensing -========= - -Python and its various dependencies are governed by varied software use -licenses. This impacts the rights and requirements of downstream consumers. - -Most licenses are fairly permissive. Notable exceptions to this are GDBM and -readline, which are both licensed under GPL Version 3. - -We build CPython against libedit - as opposed to readline - to avoid this -GPL dependency. This requires patches on CPython < 3.10. Distribution releases -before 2023 may link against readline and are therefore subject to the GPL. - -We globally disable the ``_gdbm`` extension module to avoid linking against -GDBM and introducing a GPL dependency. Distribution releases before 2023 may -link against GDBM and be subject to the GPL. - -**It is important to understand the licensing requirements when integrating -the output of this project into derived works.** To help with this, the -JSON document describing the Python distribution contains licensing metadata -and the archive contains copies of license texts. - -Reconsuming Build Artifacts -=========================== - -Produced Python distributions contain object files and libraries for the -built Python and its dependencies. It is possible for downstream consumers -to take these build artifacts and link them into a new binary. - -Reconsuming the build artifacts this way can be a bit fragile due to -incompatibilities between the host that generated them and the target that -is consuming them. - -To ensure optimal compatibility, it is highly recommended to use the same -toolchain for all operations. - -This is often harder than it sounds. For example, if these build artifacts -were to be combined into a Rust binary, the version of LLVM that the Rust -compiler itself was built against can matter. As a concrete example, the -Rust 1.31 compiler will produce LLVM intrinsics that vary from intrinsics -that would be produced with LLVM/Clang 7. At linking time, you would get -errors like the following:: - - Intrinsic has incorrect argument type! - void (i8*, i8, i64, i1)* @llvm.memset.p0i8.i64 - -The distributions that contain object files are useful for -embedding Python in a larger binary. See the -`PyOxidizer `_ sister project -for such a downstream repackager. - -Some users of these distributions might be better served by the -`PyOxy `_ -sister project. PyOxy takes these Python distributions and adds Rust code -to enhance the functionality of the Python interpreter. The official -PyOxy release binaries are single-file executables providing -a full-featured Python interpreter. diff --git a/docs/status.md b/docs/status.md new file mode 100644 index 000000000..4991885f5 --- /dev/null +++ b/docs/status.md @@ -0,0 +1,342 @@ + + +# Project Status + +There is support for producing CPython distributions for Windows, +macOS, and Linux. All distributions are highly self-contained and have +limited shared library dependencies. + +## Target Notes + +Linux x86_64 and aarch64 targets (`x86_64-*` and `aarch64-*`) are built on +native hardware using a modern LLVM toolchain. + +All other architectures are cross-compiled on x86_64 using Debian-provided +cross-compilation tools. As a result, these targets are not as highly +optimized as aarch64 and x86_64 targets. + +## Test Failures + +This repository contains a `test-distribution.py` script that can be +used to run the Python test harness from a distribution archive. + +Currently, this script is only used to validate a limited set of +functionality for each distribution. The entire Python test harness is +not run on a regular basis. Work is ongoing to perform this type of +testing on a regular basis. + +The details below on known failing and skipped tests are out of date. In +the future, this information will be updated and presented elsewhere. + +Here, we track the various known failures when running +`test-distribution.py --stdlib -- /path/to/distribution.tar.zst -u all`. + +### `test__locale` + +Known failing on: Windows + +This test fails as follows: + +``` +====================================================================== +ERROR: test_float_parsing (test.test__locale._LocaleTests) +---------------------------------------------------------------------- +Traceback (most recent call last): + File "C:\Users\gps\AppData\Local\Temp\tmpjx7a33kd\python\install\lib\test\test__locale.py", line 184, in test_float_parsing + if localeconv()['decimal_point'] != '.': +UnicodeDecodeError: 'locale' codec can't decode byte 0xa0 in position 0: decoding error + +====================================================================== +ERROR: test_lc_numeric_localeconv (test.test__locale._LocaleTests) +---------------------------------------------------------------------- +Traceback (most recent call last): + File "C:\Users\gps\AppData\Local\Temp\tmpjx7a33kd\python\install\lib\test\test__locale.py", line 130, in test_lc_numeric_localeconv + formatting = localeconv() +UnicodeDecodeError: 'locale' codec can't decode byte 0xa0 in position 0: decoding error + +---------------------------------------------------------------------- +``` + +### `test_locale` + +Known failing on: Windows + +This test fails on Windows: + +``` +====================================================================== +ERROR: test_getsetlocale_issue1813 (test.test_locale.TestMiscellaneous) +---------------------------------------------------------------------- +Traceback (most recent call last): + File "C:\Users\gps\AppData\Local\Temp\tmp8m94v2m5\python\install\lib\test\test_locale.py", line 567, in test_getsetlocale_issue1813 + locale.setlocale(locale.LC_CTYPE, loc) + File "C:\Users\gps\AppData\Local\Temp\tmp8m94v2m5\python\install\lib\locale.py", line 608, in setlocale + return _setlocale(category, locale) +locale.Error: unsupported locale setting + +---------------------------------------------------------------------- +``` + +### `test_subprocess` + +Known Failing on: Linux + +This fails in the following manner: + +``` +test_executable_without_cwd (test.test_subprocess.ProcessTestCaseNoPoll) ... Could not find platform independent libraries +Could not find platform dependent libraries +Consider setting $PYTHONHOME to [:] +Fatal Python error: initfsencoding: Unable to get the locale encoding +ModuleNotFoundError: No module named 'encodings' + +Current thread 0x00007fd77c231740 (most recent call first): +FAIL + +====================================================================== +FAIL: test_executable_without_cwd (test.test_subprocess.ProcessTestCaseNoPoll) +---------------------------------------------------------------------- +Traceback (most recent call last): + File "/tmp/tmp8hef0kr4/python/install/lib/python3.7/test/test_subprocess.py", line 436, in test_executable_without_cwd + executable=sys.executable) + File "/tmp/tmp8hef0kr4/python/install/lib/python3.7/test/test_subprocess.py", line 355, in _assert_cwd + self.assertEqual(47, p.returncode) +AssertionError: 47 != -6 +``` + +We're unsure what is going on here. The error from `initfsencoding` +is what happens when the first `import` during `Py_Initialize()` +fails. So it appears the test somehow can't locate the Python +standard library. + +### `test_tk` + +Known Failing on: Linux + +This fails in the following manner: + +``` +====================================================================== +FAIL: test_from (tkinter.test.test_tkinter.test_widgets.ScaleTest) +---------------------------------------------------------------------- +Traceback (most recent call last): + File "/tmp/tmpoqqjd5gi/python/install/lib/python3.7/tkinter/test/test_tkinter/test_widgets.py", line 867, in test_from + self.checkFloatParam(widget, 'from', 100, 14.9, 15.1, conv=float_round) + File "/tmp/tmpoqqjd5gi/python/install/lib/python3.7/tkinter/test/widget_tests.py", line 106, in checkFloatParam + self.checkParam(widget, name, value, conv=conv, **kwargs) + File "/tmp/tmpoqqjd5gi/python/install/lib/python3.7/tkinter/test/widget_tests.py", line 63, in checkParam + self.assertEqual2(widget[name], expected, eq=eq) + File "/tmp/tmpoqqjd5gi/python/install/lib/python3.7/tkinter/test/widget_tests.py", line 47, in assertEqual2 + self.assertEqual(actual, expected, msg) +AssertionError: 14.9 != 15.0 +``` + +This seems like a minor issue and might be a bug in the test itself. + +### `test_winconsoleio` + +This fails as follows: + +``` +====================================================================== +ERROR: test_ctrl_z (test.test_winconsoleio.WindowsConsoleIOTests) +---------------------------------------------------------------------- +Traceback (most recent call last): + File "C:\Users\gps\AppData\Local\Temp\tmp8m94v2m5\python\install\lib\test\test_winconsoleio.py", line 190, in test_ctrl_z + a, b = stdin.read(1), stdin.readall() +OSError: [WinError 87] The parameter is incorrect + +====================================================================== +ERROR: test_input (test.test_winconsoleio.WindowsConsoleIOTests) +---------------------------------------------------------------------- +Traceback (most recent call last): + File "C:\Users\gps\AppData\Local\Temp\tmp8m94v2m5\python\install\lib\test\test_winconsoleio.py", line 144, in test_input + self.assertStdinRoundTrip('abc123') + File "C:\Users\gps\AppData\Local\Temp\tmp8m94v2m5\python\install\lib\test\test_winconsoleio.py", line 137, in assertStdinRoundTrip + actual = input() +OSError: [WinError 87] The parameter is incorrect + +====================================================================== +FAIL: test_partial_reads (test.test_winconsoleio.WindowsConsoleIOTests) +---------------------------------------------------------------------- +Traceback (most recent call last): + File "C:\Users\gps\AppData\Local\Temp\tmp8m94v2m5\python\install\lib\test\test_winconsoleio.py", line 166, in test_partial_reads + self.assertEqual(actual, expected, 'stdin.read({})'.format(read_count)) +AssertionError: b'\r\n' != b'\xcf\xbc\xd1\x9e\xd0\xa2\xce\xbb\xd0\xa4\xd0\x99\r\n' : stdin.read(1) + +====================================================================== +FAIL: test_partial_surrogate_reads (test.test_winconsoleio.WindowsConsoleIOTests) +---------------------------------------------------------------------- +Traceback (most recent call last): + File "C:\Users\gps\AppData\Local\Temp\tmp8m94v2m5\python\install\lib\test\test_winconsoleio.py", line 183, in test_partial_surrogate_reads + self.assertEqual(actual, expected, 'stdin.read({})'.format(read_count)) +AssertionError: b'\xc3\x84\r\n' != b'\xf4\x81\xbf\xbf\xf4\x81\x80\x81\r\n' : stdin.read(1) + +---------------------------------------------------------------------- + +Ran 10 tests in 0.006s + +FAILED (failures=2, errors=2) +test test_winconsoleio failed +0:00:00 Re-running test__locale in verbose mode +test_float_parsing (test.test__locale._LocaleTests) ... ERROR +test_lc_numeric_basic (test.test__locale._LocaleTests) ... skipped 'nl_langinfo is not available' +test_lc_numeric_localeconv (test.test__locale._LocaleTests) ... ERROR +test_lc_numeric_nl_langinfo (test.test__locale._LocaleTests) ... skipped 'nl_langinfo is not available' + +====================================================================== +ERROR: test_float_parsing (test.test__locale._LocaleTests) +---------------------------------------------------------------------- +Traceback (most recent call last): + File "C:\Users\gps\AppData\Local\Temp\tmp8m94v2m5\python\install\lib\test\test__locale.py", line 184, in test_float_parsing + if localeconv()['decimal_point'] != '.': +UnicodeDecodeError: 'locale' codec can't decode byte 0xa0 in position 0: decoding error + +====================================================================== +ERROR: test_lc_numeric_localeconv (test.test__locale._LocaleTests) +---------------------------------------------------------------------- +Traceback (most recent call last): + File "C:\Users\gps\AppData\Local\Temp\tmp8m94v2m5\python\install\lib\test\test__locale.py", line 130, in test_lc_numeric_localeconv + formatting = localeconv() +UnicodeDecodeError: 'locale' codec can't decode byte 0xa0 in position 0: decoding error + +---------------------------------------------------------------------- +``` + +## Test Skips + +### Linux + +The following tests are skipped on Linux: + +test_asdl_parser + +: test irrelevant for an installed Python + +test_clinic + +: install/lib/Tools/clinic' path does not exist + +test_dbm_gnu + +: No module named '\_gdbm' + +test_devpoll + +: test works only on Solaris OS family + +test_gdb + +: test_gdb only works on source builds at the moment. + +test_kqueue + +: test works only on BSD + +test_msilib + +: No module named 'msilib' + +test_ossaudiodev + +: [Errno 2] No such file or directory: '/dev/dsp' + +test_startfile + +: object \ has no attribute 'startfile' + +test_winconsoleio + +: test only relevant on win32 + +test_winreg + +: No module named 'winreg' + +test_winsound + +: No module named 'winsound' + +test_zipfile64 + +: test requires loads of disk-space bytes and a long time to run + +### macOS + +The following tests are skipped on macOS: + +test_asdl_parser + +: test irrelevant for an installed Python + +test_clinic + +: python/install/lib/Tools/clinic' path does not exist + +test_dbm_gnu + +: No module named '\_gdbm' + +test_devpoll + +: test works only on Solaris OS family + +test_epoll + +: test works only on Linux 2.6 + +test_gdb + +: Couldn't find gdb on the path + +test_msilib + +: No module named 'msilib' + +test_multiprocessing_fork + +: test may crash on macOS (bpo-33725) + +test_nis + +: No module named 'nis' + +test_ossaudiodev + +: No module named 'ossaudiodev' + +test_spwd + +: No module named 'spwd' + +test_startfile + +: object \ has no attribute 'startfile' + +test_tix + +: tix is not built by this project + +test_tk + +: cannot run without OS X gui process + +test_ttk_guionly + +: cannot run without OS X gui process + +test_winconsoleio + +: test only relevant on win32 + +test_winreg + +: No module named 'winreg' + +test_winsound + +: No module named 'winsound' + +test_zipfile64 + +: test requires loads of disk-space bytes and a long time to run diff --git a/docs/status.rst b/docs/status.rst deleted file mode 100644 index 8982cb66f..000000000 --- a/docs/status.rst +++ /dev/null @@ -1,283 +0,0 @@ -.. _status: - -============== -Project Status -============== - -There is support for producing CPython distributions for Windows, -macOS, and Linux. All distributions are highly self-contained and have -limited shared library dependencies. - -Target Notes -============ - -Linux x86_64 and aarch64 targets (``x86_64-*`` and ``aarch64-*``) are built on -native hardware using a modern LLVM toolchain. - -All other architectures are cross-compiled on x86_64 using Debian-provided -cross-compilation tools. As a result, these targets are not as highly -optimized as aarch64 and x86_64 targets. - -Test Failures -============= - -This repository contains a ``test-distribution.py`` script that can be -used to run the Python test harness from a distribution archive. - -Currently, this script is only used to validate a limited set of -functionality for each distribution. The entire Python test harness is -not run on a regular basis. Work is ongoing to perform this type of -testing on a regular basis. - -The details below on known failing and skipped tests are out of date. In -the future, this information will be updated and presented elsewhere. - -Here, we track the various known failures when running -``test-distribution.py --stdlib -- /path/to/distribution.tar.zst -u all``. - -``test__locale`` ----------------- - -Known failing on: Windows - -This test fails as follows:: - - ====================================================================== - ERROR: test_float_parsing (test.test__locale._LocaleTests) - ---------------------------------------------------------------------- - Traceback (most recent call last): - File "C:\Users\gps\AppData\Local\Temp\tmpjx7a33kd\python\install\lib\test\test__locale.py", line 184, in test_float_parsing - if localeconv()['decimal_point'] != '.': - UnicodeDecodeError: 'locale' codec can't decode byte 0xa0 in position 0: decoding error - - ====================================================================== - ERROR: test_lc_numeric_localeconv (test.test__locale._LocaleTests) - ---------------------------------------------------------------------- - Traceback (most recent call last): - File "C:\Users\gps\AppData\Local\Temp\tmpjx7a33kd\python\install\lib\test\test__locale.py", line 130, in test_lc_numeric_localeconv - formatting = localeconv() - UnicodeDecodeError: 'locale' codec can't decode byte 0xa0 in position 0: decoding error - - ---------------------------------------------------------------------- - -``test_locale`` ---------------- - -Known failing on: Windows - -This test fails on Windows:: - - ====================================================================== - ERROR: test_getsetlocale_issue1813 (test.test_locale.TestMiscellaneous) - ---------------------------------------------------------------------- - Traceback (most recent call last): - File "C:\Users\gps\AppData\Local\Temp\tmp8m94v2m5\python\install\lib\test\test_locale.py", line 567, in test_getsetlocale_issue1813 - locale.setlocale(locale.LC_CTYPE, loc) - File "C:\Users\gps\AppData\Local\Temp\tmp8m94v2m5\python\install\lib\locale.py", line 608, in setlocale - return _setlocale(category, locale) - locale.Error: unsupported locale setting - - ---------------------------------------------------------------------- - -``test_subprocess`` -------------------- - -Known Failing on: Linux - -This fails in the following manner:: - - test_executable_without_cwd (test.test_subprocess.ProcessTestCaseNoPoll) ... Could not find platform independent libraries - Could not find platform dependent libraries - Consider setting $PYTHONHOME to [:] - Fatal Python error: initfsencoding: Unable to get the locale encoding - ModuleNotFoundError: No module named 'encodings' - - Current thread 0x00007fd77c231740 (most recent call first): - FAIL - - ====================================================================== - FAIL: test_executable_without_cwd (test.test_subprocess.ProcessTestCaseNoPoll) - ---------------------------------------------------------------------- - Traceback (most recent call last): - File "/tmp/tmp8hef0kr4/python/install/lib/python3.7/test/test_subprocess.py", line 436, in test_executable_without_cwd - executable=sys.executable) - File "/tmp/tmp8hef0kr4/python/install/lib/python3.7/test/test_subprocess.py", line 355, in _assert_cwd - self.assertEqual(47, p.returncode) - AssertionError: 47 != -6 - -We're unsure what is going on here. The error from ``initfsencoding`` -is what happens when the first ``import`` during ``Py_Initialize()`` -fails. So it appears the test somehow can't locate the Python -standard library. - -``test_tk`` ------------ - -Known Failing on: Linux - -This fails in the following manner:: - - ====================================================================== - FAIL: test_from (tkinter.test.test_tkinter.test_widgets.ScaleTest) - ---------------------------------------------------------------------- - Traceback (most recent call last): - File "/tmp/tmpoqqjd5gi/python/install/lib/python3.7/tkinter/test/test_tkinter/test_widgets.py", line 867, in test_from - self.checkFloatParam(widget, 'from', 100, 14.9, 15.1, conv=float_round) - File "/tmp/tmpoqqjd5gi/python/install/lib/python3.7/tkinter/test/widget_tests.py", line 106, in checkFloatParam - self.checkParam(widget, name, value, conv=conv, **kwargs) - File "/tmp/tmpoqqjd5gi/python/install/lib/python3.7/tkinter/test/widget_tests.py", line 63, in checkParam - self.assertEqual2(widget[name], expected, eq=eq) - File "/tmp/tmpoqqjd5gi/python/install/lib/python3.7/tkinter/test/widget_tests.py", line 47, in assertEqual2 - self.assertEqual(actual, expected, msg) - AssertionError: 14.9 != 15.0 - -This seems like a minor issue and might be a bug in the test itself. - -``test_winconsoleio`` ---------------------- - -This fails as follows:: - - ====================================================================== - ERROR: test_ctrl_z (test.test_winconsoleio.WindowsConsoleIOTests) - ---------------------------------------------------------------------- - Traceback (most recent call last): - File "C:\Users\gps\AppData\Local\Temp\tmp8m94v2m5\python\install\lib\test\test_winconsoleio.py", line 190, in test_ctrl_z - a, b = stdin.read(1), stdin.readall() - OSError: [WinError 87] The parameter is incorrect - - ====================================================================== - ERROR: test_input (test.test_winconsoleio.WindowsConsoleIOTests) - ---------------------------------------------------------------------- - Traceback (most recent call last): - File "C:\Users\gps\AppData\Local\Temp\tmp8m94v2m5\python\install\lib\test\test_winconsoleio.py", line 144, in test_input - self.assertStdinRoundTrip('abc123') - File "C:\Users\gps\AppData\Local\Temp\tmp8m94v2m5\python\install\lib\test\test_winconsoleio.py", line 137, in assertStdinRoundTrip - actual = input() - OSError: [WinError 87] The parameter is incorrect - - ====================================================================== - FAIL: test_partial_reads (test.test_winconsoleio.WindowsConsoleIOTests) - ---------------------------------------------------------------------- - Traceback (most recent call last): - File "C:\Users\gps\AppData\Local\Temp\tmp8m94v2m5\python\install\lib\test\test_winconsoleio.py", line 166, in test_partial_reads - self.assertEqual(actual, expected, 'stdin.read({})'.format(read_count)) - AssertionError: b'\r\n' != b'\xcf\xbc\xd1\x9e\xd0\xa2\xce\xbb\xd0\xa4\xd0\x99\r\n' : stdin.read(1) - - ====================================================================== - FAIL: test_partial_surrogate_reads (test.test_winconsoleio.WindowsConsoleIOTests) - ---------------------------------------------------------------------- - Traceback (most recent call last): - File "C:\Users\gps\AppData\Local\Temp\tmp8m94v2m5\python\install\lib\test\test_winconsoleio.py", line 183, in test_partial_surrogate_reads - self.assertEqual(actual, expected, 'stdin.read({})'.format(read_count)) - AssertionError: b'\xc3\x84\r\n' != b'\xf4\x81\xbf\xbf\xf4\x81\x80\x81\r\n' : stdin.read(1) - - ---------------------------------------------------------------------- - - Ran 10 tests in 0.006s - - FAILED (failures=2, errors=2) - test test_winconsoleio failed - 0:00:00 Re-running test__locale in verbose mode - test_float_parsing (test.test__locale._LocaleTests) ... ERROR - test_lc_numeric_basic (test.test__locale._LocaleTests) ... skipped 'nl_langinfo is not available' - test_lc_numeric_localeconv (test.test__locale._LocaleTests) ... ERROR - test_lc_numeric_nl_langinfo (test.test__locale._LocaleTests) ... skipped 'nl_langinfo is not available' - - ====================================================================== - ERROR: test_float_parsing (test.test__locale._LocaleTests) - ---------------------------------------------------------------------- - Traceback (most recent call last): - File "C:\Users\gps\AppData\Local\Temp\tmp8m94v2m5\python\install\lib\test\test__locale.py", line 184, in test_float_parsing - if localeconv()['decimal_point'] != '.': - UnicodeDecodeError: 'locale' codec can't decode byte 0xa0 in position 0: decoding error - - ====================================================================== - ERROR: test_lc_numeric_localeconv (test.test__locale._LocaleTests) - ---------------------------------------------------------------------- - Traceback (most recent call last): - File "C:\Users\gps\AppData\Local\Temp\tmp8m94v2m5\python\install\lib\test\test__locale.py", line 130, in test_lc_numeric_localeconv - formatting = localeconv() - UnicodeDecodeError: 'locale' codec can't decode byte 0xa0 in position 0: decoding error - - ---------------------------------------------------------------------- - - -Test Skips -========== - -Linux ------ - -The following tests are skipped on Linux: - -test_asdl_parser - test irrelevant for an installed Python -test_clinic - install/lib/Tools/clinic' path does not exist -test_dbm_gnu - No module named '_gdbm' -test_devpoll - test works only on Solaris OS family -test_gdb - test_gdb only works on source builds at the moment. -test_kqueue - test works only on BSD -test_msilib - No module named 'msilib' -test_ossaudiodev - [Errno 2] No such file or directory: '/dev/dsp' -test_startfile - object has no attribute 'startfile' -test_winconsoleio - test only relevant on win32 -test_winreg - No module named 'winreg' -test_winsound - No module named 'winsound' -test_zipfile64 - test requires loads of disk-space bytes and a long time to run - -macOS ------ - -The following tests are skipped on macOS: - -test_asdl_parser - test irrelevant for an installed Python -test_clinic - python/install/lib/Tools/clinic' path does not exist -test_dbm_gnu - No module named '_gdbm' -test_devpoll - test works only on Solaris OS family -test_epoll - test works only on Linux 2.6 -test_gdb - Couldn't find gdb on the path -test_msilib - No module named 'msilib' -test_multiprocessing_fork - test may crash on macOS (bpo-33725) -test_nis - No module named 'nis' -test_ossaudiodev - No module named 'ossaudiodev' -test_spwd - No module named 'spwd' -test_startfile - object has no attribute 'startfile' -test_tix - tix is not built by this project -test_tk - cannot run without OS X gui process -test_ttk_guionly - cannot run without OS X gui process -test_winconsoleio - test only relevant on win32 -test_winreg - No module named 'winreg' -test_winsound - No module named 'winsound' -test_zipfile64 - test requires loads of disk-space bytes and a long time to run diff --git a/docs/stylesheets/extra.css b/docs/stylesheets/extra.css new file mode 100644 index 000000000..3da66a08a --- /dev/null +++ b/docs/stylesheets/extra.css @@ -0,0 +1,65 @@ +:root { + --black: #261230; + --white: #ffffff; + --radiate: #d7ff64; + --flare: #6340ac; + --galaxy: #261230; + --space: #30173d; + --cosmic: #de5fe9; + --sun: #ffac2f; + --electron: #46ebe1; + --neutron: #cff3cf; + --supernova: #f1aff6; + --starlight: #f4f4f1; + --asteroid: #e3cee3; +} + +[data-md-color-scheme="astral-light"] { + --md-default-bg-color--dark: var(--black); + --md-primary-fg-color: var(--galaxy); + --md-typeset-a-color: var(--flare); + --md-accent-fg-color: var(--cosmic); + --md-default-fg-color--lightest: rgba(0, 0, 0, 0.14); +} + +[data-md-color-scheme="astral-dark"] { + --md-default-bg-color: var(--galaxy); + --md-default-fg-color: var(--white); + --md-default-fg-color--light: var(--white); + --md-default-fg-color--lighter: var(--white); + --md-default-fg-color--lightest: rgba(255, 255, 255, 0.5); + --md-primary-fg-color: var(--space); + --md-primary-bg-color: var(--white); + --md-accent-fg-color: var(--cosmic); + --md-typeset-color: var(--white); + --md-typeset-a-color: var(--radiate); + --md-typeset-mark-color: var(--sun); + --md-code-fg-color: var(--white); + --md-code-bg-color: var(--space); + --md-code-hl-comment-color: var(--asteroid); + --md-code-hl-punctuation-color: var(--asteroid); + --md-code-hl-generic-color: var(--supernova); + --md-code-hl-variable-color: var(--starlight); + --md-code-hl-string-color: var(--radiate); + --md-code-hl-keyword-color: var(--supernova); + --md-code-hl-operator-color: var(--supernova); + --md-code-hl-number-color: var(--electron); + --md-code-hl-special-color: var(--electron); + --md-code-hl-function-color: var(--neutron); + --md-code-hl-constant-color: var(--radiate); + --md-code-hl-name-color: var(--md-code-fg-color); + --md-typeset-table-color: hsla(0, 0%, 100%, 0.12); + --md-typeset-table-color--light: hsla(0, 0%, 100%, 0.035); +} + +.toclink { + color: unset !important; +} + +.toclink:hover { + color: var(--md-accent-fg-color) !important; +} + +.md-nav__link--active { + font-weight: bold; +} diff --git a/docs/technotes.md b/docs/technotes.md new file mode 100644 index 000000000..e8546c228 --- /dev/null +++ b/docs/technotes.md @@ -0,0 +1,156 @@ + + +# Technical Notes + +## How It Works + +The first thing the `build.py` scripts do is bootstrap an environment +for building Python. Linux builds use Docker images based on deterministic +Debian snapshots selected for each target: + +- x86-64 targets use Debian Jessie and a prebuilt Clang toolchain. +- aarch64 targets use Debian Stretch and a prebuilt Clang toolchain. +- Other cross-compiled targets generally use Debian Stretch and + Debian-provided GCC cross-compilers. +- riscv64 targets use Debian Buster and a Debian-provided GCC + cross-compiler. + +The selected toolchain is used to build Python's dependencies (OpenSSL, +ncurses, libedit, SQLite, etc.). Finally, Python itself is built. + +Python is built in such a way that extensions are statically linked +against their dependencies. For example, instead of the `sqlite3` Python +extension having a run-time dependency against `libsqlite3.so`, the +SQLite symbols are statically inlined into the Python extension object +file. Extension modules are statically linked into `python` rather than +provided as shared extensions in the `lib-dynload` directory. + +`_dbm` and `_tkinter` are handled differently. On dynamically linked +Linux builds, `_dbm` is provided as a shared extension with Berkeley DB +statically linked. This allows the module to be easily removed when the +Berkeley DB license is undesired (see the DBM section below). On macOS, +`_dbm` instead uses the system NDBM implementation. `_tkinter` is +also provided as a shared extension, with Tcl and Tk dynamically linked, +on builds that support shared extensions. + +From the built Python, we produce an archive containing the raw Python +distribution (as if you had run `make install`) as well as other files +useful for downstream consumers. + +## Setup.local Hackery + +Starting with Python 3.12, C extension modules are configured and built +using `configure`, `Modules/Setup.stdlib`, and `Makefile`. A +generated `Modules/Setup.local` file disables selected modules and +overrides whether others are linked statically or built as shared +libraries. + +Prior to 3.12, many extensions were configured and built using `setup.py` +scripts. These scripts do not provide much flexibility and rely on default +behaviors in `distutils`, as well as other inline code in `setup.py`. +This default behavior is often undesirable for our desired outcome of +producing a standalone Python distribution. + +Because of this, when building Python prior to 3.12, a custom `Setup.local` +file is generated that builds all C extensions in a specific manner. +The undesirable behavior of `setup.py` is bypassed and the Python C +extensions are compiled just the way we want. + +## Dependency Notes + +### DBM + +Python has the option of building its `_dbm` extension against NDBM, +GDBM, and Berkeley DB. GDBM and its NDBM compatibility libraries are +licensed under GNU GPL Version 3. Modern versions of Berkeley DB are +licensed under GNU AGPL v3. Versions 6.0.19 and older are licensed under +the more permissive Sleepycat License. + +On Linux, we build the `_dbm` extension against Berkeley DB 6.0.19. On +macOS, `_dbm` uses the NDBM implementation provided by the system +`libSystem` library instead. + +We explicitly disable the `_gdbm` extension on all targets to avoid +the GPL dependency. + +### readline / libedit / ncurses + +Python has the option of building its `readline` extension against +either `libreadline` or `libedit`. `libreadline` is licensed under +GNU GPL Version 3, and `libedit` has a more permissive license. + +`libedit`/`libreadline` link against a curses library, most likely +`ncurses`. And `ncurses` has tie-ins with a terminal database. This +is a thorny situation, as terminal databases can be difficult to +distribute because end-users often want software to respect their +terminal databases. But for that to work, `ncurses` needs to be compiled +in a way that respects the user's environment. + +On macOS, we use the system `libedit` and `libncurses`, which is +typically provided in `/usr/lib`. + +On Linux, we build `libedit` and `ncurses` from source and statically +link against their respective libraries. Project releases before 2023 linked +against `readline` on Linux. + +### gettext / locale Module + +The `locale` Python module exposes some functionality from the `gettext` +software (specifically `libintl`). (Technically, this functionality is exposed +from the `_locale` C extension module and `locale` re-exports symbols.) + +`gettext` is GPL version 3 or later licensed. And having it statically linked +in the Python distribution via the `_locale` module can have licensing +implications. + +Python's configure script probes for the ability to compile/link with +`-lintl`. If it works, Python is linked against `libintl`. If it doesn't, +`libintl` is omitted. (Search `configure` for `ac_cv_lib_intl_textdomain` +and `-lintl` references.) + +With the container based build environment on Linux, presence of `gettext` +and `libintl` is deterministic. However, on macOS where there is no +sandboxing of the build environment, Python's configure script can find and +use a `gettext`/`libintl` installed outside the system default (e.g. via +Homebrew or MacPorts). This can result in the built Python referencing a shared +library not reliably present on every macOS machine. So our build system +disables the configure check. + +This means that the `gettext`/`libintl` features in the Python distribution +are not available. + +### libnsl / nis Module + +The `nis` Python extension module has a dependency on `libnsl`. + +`libnsl` has historically been in base Linux distribution installations. +But it is being phased away, with it being an optional install in modern +versions of Fedora and RHEL. + +Because the `nis` extension is perceived to be likely unused functionality, +we've decided to not build it instead of adding complexity to deal with +the `libnsl` dependency. See further discussion in +. + +The `nis` module was deprecated in Python 3.11 and removed in 3.13. + +## Upgrading CPython + +This section documents some of the work that needs to be performed +when upgrading CPython major versions. + +### Review Release Notes + +CPython's release notes often have a section on build system changes. +e.g. . +These are a must review. + +### `Modules/Setup` + +The `Modules/Setup` file defines the default extension build settings. + +We need to audit it for differences such as added/removed extensions, +changes to compile settings, etc just in case we have special code +handling an extension defined in this file. + +See code in `cpython.py` dealing with this file. diff --git a/docs/technotes.rst b/docs/technotes.rst deleted file mode 100644 index 5f0cb6af5..000000000 --- a/docs/technotes.rst +++ /dev/null @@ -1,168 +0,0 @@ -.. _technotes: - -=============== -Technical Notes -=============== - -How It Works -============ - -The first thing the ``build.py`` scripts do is bootstrap an environment -for building Python. Linux builds use Docker images based on deterministic -Debian snapshots selected for each target: - -* x86-64 targets use Debian Jessie and a prebuilt Clang toolchain. -* aarch64 targets use Debian Stretch and a prebuilt Clang toolchain. -* Other cross-compiled targets generally use Debian Stretch and - Debian-provided GCC cross-compilers. -* riscv64 targets use Debian Buster and a Debian-provided GCC - cross-compiler. - -The selected toolchain is used to build Python's dependencies (OpenSSL, -ncurses, libedit, SQLite, etc.). Finally, Python itself is built. - -Python is built in such a way that extensions are statically linked -against their dependencies. For example, instead of the ``sqlite3`` Python -extension having a run-time dependency against ``libsqlite3.so``, the -SQLite symbols are statically inlined into the Python extension object -file. Extension modules are statically linked into ``python`` rather than -provided as shared extensions in the ``lib-dynload`` directory. - -``_dbm`` and ``_tkinter`` are handled differently. On dynamically linked -Linux builds, ``_dbm`` is provided as a shared extension with Berkeley DB -statically linked. This allows the module to be easily removed when the -Berkeley DB license is undesired (see the DBM section below). On macOS, -``_dbm`` instead uses the system NDBM implementation. ``_tkinter`` is -also provided as a shared extension, with Tcl and Tk dynamically linked, -on builds that support shared extensions. - -From the built Python, we produce an archive containing the raw Python -distribution (as if you had run ``make install``) as well as other files -useful for downstream consumers. - -Setup.local Hackery -=================== - -Starting with Python 3.12, C extension modules are configured and built -using ``configure``, ``Modules/Setup.stdlib``, and ``Makefile``. A -generated ``Modules/Setup.local`` file disables selected modules and -overrides whether others are linked statically or built as shared -libraries. - -Prior to 3.12, many extensions were configured and built using ``setup.py`` -scripts. These scripts do not provide much flexibility and rely on default -behaviors in ``distutils``, as well as other inline code in ``setup.py``. -This default behavior is often undesirable for our desired outcome of -producing a standalone Python distribution. - -Because of this, when building Python prior to 3.12, a custom ``Setup.local`` -file is generated that builds all C extensions in a specific manner. -The undesirable behavior of ``setup.py`` is bypassed and the Python C -extensions are compiled just the way we want. - -Dependency Notes -================ - -DBM ---- - -Python has the option of building its ``_dbm`` extension against NDBM, -GDBM, and Berkeley DB. GDBM and its NDBM compatibility libraries are -licensed under GNU GPL Version 3. Modern versions of Berkeley DB are -licensed under GNU AGPL v3. Versions 6.0.19 and older are licensed under -the more permissive Sleepycat License. - -On Linux, we build the ``_dbm`` extension against Berkeley DB 6.0.19. On -macOS, ``_dbm`` uses the NDBM implementation provided by the system -``libSystem`` library instead. - -We explicitly disable the ``_gdbm`` extension on all targets to avoid -the GPL dependency. - -readline / libedit / ncurses ----------------------------- - -Python has the option of building its ``readline`` extension against -either ``libreadline`` or ``libedit``. ``libreadline`` is licensed under -GNU GPL Version 3, and ``libedit`` has a more permissive license. - -``libedit``/``libreadline`` link against a curses library, most likely -``ncurses``. And ``ncurses`` has tie-ins with a terminal database. This -is a thorny situation, as terminal databases can be difficult to -distribute because end-users often want software to respect their -terminal databases. But for that to work, ``ncurses`` needs to be compiled -in a way that respects the user's environment. - -On macOS, we use the system ``libedit`` and ``libncurses``, which is -typically provided in ``/usr/lib``. - -On Linux, we build ``libedit`` and ``ncurses`` from source and statically -link against their respective libraries. Project releases before 2023 linked -against ``readline`` on Linux. - -gettext / locale Module ------------------------ - -The ``locale`` Python module exposes some functionality from the ``gettext`` -software (specifically ``libintl``). (Technically, this functionality is exposed -from the ``_locale`` C extension module and ``locale`` re-exports symbols.) - -``gettext`` is GPL version 3 or later licensed. And having it statically linked -in the Python distribution via the ``_locale`` module can have licensing -implications. - -Python's configure script probes for the ability to compile/link with -``-lintl``. If it works, Python is linked against ``libintl``. If it doesn't, -``libintl`` is omitted. (Search ``configure`` for ``ac_cv_lib_intl_textdomain`` -and ``-lintl`` references.) - -With the container based build environment on Linux, presence of ``gettext`` -and ``libintl`` is deterministic. However, on macOS where there is no -sandboxing of the build environment, Python's configure script can find and -use a ``gettext``/``libintl`` installed outside the system default (e.g. via -Homebrew or MacPorts). This can result in the built Python referencing a shared -library not reliably present on every macOS machine. So our build system -disables the configure check. - -This means that the ``gettext``/``libintl`` features in the Python distribution -are not available. - -libnsl / nis Module -------------------- - -The ``nis`` Python extension module has a dependency on ``libnsl``. - -``libnsl`` has historically been in base Linux distribution installations. -But it is being phased away, with it being an optional install in modern -versions of Fedora and RHEL. - -Because the ``nis`` extension is perceived to be likely unused functionality, -we've decided to not build it instead of adding complexity to deal with -the ``libnsl`` dependency. See further discussion in -https://github.com/astral-sh/python-build-standalone/issues/51. - -The ``nis`` module was deprecated in Python 3.11 and removed in 3.13. - -Upgrading CPython -================= - -This section documents some of the work that needs to be performed -when upgrading CPython major versions. - -Review Release Notes --------------------- - -CPython's release notes often have a section on build system changes. -e.g. https://docs.python.org/3/whatsnew/3.13.html#build-changes. -These are a must review. - -``Modules/Setup`` ------------------ - -The ``Modules/Setup`` file defines the default extension build settings. - -We need to audit it for differences such as added/removed extensions, -changes to compile settings, etc just in case we have special code -handling an extension defined in this file. - -See code in ``cpython.py`` dealing with this file. diff --git a/mkdocs.yml b/mkdocs.yml new file mode 100644 index 000000000..e58b70555 --- /dev/null +++ b/mkdocs.yml @@ -0,0 +1,75 @@ +site_name: Python Standalone Builds +site_description: Self-contained, highly portable, high-performance Python distributions. +site_author: astral-sh +site_url: https://docs.astral.sh/python-build-standalone/ +repo_url: https://github.com/astral-sh/python-build-standalone +repo_name: astral-sh/python-build-standalone +edit_uri: edit/main/docs/ + +theme: + name: material + features: + - navigation.instant + - navigation.instant.prefetch + - navigation.instant.progress + - navigation.tracking + - navigation.footer + - navigation.top + - toc.follow + - content.code.copy + palette: + - media: "(prefers-color-scheme)" + toggle: + icon: material/brightness-auto + name: Switch to light mode + - media: "(prefers-color-scheme: light)" + scheme: astral-light + toggle: + icon: material/brightness-7 + name: Switch to dark mode + - media: "(prefers-color-scheme: dark)" + scheme: astral-dark + toggle: + icon: material/brightness-4 + name: Switch to system preference + +markdown_extensions: + - admonition + - attr_list + - def_list + - pymdownx.details + - pymdownx.highlight: + anchor_linenums: true + - pymdownx.inlinehilite + - pymdownx.superfences + - toc: + anchorlink: true + anchorlink_class: toclink + +plugins: + - search + +extra_css: + - stylesheets/extra.css + +extra: + social: + - icon: fontawesome/brands/github + link: https://github.com/astral-sh/python-build-standalone + - icon: fontawesome/brands/discord + link: https://discord.com/invite/astral-sh + +nav: + - Introduction: index.md + - Running Distributions: running.md + - Building: building.md + - Behavior Quirks: quirks.md + - Technical Notes: technotes.md + - Distribution Archives: distributions.md + - Project Status: status.md + +validation: + omitted_files: warn + absolute_links: warn + unrecognized_links: warn + anchors: warn diff --git a/pyproject.toml b/pyproject.toml index c52450b9a..6f9b184a9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -36,6 +36,10 @@ check = [ dev = [ "moto[server]>=5.1.22", ] +docs = [ + "mkdocs>=1.6.0", + "mkdocs-material>=9.6.0", +] [tool.uv] no-build = true diff --git a/uv.lock b/uv.lock index 09c660678..af900126d 100644 --- a/uv.lock +++ b/uv.lock @@ -64,6 +64,28 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/ef/c3/f30a7a63e664acc7c2545ca0491b6ce8264536e0e5cad3965f1d1b91e960/aws_xray_sdk-2.15.0-py2.py3-none-any.whl", hash = "sha256:422d62ad7d52e373eebb90b642eb1bb24657afe03b22a8df4a8b2e5108e278a3", size = 103228, upload-time = "2025-10-29T21:00:24.12Z" }, ] +[[package]] +name = "babel" +version = "2.18.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/7d/b2/51899539b6ceeeb420d40ed3cd4b7a40519404f9baf3d4ac99dc413a834b/babel-2.18.0.tar.gz", hash = "sha256:b80b99a14bd085fcacfa15c9165f651fbb3406e66cc603abf11c5750937c992d", size = 9959554, upload-time = "2026-02-01T12:30:56.078Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/77/f5/21d2de20e8b8b0408f0681956ca2c69f1320a3848ac50e6e7f39c6159675/babel-2.18.0-py3-none-any.whl", hash = "sha256:e2b422b277c2b9a9630c1d7903c2a00d0830c409c59ac8cae9081c92f1aeba35", size = 10196845, upload-time = "2026-02-01T12:30:53.445Z" }, +] + +[[package]] +name = "backrefs" +version = "8.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ec/56/4744bcd0c82184e80c52b0ac4076c261a8ffa1f1b343ff2f6e89ce0e1cef/backrefs-8.0.tar.gz", hash = "sha256:b556cd7d36c3a3a2f256b89590b176b8eddfb73bcfaee3a3ddd84ea66d21ce50", size = 7013081, upload-time = "2026-07-26T19:54:24.638Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e3/fd/9bf53b6a6f6f519ffaac765df2f2a25e5c2fc6d32cfd2b2747099e72c911/backrefs-8.0-py310-none-any.whl", hash = "sha256:4a627b817fd2dce43b79ab48da63613340509381cd8ce0897078a0bce79a2ab8", size = 380377, upload-time = "2026-07-26T19:54:17.457Z" }, + { url = "https://files.pythonhosted.org/packages/e1/29/4bd7ae72a2634da00379c2b3bcc5439e7c94620235c6afea8af15229a973/backrefs-8.0-py311-none-any.whl", hash = "sha256:f0c35cf0102ba6b6070c12a492be3c1c1d3f5839529784b9a9565d6d04569a01", size = 392169, upload-time = "2026-07-26T19:54:18.782Z" }, + { url = "https://files.pythonhosted.org/packages/29/13/232505664e8e2a0c7a2eb0c505cfade9d715538f89a5d62bc4c272968f62/backrefs-8.0-py312-none-any.whl", hash = "sha256:87f0fae8c5f207fe9f4b2887efc71d42f4900ac78faa1af08d675ef303692dc5", size = 398084, upload-time = "2026-07-26T19:54:19.954Z" }, + { url = "https://files.pythonhosted.org/packages/8a/69/47a3dc20abc4fa5486655fde681bd55e63211b46c886d8c02223d6468431/backrefs-8.0-py313-none-any.whl", hash = "sha256:601ce68ca12385dbda06ce264406b4c4210cf5b79fd0fd627592365c92f29a88", size = 400040, upload-time = "2026-07-26T19:54:21.194Z" }, + { url = "https://files.pythonhosted.org/packages/1c/cf/e5f9b68a5b0e939a2fb933a66c20180d0c9241bf8927f7a47fa48c1675e9/backrefs-8.0-py314-none-any.whl", hash = "sha256:9ec96efa080938be92323e8e730e57718c9c88eb15ad70bbef4e1766df591408", size = 411903, upload-time = "2026-07-26T19:54:23.221Z" }, +] + [[package]] name = "blinker" version = "1.9.0" @@ -472,6 +494,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/4f/af/72ad54402e599152de6d067324c46fe6a4f531c7c65baf7e96c63db55eaf/flask_cors-6.0.2-py3-none-any.whl", hash = "sha256:e57544d415dfd7da89a9564e1e3a9e515042df76e12130641ca6f3f2f03b699a", size = 13257, upload-time = "2025-12-12T20:31:41.3Z" }, ] +[[package]] +name = "ghp-import" +version = "2.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "python-dateutil" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/d9/29/d40217cbe2f6b1359e00c6c307bb3fc876ba74068cbab3dde77f03ca0dc4/ghp-import-2.1.0.tar.gz", hash = "sha256:9c535c4c61193c2df8871222567d7fd7e5014d835f97dc7b7439069e2413d343", size = 10943, upload-time = "2022-05-02T15:47:16.11Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f7/ec/67fbef5d497f86283db54c22eec6f6140243aae73265799baaaa19cd17fb/ghp_import-2.1.0-py3-none-any.whl", hash = "sha256:8337dd7b50877f163d4c0289bc1f1c7f127550241988d568c1db512c4324a619", size = 11034, upload-time = "2022-05-02T15:47:14.552Z" }, +] + [[package]] name = "graphql-core" version = "3.2.8" @@ -733,6 +767,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/b2/c8/d148e041732d631fc76036f8b30fae4e77b027a1e95b7a84bb522481a940/librt-0.8.1-cp314-cp314t-win_arm64.whl", hash = "sha256:bf512a71a23504ed08103a13c941f763db13fb11177beb3d9244c98c29fb4a61", size = 48755, upload-time = "2026-02-17T16:12:47.943Z" }, ] +[[package]] +name = "markdown" +version = "3.10.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/29/6f/da4c6aea59b3001f2e8c0ec7497475aadaf3b021c10cab5b2858f0f32b26/markdown-3.10.3.tar.gz", hash = "sha256:3589362618f743188b4d955b874402bc814f4f83f544dc207719f4baa7d9c45f", size = 372596, upload-time = "2026-07-30T19:05:29.005Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/64/69/4a5af2bc115a9a33fefe51709749de8262be3f9ba063d1753a837cdbc49c/markdown-3.10.3-py3-none-any.whl", hash = "sha256:fa6c92a00a4a3c98b22728c64a935ae1928250ae65058a6ded814d2cc29a4cea", size = 110757, upload-time = "2026-07-30T19:05:27.883Z" }, +] + [[package]] name = "markupsafe" version = "3.0.3" @@ -818,6 +861,84 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/70/bc/6f1c2f612465f5fa89b95bead1f44dcb607670fd42891d8fdcd5d039f4f4/markupsafe-3.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:32001d6a8fc98c8cb5c947787c5d08b0a50663d139f1305bac5885d98d9b40fa", size = 14146, upload-time = "2025-09-27T18:37:28.327Z" }, ] +[[package]] +name = "mergedeep" +version = "1.3.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/3a/41/580bb4006e3ed0361b8151a01d324fb03f420815446c7def45d02f74c270/mergedeep-1.3.4.tar.gz", hash = "sha256:0096d52e9dad9939c3d975a774666af186eda617e6ca84df4c94dec30004f2a8", size = 4661, upload-time = "2021-02-05T18:55:30.623Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2c/19/04f9b178c2d8a15b076c8b5140708fa6ffc5601fb6f1e975537072df5b2a/mergedeep-1.3.4-py3-none-any.whl", hash = "sha256:70775750742b25c0d8f36c55aed03d24c3384d17c951b3175d898bd778ef0307", size = 6354, upload-time = "2021-02-05T18:55:29.583Z" }, +] + +[[package]] +name = "mkdocs" +version = "1.6.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "click" }, + { name = "colorama", marker = "sys_platform == 'win32'" }, + { name = "ghp-import" }, + { name = "jinja2" }, + { name = "markdown" }, + { name = "markupsafe" }, + { name = "mergedeep" }, + { name = "mkdocs-get-deps" }, + { name = "packaging" }, + { name = "pathspec" }, + { name = "pyyaml" }, + { name = "pyyaml-env-tag" }, + { name = "watchdog" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/bc/c6/bbd4f061bd16b378247f12953ffcb04786a618ce5e904b8c5a01a0309061/mkdocs-1.6.1.tar.gz", hash = "sha256:7b432f01d928c084353ab39c57282f29f92136665bdd6abf7c1ec8d822ef86f2", size = 3889159, upload-time = "2024-08-30T12:24:06.899Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/22/5b/dbc6a8cddc9cfa9c4971d59fb12bb8d42e161b7e7f8cc89e49137c5b279c/mkdocs-1.6.1-py3-none-any.whl", hash = "sha256:db91759624d1647f3f34aa0c3f327dd2601beae39a366d6e064c03468d35c20e", size = 3864451, upload-time = "2024-08-30T12:24:05.054Z" }, +] + +[[package]] +name = "mkdocs-get-deps" +version = "0.2.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "mergedeep" }, + { name = "platformdirs" }, + { name = "pyyaml" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ce/25/b3cccb187655b9393572bde9b09261d267c3bf2f2cdabe347673be5976a6/mkdocs_get_deps-0.2.2.tar.gz", hash = "sha256:8ee8d5f316cdbbb2834bc1df6e69c08fe769a83e040060de26d3c19fad3599a1", size = 11047, upload-time = "2026-03-10T02:46:33.632Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/88/29/744136411e785c4b0b744d5413e56555265939ab3a104c6a4b719dad33fd/mkdocs_get_deps-0.2.2-py3-none-any.whl", hash = "sha256:e7878cbeac04860b8b5e0ca31d3abad3df9411a75a32cde82f8e44b6c16ff650", size = 9555, upload-time = "2026-03-10T02:46:32.256Z" }, +] + +[[package]] +name = "mkdocs-material" +version = "9.7.7" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "babel" }, + { name = "backrefs" }, + { name = "colorama" }, + { name = "jinja2" }, + { name = "markdown" }, + { name = "mkdocs" }, + { name = "mkdocs-material-extensions" }, + { name = "paginate" }, + { name = "pygments" }, + { name = "pymdown-extensions" }, + { name = "requests" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/f1/cd/c05d3a530ba7934f144fb45f7203cd236adc25c7bdcc34673d202f4b0278/mkdocs_material-9.7.7.tar.gz", hash = "sha256:c0649c065b1b0512d60aad8c10f947f8e455284475239b364b610f2deb4d0855", size = 4097923, upload-time = "2026-07-17T16:21:33.156Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ad/21/17c1bc9e6f47c972ad66fb2ac2568f99f90f1207eeb6fc3b34d094dba7b5/mkdocs_material-9.7.7-py3-none-any.whl", hash = "sha256:8ea9bb1737a5b524a5f9dcf2e1b4ebda8274ae3008aa7845720a97083bef708f", size = 9305438, upload-time = "2026-07-17T16:21:30.017Z" }, +] + +[[package]] +name = "mkdocs-material-extensions" +version = "1.3.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/79/9b/9b4c96d6593b2a541e1cb8b34899a6d021d208bb357042823d4d2cabdbe7/mkdocs_material_extensions-1.3.1.tar.gz", hash = "sha256:10c9511cea88f568257f960358a467d12b970e1f7b2c0e5fb2bb48cab1928443", size = 11847, upload-time = "2023-11-22T19:09:45.208Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5b/54/662a4743aa81d9582ee9339d4ffa3c8fd40a4965e033d77b9da9774d3960/mkdocs_material_extensions-1.3.1-py3-none-any.whl", hash = "sha256:adff8b62700b25cb77b53358dad940f3ef973dd6db797907c49e3c2ef3ab4e31", size = 8728, upload-time = "2023-11-22T19:09:43.465Z" }, +] + [[package]] name = "moto" version = "5.1.22" @@ -992,6 +1113,24 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/cb/70/52310f9ece5f4eb02e0b31d538b51f729169517767a8d0100a25db31d67f/openapi_spec_validator-0.8.4-py3-none-any.whl", hash = "sha256:cf905117063d7c4d495c8a5a167a1f2a8006da6ffa8ba234a7ed0d0f11454d51", size = 50330, upload-time = "2026-03-01T15:48:17.668Z" }, ] +[[package]] +name = "packaging" +version = "26.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/7d/fa/3944b40b07da9ce895c0e6303a5ab7d53da063554f534556b134a54d6093/packaging-26.3.tar.gz", hash = "sha256:94edc256424af38762eb31306eed28beb9f0efc50a8837492c9d6fd6004aed79", size = 313412, upload-time = "2026-08-04T18:15:28.737Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/63/34/ba1c580383c9eada3711951fef0795c80b829a078d72188184bcab9dd527/packaging-26.3-py3-none-any.whl", hash = "sha256:d7193f7c8e4e93f444fde0262bf90af30e16fa0ad0ad44cb553c87339b23cd1c", size = 129956, upload-time = "2026-08-04T18:15:27.159Z" }, +] + +[[package]] +name = "paginate" +version = "0.5.7" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ec/46/68dde5b6bc00c1296ec6466ab27dddede6aec9af1b99090e1107091b3b84/paginate-0.5.7.tar.gz", hash = "sha256:22bd083ab41e1a8b4f3690544afb2c60c25e5c9a63a30fa2f483f6c60c8e5945", size = 19252, upload-time = "2024-08-25T14:17:24.139Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/90/96/04b8e52da071d28f5e21a805b19cb9390aa17a47462ac87f5e2696b9566d/paginate-0.5.7-py2.py3-none-any.whl", hash = "sha256:b885e2af73abcf01d9559fd5216b57ef722f8c42affbb63942377668e35c7591", size = 13746, upload-time = "2024-08-25T14:17:22.55Z" }, +] + [[package]] name = "pathable" version = "0.5.0" @@ -1010,6 +1149,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/ef/3c/2c197d226f9ea224a9ab8d197933f9da0ae0aac5b6e0f884e2b8d9c8e9f7/pathspec-1.0.4-py3-none-any.whl", hash = "sha256:fb6ae2fd4e7c921a165808a552060e722767cfa526f99ca5156ed2ce45a5c723", size = 55206, upload-time = "2026-01-27T03:59:45.137Z" }, ] +[[package]] +name = "platformdirs" +version = "4.11.7" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/69/b7/802a56eca9f2fac455b8bab5375a2647b0f0e14a2cd63ef077de3c4a7658/platformdirs-4.11.7.tar.gz", hash = "sha256:4f41487eeeeeb07f3a6625e61d9bc0ae6809f92d3386dbd74392fbb76108104d", size = 35127, upload-time = "2026-09-01T13:35:10.502Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/27/6e/80993e10a0482f630cef528635789233224f36b1ffd11592aa15d13ff9ce/platformdirs-4.11.7-py3-none-any.whl", hash = "sha256:8a02cb259042c79d1cd0450facc2fe6dc9d303ae7901afbe33bf8ea0b188cef6", size = 23938, upload-time = "2026-09-01T13:35:09.02Z" }, +] + [[package]] name = "py-partiql-parser" version = "0.6.3" @@ -1175,6 +1323,28 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/00/4b/ccc026168948fec4f7555b9164c724cf4125eac006e176541483d2c959be/pydantic_settings-2.13.1-py3-none-any.whl", hash = "sha256:d56fd801823dbeae7f0975e1f8c8e25c258eb75d278ea7abb5d9cebb01b56237", size = 58929, upload-time = "2026-02-19T13:45:06.034Z" }, ] +[[package]] +name = "pygments" +version = "2.21.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/49/2e/ced460408999b33da6b31b0021b0f37d329e202d4169aeb164493778f25b/pygments-2.21.0.tar.gz", hash = "sha256:610ca751c9bc2492b38eb9a38a7fbc93edbbb2d7182edaf34e66ae493dee5c8c", size = 5005329, upload-time = "2026-08-17T08:02:48.824Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/71/46/17f022dd3e953bf20a04a028a21ec746d942f8d2af30fa0f124fa0e6a684/pygments-2.21.0-py3-none-any.whl", hash = "sha256:2363c69b61c4a97c838da3b130dcd6468f4848992b21a82f2a63ec34377137d9", size = 1250147, upload-time = "2026-08-17T08:02:44.912Z" }, +] + +[[package]] +name = "pymdown-extensions" +version = "11.0.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "markdown" }, + { name = "pyyaml" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ad/17/2db4b414de89659144488e0d9c6c0bf0c8395841dc12d81d0532cc6ef310/pymdown_extensions-11.0.2.tar.gz", hash = "sha256:9506fcbe66fa355a775b768084334238dd6805020ac4b92bea0c0dda6f8f223d", size = 855419, upload-time = "2026-08-22T19:28:47.236Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a6/43/9f45ec4d14e596efc32c925a78104934790438b0c0628b70d741016734ad/pymdown_extensions-11.0.2-py3-none-any.whl", hash = "sha256:259910762019732caa1dfd76f3faa62c59f191d46573e80bcb1d13c0f675bbe5", size = 269929, upload-time = "2026-08-22T19:28:45.389Z" }, +] + [[package]] name = "pyparsing" version = "3.3.2" @@ -1212,6 +1382,10 @@ check = [ dev = [ { name = "moto", extra = ["server"] }, ] +docs = [ + { name = "mkdocs" }, + { name = "mkdocs-material" }, +] [package.metadata] requires-dist = [ @@ -1236,6 +1410,10 @@ check = [ { name = "types-pyyaml", specifier = ">=6.0.12.20250915" }, ] dev = [{ name = "moto", extras = ["server"], specifier = ">=5.1.22" }] +docs = [ + { name = "mkdocs", specifier = ">=1.6.0" }, + { name = "mkdocs-material", specifier = ">=9.6.0" }, +] [[package]] name = "python-dateutil" @@ -1344,6 +1522,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/f1/12/de94a39c2ef588c7e6455cfbe7343d3b2dc9d6b6b2f40c4c6565744c873d/pyyaml-6.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:ebc55a14a21cb14062aa4162f906cd962b28e2e9ea38f9b4391244cd8de4ae0b", size = 149341, upload-time = "2025-09-25T21:32:56.828Z" }, ] +[[package]] +name = "pyyaml-env-tag" +version = "1.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pyyaml" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/eb/2e/79c822141bfd05a853236b504869ebc6b70159afc570e1d5a20641782eaa/pyyaml_env_tag-1.1.tar.gz", hash = "sha256:2eb38b75a2d21ee0475d6d97ec19c63287a7e140231e4214969d0eac923cd7ff", size = 5737, upload-time = "2025-05-13T15:24:01.64Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/04/11/432f32f8097b03e3cd5fe57e88efb685d964e2e5178a48ed61e841f7fdce/pyyaml_env_tag-1.1-py3-none-any.whl", hash = "sha256:17109e1a528561e32f026364712fee1264bc2ea6715120891174ed1b980d2e04", size = 4722, upload-time = "2025-05-13T15:23:59.629Z" }, +] + [[package]] name = "referencing" version = "0.37.0" @@ -1853,6 +2043,38 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/39/08/aaaad47bc4e9dc8c725e68f9d04865dbcb2052843ff09c97b08904852d84/urllib3-2.6.3-py3-none-any.whl", hash = "sha256:bf272323e553dfb2e87d9bfd225ca7b0f467b919d7bbd355436d3fd37cb0acd4", size = 131584, upload-time = "2026-01-07T16:24:42.685Z" }, ] +[[package]] +name = "watchdog" +version = "6.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/db/7d/7f3d619e951c88ed75c6037b246ddcf2d322812ee8ea189be89511721d54/watchdog-6.0.0.tar.gz", hash = "sha256:9ddf7c82fda3ae8e24decda1338ede66e1c99883db93711d8fb941eaa2d8c282", size = 131220, upload-time = "2024-11-01T14:07:13.037Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0c/56/90994d789c61df619bfc5ce2ecdabd5eeff564e1eb47512bd01b5e019569/watchdog-6.0.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d1cdb490583ebd691c012b3d6dae011000fe42edb7a82ece80965b42abd61f26", size = 96390, upload-time = "2024-11-01T14:06:24.793Z" }, + { url = "https://files.pythonhosted.org/packages/55/46/9a67ee697342ddf3c6daa97e3a587a56d6c4052f881ed926a849fcf7371c/watchdog-6.0.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bc64ab3bdb6a04d69d4023b29422170b74681784ffb9463ed4870cf2f3e66112", size = 88389, upload-time = "2024-11-01T14:06:27.112Z" }, + { url = "https://files.pythonhosted.org/packages/44/65/91b0985747c52064d8701e1075eb96f8c40a79df889e59a399453adfb882/watchdog-6.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c897ac1b55c5a1461e16dae288d22bb2e412ba9807df8397a635d88f671d36c3", size = 89020, upload-time = "2024-11-01T14:06:29.876Z" }, + { url = "https://files.pythonhosted.org/packages/e0/24/d9be5cd6642a6aa68352ded4b4b10fb0d7889cb7f45814fb92cecd35f101/watchdog-6.0.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:6eb11feb5a0d452ee41f824e271ca311a09e250441c262ca2fd7ebcf2461a06c", size = 96393, upload-time = "2024-11-01T14:06:31.756Z" }, + { url = "https://files.pythonhosted.org/packages/63/7a/6013b0d8dbc56adca7fdd4f0beed381c59f6752341b12fa0886fa7afc78b/watchdog-6.0.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ef810fbf7b781a5a593894e4f439773830bdecb885e6880d957d5b9382a960d2", size = 88392, upload-time = "2024-11-01T14:06:32.99Z" }, + { url = "https://files.pythonhosted.org/packages/d1/40/b75381494851556de56281e053700e46bff5b37bf4c7267e858640af5a7f/watchdog-6.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:afd0fe1b2270917c5e23c2a65ce50c2a4abb63daafb0d419fde368e272a76b7c", size = 89019, upload-time = "2024-11-01T14:06:34.963Z" }, + { url = "https://files.pythonhosted.org/packages/39/ea/3930d07dafc9e286ed356a679aa02d777c06e9bfd1164fa7c19c288a5483/watchdog-6.0.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:bdd4e6f14b8b18c334febb9c4425a878a2ac20efd1e0b231978e7b150f92a948", size = 96471, upload-time = "2024-11-01T14:06:37.745Z" }, + { url = "https://files.pythonhosted.org/packages/12/87/48361531f70b1f87928b045df868a9fd4e253d9ae087fa4cf3f7113be363/watchdog-6.0.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:c7c15dda13c4eb00d6fb6fc508b3c0ed88b9d5d374056b239c4ad1611125c860", size = 88449, upload-time = "2024-11-01T14:06:39.748Z" }, + { url = "https://files.pythonhosted.org/packages/5b/7e/8f322f5e600812e6f9a31b75d242631068ca8f4ef0582dd3ae6e72daecc8/watchdog-6.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6f10cb2d5902447c7d0da897e2c6768bca89174d0c6e1e30abec5421af97a5b0", size = 89054, upload-time = "2024-11-01T14:06:41.009Z" }, + { url = "https://files.pythonhosted.org/packages/68/98/b0345cabdce2041a01293ba483333582891a3bd5769b08eceb0d406056ef/watchdog-6.0.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:490ab2ef84f11129844c23fb14ecf30ef3d8a6abafd3754a6f75ca1e6654136c", size = 96480, upload-time = "2024-11-01T14:06:42.952Z" }, + { url = "https://files.pythonhosted.org/packages/85/83/cdf13902c626b28eedef7ec4f10745c52aad8a8fe7eb04ed7b1f111ca20e/watchdog-6.0.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:76aae96b00ae814b181bb25b1b98076d5fc84e8a53cd8885a318b42b6d3a5134", size = 88451, upload-time = "2024-11-01T14:06:45.084Z" }, + { url = "https://files.pythonhosted.org/packages/fe/c4/225c87bae08c8b9ec99030cd48ae9c4eca050a59bf5c2255853e18c87b50/watchdog-6.0.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a175f755fc2279e0b7312c0035d52e27211a5bc39719dd529625b1930917345b", size = 89057, upload-time = "2024-11-01T14:06:47.324Z" }, + { url = "https://files.pythonhosted.org/packages/30/ad/d17b5d42e28a8b91f8ed01cb949da092827afb9995d4559fd448d0472763/watchdog-6.0.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:c7ac31a19f4545dd92fc25d200694098f42c9a8e391bc00bdd362c5736dbf881", size = 87902, upload-time = "2024-11-01T14:06:53.119Z" }, + { url = "https://files.pythonhosted.org/packages/5c/ca/c3649991d140ff6ab67bfc85ab42b165ead119c9e12211e08089d763ece5/watchdog-6.0.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:9513f27a1a582d9808cf21a07dae516f0fab1cf2d7683a742c498b93eedabb11", size = 88380, upload-time = "2024-11-01T14:06:55.19Z" }, + { url = "https://files.pythonhosted.org/packages/a9/c7/ca4bf3e518cb57a686b2feb4f55a1892fd9a3dd13f470fca14e00f80ea36/watchdog-6.0.0-py3-none-manylinux2014_aarch64.whl", hash = "sha256:7607498efa04a3542ae3e05e64da8202e58159aa1fa4acddf7678d34a35d4f13", size = 79079, upload-time = "2024-11-01T14:06:59.472Z" }, + { url = "https://files.pythonhosted.org/packages/5c/51/d46dc9332f9a647593c947b4b88e2381c8dfc0942d15b8edc0310fa4abb1/watchdog-6.0.0-py3-none-manylinux2014_armv7l.whl", hash = "sha256:9041567ee8953024c83343288ccc458fd0a2d811d6a0fd68c4c22609e3490379", size = 79078, upload-time = "2024-11-01T14:07:01.431Z" }, + { url = "https://files.pythonhosted.org/packages/d4/57/04edbf5e169cd318d5f07b4766fee38e825d64b6913ca157ca32d1a42267/watchdog-6.0.0-py3-none-manylinux2014_i686.whl", hash = "sha256:82dc3e3143c7e38ec49d61af98d6558288c415eac98486a5c581726e0737c00e", size = 79076, upload-time = "2024-11-01T14:07:02.568Z" }, + { url = "https://files.pythonhosted.org/packages/ab/cc/da8422b300e13cb187d2203f20b9253e91058aaf7db65b74142013478e66/watchdog-6.0.0-py3-none-manylinux2014_ppc64.whl", hash = "sha256:212ac9b8bf1161dc91bd09c048048a95ca3a4c4f5e5d4a7d1b1a7d5752a7f96f", size = 79077, upload-time = "2024-11-01T14:07:03.893Z" }, + { url = "https://files.pythonhosted.org/packages/2c/3b/b8964e04ae1a025c44ba8e4291f86e97fac443bca31de8bd98d3263d2fcf/watchdog-6.0.0-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:e3df4cbb9a450c6d49318f6d14f4bbc80d763fa587ba46ec86f99f9e6876bb26", size = 79078, upload-time = "2024-11-01T14:07:05.189Z" }, + { url = "https://files.pythonhosted.org/packages/62/ae/a696eb424bedff7407801c257d4b1afda455fe40821a2be430e173660e81/watchdog-6.0.0-py3-none-manylinux2014_s390x.whl", hash = "sha256:2cce7cfc2008eb51feb6aab51251fd79b85d9894e98ba847408f662b3395ca3c", size = 79077, upload-time = "2024-11-01T14:07:06.376Z" }, + { url = "https://files.pythonhosted.org/packages/b5/e8/dbf020b4d98251a9860752a094d09a65e1b436ad181faf929983f697048f/watchdog-6.0.0-py3-none-manylinux2014_x86_64.whl", hash = "sha256:20ffe5b202af80ab4266dcd3e91aae72bf2da48c0d33bdb15c66658e685e94e2", size = 79078, upload-time = "2024-11-01T14:07:07.547Z" }, + { url = "https://files.pythonhosted.org/packages/07/f6/d0e5b343768e8bcb4cda79f0f2f55051bf26177ecd5651f84c07567461cf/watchdog-6.0.0-py3-none-win32.whl", hash = "sha256:07df1fdd701c5d4c8e55ef6cf55b8f0120fe1aef7ef39a1c6fc6bc2e606d517a", size = 79065, upload-time = "2024-11-01T14:07:09.525Z" }, + { url = "https://files.pythonhosted.org/packages/db/d9/c495884c6e548fce18a8f40568ff120bc3a4b7b99813081c8ac0c936fa64/watchdog-6.0.0-py3-none-win_amd64.whl", hash = "sha256:cbafb470cf848d93b5d013e2ecb245d4aa1c8fd0504e863ccefa32445359d680", size = 79070, upload-time = "2024-11-01T14:07:10.686Z" }, + { url = "https://files.pythonhosted.org/packages/33/e8/e40370e6d74ddba47f002a32919d91310d6074130fe4e17dabcafc15cbf1/watchdog-6.0.0-py3-none-win_ia64.whl", hash = "sha256:a1914259fa9e1454315171103c6a30961236f508b9b623eae470268bbcc6a22f", size = 79067, upload-time = "2024-11-01T14:07:11.845Z" }, +] + [[package]] name = "werkzeug" version = "3.1.7" From c721f344b5d4c5be678abfa1008d59cf29b56f9c Mon Sep 17 00:00:00 2001 From: "Jonathan J. Helmus" Date: Thu, 10 Sep 2026 12:50:35 -0500 Subject: [PATCH 2/2] add action to publish docs to astral-sh/docs --- .github/workflows/publish-docs.yml | 92 ++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 .github/workflows/publish-docs.yml diff --git a/.github/workflows/publish-docs.yml b/.github/workflows/publish-docs.yml new file mode 100644 index 000000000..0486e1be2 --- /dev/null +++ b/.github/workflows/publish-docs.yml @@ -0,0 +1,92 @@ +# Publish documentation via a pull request to astral-sh/docs +name: Publish docs + +on: + workflow_dispatch: + inputs: + ref: + description: "The commit SHA, tag, or branch to publish. Defaults to the selected workflow ref." + default: "" + type: string + +permissions: + contents: read + +concurrency: + group: publish-docs + cancel-in-progress: false + +jobs: + publish: + name: Publish documentation + environment: release + runs-on: ubuntu-latest + steps: + - name: Checkout source + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + ref: ${{ inputs.ref || github.ref }} + persist-credentials: false + + - name: Set up uv + uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0 + with: + enable-cache: false + python-version: "3.12" + + - name: Build docs + run: uv run --only-group docs mkdocs build --strict --site-dir site/python-build-standalone + + - name: Record source revision + run: echo "DOCS_REVISION=$(git rev-parse HEAD)" >> "$GITHUB_ENV" + + - name: Checkout docs repository + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + repository: astral-sh/docs + ref: main + path: astral-docs + token: ${{ secrets.ASTRAL_DOCS_PAT }} + persist-credentials: false + + - name: Copy docs + run: | + mkdir -p astral-docs/site/python-build-standalone + rsync --archive --delete site/python-build-standalone/ astral-docs/site/python-build-standalone/ + + - name: Commit docs + id: commit + working-directory: astral-docs + run: | + git config user.name "astral-docs-bot" + git config user.email "176161322+astral-docs-bot@users.noreply.github.com" + + branch_name="update-python-build-standalone-docs-${GITHUB_RUN_ID}-${GITHUB_RUN_ATTEMPT}" + git checkout -b "$branch_name" + git add site/python-build-standalone + if git diff --cached --quiet; then + echo "Documentation is already up to date." + echo "changed=false" >> "$GITHUB_OUTPUT" + exit 0 + fi + + git commit -m "Update python-build-standalone documentation for ${DOCS_REVISION}" + echo "changed=true" >> "$GITHUB_OUTPUT" + echo "branch_name=$branch_name" >> "$GITHUB_OUTPUT" + + - name: Create pull request + if: steps.commit.outputs.changed == 'true' + working-directory: astral-docs + env: + GH_TOKEN: ${{ secrets.ASTRAL_DOCS_PAT }} + DOCS_BRANCH: ${{ steps.commit.outputs.branch_name }} + run: | + gh auth setup-git + git push origin "$DOCS_BRANCH" + gh pr create \ + --repo astral-sh/docs \ + --base main \ + --head "$DOCS_BRANCH" \ + --title "Update python-build-standalone documentation" \ + --body "Automated documentation update from https://github.com/${GITHUB_REPOSITORY}/commit/${DOCS_REVISION}." \ + --label documentation