portable-python 2.0.0__tar.gz → 2.0.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (105) hide show
  1. portable_python-2.0.1/.claude/settings.json +10 -0
  2. portable_python-2.0.1/.dockerignore +15 -0
  3. portable_python-2.0.1/.github/workflows/release.yml +26 -0
  4. portable_python-2.0.1/.github/workflows/tests.yml +59 -0
  5. portable_python-2.0.1/.gitignore +28 -0
  6. portable_python-2.0.1/CLAUDE.md +25 -0
  7. portable_python-2.0.1/Dockerfile +18 -0
  8. portable_python-2.0.1/MANIFEST.in +2 -0
  9. {portable_python-2.0.0/src/portable_python.egg-info → portable_python-2.0.1}/PKG-INFO +68 -26
  10. {portable_python-2.0.0 → portable_python-2.0.1}/README.rst +60 -2
  11. portable_python-2.0.1/docs/architecture/build-setup.md +29 -0
  12. portable_python-2.0.1/docs/architecture/config.md +30 -0
  13. portable_python-2.0.1/docs/architecture/cpython.md +24 -0
  14. portable_python-2.0.1/docs/architecture/index.md +30 -0
  15. portable_python-2.0.1/docs/architecture/module-builder.md +26 -0
  16. portable_python-2.0.1/docs/architecture/ppg.md +21 -0
  17. portable_python-2.0.1/docs/architecture/python-builder.md +25 -0
  18. portable_python-2.0.1/docs/architecture/python-inspector.md +27 -0
  19. portable_python-2.0.1/docs/changelog.md +13 -0
  20. portable_python-2.0.1/docs/cli/build-report.md +24 -0
  21. portable_python-2.0.1/docs/cli/build.md +30 -0
  22. portable_python-2.0.1/docs/cli/diagnostics.md +17 -0
  23. portable_python-2.0.1/docs/cli/index.md +19 -0
  24. portable_python-2.0.1/docs/cli/inspect.md +29 -0
  25. portable_python-2.0.1/docs/cli/lib-auto-correct.md +24 -0
  26. portable_python-2.0.1/docs/cli/list.md +24 -0
  27. portable_python-2.0.1/docs/cli/recompress.md +23 -0
  28. portable_python-2.0.1/docs/concepts/build-layout.md +49 -0
  29. portable_python-2.0.1/docs/concepts/folder-masking.md +26 -0
  30. portable_python-2.0.1/docs/concepts/index.md +10 -0
  31. portable_python-2.0.1/docs/concepts/portability.md +35 -0
  32. portable_python-2.0.1/docs/concepts/ppp-marker.md +24 -0
  33. portable_python-2.0.1/docs/concepts/static-linking.md +31 -0
  34. portable_python-2.0.1/docs/concepts/telltale-detection.md +49 -0
  35. portable_python-2.0.1/docs/configuration/index.md +7 -0
  36. portable_python-2.0.1/docs/configuration/portable-python-yml.md +82 -0
  37. portable_python-2.0.1/docs/guides/add-a-config-option.md +20 -0
  38. portable_python-2.0.1/docs/guides/add-an-external-module.md +59 -0
  39. portable_python-2.0.1/docs/guides/build-a-portable-python.md +61 -0
  40. portable_python-2.0.1/docs/guides/bump-components.md +66 -0
  41. portable_python-2.0.1/docs/guides/bump-python-support.md +18 -0
  42. portable_python-2.0.1/docs/guides/ci-cd.md +31 -0
  43. portable_python-2.0.1/docs/guides/fix-a-portability-issue.md +18 -0
  44. portable_python-2.0.1/docs/guides/index.md +12 -0
  45. portable_python-2.0.1/docs/guides/local-development.md +75 -0
  46. portable_python-2.0.1/docs/index.md +32 -0
  47. portable_python-2.0.1/docs/log.md +25 -0
  48. portable_python-2.0.1/docs/modules/external-modules.md +54 -0
  49. portable_python-2.0.1/docs/modules/index.md +7 -0
  50. portable_python-2.0.1/docs/overview.md +62 -0
  51. portable_python-2.0.1/docs/release.md +52 -0
  52. portable_python-2.0.1/lock-deps.sh +5 -0
  53. portable_python-2.0.1/portable-python.yml +67 -0
  54. {portable_python-2.0.0 → portable_python-2.0.1}/pyproject.toml +75 -1
  55. portable_python-2.0.1/requirements.txt +48 -0
  56. portable_python-2.0.1/retired/README.md +9 -0
  57. portable_python-2.0.1/retired/toolchain.py +52 -0
  58. portable_python-2.0.1/scripts/bashrc.sh +4 -0
  59. portable_python-2.0.1/scripts/check_okf.py +124 -0
  60. portable_python-2.0.1/scripts/portable-python.sh +21 -0
  61. {portable_python-2.0.0 → portable_python-2.0.1}/src/portable_python/external/__init__.py +1 -0
  62. {portable_python-2.0.0 → portable_python-2.0.1}/src/portable_python/external/xcpython.py +25 -8
  63. {portable_python-2.0.0 → portable_python-2.0.1}/src/portable_python/external/xtkinter.py +6 -1
  64. {portable_python-2.0.0 → portable_python-2.0.1/src/portable_python.egg-info}/PKG-INFO +68 -26
  65. portable_python-2.0.1/src/portable_python.egg-info/SOURCES.txt +97 -0
  66. portable_python-2.0.1/src/portable_python.egg-info/requires.txt +5 -0
  67. portable_python-2.0.1/src/portable_python.egg-info/scm_file_list.json +93 -0
  68. portable_python-2.0.1/src/portable_python.egg-info/scm_version.json +8 -0
  69. portable_python-2.0.1/tests/__init__.py +0 -0
  70. portable_python-2.0.1/tests/conftest.py +18 -0
  71. portable_python-2.0.1/tests/sample-config1.yml +50 -0
  72. portable_python-2.0.1/tests/sample-config2.yml +7 -0
  73. portable_python-2.0.1/tests/sample-incomplete.yml +2 -0
  74. {portable_python-2.0.0 → portable_python-2.0.1}/tests/test_failed.py +1 -1
  75. {portable_python-2.0.0 → portable_python-2.0.1}/tests/test_inspector.py +2 -2
  76. portable_python-2.0.1/tox.ini +31 -0
  77. portable_python-2.0.0/DEVELOP.md +0 -68
  78. portable_python-2.0.0/MANIFEST.in +0 -5
  79. portable_python-2.0.0/requirements.txt +0 -5
  80. portable_python-2.0.0/setup.py +0 -41
  81. portable_python-2.0.0/src/portable_python.egg-info/SOURCES.txt +0 -36
  82. portable_python-2.0.0/src/portable_python.egg-info/requires.txt +0 -5
  83. {portable_python-2.0.0 → portable_python-2.0.1}/LICENSE +0 -0
  84. {portable_python-2.0.0 → portable_python-2.0.1}/SECURITY.md +0 -0
  85. {portable_python-2.0.0 → portable_python-2.0.1}/setup.cfg +0 -0
  86. {portable_python-2.0.0 → portable_python-2.0.1}/src/portable_python/__init__.py +0 -0
  87. {portable_python-2.0.0 → portable_python-2.0.1}/src/portable_python/__main__.py +0 -0
  88. {portable_python-2.0.0 → portable_python-2.0.1}/src/portable_python/cli.py +0 -0
  89. {portable_python-2.0.0 → portable_python-2.0.1}/src/portable_python/config.py +0 -0
  90. {portable_python-2.0.0 → portable_python-2.0.1}/src/portable_python/cpython.py +0 -0
  91. {portable_python-2.0.0 → portable_python-2.0.1}/src/portable_python/external/_inspect.py +0 -0
  92. {portable_python-2.0.0 → portable_python-2.0.1}/src/portable_python/inspector.py +0 -0
  93. {portable_python-2.0.0 → portable_python-2.0.1}/src/portable_python/tracking.py +0 -0
  94. {portable_python-2.0.0 → portable_python-2.0.1}/src/portable_python/versions.py +0 -0
  95. {portable_python-2.0.0 → portable_python-2.0.1}/src/portable_python.egg-info/dependency_links.txt +0 -0
  96. {portable_python-2.0.0 → portable_python-2.0.1}/src/portable_python.egg-info/entry_points.txt +0 -0
  97. {portable_python-2.0.0 → portable_python-2.0.1}/src/portable_python.egg-info/top_level.txt +0 -0
  98. {portable_python-2.0.0 → portable_python-2.0.1}/tests/test_build.py +0 -0
  99. {portable_python-2.0.0 → portable_python-2.0.1}/tests/test_cleanup.py +0 -0
  100. {portable_python-2.0.0 → portable_python-2.0.1}/tests/test_invoker.py +0 -0
  101. {portable_python-2.0.0 → portable_python-2.0.1}/tests/test_list.py +0 -0
  102. {portable_python-2.0.0 → portable_python-2.0.1}/tests/test_prefix.py +0 -0
  103. {portable_python-2.0.0 → portable_python-2.0.1}/tests/test_recompress.py +0 -0
  104. {portable_python-2.0.0 → portable_python-2.0.1}/tests/test_report.py +0 -0
  105. {portable_python-2.0.0 → portable_python-2.0.1}/tests/test_setup.py +0 -0
