docs/ was one flat folder: the user guides, the CLI manual, the device manuals, the code notes and an old survey side by side. It is now guide/ (features, configuration, connecting, terminals), cli/ (the manual as its README, the cookbook), devices/ (which manual is yours as its README, then one per device) and development/ (architecture, the survey); screenshots/ stays put. The index follows the folders. The device manuals are named for the device they are about: the PicoCalc's is picocalc-lyra.md, since MeshTerm runs on the PicoCalc's Luckfox Lyra core and on none of the others, and the uConsole's stays uconsole.md, since its CM4 and CM5 run it alike. A new cardputer-zero.md opens on a warning that the device is not supported yet, says what has been built and tested only in the simulator, and how to try it there. Every relative link was resolved from where it was written and rewritten from where it now lives, and the repo-root spellings in code, config and the release skill moved with them; the changelog's GitHub URLs too. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
133 lines
5.6 KiB
TOML
133 lines
5.6 KiB
TOML
[build-system]
|
|
# 1.26 is where hatchling started writing the PEP 639 fields below (`License-Expression`,
|
|
# `License-File`) into the metadata; an older one builds a wheel that says nothing about
|
|
# the licence at all, silently.
|
|
requires = ["hatchling>=1.26"]
|
|
build-backend = "hatchling.build"
|
|
|
|
[project]
|
|
# The distribution name only. The import package and the console script both stay
|
|
# `meshterm` — PyPI prohibits that name (see pypi/support#12162), and nothing about the
|
|
# app changes because of it. `[tool.hatch.build.targets.wheel]` below is what keeps the
|
|
# wheel shipping the `meshterm/` package under this different name.
|
|
name = "mesh-term"
|
|
dynamic = ["version"]
|
|
description = "MeshTerm is a full-featured TUI MeshCore client for your terminal. Connects to a companion over USB, Bluetooth, or TCP. For Windows, macOS, and Linux."
|
|
readme = "README.md"
|
|
requires-python = ">=3.10"
|
|
authors = [{ name = "Jean-Pierre Martineau" }]
|
|
license = "Apache-2.0"
|
|
license-files = ["LICENSE", "NOTICE"]
|
|
keywords = ["meshcore", "lora", "mesh", "radio", "cli"]
|
|
# No `License ::` entry: PEP 639 forbids one alongside the SPDX expression above.
|
|
classifiers = [
|
|
"Development Status :: 4 - Beta",
|
|
"Environment :: Console",
|
|
"Intended Audience :: End Users/Desktop",
|
|
"Operating System :: MacOS",
|
|
"Operating System :: Microsoft :: Windows",
|
|
"Operating System :: POSIX :: Linux",
|
|
"Programming Language :: Python :: 3.10",
|
|
"Programming Language :: Python :: 3.11",
|
|
"Programming Language :: Python :: 3.12",
|
|
"Programming Language :: Python :: 3.13",
|
|
"Programming Language :: Python :: 3.14",
|
|
"Programming Language :: Python :: 3.14",
|
|
"Topic :: Communications :: Ham Radio",
|
|
"Topic :: System :: Networking",
|
|
]
|
|
|
|
dependencies = [
|
|
"meshcore>=2.3", # companion-device protocol (serial/BLE/TCP)
|
|
"pycryptodome>=3.20", # AES/HMAC for decrypting overheard channel packets
|
|
"pyserial>=3.5", # serial-port enumeration for device discovery
|
|
"bleak>=0.22", # Bluetooth LE scanning + companion connection
|
|
"typer>=0.12", # scripted CLI; subcommands mirror the menu
|
|
"rich>=13.7", # modern console rendering (progress, tables, panels)
|
|
"markdown-it-py>=3.0", # CommonMark parser behind the written About pages
|
|
"prompt_toolkit>=3.0", # full-screen interactive TUI (terminal, input, resize)
|
|
"segno>=1.6", # pure-Python QR codes (channel share links)
|
|
"tomli>=2.0; python_version < '3.11'", # TOML config reader on 3.10
|
|
"tomli-w>=1.0", # TOML writer: preferences and device-config backups
|
|
]
|
|
|
|
[project.optional-dependencies]
|
|
dev = [
|
|
"pytest>=8.0",
|
|
"pytest-asyncio>=0.23",
|
|
# Pinned to a minor line, not floated. A formatter that drifts between machines is
|
|
# not a gate: 0.16 formats Python inside Markdown and 0.15 does not, so an
|
|
# unpinned `ruff>=0.4` had CI and a laptop disagreeing about a clean tree.
|
|
"ruff>=0.16.6,<0.17",
|
|
# The SPI radio's node, run for real in tests/test_radionode_live.py on a fake radio.
|
|
# The bare library is pure Python everywhere; only the `hardware` extra is Linux-bound.
|
|
"openhop-core>=1.1.3",
|
|
]
|
|
# A LoRa chip on this machine's own SPI bus (the uConsole AIO), driven by a node MeshTerm
|
|
# runs itself — see meshterm/core/spiradio.py. Linux only, and nowhere else worth carrying.
|
|
spi = [
|
|
"openhop-core[hardware]>=1.1.3",
|
|
]
|
|
|
|
[project.urls]
|
|
Homepage = "https://github.com/jpmartineau/MeshTerm"
|
|
Repository = "https://github.com/jpmartineau/MeshTerm"
|
|
Issues = "https://github.com/jpmartineau/MeshTerm/issues"
|
|
Changelog = "https://github.com/jpmartineau/MeshTerm/blob/main/CHANGELOG.md"
|
|
|
|
[project.scripts]
|
|
meshterm = "meshterm.cli:main"
|
|
|
|
# The one place a version is written; `[project] version` is dynamic so the package
|
|
# attribute and the distribution metadata cannot drift apart.
|
|
[tool.hatch.version]
|
|
path = "meshterm/__init__.py"
|
|
|
|
[tool.hatch.build.targets.wheel]
|
|
packages = ["meshterm"]
|
|
|
|
# The sdist is the package's source, not the repository's: what someone needs to build
|
|
# and test the wheel. Hatchling's default is everything git does not ignore, which swept
|
|
# in the Claude skills, the GitHub configuration, the PyInstaller spec, the device-side
|
|
# shell scripts (one of which carries data under another licence) and the developer
|
|
# environment template — none of which builds, tests, or documents the package. Kept:
|
|
# the package, the tests and their fixture, the manual, and the files a build reads.
|
|
[tool.hatch.build.targets.sdist]
|
|
exclude = [
|
|
"/.claude",
|
|
"/.github",
|
|
"/.dev.env.example",
|
|
"/.git-blame-ignore-revs",
|
|
"/.gitattributes",
|
|
"/CLAUDE.md",
|
|
"/docs/development/survey-*.md",
|
|
"/packaging",
|
|
"/scripts",
|
|
]
|
|
|
|
[tool.ruff]
|
|
line-length = 100
|
|
target-version = "py310"
|
|
# Helper scripts for the Claude skills; they are not part of the package. And `docs/`,
|
|
# which holds dated survey documents: ruff formats Python blocks inside Markdown, and the
|
|
# code they quote is an excerpt of how a file looked on a past date. Reformatting a
|
|
# quotation edits the record — and the excerpts are call fragments, not whole programs, so
|
|
# the formatter's idea of "fixed" turns them into something that was never there.
|
|
extend-exclude = [".claude", "docs"]
|
|
|
|
[tool.ruff.lint]
|
|
select = ["E", "F", "I", "UP", "B", "D"]
|
|
ignore = ["D203", "D213"] # pick one blank-line-before-class / multi-line-summary style
|
|
|
|
[tool.ruff.lint.pydocstyle]
|
|
convention = "google"
|
|
|
|
[tool.ruff.lint.flake8-bugbear]
|
|
# Typer declares CLI parameters by calling these in the default; the objects they
|
|
# return are inert sentinels the command never mutates, which is what B008 guards.
|
|
extend-immutable-calls = ["typer.Argument", "typer.Option"]
|
|
|
|
[tool.pytest.ini_options]
|
|
asyncio_mode = "auto"
|
|
testpaths = ["tests"]
|