Portable python binaries
========================
.. image:: https://img.shields.io/pypi/v/portable-python.svg
:target: https://pypi.org/project/portable-python/
:alt: Version on pypi
.. image:: https://github.com/codrsquad/portable-python/workflows/Tests/badge.svg
:target: https://github.com/codrsquad/portable-python/actions
:alt: Tested with Github Actions
.. image:: https://codecov.io/gh/codrsquad/portable-python/branch/main/graph/badge.svg
:target: https://codecov.io/gh/codrsquad/portable-python
:alt: Test coverage
.. image:: https://img.shields.io/pypi/pyversions/portable-python.svg
:target: https://github.com/codrsquad/portable-python
:alt: Python versions tested (link to github project)
``Portable-Python`` is a CLI (and a python library) for compiling python binaries
from source than can be decompressed in any folder, and used from there without
further ado (ie: no need to run an "installer").
Motivation
----------
The idea here is to allow for automated systems to:
- Easily obtain a python binary, that can be used in sandboxes / workstations / laptops / instances...
- Inspect any python installation, and point out how portable it is, which
shared or non-standard libraries it is using
Installation
------------
``portable-python`` is a regular python CLI, it can be installed with:
pickley_::
pickley install portable-python
portable-python --help
portable-python inspect /usr/bin/python3
Or pipx_::
pipx install portable-python
portable-python inspect /usr/bin/python3
Using ``pip install`` (a CI builder would probably do this)::
/usr/bin/python3 -mvenv /tmp/pp
/tmp/pp/bin/python -mpip install portable-python
/tmp/pp/bin/portable-python --help
/tmp/pp/bin/portable-python inspect /usr/bin/python3
Supported operating systems
---------------------------
Portable python binaries can be built for Linux and MacOS (Intel/M1/M2).
Currently **Windows is NOT supported**, contributions are welcome.
Python binaries can be produced as "portable" (statically linked, can run from any folder
where the binary is unpacked in), or with a ``--prefix`` (build targeted to live in a
pre-determined folder, like ``/apps/pythonM.m``)
================ ======== ========
Operating system Portable --prefix
================ ======== ========
Linux ✅ ✅
Macos ✅ ✅
Windows ❌ ❌
================ ======== ========
Building a portable cpython
===========================
Once ``portable-python`` is installed:
Build a binary::
cd some-temp-folder
portable-python build 3.9.7
ls -l dist/cpython-3.9.7-macos-arm64.tar.gz
Unpack it somewhere::
tar -C ~/tmp/versions/ -xf dist/cpython-3.9.7-macos-arm64.tar.gz
ls -l ~/tmp/versions/
It's ready to be used::
~/tmp/versions/3.9.7/bin/python --version
Note that you can use ``--dryrun`` mode to inspect what would be done without doing it::
$ portable-python --dryrun build 3.9.7
INFO selected: xz openssl gdbm (3 modules) xz:5.2.5 openssl:1.1.1k gdbm:1.18.1
INFO Platform: macos-x86_64
...
--------------
-- xz:5.2.5 --
--------------
Would download https://tukaani.org/xz/xz-5.2.5.tar.gz
Would untar build/sources/xz-5.2.5.tar.gz -> build/components/xz
INFO env PATH=build/deps/bin:/usr/bin:/bin
INFO env MACOSX_DEPLOYMENT_TARGET=10.14
Would run: ./configure --prefix=build/deps --enable-shared=no --enable-static=yes ...
...
-------------------
-- cpython:3.9.7 --
-------------------
Would download https://www.python.org/ftp/python/3.9.7/Python-3.9.7.tar.xz
Would untar build/sources/Python-3.9.7.tar.xz -> build/components/cpython
...
Would run: ./configure --prefix=/ppp-marker/3.9.7 --enable-optimizations ...
Would run: /usr/bin/make
Would run: /usr/bin/make install DESTDIR=build
...
Would tar build/3.9.7 -> dist/cpython-3.9.7-macos-x86_64.tar.gz
Library
-------
Portable Python can be used as a python library to invoke builds, or inspect an installation.
Invoke a build from python code::
from portable_python import BuildSetup
setup = BuildSetup("cpython:3.9.7")
setup.compile()
Invoke an inspection from python code::
from portable_python.inspector import PythonInspector
inspector = PythonInspector("/usr/bin/python3")
print(inspector.represented())
problem = inspector.full_so_report.get_problem(portable=True)
if problem:
print("oops, it is not portable!: %s" % problem)
From source, contributions welcome!::
git clone https://github.com/codrsquad/portable-python.git
cd portable-python
python3 -mvenv .venv
.venv/bin/pip install -r requirements.txt -r tests/requirements.txt
.venv/bin/pip install -e .
.venv/bin/portable-python --help
.venv/bin/portable-python inspect /usr/bin/python3
tox -e py311
tox -e style
Build folder structure
----------------------
``portable-python`` uses this file structure (build/ and dist/ folders configurable)::
build/
ppp-marker/3.9.7/ # Full installation (after build completes)
components/ # Builds of statically compiled extension modules are here
deps/ # --prefix=.../deps passed to all component ./configure scripts
sources/
openssl-1.1.1k.tar.gz # Downloaded artifacts (downloaded only once)
dist/
cpython-3.9.7-macos-arm64.tar.gz # Ready-to-go portable binary tarball
Guiding principles
------------------
- Focuses on just one thing: compile a portable python, and validate that it is indeed portable,
produce outcome in (configurable) ``./dist/`` folder and that's it
- No patches: C compilation is done as simply as possible without modifying the upstream source code.
Rely solely on the make/configure scripts, typically via stuff like ``--enable-shared=no``
- Builds are validated, an important part of the effort was to write up code that is able to
``inspect`` a python installation and detect whether it is portable or not (and why not if so).
- Only the last few non-EOL versions of python are supported (no historical stuff)
- As time goes on, the code of this tool will evolve so that the latest pythons keep building
(but won't worry that older versions still keep building)
For this repo itself:
- Code is pure python, it is a CLI with one entry-point called ``portable-python``
- Can be ran in a debugger
- 100% test coverage, has a ``--dryrun`` mode to help with testing / debugging / seeing what would be done quickly
- No shell scripts (those are hard to maintain/test/debug)
- Can be ``pip install``-ed and reused
.. _pickley: https://pypi.org/project/pickley/
.. _pipx: https://pypi.org/project/pipx/
Raw data
{
"_id": null,
"home_page": "https://github.com/codrsquad/portable-python",
"name": "portable-python",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.6",
"maintainer_email": null,
"keywords": "python, portable, binary",
"author": "Zoran Simic",
"author_email": "zoran@simicweb.com",
"download_url": "https://files.pythonhosted.org/packages/4a/24/b73e4be5212118facbae6974351204cd24e5207ab159d99d3fc8ca0664b8/portable_python-1.9.6.tar.gz",
"platform": null,
"description": "Portable python binaries\n========================\n\n.. image:: https://img.shields.io/pypi/v/portable-python.svg\n :target: https://pypi.org/project/portable-python/\n :alt: Version on pypi\n\n.. image:: https://github.com/codrsquad/portable-python/workflows/Tests/badge.svg\n :target: https://github.com/codrsquad/portable-python/actions\n :alt: Tested with Github Actions\n\n.. image:: https://codecov.io/gh/codrsquad/portable-python/branch/main/graph/badge.svg\n :target: https://codecov.io/gh/codrsquad/portable-python\n :alt: Test coverage\n\n.. image:: https://img.shields.io/pypi/pyversions/portable-python.svg\n :target: https://github.com/codrsquad/portable-python\n :alt: Python versions tested (link to github project)\n\n\n``Portable-Python`` is a CLI (and a python library) for compiling python binaries\nfrom source than can be decompressed in any folder, and used from there without\nfurther ado (ie: no need to run an \"installer\").\n\n\nMotivation\n----------\n\nThe idea here is to allow for automated systems to:\n\n- Easily obtain a python binary, that can be used in sandboxes / workstations / laptops / instances...\n\n- Inspect any python installation, and point out how portable it is, which\n shared or non-standard libraries it is using\n\n\nInstallation\n------------\n\n``portable-python`` is a regular python CLI, it can be installed with:\n\npickley_::\n\n pickley install portable-python\n portable-python --help\n portable-python inspect /usr/bin/python3\n\nOr pipx_::\n\n pipx install portable-python\n portable-python inspect /usr/bin/python3\n\nUsing ``pip install`` (a CI builder would probably do this)::\n\n /usr/bin/python3 -mvenv /tmp/pp\n /tmp/pp/bin/python -mpip install portable-python\n /tmp/pp/bin/portable-python --help\n /tmp/pp/bin/portable-python inspect /usr/bin/python3\n\n\nSupported operating systems\n---------------------------\n\nPortable python binaries can be built for Linux and MacOS (Intel/M1/M2).\n\nCurrently **Windows is NOT supported**, contributions are welcome.\n\nPython binaries can be produced as \"portable\" (statically linked, can run from any folder\nwhere the binary is unpacked in), or with a ``--prefix`` (build targeted to live in a\npre-determined folder, like ``/apps/pythonM.m``)\n\n================ ======== ========\nOperating system Portable --prefix\n================ ======== ========\nLinux \u2705 \u2705\nMacos \u2705 \u2705\nWindows \u274c \u274c\n================ ======== ========\n\n\nBuilding a portable cpython\n===========================\n\nOnce ``portable-python`` is installed:\n\nBuild a binary::\n\n cd some-temp-folder\n portable-python build 3.9.7\n ls -l dist/cpython-3.9.7-macos-arm64.tar.gz\n\nUnpack it somewhere::\n\n tar -C ~/tmp/versions/ -xf dist/cpython-3.9.7-macos-arm64.tar.gz\n ls -l ~/tmp/versions/\n\nIt's ready to be used::\n\n ~/tmp/versions/3.9.7/bin/python --version\n\n\nNote that you can use ``--dryrun`` mode to inspect what would be done without doing it::\n\n $ portable-python --dryrun build 3.9.7\n\n INFO selected: xz openssl gdbm (3 modules) xz:5.2.5 openssl:1.1.1k gdbm:1.18.1\n INFO Platform: macos-x86_64\n ...\n --------------\n -- xz:5.2.5 --\n --------------\n Would download https://tukaani.org/xz/xz-5.2.5.tar.gz\n Would untar build/sources/xz-5.2.5.tar.gz -> build/components/xz\n INFO env PATH=build/deps/bin:/usr/bin:/bin\n INFO env MACOSX_DEPLOYMENT_TARGET=10.14\n Would run: ./configure --prefix=build/deps --enable-shared=no --enable-static=yes ...\n ...\n -------------------\n -- cpython:3.9.7 --\n -------------------\n Would download https://www.python.org/ftp/python/3.9.7/Python-3.9.7.tar.xz\n Would untar build/sources/Python-3.9.7.tar.xz -> build/components/cpython\n ...\n Would run: ./configure --prefix=/ppp-marker/3.9.7 --enable-optimizations ...\n Would run: /usr/bin/make\n Would run: /usr/bin/make install DESTDIR=build\n ...\n Would tar build/3.9.7 -> dist/cpython-3.9.7-macos-x86_64.tar.gz\n\n\nLibrary\n-------\n\nPortable Python can be used as a python library to invoke builds, or inspect an installation.\n\nInvoke a build from python code::\n\n from portable_python import BuildSetup\n\n setup = BuildSetup(\"cpython:3.9.7\")\n setup.compile()\n\n\nInvoke an inspection from python code::\n\n from portable_python.inspector import PythonInspector\n\n inspector = PythonInspector(\"/usr/bin/python3\")\n print(inspector.represented())\n problem = inspector.full_so_report.get_problem(portable=True)\n if problem:\n print(\"oops, it is not portable!: %s\" % problem)\n\n\nFrom source, contributions welcome!::\n\n git clone https://github.com/codrsquad/portable-python.git\n cd portable-python\n python3 -mvenv .venv\n .venv/bin/pip install -r requirements.txt -r tests/requirements.txt\n .venv/bin/pip install -e .\n .venv/bin/portable-python --help\n .venv/bin/portable-python inspect /usr/bin/python3\n\n tox -e py311\n tox -e style\n\n\nBuild folder structure\n----------------------\n\n``portable-python`` uses this file structure (build/ and dist/ folders configurable)::\n\n build/\n ppp-marker/3.9.7/ # Full installation (after build completes)\n components/ # Builds of statically compiled extension modules are here\n deps/ # --prefix=.../deps passed to all component ./configure scripts\n sources/\n openssl-1.1.1k.tar.gz # Downloaded artifacts (downloaded only once)\n dist/\n cpython-3.9.7-macos-arm64.tar.gz # Ready-to-go portable binary tarball\n\n\nGuiding principles\n------------------\n\n- Focuses on just one thing: compile a portable python, and validate that it is indeed portable,\n produce outcome in (configurable) ``./dist/`` folder and that's it\n\n- No patches: C compilation is done as simply as possible without modifying the upstream source code.\n Rely solely on the make/configure scripts, typically via stuff like ``--enable-shared=no``\n\n- Builds are validated, an important part of the effort was to write up code that is able to\n ``inspect`` a python installation and detect whether it is portable or not (and why not if so).\n\n- Only the last few non-EOL versions of python are supported (no historical stuff)\n\n- As time goes on, the code of this tool will evolve so that the latest pythons keep building\n (but won't worry that older versions still keep building)\n\n\nFor this repo itself:\n\n- Code is pure python, it is a CLI with one entry-point called ``portable-python``\n\n - Can be ran in a debugger\n\n - 100% test coverage, has a ``--dryrun`` mode to help with testing / debugging / seeing what would be done quickly\n\n - No shell scripts (those are hard to maintain/test/debug)\n\n - Can be ``pip install``-ed and reused\n\n\n.. _pickley: https://pypi.org/project/pickley/\n\n.. _pipx: https://pypi.org/project/pipx/\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "Portable python binaries",
"version": "1.9.6",
"project_urls": {
"Documentation": "https://github.com/codrsquad/portable-python/wiki",
"Homepage": "https://github.com/codrsquad/portable-python",
"Release notes": "https://github.com/codrsquad/portable-python/wiki/Release-notes",
"Source": "https://github.com/codrsquad/portable-python"
},
"split_keywords": [
"python",
" portable",
" binary"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "c6b508e69f76e75d2ca2dfd46c5c67cbe84e03666fe726cbfad7b708315b0966",
"md5": "4554d335fe5bba3fc113616616d6e0f0",
"sha256": "bc9d80186e11e2d7fe9e9ce844375ab5332a0015a45d3a9c8a09941b044502b0"
},
"downloads": -1,
"filename": "portable_python-1.9.6-py3-none-any.whl",
"has_sig": false,
"md5_digest": "4554d335fe5bba3fc113616616d6e0f0",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.6",
"size": 40698,
"upload_time": "2024-11-20T21:53:10",
"upload_time_iso_8601": "2024-11-20T21:53:10.008578Z",
"url": "https://files.pythonhosted.org/packages/c6/b5/08e69f76e75d2ca2dfd46c5c67cbe84e03666fe726cbfad7b708315b0966/portable_python-1.9.6-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "4a24b73e4be5212118facbae6974351204cd24e5207ab159d99d3fc8ca0664b8",
"md5": "7ae4afd4898e3afd646525909bfc90b7",
"sha256": "51837fd66fad2ecf7500032f10990fa0f6d0524d3b3071b397ef0eb526c0fcc1"
},
"downloads": -1,
"filename": "portable_python-1.9.6.tar.gz",
"has_sig": false,
"md5_digest": "7ae4afd4898e3afd646525909bfc90b7",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.6",
"size": 46609,
"upload_time": "2024-11-20T21:53:12",
"upload_time_iso_8601": "2024-11-20T21:53:12.041749Z",
"url": "https://files.pythonhosted.org/packages/4a/24/b73e4be5212118facbae6974351204cd24e5207ab159d99d3fc8ca0664b8/portable_python-1.9.6.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-11-20 21:53:12",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "codrsquad",
"github_project": "portable-python",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"requirements": [],
"tox": true,
"lcname": "portable-python"
}