@@ -0,0 +1,10 @@
1
+ {
2
+ "permissions": {
3
+ "allow": [
4
+ "Bash(.venv/bin/portable-python:*)",
5
+ "Bash(.venv/bin/pytest:*)",
6
+ "Bash(.venv/bin/python scripts/check_okf.py:*)",
7
+ "Bash(tox:*)"
8
+ ]
9
+ }
10
+ }
@@ -0,0 +1,15 @@
1
+ .*cache
2
+ .DS_Store*
3
+ *.egg*
4
+ .idea
5
+ *.lock
6
+ *.log
7
+ .tox
8
+ .venv*
9
+ .*version
10
+
11
+ _Dockerfile*
12
+ __pycache__
13
+ _tmp
14
+ build
15
+ dist
@@ -0,0 +1,26 @@
1
+ name: Release
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - 'v[0-9]*'
7
+
8
+ jobs:
9
+ publish:
10
+
11
+ runs-on: ubuntu-latest
12
+ environment: release
13
+ permissions:
14
+ id-token: write # mandatory for trusted publishing
15
+
16
+ steps:
17
+ - uses: actions/checkout@v6
18
+ - uses: actions/setup-python@v6
19
+ with:
20
+ python-version: "3.14"
21
+
22
+ - uses: astral-sh/setup-uv@v7
23
+ - run: uvx --with tox-uv tox -e py,style
24
+ - run: uv build
25
+ - name: Publish to PyPI
26
+ uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,59 @@
1
+ name: Tests
2
+
3
+ on:
4
+ push:
5
+ branches: [ main ]
6
+ pull_request:
7
+ branches: [ main ]
8
+
9
+ concurrency:
10
+ group: ${{ github.workflow }}-${{ github.ref }}
11
+ cancel-in-progress: true
12
+
13
+ jobs:
14
+ test:
15
+ name: Test py${{ matrix.python-version }}
16
+ runs-on: ubuntu-latest
17
+
18
+ strategy:
19
+ fail-fast: false
20
+ matrix:
21
+ python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"]
22
+
23
+ steps:
24
+ - uses: actions/checkout@v6
25
+ - uses: actions/setup-python@v6
26
+ with:
27
+ python-version: ${{ matrix.python-version }}
28
+
29
+ - uses: astral-sh/setup-uv@v7
30
+ - run: uvx --with tox-uv tox -e py
31
+
32
+ - uses: coverallsapp/github-action@v2
33
+ with:
34
+ file: .tox/test-reports/coverage.xml
35
+ flag-name: python-${{ matrix.python-version }}
36
+ parallel: true
37
+
38
+ coveralls-finish:
39
+ name: Finish Coveralls
40
+ needs: [test]
41
+ runs-on: ubuntu-latest
42
+ steps:
43
+ - name: Finish parallel build
44
+ uses: coverallsapp/github-action@v2
45
+ with:
46
+ parallel-finished: true
47
+
48
+ linters:
49
+
50
+ runs-on: ubuntu-latest
51
+
52
+ steps:
53
+ - uses: actions/checkout@v6
54
+ - uses: actions/setup-python@v6
55
+ with:
56
+ python-version: "3.14"
57
+
58
+ - uses: astral-sh/setup-uv@v7
59
+ - run: uvx --with tox-uv tox -e style
@@ -0,0 +1,28 @@
1
+ # Various
2
+ *~
3
+ \#*#
4
+ .\#*
5
+ .*cache
6
+ .DS_Store*
7
+ *.swp
8
+ .*version
9
+ .idea/
10
+ .vscode/
11
+ ehthumbs.db
12
+ Icon?
13
+ Thumbs.db
14
+ .new*
15
+
16
+ # Build artifacts
17
+ _Dockerfile*
18
+ __pycache__/
19
+ *.egg*
20
+ .tox/
21
+ .venv*/
22
+ build/
23
+ dist/
24
+ root/
25
+ venv*/
26
+
27
+ pp*.yml
28
+ uv.lock
@@ -0,0 +1,25 @@
1
+ # CLAUDE.md
2
+
3
+ Guidance for Claude Code working in this repository.
4
+
5
+ `portable-python` is a CLI and Python library that compiles portable (statically-linked, relocatable) CPython binaries from source — see [`docs/overview.md`](docs/overview.md) for the full picture.
6
+
7
+ ## Documentation lives in `docs/`
8
+
9
+ The authoritative, self-contained documentation is the OKF knowledge bundle under **`docs/`** — start at [`docs/index.md`](docs/index.md). **Don't duplicate it in this file — link to it.** When you change behavior, update the matching `docs/` entry and add a line to [`docs/log.md`](docs/log.md).
10
+
11
+ | Looking for… | Go to |
12
+ |--------------|-------|
13
+ | What it does, guiding principles, end-to-end build flow | [`docs/overview.md`](docs/overview.md) |
14
+ | Core classes & how they collaborate | [`docs/architecture/`](docs/architecture/index.md) |
15
+ | Concepts: portability, static linking, telltale detection, folder masking, ppp-marker, build layout | [`docs/concepts/`](docs/concepts/index.md) |
16
+ | CLI commands & options | [`docs/cli/`](docs/cli/index.md) |
17
+ | External modules (the statically-linked C libraries) | [`docs/modules/`](docs/modules/index.md) |
18
+ | Configuration (`portable-python.yml`) | [`docs/configuration/`](docs/configuration/index.md) |
19
+ | Dev setup, tests, code style, debugging, Docker, CI/CD, and common tasks | [`docs/guides/`](docs/guides/index.md) |
20
+
21
+ ## Working in this repo
22
+
23
+ - Check **runez** before reimplementing file / system / CLI / logging / version helpers — see [`docs/guides/local-development.md`](docs/guides/local-development.md).
24
+ - The docs use the OKF format; keep the bundle conformant (`scripts/check_okf.py docs`) when you edit it.
25
+ - As changes land, keep a top section in [`docs/changelog.md`](docs/changelog.md) for the upcoming release — `## Unreleased`, or the next version directly once it's known. Maintain it as PRs come in; it's double-checked at release. Don't fuss over marking released-vs-unreleased (small audience, `git tag` says what's out).
@@ -0,0 +1,18 @@
1
+ FROM ubuntu:22.04
2
+
3
+ ARG DEBIAN_FRONTEND=noninteractive
4
+ ENV TZ=Etc/UTC
5
+
6
+ RUN apt-get update && apt-get install -y git htop build-essential \
7
+ gdb lcov patchelf python3-pip python3-venv tcl \
8
+ libexpat1-dev libffi-dev zlib1g-dev libgdbm-dev libgdbm-compat-dev \
9
+ libssl-dev libsqlite3-dev uuid-dev \
10
+ liblzma-dev libbz2-dev libzstd-dev libmpdec-dev
11
+
12
+ RUN /usr/bin/python3 -mpip install -U pip setuptools
13
+
14
+ COPY ./scripts/portable-python.sh /usr/local/bin/portable-python
15
+ COPY ./scripts/bashrc.sh /root/.bashrc
16
+ WORKDIR /src
17
+
18
+ CMD ["/bin/bash"]
@@ -0,0 +1,2 @@
1
+ include LICENSE
2
+ include README.rst
@@ -1,13 +1,9 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: portable-python
3
- Version: 2.0.0
3
+ Version: 2.0.1
4
4
  Summary: Portable python binaries
