mirror of
https://github.com/niess/python-appimage.git
synced 2026-03-14 04:10:15 +01:00
Add documentation with mkdocs
This commit is contained in:
6
.github/workflows/appimage.yml
vendored
6
.github/workflows/appimage.yml
vendored
@@ -1,9 +1,11 @@
|
||||
name: AppImage
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
paths:
|
||||
- '.github/workflows/appimage.yml'
|
||||
- 'python_appimage/**'
|
||||
- '.github/workflows/appimage.yml'
|
||||
- 'python_appimage/**'
|
||||
schedule:
|
||||
- cron: '0 3 * * 0'
|
||||
|
||||
|
||||
8
.github/workflows/applications.yml
vendored
8
.github/workflows/applications.yml
vendored
@@ -1,10 +1,12 @@
|
||||
name: Applications
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
paths:
|
||||
- '.github/workflows/applications.yml'
|
||||
- 'applications/**'
|
||||
- 'python_appimage/**'
|
||||
- '.github/workflows/applications.yml'
|
||||
- 'applications/**'
|
||||
- 'python_appimage/**'
|
||||
|
||||
jobs:
|
||||
Test:
|
||||
|
||||
4
.github/workflows/pypi.yml
vendored
4
.github/workflows/pypi.yml
vendored
@@ -1,8 +1,10 @@
|
||||
name: PyPI
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
paths:
|
||||
- 'VERSION'
|
||||
- 'VERSION'
|
||||
|
||||
jobs:
|
||||
Test:
|
||||
|
||||
141
docs/docs/apps.md
Normal file
141
docs/docs/apps.md
Normal file
@@ -0,0 +1,141 @@
|
||||
<!-- This document describes the usage of the python-appimage utility
|
||||
|
||||
The intended audience is developers. In addition, this document also provides
|
||||
some tips for packaging Python based applications.
|
||||
-->
|
||||
|
||||
<script src="../js/highlight.min.js" defer></script>
|
||||
<script src="../js/apps.js" defer></script>
|
||||
|
||||
|
||||
# Developers corner
|
||||
|
||||
Python [AppImages][APPIMAGE] are built with the `python-appimage`{.inline}
|
||||
utility, available from [PyPI][PYPI]. This utility can also help packaging
|
||||
Python based applications as AppImages, using an existing Python AppImage and a
|
||||
recipe folder.
|
||||
{.justify}
|
||||
|
||||
!!! Caution
|
||||
The `python-appimage`{.inline} utility can only package applications that
|
||||
can be directly installed with `pip`{.inline}. For more advanced usage, one
|
||||
needs to extract the Python AppImage and to edit it, e.g. as explained in
|
||||
the [Advanced installation](index.md#advanced-installation) section.
|
||||
Additional details on this use case are provided
|
||||
[below](#advanced-packaging).
|
||||
{.justify}
|
||||
|
||||
|
||||
## Building a Python AppImage
|
||||
|
||||
The primary scope of `python-appimage`{.inline} is to relocate an existing
|
||||
Python installation inside an AppDir, and to build the corresponding AppImage.
|
||||
For example, the following
|
||||
{.justify}
|
||||
|
||||
```bash
|
||||
python-appimage build local -p $(which python2)
|
||||
```
|
||||
|
||||
should build an AppImage of your local Python 2 installation, provided that it
|
||||
exists.
|
||||
|
||||
!!! Tip
|
||||
Help on available arguments and options to `python-appimage`{.inline} can be
|
||||
obtained with the `-h`{.inline .language-bash} flag. For example,
|
||||
`python-appimage build local -h`{.inline .language-none} provides help on
|
||||
local builds.
|
||||
{.justify}
|
||||
|
||||
|
||||
<div markdown="1" class="capsule">
|
||||
### Auxiliary tools
|
||||
|
||||
The `python-appimage`{.inline} utility relies on auxiliary tools that are
|
||||
downloaded and installed at runtime, on need. Those are
|
||||
[appimagetool][APPIMAGETOOL] for building AppImages, and [patchelf][PATCHELF] in
|
||||
order to edit ELFs runtime paths (`RPATH`{.inline}). Auxiliary tools are
|
||||
installed to the the user space. One can get their location with the
|
||||
`which`{.inline .language-none} command word. For example,
|
||||
{.justify}
|
||||
|
||||
```bash
|
||||
python-appimage which appimagetool
|
||||
```
|
||||
|
||||
returns the location of `appimagetool`{.inline}, if it has been installed. If
|
||||
not, the `install`{.inline} command word can be used in order to trigger its
|
||||
installation.
|
||||
{.justify}
|
||||
</div>
|
||||
|
||||
|
||||
## Manylinux Python AppImage
|
||||
|
||||
AppImages of your local `python`{.inline} are unlikely to be portable, except if
|
||||
you run an ancient Linux distribution. Indeed, a core component preventing
|
||||
portability across Linuses is the use of different versions of the
|
||||
`glibc`{.inline} system library. Hopefully, `glibc`{.inline} is highly backward
|
||||
compatible. Therefore, a simple work-around is to compile binaries using the
|
||||
oldest Linux distro you can afford to. This is the strategy used for creating
|
||||
portable AppImages, as well as for distributing Python site packages as
|
||||
ready-to-use binary [wheels][WHEELS].
|
||||
{.justify}
|
||||
|
||||
The Python Packaging Authority (PyPA) has defined standard platform tags for
|
||||
building Python site packages, labelled [manylinux][MANYLINUX]. These build
|
||||
platforms are available as Docker images with various versions of Python already
|
||||
installed. The `python-appimage`{.inline} utility can be used to package those
|
||||
installs as AppImages. For example, the following command
|
||||
{.justify}
|
||||
|
||||
```bash
|
||||
python-appimage build manylinux 2014_x86_64 cp310-cp310
|
||||
```
|
||||
|
||||
should build an AppImage of Python 3.10 using the CPython (_cp310-cp310_)
|
||||
install found in the `manylinux2014_x86_64`{.inline} Docker image.
|
||||
{.justify}
|
||||
|
||||
!!! Note
|
||||
Docker needs to be already installed on your system in order to build
|
||||
Manylinux Python images. However, the command above can be run on the host.
|
||||
That is, you need **not** to explictly shell inside the manylinux Docker
|
||||
image.
|
||||
{.justify}
|
||||
|
||||
!!! Tip
|
||||
A compilation of ready-to-use Manylinux Python AppImages is available from
|
||||
the [releases][RELEASES] area of the `python-appimage`{.inline} [GitHub
|
||||
repository][GITHUB]. These AppImages are updated weekly, on every Sunday.
|
||||
{.justify}
|
||||
|
||||
|
||||
## Simple packaging
|
||||
|
||||
The recipe folder contains
|
||||
the app metadata, a Python requirements file and an entry point script. Examples
|
||||
of recipes can be found on GitHub in the [applications][APPLICATIONS] folder.
|
||||
{.justify}
|
||||
|
||||
|
||||
## Advanced packaging
|
||||
|
||||
Alternatively, you can also manualy extract one of the Python
|
||||
[AppImages][APPIMAGE] as explained above and directly modify the content, e.g.
|
||||
`pip install`{.inline} your custom packages. Then, simply rebuild the AppImage
|
||||
using your favourite tool, e.g. [appimagetool][APPIMAGETOOL],
|
||||
[linuxdeploy][LINUXDEPLOY] or `python-appimage`{.inline}.
|
||||
{.justify}
|
||||
|
||||
|
||||
[APPIMAGE]: https://appimage.org
|
||||
[APPIMAGETOOL]: https://appimage.github.io/appimagetool
|
||||
[APPLICATIONS]: https://github.com/niess/python-appimage/tree/master/applications
|
||||
[GITHUB]: https://github.com/niess/python-appimage
|
||||
[LINUXDEPLOY]: https://github.com/linuxdeploy/linuxdeploy
|
||||
[MANYLINUX]: https://github.com/pypa/manylinux
|
||||
[PATCHELF]: https://github.com/NixOS/patchelf
|
||||
[PYPI]: https://pypi.org/project/python-appimage
|
||||
[RELEASES]: https://github.com/niess/python-appimage/releases
|
||||
[WHEELS]: https://pythonwheels.com/
|
||||
97
docs/docs/css/extra.css
Normal file
97
docs/docs/css/extra.css
Normal file
@@ -0,0 +1,97 @@
|
||||
/* Text justification */
|
||||
.justify {
|
||||
text-align: justify;
|
||||
text-justify: inter-word;
|
||||
}
|
||||
|
||||
|
||||
/* Patch for code highlighting */
|
||||
code.inline {
|
||||
background: transparent !important;
|
||||
color: black;
|
||||
display: inline;
|
||||
overflow-wrap: break-word;
|
||||
}
|
||||
|
||||
pre code.hljs {
|
||||
background: #2e3440;
|
||||
color: #d8dee9;
|
||||
}
|
||||
|
||||
/* Wrap with a capsule */
|
||||
.capsule {
|
||||
margin-bottom: 10px;
|
||||
padding: 5px 20px 5px 20px;
|
||||
border: thin solid;
|
||||
-webkit-border-radius: 5px;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
/* Appimages summary table */
|
||||
.appimages-summary-table {
|
||||
border-collapse: collapse;
|
||||
caption-side: bottom;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
box-shadow: 0 0 20px rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
.appimages-summary-table caption {
|
||||
font-size: 1.2em;
|
||||
font-style: italic;
|
||||
padding: 12px 15px;
|
||||
}
|
||||
|
||||
.appimages-summary-table th,
|
||||
.appimages-summary-table td {
|
||||
font-weight: normal;
|
||||
padding: 12px 15px;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.appimages-summary-table thead tr,
|
||||
.appimages-summary-table tbody td:first-child {
|
||||
background-color: #2e3440;
|
||||
color: #d8dee9;
|
||||
text-align: left;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.appimages-summary-table tbody tr {
|
||||
border-bottom: 1px solid #dddddd;
|
||||
}
|
||||
|
||||
.appimages-summary-table tbody tr:nth-of-type(even) {
|
||||
background-color: #f3f3f3;
|
||||
}
|
||||
|
||||
.appimages-summary-table tbody tr:last-of-type {
|
||||
border-bottom: 2px solid #2e3440;
|
||||
}
|
||||
|
||||
.appimages-summary-table-inner,
|
||||
.appimages-summary-table-inner tbody,
|
||||
.appimages-summary-table-inner tbody tr,
|
||||
.appimages-summary-table-inner tbody tr:last-of-type {
|
||||
border: none;
|
||||
}
|
||||
|
||||
.appimages-summary-table-inner td
|
||||
{
|
||||
padding: 3px 4px;
|
||||
}
|
||||
|
||||
.appimages-summary-table-inner tbody tr:nth-of-type(even),
|
||||
.appimages-summary-table-inner tbody td:first-child {
|
||||
background-color: transparent;
|
||||
border: none !important;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
/* Resized badge */
|
||||
.smaller-appimage-badge img {
|
||||
height: 18px;
|
||||
width: auto;
|
||||
}
|
||||
1
docs/docs/css/nord.min.css
vendored
Normal file
1
docs/docs/css/nord.min.css
vendored
Normal file
@@ -0,0 +1 @@
|
||||
pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}.hljs{background:#2e3440}.hljs,.hljs-subst{color:#d8dee9}.hljs-selector-tag{color:#81a1c1}.hljs-selector-id{color:#8fbcbb;font-weight:700}.hljs-selector-attr,.hljs-selector-class{color:#8fbcbb}.hljs-property,.hljs-selector-pseudo{color:#88c0d0}.hljs-addition{background-color:rgba(163,190,140,.5)}.hljs-deletion{background-color:rgba(191,97,106,.5)}.hljs-built_in,.hljs-class,.hljs-type{color:#8fbcbb}.hljs-function,.hljs-function>.hljs-title,.hljs-title.hljs-function{color:#88c0d0}.hljs-keyword,.hljs-literal,.hljs-symbol{color:#81a1c1}.hljs-number{color:#b48ead}.hljs-regexp{color:#ebcb8b}.hljs-string{color:#a3be8c}.hljs-title{color:#8fbcbb}.hljs-params{color:#d8dee9}.hljs-bullet{color:#81a1c1}.hljs-code{color:#8fbcbb}.hljs-emphasis{font-style:italic}.hljs-formula{color:#8fbcbb}.hljs-strong{font-weight:700}.hljs-link:hover{text-decoration:underline}.hljs-comment,.hljs-quote{color:#4c566a}.hljs-doctag{color:#8fbcbb}.hljs-meta,.hljs-meta .hljs-keyword{color:#5e81ac}.hljs-meta .hljs-string{color:#a3be8c}.hljs-attr{color:#8fbcbb}.hljs-attribute{color:#d8dee9}.hljs-name{color:#81a1c1}.hljs-section{color:#88c0d0}.hljs-tag{color:#81a1c1}.hljs-template-variable,.hljs-variable{color:#d8dee9}.hljs-template-tag{color:#5e81ac}.language-abnf .hljs-attribute{color:#88c0d0}.language-abnf .hljs-symbol{color:#ebcb8b}.language-apache .hljs-attribute{color:#88c0d0}.language-apache .hljs-section{color:#81a1c1}.language-arduino .hljs-built_in{color:#88c0d0}.language-aspectj .hljs-meta{color:#d08770}.language-aspectj>.hljs-title{color:#88c0d0}.language-bnf .hljs-attribute{color:#8fbcbb}.language-clojure .hljs-name{color:#88c0d0}.language-clojure .hljs-symbol{color:#ebcb8b}.language-coq .hljs-built_in{color:#88c0d0}.language-cpp .hljs-meta .hljs-string{color:#8fbcbb}.language-css .hljs-built_in{color:#88c0d0}.language-css .hljs-keyword{color:#d08770}.language-diff .hljs-meta,.language-ebnf .hljs-attribute{color:#8fbcbb}.language-glsl .hljs-built_in{color:#88c0d0}.language-groovy .hljs-meta:not(:first-child),.language-haxe .hljs-meta,.language-java .hljs-meta{color:#d08770}.language-ldif .hljs-attribute{color:#8fbcbb}.language-lisp .hljs-name,.language-lua .hljs-built_in,.language-moonscript .hljs-built_in,.language-nginx .hljs-attribute{color:#88c0d0}.language-nginx .hljs-section{color:#5e81ac}.language-pf .hljs-built_in,.language-processing .hljs-built_in{color:#88c0d0}.language-scss .hljs-keyword,.language-stylus .hljs-keyword{color:#81a1c1}.language-swift .hljs-meta{color:#d08770}.language-vim .hljs-built_in{color:#88c0d0;font-style:italic}.language-yaml .hljs-meta{color:#d08770}
|
||||
264
docs/docs/index.md
Normal file
264
docs/docs/index.md
Normal file
@@ -0,0 +1,264 @@
|
||||
<!-- This document describes the usage of Python AppImages, as runtimes.
|
||||
|
||||
Note that some parts of this document are generated dynamically according to the
|
||||
reader's system configuration, and depending on released AppImages. The intent
|
||||
is to provide relevant examples to the reader, as well as a dynamic summary of
|
||||
available Python AppImages.
|
||||
-->
|
||||
|
||||
<script src="js/highlight.min.js" defer></script>
|
||||
<script src="js/index.js" defer></script>
|
||||
|
||||
|
||||
# Python AppImages
|
||||
|
||||
We provide relocatable Python runtimes for _Linux_ systems, as
|
||||
[AppImages][APPIMAGE]. These runtimes have been extracted from
|
||||
[manylinux][MANYLINUX] Docker images.
|
||||
{.justify .append-releases-list}
|
||||
|
||||
## Basic installation
|
||||
|
||||
Installing Python from an [AppImage][APPIMAGE] is as simple as downloading a
|
||||
single file and changing its mode to executable. For example, as
|
||||
{.justify}
|
||||
|
||||
``` { .bash #basic-installation-example }
|
||||
wget https://github.com/niess/python-appimage/releases/download\
|
||||
/python3.10/python3.10.2-cp310-cp310-manylinux2014_x86_64.AppImage
|
||||
|
||||
chmod +x python3.10.2-cp310-cp310-manylinux2014_x86_64.AppImage
|
||||
```
|
||||
|
||||
!!! Note
|
||||
As can be seen from the previous [example](#basic-installation-example), the
|
||||
AppImage name contains several informations. That are, the Python full
|
||||
version (*3.10.2*{#example-full-version}), the CPython tag
|
||||
(*cp310-cp310*{#example-python-tag}), the Linux compatibility tag
|
||||
(*manylinux2014*{#example-linux-tag}) and the machine architecture
|
||||
(*x86_64*{#example-arch-tag}).
|
||||
{.justify}
|
||||
|
||||
!!! Caution
|
||||
One needs to **select an AppImage** that matches **system requirements**. A
|
||||
summmary of available Python AppImages is provided at the
|
||||
[bottom](#available-python-appimages) of this page.
|
||||
{.justify}
|
||||
|
||||
|
||||
<div markdown="1" class="capsule">
|
||||
### Creating a symbolic link
|
||||
|
||||
Since AppImages native names are rather lengthy, one might create a symbolic
|
||||
link, e.g. as
|
||||
{.justify}
|
||||
|
||||
``` { .bash #basic-installation-example-symlink }
|
||||
ln -s python3.10.2-cp310-cp310-manylinux2014_x86_64.AppImage python3.10
|
||||
```
|
||||
|
||||
Then, executing the AppImage as
|
||||
`./python3.10`{#basic-installation-example-execution .inline} should start a
|
||||
Python interactive session on _almost_ any Linux, provided that **fuse** is
|
||||
supported.
|
||||
{.justify}
|
||||
</div>
|
||||
|
||||
|
||||
!!! Tip
|
||||
Fuse is not supported on Windows Subsytem for Linux v1 (WSL1), preventing
|
||||
AppImages direct execution. Yet, one can still extract the content of Python
|
||||
AppImages and use them, as explained in the [Advanced
|
||||
installation](#advanced-installation) section.
|
||||
{.justify}
|
||||
|
||||
|
||||
## Installing site packages
|
||||
|
||||
Site packages can be installed using `pip`{.inline}, distributed with the
|
||||
AppImage. For example, the following
|
||||
{.justify}
|
||||
|
||||
``` {.bash #site-packages-example}
|
||||
./python3.10 -m pip install numpy
|
||||
```
|
||||
|
||||
installs the numpy package, where it is assumed that a symlink to the AppImage
|
||||
has been previously created. When using the **basic installation** scheme, by
|
||||
default Python packages are installed to your **user space**, i.e. under
|
||||
`~/.local`{.inline} on Linux.
|
||||
{.justify}
|
||||
|
||||
!!! Note
|
||||
AppImage are read-only. Therefore, site packages cannot be directly
|
||||
installed to the AppImage. However, the AppImage can be extracted, as
|
||||
explained in the [Advanced installation](#advanced-installation) section.
|
||||
{.justify}
|
||||
|
||||
|
||||
<div markdown="1" class="capsule">
|
||||
### Alternative site packages location
|
||||
|
||||
One can
|
||||
specify an alternative installation directory for site packages using the
|
||||
`--target`{.inline .language-bash} option of pip. For example, the following
|
||||
{.justify}
|
||||
|
||||
``` {.bash #site-packages-example-target}
|
||||
./python3.10 -m pip install --target=$(pwd)/packages numpy
|
||||
```
|
||||
|
||||
installs the numpy package besides the AppImage, in a `packages`{.inline}
|
||||
folder.
|
||||
{.justify}
|
||||
</div>
|
||||
|
||||
!!! Tip
|
||||
Packages installed in non standard locations are not automatically
|
||||
found by Python. Their location must be aded to
|
||||
`sys.path`{.inline .language-python}, e.g. using the
|
||||
`PYTHONPATH`{.inline .language-bash} environment variable.
|
||||
{.justify}
|
||||
|
||||
!!! Caution
|
||||
While Python AppImages are relocatable, site packages might not be. In
|
||||
particular, packages installing executable Python scripts assume a fix
|
||||
location of the Python runtime. If the Python AppImage is moved, then these
|
||||
scripts will fail. This can be patched by editing the script
|
||||
[shebang][SHEBANG], or be reinstalling the corresponding package.
|
||||
{.justify}
|
||||
|
||||
|
||||
## Isolating from the user space
|
||||
|
||||
Python AppImages are not isolated from the user space. Therefore, by default
|
||||
site packages located under `~/.local`{.inline} are loaded instead of system
|
||||
ones. Note that this is the usual Python runtime behaviour. However, it can be
|
||||
conflictual in some cases.
|
||||
{.justify}
|
||||
|
||||
In order to disable user site packages, one can use the
|
||||
`-s`{.inline .language-bash} option of the Python runtime. For example,
|
||||
invoking the Python AppImage as
|
||||
`./python3.10 -s`{.inline .language-bash #user-isolation-example} prevents user
|
||||
packages to be loaded.
|
||||
{.justify}
|
||||
|
||||
|
||||
## Using a virtual environement
|
||||
|
||||
Isolation can also be achieved with a [virtual environment][VENV]. Python
|
||||
AppImages can create a `venv`{.inline} using the standard syntax, e.g. as
|
||||
{.justify}
|
||||
|
||||
``` {.bash #venv-example}
|
||||
./python3.10 -m venv /path/to/new/virtual/environment
|
||||
```
|
||||
|
||||
However, the virtual environment fails setting up `pip`{.inline}, despite the
|
||||
latter is packaged with the AppImage. Yet, this can be patched by calling
|
||||
`ensurepip`{.inline} from within the `venv`{.inline}, after its creation. For
|
||||
example, as
|
||||
{.justify}
|
||||
|
||||
```bash
|
||||
source /path/to/new/virtual/environment/bin/activate
|
||||
|
||||
python -m ensurepip
|
||||
```
|
||||
|
||||
|
||||
## Advanced installation
|
||||
|
||||
The [basic installation](#basic-installation) scheme described previously has
|
||||
some limitations when using Python AppImages as a runtime. For example, site
|
||||
packages need to be installed to a separate location. This can be solved by
|
||||
extracting a Python AppImage to an `*.AppDir`{.inline} directory, e.g. as
|
||||
{.justify}
|
||||
|
||||
``` {.bash #advanced-installation-example}
|
||||
./python3.10.2-cp310-cp310-manylinux2014_x86_64.AppImage --appimage-extract
|
||||
|
||||
mv squashfs-root python3.10.2-cp310-cp310-manylinux2014_x86_64.AppDir
|
||||
|
||||
ln -s python3.10.2-cp310-cp310-manylinux2014_x86_64.AppDir/AppRun python3.10
|
||||
```
|
||||
|
||||
Then, by default **site packages** are installed to the extracted **AppDir**,
|
||||
when using `pip`{.inline}. In addition, executable scripts installed by
|
||||
`pip`{.inline} are patched in order to use relative [shebangs][SHEBANG].
|
||||
Consequently, the AppDir can be freely moved around.
|
||||
{.justify}
|
||||
|
||||
!!! Note
|
||||
Python AppDirs follow the [manylinux][MANYLINUX] installation scheme.
|
||||
Executable scripts are installed under `AppDir/opt/pythonX.Y/bin`{.inline}
|
||||
where _X_ and _Y_ in _pythonX.Y_ stand for the major and minor version
|
||||
numbers. Site packages are located under
|
||||
`AppDir/opt/pythonX.Y/lib/pythonX.Y/site-packages`{.inline}.
|
||||
{.justify}
|
||||
|
||||
!!! Tip
|
||||
As for Python AppImages, by default the extracted runtime is [not isolated
|
||||
from the user space](#isolating-from-the-user-space). This behaviour can be
|
||||
changed by editing the `AppDir/AppRun`{.inline} wrapper script, and by
|
||||
adding the `-s`{.inline .language-bash} option at the very bottom, where
|
||||
Python is invoked.
|
||||
{.justify}
|
||||
|
||||
|
||||
<div markdown="1" class="capsule">
|
||||
### Repackaging the AppImage
|
||||
|
||||
An extracted AppDir can be re-packaged as an AppImage using
|
||||
[appimagetool][APPIMAGETOOL], e.g. as
|
||||
{.justify}
|
||||
|
||||
``` {.bash #repackaging-example}
|
||||
wget https://github.com/AppImage/AppImageKit/releases/download/continuous/\
|
||||
appimagetool-x86_64.AppImage
|
||||
|
||||
chmod +x appimagetool-x86_64.AppImage
|
||||
|
||||
./appimagetool-x86_64.AppImage \
|
||||
python3.10.2-cp310-cp310-manylinux2014_x86_64.AppDir \
|
||||
python3.10.2-cp310-cp310-manylinux2014_x86_64.AppImage
|
||||
```
|
||||
|
||||
This allows to customize your Python AppImage, for example by adding your
|
||||
preferred site packages.
|
||||
{.justify}
|
||||
</div>
|
||||
|
||||
!!! Note
|
||||
Python AppImages can also be used for packaging Python based applications,
|
||||
as AppImages. Additional details are provided in the [developers
|
||||
section](apps).
|
||||
{.justify}
|
||||
|
||||
|
||||
## Available Python AppImages
|
||||
|
||||
A summary of available Python AppImages [releases][RELEASES] is provided in the
|
||||
[table](#appimages-download-links) below. Clicking on a badge should download
|
||||
the corresponding AppImage.
|
||||
|
||||
!!! Caution
|
||||
According to your browser, your system would not be compatible with Python
|
||||
Appimages.
|
||||
{.justify #suggest-appimage-download}
|
||||
|
||||
<div id="appimages-download-links">
|
||||
<p style="color: red; text-align: center">
|
||||
<could not download release data from
|
||||
https://github.com/niess/python-appimage/releases>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
|
||||
[APPIMAGE]: https://appimage.org
|
||||
[APPIMAGETOOL]: https://appimage.github.io/appimagetool
|
||||
[MANYLINUX]: https://github.com/pypa/manylinux
|
||||
[RELEASES]: https://github.com/niess/python-appimage/releases
|
||||
[SHEBANG]: https://en.wikipedia.org/wiki/Shebang_(Unix)
|
||||
[VENV]: https://docs.python.org/3/library/venv.html
|
||||
5
docs/docs/js/apps.js
Normal file
5
docs/docs/js/apps.js
Normal file
@@ -0,0 +1,5 @@
|
||||
/* Perform the syntaxic highlighting */
|
||||
hljs.configure({
|
||||
cssSelector: "code"
|
||||
});
|
||||
hljs.highlightAll();
|
||||
1160
docs/docs/js/highlight.min.js
vendored
Normal file
1160
docs/docs/js/highlight.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
260
docs/docs/js/index.js
Normal file
260
docs/docs/js/index.js
Normal file
@@ -0,0 +1,260 @@
|
||||
/*-Update content according to release metadata */
|
||||
$.getJSON("https://api.github.com/repos/niess/python-appimage/releases").done(function(data) {
|
||||
|
||||
/* Unpack release metadata */
|
||||
const releases = []
|
||||
for (const datum of data) {
|
||||
var full_version = undefined;
|
||||
const assets = [];
|
||||
for (const asset of datum.assets) {
|
||||
if (asset.name.endsWith(".AppImage")) {
|
||||
/* Parse AppImage metadata */
|
||||
const tmp0 = asset.name.split("manylinux")
|
||||
const tag = tmp0[1].slice(0,-9);
|
||||
const tmp1 = tag.split(/_(.+)/);
|
||||
const linux = tmp1[0]
|
||||
const arch = tmp1[1]
|
||||
const tmp2 = tmp0[0].split("-")
|
||||
const python = tmp2[1] + "-" + tmp2[2]
|
||||
assets.push({
|
||||
name: asset.name,
|
||||
url: asset.browser_download_url,
|
||||
python: python,
|
||||
linux: linux,
|
||||
arch: arch
|
||||
});
|
||||
|
||||
if (full_version === undefined) {
|
||||
const index = asset.name.indexOf("-")
|
||||
full_version = asset.name.slice(6, index)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
releases.push({
|
||||
version: datum.name.slice(7),
|
||||
full_version: full_version,
|
||||
assets: assets,
|
||||
url: datum.html_url
|
||||
});
|
||||
}
|
||||
|
||||
/* Sort releases */
|
||||
releases.sort(function(a, b) {
|
||||
const tmpa = a.version.split(".")
|
||||
const tmpb = b.version.split(".")
|
||||
a0 = Number(tmpa[0])
|
||||
a1 = Number(tmpa[1])
|
||||
b0 = Number(tmpb[0])
|
||||
b1 = Number(tmpb[1])
|
||||
|
||||
if (a0 != b0) {
|
||||
return a0 - b0;
|
||||
} else {
|
||||
return a1 - b1;
|
||||
}
|
||||
});
|
||||
|
||||
/* Generate the releases list */
|
||||
{
|
||||
const elements = []
|
||||
for (const release of releases) {
|
||||
elements.push(`<a href="${release.url}">${release.version}</a>`)
|
||||
}
|
||||
$(".append-releases-list").append(
|
||||
" Available Python versions are " +
|
||||
elements.slice(0, -1).join(", ") +
|
||||
" and " +
|
||||
elements[elements.length - 1] +
|
||||
"."
|
||||
);
|
||||
}
|
||||
|
||||
/* Detect the host architecture */
|
||||
var host_arch = undefined;
|
||||
{
|
||||
var re = /Linux +(?<arch>[a-z0-9_]+)/g;
|
||||
const result = re.exec(navigator.userAgent);
|
||||
if (result) {
|
||||
host_arch = result.groups.arch;
|
||||
if (host_arch == "x64") {
|
||||
host_arch = "x86_64";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Strip blocks of whitespaces, e.g. at line start */
|
||||
function stripws (s) { return s.replace(/ +/g, ""); }
|
||||
|
||||
/* Utility function for setting a code snippet */
|
||||
function set_snippet (selector, code) {
|
||||
$(selector).children().html(stripws(code));
|
||||
}
|
||||
|
||||
/* Generate the examples */
|
||||
var suggested_appimage = undefined;
|
||||
{
|
||||
const release = releases[releases.length - 1];
|
||||
const arch = (host_arch === undefined) ? "x86_64" : host_arch;
|
||||
var asset = undefined;
|
||||
for (const a of release.assets) {
|
||||
if (a.arch == arch) {
|
||||
if (asset == undefined) {
|
||||
asset = a;
|
||||
} else if (Number(a.linux) > Number(asset.linux)) {
|
||||
asset = a;
|
||||
}
|
||||
}
|
||||
}
|
||||
suggested_appimage = asset;
|
||||
|
||||
const pattern = "download";
|
||||
const i = asset.url.indexOf(pattern) + pattern.length;
|
||||
const url0 = asset.url.slice(0, i);
|
||||
const url1 = asset.url.slice(i + 1);
|
||||
set_snippet("#basic-installation-example", `\
|
||||
wget ${url0}\\
|
||||
/${url1}
|
||||
|
||||
chmod +x ${asset.name}</code></pre>
|
||||
`);
|
||||
|
||||
$("#example-full-version").text(release.full_version);
|
||||
$("#example-python-tag").text(asset.python);
|
||||
$("#example-linux-tag").text("manylinux" + asset.linux);
|
||||
$("#example-arch-tag").text(asset.arch);
|
||||
|
||||
set_snippet("#basic-installation-example-symlink", `\
|
||||
ln -s ${asset.name} python${release.version}
|
||||
`);
|
||||
|
||||
$("#basic-installation-example-execution").html(
|
||||
`./python${release.version}`
|
||||
);
|
||||
|
||||
set_snippet("#site-packages-example", `\
|
||||
./python${release.version} -m pip install numpy
|
||||
`);
|
||||
|
||||
set_snippet("#site-packages-example-target", `\
|
||||
./python${release.version} -m pip install --target=$(pwd)/packages numpy
|
||||
`);
|
||||
|
||||
$("#user-isolation-example").html(
|
||||
`./python${release.version} -s`);
|
||||
|
||||
set_snippet("#venv-example", `\
|
||||
./python${release.version} -m venv /path/to/new/virtual/environment
|
||||
`);
|
||||
|
||||
const appdir = asset.name.slice(0, -8) + "AppDir";
|
||||
|
||||
set_snippet("#advanced-installation-example", `\
|
||||
./${asset.name} --appimage-extract
|
||||
|
||||
mv squashfs-root ${appdir}
|
||||
|
||||
ln -s ${appdir}/AppRun python${release.version}
|
||||
`);
|
||||
}
|
||||
|
||||
|
||||
function badge (asset, pad) {
|
||||
const colors = {i686: "lightgrey", x86_64: "blue"};
|
||||
const python = asset.python.split("-")[1];
|
||||
const arch = asset.arch.replace("_", "__");
|
||||
var color = colors[asset.arch];
|
||||
if (color === undefined) {
|
||||
color = "red";
|
||||
}
|
||||
|
||||
const img = `<img src="https://img.shields.io/badge/${python}-${arch}-${color}" alt="${asset.arch}">`
|
||||
|
||||
if (pad) {
|
||||
return `<a href=${asset.url}>${img}</a>`;
|
||||
} else {
|
||||
return `<a href=${asset.url}><span class="smaller-appimage-badge">${img}</span></a>`;
|
||||
}
|
||||
}
|
||||
|
||||
/* Generate the download links summary */
|
||||
{
|
||||
/* Find all Linux tags */
|
||||
function unique (arr) {
|
||||
var u = {}, a = [];
|
||||
for(var i = 0, l = arr.length; i < l; ++i){
|
||||
if(!u.hasOwnProperty(arr[i])) {
|
||||
a.push(arr[i]);
|
||||
u[arr[i]] = 1;
|
||||
}
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
const all_linuses = [];
|
||||
for (const release of releases) {
|
||||
for (const asset of release.assets) {
|
||||
all_linuses.push(asset.linux);
|
||||
}
|
||||
}
|
||||
const linuses = unique(all_linuses);
|
||||
|
||||
/* Build the table header */
|
||||
const html = [];
|
||||
html.push("<table class=\"appimages-summary-table\"><thead><tr><th></th>");
|
||||
for (const linux of linuses) {
|
||||
html.push(`<th>Manylinux ${linux}</th>`);
|
||||
}
|
||||
html.push("</tr></thead>");
|
||||
|
||||
/* Build the table rows */
|
||||
html.push("<tbody>");
|
||||
for (const release of releases) {
|
||||
html.push(`<tr><td>Python ${release.version}</td>`)
|
||||
for (linux of linuses) {
|
||||
const candidates = [];
|
||||
for (asset of release.assets) {
|
||||
if (asset.linux == linux) {
|
||||
candidates.push(badge(asset, true));
|
||||
}
|
||||
}
|
||||
if (candidates.length > 0) {
|
||||
html.push(
|
||||
"<td><table class=\"appimages-summary-table-inner\"><tbody><tr><td>" +
|
||||
candidates.join("</td></tr><tr><td>") +
|
||||
"</td></tr></tbody></table></td>"
|
||||
);
|
||||
} else {
|
||||
html.push("<td>∅</td>");
|
||||
}
|
||||
}
|
||||
html.push(`</tr>`)
|
||||
}
|
||||
html.push("</tbody>");
|
||||
html.push("<caption>Summary of available Python AppImages.</caption>");
|
||||
html.push("</table>");
|
||||
|
||||
$("#appimages-download-links").html(html.join("\n"));
|
||||
}
|
||||
|
||||
/* Suggest an AppImage */
|
||||
if (host_arch != undefined) {
|
||||
const body = $("#suggest-appimage-download");
|
||||
body.html(stripws(`\
|
||||
According to your browser, your system is an ${host_arch} Linux.
|
||||
Therefore, we recommend that you download an ${host_arch} AppImage
|
||||
with Manylinux ${suggested_appimage.linux} compatibility. For
|
||||
example, ${badge(suggested_appimage, false)}.
|
||||
`));
|
||||
|
||||
const parents = body.parent();
|
||||
parents.attr("class", "admonition tip");
|
||||
parents.children().first().text("Tip");
|
||||
}
|
||||
|
||||
/* Perform the syntaxic highlighting */
|
||||
hljs.configure({
|
||||
cssSelector: "code"
|
||||
});
|
||||
hljs.highlightAll();
|
||||
});
|
||||
23
docs/mkdocs.yml
Normal file
23
docs/mkdocs.yml
Normal file
@@ -0,0 +1,23 @@
|
||||
site_name: Python AppImage
|
||||
site_description: AppImage distributions of Python
|
||||
site_author: Valentin Niess
|
||||
copyright: GPL-3.0
|
||||
|
||||
repo_url: https://github.com/niess/python-appimage
|
||||
edit_uri: edit/master/docs/docs
|
||||
|
||||
nav:
|
||||
- Python AppImages: index.md
|
||||
- Developers corner: apps.md
|
||||
|
||||
theme:
|
||||
name: readthedocs
|
||||
navigation_depth: 3
|
||||
highlightjs: no
|
||||
|
||||
markdown_extensions:
|
||||
- admonition
|
||||
- attr_list
|
||||
- md_in_html
|
||||
|
||||
extra_css: [css/extra.css, css/nord.min.css]
|
||||
1
docs/requirements.txt
Normal file
1
docs/requirements.txt
Normal file
@@ -0,0 +1 @@
|
||||
mkdocs==1.2.3
|
||||
@@ -63,7 +63,12 @@ def patch_pip_install():
|
||||
shebang = shebang.split()
|
||||
python_x_y = os.path.basename(shebang.pop(0))
|
||||
if not python_x_y.startswith('python'):
|
||||
continue
|
||||
head, altbody = body.split(os.linesep, 1)
|
||||
if head.startswith("'''exec' /"): # Patch for alt shebang
|
||||
body = altbody.split(os.linesep, 1)[1]
|
||||
python_x_y = os.path.basename(head.split()[1])
|
||||
else:
|
||||
continue
|
||||
|
||||
relpath = os.path.relpath(
|
||||
sys.prefix + '/../../usr/bin/' + python_x_y,
|
||||
|
||||
Reference in New Issue
Block a user