Add documentation with mkdocs

This commit is contained in:
Valentin Niess
2022-02-15 16:46:31 +01:00
parent 6d308d3c30
commit 2f9407dda1
13 changed files with 1970 additions and 7 deletions

View File

@@ -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'

View File

@@ -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:

View File

@@ -1,8 +1,10 @@
name: PyPI
on:
push:
branches:
- master
paths:
- 'VERSION'
- 'VERSION'
jobs:
Test:

141
docs/docs/apps.md Normal file
View 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
View 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
View 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
View 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">
&lt;could not download release data from
https://github.com/niess/python-appimage/releases&gt;
</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
View 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

File diff suppressed because one or more lines are too long

260
docs/docs/js/index.js Normal file
View 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>&empty;</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
View 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
View File

@@ -0,0 +1 @@
mkdocs==1.2.3

View File

@@ -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,