5
- Home-page: https://github.com/codrsquad/portable-python
6
- Author: Zoran Simic
7
- Author-email: zoran@simicweb.com
8
- License: MIT
9
- Project-URL: Documentation, https://github.com/codrsquad/portable-python/wiki
10
- Project-URL: Release notes, https://github.com/codrsquad/portable-python/wiki/Release-notes
5
+ Author-email: Zoran Simic <zoran@simicweb.com>
6
+ License-Expression: MIT
11
7
  Project-URL: Source, https://github.com/codrsquad/portable-python
12
8
  Keywords: python,portable,binary
13
9
  Classifier: Development Status :: 5 - Production/Stable
@@ -31,24 +27,12 @@ Classifier: Topic :: Utilities
31
27
  Requires-Python: >=3.10
32
28
  Description-Content-Type: text/x-rst
33
29
  License-File: LICENSE
34
- Requires-Dist: click~=8.0
35
- Requires-Dist: pyyaml~=6.0
36
- Requires-Dist: requests<3.0
37
- Requires-Dist: runez~=5.5
38
- Requires-Dist: urllib3~=1.26
39
- Dynamic: author
40
- Dynamic: author-email
41
- Dynamic: classifier
42
- Dynamic: description
43
- Dynamic: description-content-type
44
- Dynamic: home-page
45
- Dynamic: keywords
46
- Dynamic: license
30
+ Requires-Dist: click<9
31
+ Requires-Dist: pyyaml<7
32
+ Requires-Dist: requests<3
33
+ Requires-Dist: runez<6
34
+ Requires-Dist: urllib3<3
47
35
  Dynamic: license-file
