scripts/cardputer-zero/build-deb.sh runs on arm64 Debian 13 (the Cardputer itself) and makes meshterm_<version>-<revision>_arm64.deb. MeshTerm and all its Python packages, the spi extra included, go in /usr/lib/meshterm, compiled to bytecode. The package depends only on python3: the store app installs a missing dependency with apt-get but never runs apt-get update, so a Debian dependency can fail. For the same reason the package carries Terminus beside its OFL, because an app from the launcher has no terminal for --fetch-fonts. packaging/notices.py gets a site-directory mode, because the walk of the closure asks for no extras and so misses the spi packages. scripts/cardputer-zero/store holds the listing that czdev publish reads and a 256-pixel icon. The screenshots are still to make. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
74 lines
3.0 KiB
Python
74 lines
3.0 KiB
Python
# SPDX-License-Identifier: Apache-2.0
|
|
"""Download the Terminus 12-pixel fonts that the emulator draws in: one time, only on request.
|
|
|
|
Terminus has the SIL Open Font License. Thus the repository and the wheel never carry it.
|
|
The Debian package for the Cardputer Zero carries it next to its licence, because an app
|
|
from the launcher has no terminal in which to run this download. That build also uses
|
|
this module (refer to ``scripts/cardputer-zero/build-deb.sh``). This module
|
|
downloads the upstream release and checks that it is the correct archive. Then it
|
|
extracts ``ter-u12n.bdf``, ``ter-u12b.bdf``, and the licence next to them into the
|
|
directory that the emulator reads (:func:`~.font.font_dir`). ``meshterm emulate
|
|
--fetch-fonts`` runs it.
|
|
|
|
Python can fail to download the archive, for example when a certificate store rejects the
|
|
mirror. Then you can download the archive in a different way and give it with
|
|
``--archive``. In both cases, the module checks the archive against the same digest.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import hashlib
|
|
import io
|
|
import tarfile
|
|
import urllib.request
|
|
from collections.abc import Callable
|
|
from pathlib import Path
|
|
|
|
from .font import BOLD_BDF, REGULAR_BDF, font_dir
|
|
|
|
URL = (
|
|
"https://sourceforge.net/projects/terminus-font/files/terminus-font-4.49/"
|
|
"terminus-font-4.49.1.tar.gz/download"
|
|
)
|
|
#: The SHA-256 of the release archive, so that a mirror cannot return a different file.
|
|
SHA256 = "d961c1b781627bf417f9b340693d64fc219e0113ad3a3af1a3424c7aa373ef79"
|
|
_ROOT = "terminus-font-4.49.1/"
|
|
_WANTED = (REGULAR_BDF, BOLD_BDF, "OFL.TXT")
|
|
|
|
|
|
def install_terminus(archive: Path | None = None, say: Callable[[str], None] = print) -> Path:
|
|
"""Download (or take) Terminus 4.49.1, check it, and install the fonts and the licence.
|
|
|
|
Args:
|
|
archive: The release archive, already downloaded. ``None`` downloads it.
|
|
say: Where the progress lines go.
|
|
|
|
Returns:
|
|
The directory that the fonts were installed into.
|
|
|
|
Raises:
|
|
ValueError: The archive is not the release (its digest is different), or a file
|
|
is missing from it.
|
|
OSError: The download or a write failed.
|
|
"""
|
|
target = font_dir()
|
|
if archive is not None:
|
|
say(f"installing Terminus 4.49.1 from {archive} into {target}")
|
|
data = archive.read_bytes()
|
|
else:
|
|
say(f"fetching Terminus 4.49.1 into {target}")
|
|
with urllib.request.urlopen(URL, timeout=60) as response: # noqa: S310 - fixed https URL
|
|
data = response.read()
|
|
digest = hashlib.sha256(data).hexdigest()
|
|
if digest != SHA256:
|
|
raise ValueError(f"refusing the archive: sha256 {digest} is not the release's {SHA256}")
|
|
target.mkdir(parents=True, exist_ok=True)
|
|
with tarfile.open(fileobj=io.BytesIO(data), mode="r:gz") as tar:
|
|
for name in _WANTED:
|
|
member = tar.extractfile(_ROOT + name)
|
|
if member is None:
|
|
raise ValueError(f"the archive has no {name}")
|
|
(target / name).write_bytes(member.read())
|
|
say(f" {name}")
|
|
return target
|