Răsfoiți Sursa

Add documentation with mkdocs

Valentin Niess 4 ani în urmă
părinte
comite
2f9407dda1

+ 4 - 2
.github/workflows/appimage.yml

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

+ 5 - 3
.github/workflows/applications.yml

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

+ 3 - 1
.github/workflows/pypi.yml

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

+ 141 - 0
docs/docs/apps.md

@@ -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 - 0
docs/docs/css/extra.css

@@ -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;
+}

Fișier diff suprimat deoarece este prea mare
+ 0 - 0
docs/docs/css/nord.min.css


+ 264 - 0
docs/docs/index.md

@@ -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 - 0
docs/docs/js/apps.js

@@ -0,0 +1,5 @@
+/* Perform the syntaxic highlighting */
+hljs.configure({
+    cssSelector: "code"
+});
+hljs.highlightAll();

Fișier diff suprimat deoarece este prea mare
+ 310 - 0
docs/docs/js/highlight.min.js


+ 260 - 0
docs/docs/js/index.js

@@ -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 - 0
docs/mkdocs.yml

@@ -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 - 0
docs/requirements.txt

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

+ 6 - 1
python_appimage/data/sitecustomize.py

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

Unele fișiere nu au fost afișate deoarece prea multe fișiere au fost modificate în acest diff