48
- Dynamic: project-url
49
- Dynamic: requires-dist
50
- Dynamic: requires-python
51
- Dynamic: summary
52
36
 
53
37
  Portable python binaries
54
38
  ========================
@@ -61,8 +45,8 @@ Portable python binaries
61
45
  :target: https://github.com/codrsquad/portable-python/actions
62
46
  :alt: Tested with Github Actions
63
47
 
64
- .. image:: https://codecov.io/gh/codrsquad/portable-python/branch/main/graph/badge.svg
65
- :target: https://codecov.io/gh/codrsquad/portable-python
48
+ .. image:: https://coveralls.io/repos/github/codrsquad/portable-python/badge.svg?branch=main
49
+ :target: https://coveralls.io/github/codrsquad/portable-python?branch=main
66
50
  :alt: Test coverage
67
51
 
68
52
  .. image:: https://img.shields.io/pypi/pyversions/portable-python.svg
@@ -180,6 +164,64 @@ Note that you can use ``--dryrun`` mode to inspect what would be done without do
180
164
  Would tar build/3.9.7 -> dist/cpython-3.9.7-macos-x86_64.tar.gz
181
165
 
182
166
 
167
+ CLI reference
168
+ -------------
169
+
170
+ Main entry point::
171
+
172
+ portable-python [OPTIONS] COMMAND [ARGS]
173
+
174
+ **Global options**:
175
+
176
+ - ``--config PATH``: Config file (default: ``portable-python.yml``)
177
+ - ``--quiet``: Turn off DEBUG logging
178
+ - ``--dryrun`` / ``-n``: Show what would be done
179
+ - ``--target PLATFORM``: Override detected platform (for testing)
180
+
181
+
182
+ **build** ``<PYTHON_SPEC>`` - Build a portable Python binary::
183
+
184
+ portable-python build 3.13.2 -m openssl,zlib
185
+
186
+ - ``--modules, -m CSV``: External modules to include
187
+ - ``--prefix, -p PATH``: Use ``--prefix`` (non-portable)
188
+
189
+
190
+ **build-report** ``[PYTHON_SPEC]`` - Show module status and what will be compiled:
191
+
192
+ - ``--modules, -m CSV``: Specific modules to check
193
+ - Validates that modules can be built
194
+
195
+
196
+ **inspect** ``<PATH>`` - Check if a Python installation is portable::
197
+
198
+ portable-python inspect /usr/bin/python3
199
+
200
+ - ``--modules, -m MODULES``: Which modules to inspect
201
+ - ``--verbose, -v``: Show full ``.so`` report
202
+ - ``--prefix, -p``: Built with ``--prefix`` (not portable)
203
+ - ``--skip-so, -s``: Don't check all ``.so`` files
204
+
205
+
206
+ **list** ``[FAMILY]`` - List available versions (default: cpython)::
207
+
208
+ portable-python list cpython
209
+
210
+ - ``--json``: Output as JSON
211
+
212
+
213
+ **diagnostics** - Show system diagnostics
214
+
215
+
216
+ **recompress** ``<PATH> <EXT>`` - Re-compress existing binary tarball (for comparing compression sizes)
217
+
218
+
219
+ **lib-auto-correct** ``<PATH>`` - Auto-correct exes/libs to use relative paths:
220
+
221
+ - ``--commit``: Actually perform changes (dryrun by default)
222
+ - ``--prefix, -p PATH``: Expected ``--prefix`` from build
223
+
224
+
183
225
  Library
