MeshTerm 0.3.4
Installers / windows-x64 (push) Canceled after 0s
Installers / macos-x64 (push) Canceled after 0s
Installers / macos-arm64 (push) Canceled after 0s
Installers / linux-x64 (push) Canceled after 0s
Installers / linux-arm64 (push) Canceled after 0s
GitHub release / build (push) Canceled after 0s
GitHub release / create the release (push) Canceled after 0s

The macOS installers of 0.3.3 never built: the notices step refused pyobjc-core and
pyobjc-framework-libdispatch, whose wheels ship no licence text. Their MIT text is vendored
now, and a test checks every vendored path on every platform.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
Jean-Pierre MartineauandClaude Fable 5.1 committed 2026-09-13 15:50:53 -04:00
1 parent 48f975b33b
commit bca1c83dcd
7 files changed
+76 -9

No files matched your search

+15 -1
View File
@@ -17,6 +17,19 @@ allowed to change behaviour, not just add to it.
## [Unreleased]
## [0.3.4] — 2026-09-13
### Fixed
- **The macOS installers build again.** 0.3.3's release never published: both macOS legs
stopped at the new third-party notices step, which refuses to bundle a dependency whose
wheel carries no licence text — and on macOS bleak's Bluetooth backend pulls in two such
wheels, `pyobjc-core` and `pyobjc-framework-libdispatch`. Their MIT text is vendored
beside pyserial's and pywinrt's now, verified against the wheels themselves, and a test
checks every vendored path on every platform so a gap that only one runner can hit is
caught here first. The 0.3.3 tag stands with no release behind it; this is the same
code with its installers.
## [0.3.3] — 2026-09-13
### Added
@@ -697,7 +710,8 @@ 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.3.3...HEAD
[Unreleased]: https://github.com/jpmartineau/MeshTerm/compare/v0.3.4...HEAD
[0.3.4]: https://github.com/jpmartineau/MeshTerm/releases/tag/v0.3.4
[0.3.3]: https://github.com/jpmartineau/MeshTerm/releases/tag/v0.3.3
[0.3.2]: https://github.com/jpmartineau/MeshTerm/releases/tag/v0.3.2
[0.3.1]: https://github.com/jpmartineau/MeshTerm/releases/tag/v0.3.1
+6 -6
View File
@@ -79,14 +79,14 @@ if anything goes wrong at startup the window closes before you can read why.
**Windows** — open Windows Terminal or PowerShell, `cd` to your downloads, then:
```powershell
.\meshterm-0.3.3-windows-x64.exe
.\meshterm-0.3.4-windows-x64.exe
```
**macOS and Linux** — open Terminal, `cd` to your downloads, then:
```bash
chmod +x meshterm-0.3.3-*
./meshterm-0.3.3-*
chmod +x meshterm-0.3.4-*
./meshterm-0.3.4-*
```
### A word about terminals, on Windows
@@ -124,7 +124,7 @@ becomes just `meshterm` from anywhere.
> project.
>
> - **macOS**: *"cannot be opened because the developer cannot be verified"*. Clear it with
> `xattr -d com.apple.quarantine meshterm-0.3.3-*` and run it again.
> `xattr -d com.apple.quarantine meshterm-0.3.4-*` 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.
@@ -134,10 +134,10 @@ becomes just `meshterm` from anywhere.
> MeshTerm uses that same folder. Set `MESHTERM_HOME` to try one in isolation:
>
> ```bash
> MESHTERM_HOME=~/meshterm-test ./meshterm-0.3.3-* # macOS, Linux
> MESHTERM_HOME=~/meshterm-test ./meshterm-0.3.4-* # macOS, Linux
> ```
> ```powershell
> $env:MESHTERM_HOME = "$HOME\meshterm-test"; .\meshterm-0.3.3-windows-x64.exe
> $env:MESHTERM_HOME = "$HOME\meshterm-test"; .\meshterm-0.3.4-windows-x64.exe
> ```
>
> Same variable if you run two radios and want them kept apart.
+1 -1
View File
@@ -1460,7 +1460,7 @@ each link; the scripted face prints the link alone.
**`--json`:**
```json
{"page":"discord","title":"Join Discord","version":"0.3.3","text":"Join the Discord\n Questions, ideas, bug reports, and mesh talk.\n\n • https://discord.gg/AZwe5Uvb3S","links":["https://discord.gg/AZwe5Uvb3S"]}
{"page":"discord","title":"Join Discord","version":"0.3.4","text":"Join the Discord\n Questions, ideas, bug reports, and mesh talk.\n\n • https://discord.gg/AZwe5Uvb3S","links":["https://discord.gg/AZwe5Uvb3S"]}
```
| Field | Type | Meaning |
+1 -1
View File
@@ -6,7 +6,7 @@ Supports USB, Bluetooth and TCP companion connection. For Windows, macOS and Lin
from datetime import datetime
__version__ = "0.3.3"
__version__ = "0.3.4"
__author__ = "Jean-Pierre Martineau"
#: The year MeshTerm was first published; the copyright span starts here.
+9
View File
@@ -63,8 +63,17 @@ ROOT_DISTRIBUTION = "mesh-term"
#: in a Windows build's closure. All nine are generated and published together by the
#: pywinrt project and share the one upstream license file, which none of their
#: wheels include.
#: * ``pyobjc-core`` and ``pyobjc-framework-libdispatch`` — two of the four pyobjc
#: packages bleak's macOS BLE backend (``bleak.backends.corebluetooth``) pulls in on
#: ``sys_platform == "darwin"``, so they only appear in a macOS build's closure, which
#: is where the 0.3.3 release build caught them. Their 12.2.2 wheels ship no license
#: file; the other two (Cocoa, CoreBluetooth) do, and are read from their dist-info
#: like everything else. All four come from the one pyobjc repository and its single
#: MIT text.
_VENDORED_LICENSE_GAPS: dict[str, tuple[str, ...]] = {
"pyserial": ("vendored-licenses/pyserial-LICENSE.txt",),
"pyobjc-core": ("vendored-licenses/pyobjc-LICENSE.txt",),
"pyobjc-framework-libdispatch": ("vendored-licenses/pyobjc-LICENSE.txt",),
"winrt-runtime": ("vendored-licenses/pywinrt-LICENSE.txt",),
"winrt-windows-devices-bluetooth": ("vendored-licenses/pywinrt-LICENSE.txt",),
"winrt-windows-devices-bluetooth-advertisement": ("vendored-licenses/pywinrt-LICENSE.txt",),
@@ -0,0 +1,28 @@
Vendored by packaging/notices.py -- not part of any pyobjc distribution.
Two pyobjc wheels on PyPI ship no license file of any kind: pyobjc-core 12.2.2 and
pyobjc-framework-libdispatch 12.2.2 carry an MIT license classifier and nothing matching
LICENSE*, LICENCE*, COPYING*, or NOTICE* in their dist-info -- verified by inspecting the
macOS universal2 wheels directly (the two sibling wheels bleak also pulls in,
pyobjc-framework-Cocoa and pyobjc-framework-CoreBluetooth, do carry licenses/LICENSE.txt
and are read from there). First caught by the macOS legs of the 0.3.3 release build, which
refused to bundle them unnoticed; they only appear in a macOS build's closure, since bleak
marks them sys_platform == "darwin".
All pyobjc packages are built and published together from the one pyobjc repository and
share its single license text, reproduced below unmodified. Pulled 2026-09-13 from:
https://raw.githubusercontent.com/ronaldoussoren/pyobjc/master/pyobjc-core/License.txt
Its copyright range (2003-2025) covers the pinned 12.2.2 release.
----------------------------------------------------------------------------------------
(This is the MIT license, note that libffi-src is a separate product with its own license)
Copyright 2002, 2003 - Bill Bumgarner, Ronald Oussoren, Steve Majewski, Lele Gaifax, et.al.
Copyright 2003-2025 - Ronald Oussoren
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+16
View File
@@ -146,3 +146,19 @@ def test_write_third_party_notices_writes_utf8_lf(tmp_path: Path) -> None:
raw = out.read_bytes()
assert b"\r\n" not in raw
assert raw.decode("utf-8") == notices.render(notices.collect_notices())
def test_every_vendored_license_gap_has_its_file() -> None:
"""A gap-table entry whose file is missing would fail only on the platform that hits it.
The pyobjc entries are exercised by a macOS build alone and the winrt ones by a
Windows build alone, so a typo in a path would surface on a release runner rather
than here. Check every entry on every platform: the file exists, is non-empty, and
the key is in the canonical (lowercase, hyphenated) form ``collect_notices`` looks up.
"""
for name, paths in notices._VENDORED_LICENSE_GAPS.items():
assert name == name.lower().replace("_", "-"), name
for rel in paths:
path = Path(notices.__file__).parent / rel
assert path.is_file(), f"{name}: {rel} is missing"
assert path.read_text(encoding="utf-8").strip(), f"{name}: {rel} is empty"