Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9b2c5527f8 | ||
|
|
141698678e | ||
|
|
8cc1cae213 |
No files matched your search
@@ -111,5 +111,9 @@ jobs:
|
||||
run: |
|
||||
python -m venv /tmp/fresh
|
||||
/tmp/fresh/bin/pip install --quiet dist/*.whl
|
||||
cd /tmp && /tmp/fresh/bin/meshterm --help > /dev/null
|
||||
echo "the wheel installs and the console script runs"
|
||||
cd /tmp
|
||||
/tmp/fresh/bin/meshterm --help > /dev/null
|
||||
# A tool-provided subcommand, not just --help: the tools are discovered at
|
||||
# runtime, so a broken package still answers --help perfectly well.
|
||||
/tmp/fresh/bin/meshterm contacts --help > /dev/null
|
||||
echo "the wheel installs, the console script runs, and its tools registered"
|
||||
@@ -78,8 +78,14 @@ jobs:
|
||||
# source tree fails here rather than on someone's laptop.
|
||||
cd "$(mktemp -d)"
|
||||
"$GITHUB_WORKSPACE/$bin" --help > /dev/null
|
||||
# Reads the asset files, so a bundle missing its pages fails here.
|
||||
"$GITHUB_WORKSPACE/$bin" specimen > /dev/null
|
||||
echo "runs, and finds its assets"
|
||||
# And a tool-provided subcommand, which is the check that matters. Every tool is
|
||||
# found at runtime by `pkgutil.iter_modules`, so a bundle that omits them still
|
||||
# starts, still prints help, still draws the specimen — and has an empty menu
|
||||
# with nothing in it but Quit. `--help` passing proves almost nothing on its own.
|
||||
"$GITHUB_WORKSPACE/$bin" contacts --help > /dev/null
|
||||
echo "runs, finds its assets, and its tools registered"
|
||||
|
||||
- name: Name it after the version and the platform
|
||||
shell: bash
|
||||
|
||||
+29
-1
@@ -7,8 +7,35 @@ numbers follow [Semantic Versioning](https://semver.org/spec/v2.0.0.html) — wi
|
||||
SemVer itself makes for a leading zero: while the major version is `0`, a **minor** bump is
|
||||
allowed to change behaviour, not just add to it.
|
||||
|
||||
<!--
|
||||
At 0.9.0 — the first public release — everything below collapses into a single entry
|
||||
reading "first public release", with the headline features under it. Nobody arriving at
|
||||
a project on its launch day wants a changelog of the fortnight before it: the versions
|
||||
under 0.9.0 were never released anywhere, and their entries are notes to ourselves about
|
||||
getting ready. Keep the dates and the tags; replace the prose.
|
||||
-->
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## [0.2.2] — 2026-09-07
|
||||
|
||||
### Fixed
|
||||
|
||||
- **The downloadable builds were missing every tool.** They started, printed help and drew
|
||||
the specimen card, and had a menu with nothing in it but Quit — no contacts, no map, no
|
||||
trace, no chat. Tools are found at runtime with `pkgutil.iter_modules`, which finds
|
||||
nothing inside a frozen bundle, so none of them registered. The packaging now collects
|
||||
them, and the smoke tests run a tool-provided subcommand instead of only `--help`, which
|
||||
a gutted build passes perfectly well.
|
||||
|
||||
### Added
|
||||
|
||||
- `MESHTERM_HOME` points config and data somewhere other than `~/.meshterm`. Every copy of
|
||||
MeshTerm shared one directory, so trying a downloaded build meant letting it open the
|
||||
same history database as the one you use — the valuable half of an install, with no way
|
||||
to keep a second copy away from it. Also useful for a portable install, or two radios
|
||||
kept apart.
|
||||
|
||||
## [0.2.1] — 2026-09-07
|
||||
|
||||
### Fixed
|
||||
@@ -83,6 +110,7 @@ deliberately not reconstructed here.
|
||||
- Two `TYPE_CHECKING` imports the test suite referenced but never imported, on paths that
|
||||
happened never to run.
|
||||
|
||||
[Unreleased]: https://github.com/jpmartineau/MeshTerm/compare/v0.2.1...HEAD
|
||||
[Unreleased]: https://github.com/jpmartineau/MeshTerm/compare/v0.2.2...HEAD
|
||||
[0.2.2]: https://github.com/jpmartineau/MeshTerm/releases/tag/v0.2.2
|
||||
[0.2.1]: https://github.com/jpmartineau/MeshTerm/releases/tag/v0.2.1
|
||||
[0.2.0]: https://github.com/jpmartineau/MeshTerm/tree/v0.2.0
|
||||
@@ -58,22 +58,51 @@ your mesh's history is worth.
|
||||
### Download a build
|
||||
|
||||
**[⬇ Latest release](https://github.com/jpmartineau/MeshTerm/releases/latest)** — one file,
|
||||
no Python needed. Windows, macOS (Apple silicon) and Linux (x64 and ARM64, so the uConsole
|
||||
is covered).
|
||||
no Python needed. Windows, macOS (Intel and Apple silicon), and Linux (x64 and ARM64, so
|
||||
the uConsole is covered).
|
||||
|
||||
Download it, make it runnable, and run it:
|
||||
MeshTerm is a terminal program, so **open a terminal and run it from there.** You can
|
||||
double-click it and it will work, but you'll get whatever console your system picks, and
|
||||
if anything goes wrong at startup the window closes before you can read why.
|
||||
|
||||
```bash
|
||||
chmod +x meshterm-* # macOS and Linux only
|
||||
./meshterm-*
|
||||
**Windows** — open Windows Terminal or PowerShell, `cd` to your downloads, then:
|
||||
|
||||
```powershell
|
||||
.\meshterm-0.2.2-windows-x64.exe
|
||||
```
|
||||
|
||||
> **Your system will complain the first time.** These builds aren't code-signed — signing
|
||||
> costs money on both platforms and this is a free side project. macOS says *"cannot be
|
||||
> opened because the developer cannot be verified"*; clear it with
|
||||
> `xattr -d com.apple.quarantine meshterm-*` and run it again. Windows shows *"Windows
|
||||
> protected your PC"*; click **More info → Run anyway**. Each release ships a `SHA256SUMS`
|
||||
> file if you'd rather check the download yourself.
|
||||
**macOS and Linux** — open Terminal, `cd` to your downloads, then:
|
||||
|
||||
```bash
|
||||
chmod +x meshterm-0.2.2-*
|
||||
./meshterm-0.2.2-*
|
||||
```
|
||||
|
||||
Rename it to something you don't mind typing and put it somewhere on your `PATH`, and it
|
||||
becomes just `meshterm` from anywhere.
|
||||
|
||||
> **Your system will complain the first time, and it's right to.** These builds aren't
|
||||
> code-signed — signing costs real money on both platforms and this is a free side
|
||||
> project.
|
||||
>
|
||||
> - **macOS**: *"cannot be opened because the developer cannot be verified"*. Clear it with
|
||||
> `xattr -d com.apple.quarantine meshterm-0.2.2-*` and run it again.
|
||||
> - **Windows**: *"Windows protected your PC"*. Click **More info → Run anyway**.
|
||||
>
|
||||
> Every release ships a `SHA256SUMS` file if you'd rather check the download first.
|
||||
|
||||
> **Trying a build without touching your real data.** MeshTerm keeps everything in
|
||||
> `~/.meshterm` — your history database, contacts, channel keys — and *every* copy of
|
||||
> MeshTerm uses that same folder. Set `MESHTERM_HOME` to try one in isolation:
|
||||
>
|
||||
> ```bash
|
||||
> MESHTERM_HOME=~/meshterm-test ./meshterm-0.2.2-* # macOS, Linux
|
||||
> ```
|
||||
> ```powershell
|
||||
> $env:MESHTERM_HOME = "$HOME\meshterm-test"; .\meshterm-0.2.2-windows-x64.exe
|
||||
> ```
|
||||
>
|
||||
> Same variable if you run two radios and want them kept apart.
|
||||
|
||||
### Or install with pip
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ Supports USB, Bluetooth and TCP companion connection. For Windows, macOS and Lin
|
||||
|
||||
from datetime import datetime
|
||||
|
||||
__version__ = "0.2.1"
|
||||
__version__ = "0.2.2"
|
||||
__author__ = "Jean-Pierre Martineau"
|
||||
|
||||
#: The year MeshTerm was first published; the copyright span starts here.
|
||||
|
||||
+19
-2
@@ -15,6 +15,7 @@ keys used to sit in this file with no screen behind them.
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
import sys
|
||||
from dataclasses import dataclass, field
|
||||
from pathlib import Path
|
||||
@@ -26,15 +27,31 @@ else: # pragma: no cover - exercised only on 3.10
|
||||
import tomli as tomllib
|
||||
|
||||
|
||||
#: Points MeshTerm's config and data somewhere other than the home directory. For trying a
|
||||
#: build without letting it near a real history, for a portable install on a stick, and for
|
||||
#: running two radios out of two directories. Read every time rather than cached, so a test
|
||||
#: can move it between cases.
|
||||
CONFIG_DIR_ENV = "MESHTERM_HOME"
|
||||
|
||||
|
||||
def default_config_dir() -> Path:
|
||||
"""Return the directory MeshTerm uses for config and data.
|
||||
|
||||
Resolves to ``.meshterm`` under the OS-defined home directory (``%USERPROFILE%``
|
||||
on Windows, ``$HOME`` on Unix), as reported by :meth:`Path.home`.
|
||||
``$MESHTERM_HOME`` wins if it is set and not empty. Otherwise this resolves to
|
||||
``.meshterm`` under the OS-defined home directory (``%USERPROFILE%`` on Windows,
|
||||
``$HOME`` on Unix), as reported by :meth:`Path.home`.
|
||||
|
||||
The override exists because the database is the valuable part of an install — a
|
||||
running record of everything the radio has overheard — and there was no way to point a
|
||||
second copy of MeshTerm at a different one. A downloaded build would happily open the
|
||||
same 34MB file as the checkout it was built from.
|
||||
|
||||
Returns:
|
||||
The resolved configuration directory path (not guaranteed to exist).
|
||||
"""
|
||||
override = os.environ.get(CONFIG_DIR_ENV, "").strip()
|
||||
if override:
|
||||
return Path(override).expanduser()
|
||||
return Path.home() / ".meshterm"
|
||||
|
||||
|
||||
|
||||
@@ -18,6 +18,11 @@ datas = [
|
||||
]
|
||||
|
||||
hiddenimports = [
|
||||
# Every tool module. `meshterm.tools` finds these with `pkgutil.iter_modules` at
|
||||
# import time, so nothing static ever names one, and a frozen build without this line
|
||||
# starts with an empty registry: no menu entries but Quit, and no CLI subcommands.
|
||||
# The app launches and looks like it works, which is the worst way for this to fail.
|
||||
*collect_submodules("meshterm.tools"),
|
||||
# bleak picks its backend at runtime by platform, so static analysis never sees the
|
||||
# one that actually gets used. Collect all of them and let the unused ones sit.
|
||||
*collect_submodules("bleak.backends"),
|
||||
|
||||
+30
-1
@@ -8,7 +8,9 @@ from __future__ import annotations
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
from meshterm.core.config import Settings
|
||||
import pytest
|
||||
|
||||
from meshterm.core.config import CONFIG_DIR_ENV, Settings, default_config_dir
|
||||
|
||||
|
||||
def test_connect_on_start_defaults_true() -> None:
|
||||
@@ -42,3 +44,30 @@ def test_tcp_profile_defaults_port(tmp_path: Path) -> None:
|
||||
config.write_text('[profiles.wifi]\nhost = "meshcore.local"\n', encoding="utf-8")
|
||||
profile = Settings.load(config).profiles["wifi"]
|
||||
assert profile.is_tcp and profile.tcp_endpoint == "meshcore.local:5000"
|
||||
|
||||
|
||||
def test_config_dir_defaults_to_the_home_directory(monkeypatch: pytest.MonkeyPatch) -> None:
|
||||
"""With no override set, config and data live in ``.meshterm`` under the user's home."""
|
||||
monkeypatch.delenv(CONFIG_DIR_ENV, raising=False)
|
||||
assert default_config_dir() == Path.home() / ".meshterm"
|
||||
|
||||
|
||||
def test_config_dir_follows_the_override(monkeypatch: pytest.MonkeyPatch, tmp_path: Path) -> None:
|
||||
"""``$MESHTERM_HOME`` moves the whole directory, so a build can run beside a real one.
|
||||
|
||||
This is what keeps a downloaded binary from opening the same database as the checkout
|
||||
it was built from — the history is the valuable half of an install, and there was no
|
||||
way to point a second copy somewhere else.
|
||||
"""
|
||||
monkeypatch.setenv(CONFIG_DIR_ENV, str(tmp_path / "elsewhere"))
|
||||
assert default_config_dir() == tmp_path / "elsewhere"
|
||||
|
||||
|
||||
def test_config_dir_ignores_an_empty_override(monkeypatch: pytest.MonkeyPatch) -> None:
|
||||
"""An unset-but-present or whitespace value falls back rather than resolving to nowhere.
|
||||
|
||||
A shell that exports the variable empty is common enough that treating "" as "put the
|
||||
data in the current directory" would be a nasty way to scatter someone's history.
|
||||
"""
|
||||
monkeypatch.setenv(CONFIG_DIR_ENV, " ")
|
||||
assert default_config_dir() == Path.home() / ".meshterm"
|
||||
Reference in new issue
Block a user