184
226
  -------
185
227
 
@@ -9,8 +9,8 @@ Portable python binaries
9
9
  :target: https://github.com/codrsquad/portable-python/actions
10
10
  :alt: Tested with Github Actions
11
11
 
12
- .. image:: https://codecov.io/gh/codrsquad/portable-python/branch/main/graph/badge.svg
13
- :target: https://codecov.io/gh/codrsquad/portable-python
12
+ .. image:: https://coveralls.io/repos/github/codrsquad/portable-python/badge.svg?branch=main
13
+ :target: https://coveralls.io/github/codrsquad/portable-python?branch=main
14
14
  :alt: Test coverage
15
15
 
16
16
  .. image:: https://img.shields.io/pypi/pyversions/portable-python.svg
@@ -128,6 +128,64 @@ Note that you can use ``--dryrun`` mode to inspect what would be done without do
128
128
  Would tar build/3.9.7 -> dist/cpython-3.9.7-macos-x86_64.tar.gz
129
129
 
130
130
 
131
+ CLI reference
132
+ -------------
133
+
134
+ Main entry point::
135
+
136
+ portable-python [OPTIONS] COMMAND [ARGS]
137
+
138
+ **Global options**:
139
+
140
+ - ``--config PATH``: Config file (default: ``portable-python.yml``)
141
+ - ``--quiet``: Turn off DEBUG logging
142
+ - ``--dryrun`` / ``-n``: Show what would be done
143
+ - ``--target PLATFORM``: Override detected platform (for testing)
144
+
145
+
146
+ **build** ``<PYTHON_SPEC>`` - Build a portable Python binary::
147
+
148
+ portable-python build 3.13.2 -m openssl,zlib
149
+
150
+ - ``--modules, -m CSV``: External modules to include
151
+ - ``--prefix, -p PATH``: Use ``--prefix`` (non-portable)
152
+
153
+
154
+ **build-report** ``[PYTHON_SPEC]`` - Show module status and what will be compiled:
155
+
156
+ - ``--modules, -m CSV``: Specific modules to check
157
+ - Validates that modules can be built
158
+
159
+
160
+ **inspect** ``<PATH>`` - Check if a Python installation is portable::
161
+
162
+ portable-python inspect /usr/bin/python3
163
+
164
+ - ``--modules, -m MODULES``: Which modules to inspect
165
+ - ``--verbose, -v``: Show full ``.so`` report
166
+ - ``--prefix, -p``: Built with ``--prefix`` (not portable)
167
+ - ``--skip-so, -s``: Don't check all ``.so`` files
168
+
169
+
170
+ **list** ``[FAMILY]`` - List available versions (default: cpython)::
171
+
172
+ portable-python list cpython
173
+
174
+ - ``--json``: Output as JSON
175
+
176
+
177
+ **diagnostics** - Show system diagnostics
178
+
179
+
180
+ **recompress** ``<PATH> <EXT>`` - Re-compress existing binary tarball (for comparing compression sizes)
181
+
182
+
183
+ **lib-auto-correct** ``<PATH>`` - Auto-correct exes/libs to use relative paths:
184
+
185
+ - ``--commit``: Actually perform changes (dryrun by default)
186
+ - ``--prefix, -p PATH``: Expected ``--prefix`` from build
187
+
188
+
131
189
  Library
132
190
  -------
133
191
 
@@ -0,0 +1,29 @@
1
+ ---
2
+ type: Class
3
+ title: BuildSetup
4
+ description: Orchestrates a build end to end — resolves the spec, builds external modules then CPython, validates, and compresses the result.
5
+ tags: [class, build, coordinator]
6
+ timestamp: 2026-06-23T00:00:00Z
7
+ ---
8
+
9
+ # BuildSetup
10
+
11
+ The build orchestrator (`__init__.py`). The [`build`](/cli/build.md) command — and library users — construct one from a python spec and call `compile()`:
12
+
13
+ ```python
14
+ from portable_python import BuildSetup
15
+
16
+ BuildSetup("cpython:3.13.2").compile()
17
+ ```
18
+
19
+ ## Mental model
20
+
21
+ A conductor: it compiles nothing itself, it sequences the pieces. `compile()` is the spine — it cleans the [build folders](/concepts/build-layout.md), enters a [`BuildContext`](/concepts/folder-masking.md) (macOS isolation), builds the [external modules](/modules/index.md) into `build/deps/`, then builds CPython through its [`PythonBuilder`](/architecture/python-builder.md) (a [`Cpython`](/architecture/cpython.md)), and finally compresses the install into `dist/`. **External libraries first, CPython last.**
22
+
23
+ It owns the [`Folders`](/architecture/config.md) (resolved paths) and the python builder; shared config, target platform, and version family come from [`PPG`](/architecture/ppg.md).
24
+
25
+ ## Worth knowing
26
+
27
+ - **Start reading at `compile()`** — it calls everything else in order.
28
+ - A `--prefix` makes the build **non-portable**; without it the result is relocatable (see [ppp-marker](/concepts/ppp-marker.md) and [portability](/concepts/portability.md)).
29
+ - It requires a full `X.Y.Z` spec — a bare `3.13` is rejected; `"latest"` (or empty) resolves to the newest known version.
@@ -0,0 +1,30 @@
1
+ ---
2
+ type: Class
3
+ title: Config & Folders
4
+ description: Config loads and merges YAML configuration with platform-specific overrides; Folders resolves the templated build/dist/sources paths.
5
+ tags: [class, configuration, folders, yaml]
6
+ timestamp: 2026-06-23T00:00:00Z
7
+ ---
8
+
9
+ # Config & Folders
10
+
11
+ `Config` (`config.py`) loads, merges, and queries the YAML [configuration](/configuration/portable-python-yml.md). `Folders` (`versions.py`) turns its templated path settings into concrete filesystem paths. Both are reached through [`PPG`](/architecture/ppg.md).
12
+
13
+ ## Merge & precedence
14
+
15
+ The mental model is layering. A built-in `DEFAULT_CONFIG` provides sane defaults; user files (default `portable-python.yml`, plus any `include:`d files) layer on top. Within a file, **platform-specific** sections override generic ones, and the most specific match for the [target platform](/architecture/ppg.md) wins:
16
+
17
+ ```yaml
18
+ ext: gz # generic default
19
+ windows:
20
+ ext: zip # used only when targeting windows
21
+ macos:
22
+ env:
23
+ MACOSX_DEPLOYMENT_TARGET: 13
24
+ ```
25
+
26
+ A lookup returns that most-specific value (with the option to ignore platform overrides).
27
+
28
+ ## Folders
29
+
30
+ `Folders` resolves the templated `folders:` settings (placeholders like `{build}`, `{version}`, `{abi_suffix}`) into the concrete `build/`, `deps/`, `dist/`, … paths every component uses — including the [ppp-marker](/concepts/ppp-marker.md) install prefix. See [build layout](/concepts/build-layout.md) for the resulting tree.
@@ -0,0 +1,24 @@
1
+ ---
2
+ type: Class
3
+ title: Cpython
4
+ description: The concrete PythonBuilder that compiles CPython — configure/make/install, optimization flags, and the finalize step that makes the install relocatable.
5
+ tags: [class, cpython, build, finalize]
6
+ timestamp: 2026-06-23T00:00:00Z
7
+ ---
8
+
9
+ # Cpython
10
+
11
+ The concrete [`PythonBuilder`](/architecture/python-builder.md) that compiles CPython (`cpython.py`); `CPythonFamily.get_builder()` returns it (see [`PPG`](/architecture/ppg.md)). Most of its work is two things: configuring the build, and finalizing the install so it's relocatable.
12
+
13
+ ## Configure
14
+
15
+ CPython is configured purely through flags — never source patches (the [no-patches principle](/overview.md)). Defaults come from `cpython-configure` in [config](/configuration/portable-python-yml.md) (optimizations, LTO, ensurepip), plus computed flags that point the build at the statically-compiled [deps](/concepts/static-linking.md).
16
+
17
+ ## Finalize — making it relocatable
18
+
19
+ After `make install`, a portable build's interpreter still thinks it lives at the placeholder [`/ppp-marker/{version}`](/concepts/ppp-marker.md). Finalizing turns it into a [portable](/concepts/portability.md) install:
20
+
21
+ - **Trim** — remove tests / idle / 2to3 before byte-compiling, then prune seldom-used pycaches after (driven by the `cpython-clean-*` config).
22
+ - **Byte-compile** the standard library.
23
+ - **Relativize** — rewrite `bin/` shebangs and the absolute paths baked into `sysconfig` so everything resolves relative to the install's own location.
24
+ - **Verify** — sanity-check that `venv` works in the finished build.
@@ -0,0 +1,30 @@
1
+ # Architecture
2
+
3
+ The core classes and how they collaborate during a build.
4
+ ## Global state & configuration
5
+
6
+ * [PPG](/architecture/ppg.md) - Global singleton holding config, target platform, and version families.
7
+ * [Config](/architecture/config.md) - Loads and merges YAML configuration; the `Folders` helper resolves build paths.
8
+
9
+ ## Build coordination
10
+
11
+ * [BuildSetup](/architecture/build-setup.md) - Drives the overall compilation: resolve spec, select modules, build, validate, compress.
12
+ * [ModuleBuilder](/architecture/module-builder.md) - Abstract base for anything that gets compiled (external C libs and Python itself).
13
+ * [PythonBuilder](/architecture/python-builder.md) - `ModuleBuilder` specialization for python implementations.
14
+ * [Cpython](/architecture/cpython.md) - Concrete builder: CPython's configure/make/install, optimization, and finalization.
15
+
16
+ ## Validation
17
+
18
+ * [PythonInspector](/architecture/python-inspector.md) - Validates the portability of a built (or any) python by checking shared-library dependencies and paths.
19
+
20
+ ## Collaboration at a glance
21
+
22
+ ```
23
+ PPG (config, target, families)
24
+ └─ BuildSetup(python_spec)
25
+ ├─ Folders (resolved build/dist/... paths)
26
+ ├─ BuildContext (macOS folder masking, isolation)
27
+ └─ python_builder : Cpython (a PythonBuilder, a ModuleBuilder)
28
+ └─ modules : ModuleCollection
29
+ └─ candidates/selected : ModuleBuilder (Openssl, Zlib, ...)
30
+ ```
@@ -0,0 +1,26 @@
1
+ ---
2
+ type: Class
3
+ title: ModuleBuilder
4
+ description: Abstract base for everything that gets compiled — external C libraries and CPython itself — providing the common download/configure/make/install flow and environment injection.
5
+ tags: [class, abstract, build, module]
6
+ timestamp: 2026-06-23T00:00:00Z
7
+ ---
8
+
9
+ # ModuleBuilder
10
+
11
+ The abstract base for everything the tool compiles (`__init__.py`). Both the [external C modules](/modules/index.md) and [`PythonBuilder`](/architecture/python-builder.md) (hence [`Cpython`](/architecture/cpython.md)) extend it, so every component is built the same way and lands in the same [build layout](/concepts/build-layout.md).
12
+
13
+ ## Mental model
14
+
15
+ A subclass is mostly **declarative**: it sets a few `m_*` class attributes (name, [telltale](/concepts/telltale-detection.md) marker, Debian package, include subfolder) and provides a source `url` + `version`. The base class runs the rest of the flow — download → unpack → patch → configure → make → install — into the shared `build/deps/` prefix. Platform differences are isolated to `_do_linux_compile()` / `_do_macos_compile()`, dispatched on [`PPG.target`](/architecture/ppg.md).
16
+
17
+ Two mechanisms recur everywhere and are worth understanding:
18
+
19
+ - **Environment injection** (`xenv_*` methods) — each contributes one variable (CPATH, LDFLAGS, PATH, …) pointing the compiler at `build/deps/`. This is how a statically-built dependency gets found by the next build; see [static linking](/concepts/static-linking.md).
20
+ - **Per-module config overrides** — `cfg_*` helpers read `{module}-version`, `{module}-url`, `{module}-configure`, … from [configuration](/configuration/portable-python-yml.md), so any default can be overridden without code changes.
21
+
22
+ `linker_outcome()` decides, per module and platform, whether it will be linked `static` / `shared`, is `absent`, or would `fail` — the verdict surfaced by [`build-report`](/cli/build-report.md).
23
+
24
+ ## Adding one
25
+
26
+ Subclass `ModuleBuilder`, set the `m_*` attributes, implement `url` / `version` and `_do_linux_compile()` — see the [guide](/guides/add-an-external-module.md).
@@ -0,0 +1,21 @@
1
+ ---
2
+ type: Class
3
+ title: PPG
4
+ description: Global singleton holding shared configuration, the target platform, and the registry of supported python version families.
5
+ tags: [class, global-state, singleton, versions]
6
+ timestamp: 2026-06-23T00:00:00Z
7
+ ---
8
+
9
+ # PPG
10
+
11
+ `PPG` ("**P**ortable **P**ython **G**lobals") is the global state holder (`versions.py`) — the one place the rest of the code reaches for three process-wide facts: the merged [configuration](/architecture/config.md), the target platform (OS/arch), and the registry of python version families. The CLI's `main` initializes it once; everything else reads from it.
12
+
13
+ Like [`ppp-marker`](/concepts/ppp-marker.md), the name is a deliberately uncommon, greppable token — searching for `PPG` surfaces only its own usages, with no collisions in upstream CPython or third-party source.
14
+
15
+ ## Why a singleton
16
+
17
+ The build depends on global facts — which config is active, what platform we target, which python versions exist — so centralizing them avoids threading that state through every constructor and gives the CLI one initialization point. Shared helpers hang off it too: resolving a python on `PATH`, building [`Folders`](/architecture/config.md) for a version, and expanding [telltale](/concepts/telltale-detection.md) markers against the target's system includes.
18
+
19
+ ## Version families
20
+
21
+ A `VersionFamily` (e.g. `CPythonFamily`) lists the available versions and hands back the right builder ([`Cpython`](/architecture/cpython.md) for cpython). Versions are fetched lazily and cached — from `python.org/ftp`, or GitHub tags when configured — which is why [`list`](/cli/list.md) hits the network on first use. A family also pins the minimum supported version (non-EOL only).
@@ -0,0 +1,25 @@
1
+ ---
2
+ type: Class
3
+ title: PythonBuilder
4
+ description: A ModuleBuilder specialization for python implementations — adds module selection, the python install layout, and helpers to run the freshly built interpreter.
5
+ tags: [class, abstract, python, build]
6
+ timestamp: 2026-06-23T00:00:00Z
7
+ ---
8
+
9
+ # PythonBuilder
10
+
11
+ The abstract [`ModuleBuilder`](/architecture/module-builder.md) specialization for building a python interpreter (`__init__.py`); the concrete implementation is [`Cpython`](/architecture/cpython.md).
12
+
13
+ ## What it adds over ModuleBuilder
14
+
15
+ Beyond the base compile flow, a `PythonBuilder` owns the **module selection** (which [external modules](/modules/index.md) to build) and can **run the freshly-built interpreter** — used during finalize and validation.
16
+
17
+ ## ModuleCollection
18
+
19
+ A `PythonBuilder` owns a `ModuleCollection` that resolves which external modules actually get built — a distinction worth keeping straight:
20
+
21
+ - **candidates** — every module this builder *could* compile.
22
+ - **selected** — the ones chosen for *this* build (config + `--modules` + auto-selection). This is what's actually compiled, not all candidates.
23
+ - **auto-selected** — modules force-included because the build can't succeed without them (each module's `auto_select_reason()`).
24
+
25
+ It's what [`build-report`](/cli/build-report.md) renders.
@@ -0,0 +1,27 @@
1
+ ---
2
+ type: Class
3
+ title: PythonInspector
4
+ description: Validates the portability of a python installation by parsing the dynamic-library dependencies of every executable and .so, and reporting any non-portable references.
5
+ tags: [class, inspection, validation, portability]
6
+ timestamp: 2026-06-23T00:00:00Z
7
+ ---
8
+
9
+ # PythonInspector
10
+
11
+ `PythonInspector` (`inspector.py`) answers the question the whole project exists for: *is this python [portable](/concepts/portability.md), and if not, why not?* It powers the [`inspect`](/cli/inspect.md) command and the portability gate at the end of [`BuildSetup.compile()`](/architecture/build-setup.md).
12
+
13
+ ## How it works
14
+
15
+ It walks every executable and `.so` in an installation, lists each one's dynamic-library dependencies (parsing `ldd` on Linux / `otool` on macOS), and classifies every reference:
16
+
17
+ - **system / standard** library → fine;
18
+ - **relative / self** reference → fine (what a relocatable build should have);
19
+ - **absolute, non-system** reference → a portability problem.
20
+
21
+ For a portable build, any problem fails the inspection (the report exposes a single "first problem" verdict that callers check).
22
+
23
+ ## Relativization
24
+
25
+ The fix lives in `LibAutoCorrect`, which rewrites the absolute library paths (rpaths) baked into binaries so they resolve relative to the install — `patchelf` on Linux (an `$ORIGIN`-relative rpath), `install_name_tool` on macOS (`@rpath` / `@loader_path`). It runs **during** finalize (so the result passes the portable check) and is exposed standalone as [`lib-auto-correct`](/cli/lib-auto-correct.md).
26
+
27
+ The same step also supports **non-portable** builds: with `--prefix` or `--enable-shared`, it additionally keeps the real prefix's `lib/` in the rpath, so a build pinned to a fixed location still finds its libraries. (CPython is built with a deliberately long rpath — unlike `chrpath`, `patchelf` can set a fresh rpath of any length, leaving room to rewrite it.)
@@ -0,0 +1,13 @@
1
+ ---
2
+ type: Changelog
3
+ title: Changelog
4
+ description: High-level release highlights for portable-python, newest first.
5
+ tags: [changelog, releases]
6
+ timestamp: 2026-06-23T00:00:00Z
7
+ ---
8
+
9
+ ## v2.0.1
10
+
11
+ - Bumped the bundled components (OpenSSL, SQLite, Tcl/Tk, …) to current versions.
12
+ - Refreshed dependencies and modernized CI (now on uv / tox-uv, with updated GitHub Actions).
13
+ - Added an OKF documentation bundle under `docs/` (the old top-level docs folded into it).
@@ -0,0 +1,24 @@
1
+ ---
2
+ type: CLI Command
3
+ title: build-report
4
+ description: Show the status of buildable modules — which will be auto-compiled, which are present on the system, and which would fail — without building anything.
5
+ tags: [cli, build, report, command]
6
+ timestamp: 2026-06-23T00:00:00Z
7
+ ---
8
+
9
+ # build-report
10
+
11
+ Show which [modules](/modules/index.md) would be compiled for a spec, and whether the selection can actually build on this host — **without** building. The fastest way to catch a "broken" module before committing to a full compile.
12
+
13
+ ```
14
+ portable-python build-report [OPTIONS] [PYTHON_SPEC]
15
+ ```
16
+
17
+ For each candidate module it shows the [telltale](/concepts/telltale-detection.md) status and the linker outcome — `static` (will be compiled), `shared` (system copy used), `absent`, or `failed` (can't build here, e.g. a `-`-sigil Debian dev package is present). `PYTHON_SPEC` defaults to the latest known version.
18
+
19
+ # Examples
20
+
21
+ ```shell
22
+ portable-python build-report 3.13.2
23
+ portable-python build-report 3.13.2 -m openssl,sqlite
24
+ ```