Files
MeshTerm/pyproject.toml
T
Jean-Pierre MartineauandClaude Opus 5.5 e6f6cf2621 The README and the project documents are in ASD-STE100
The README, CONTRIBUTING, SECURITY, the docs index, the development
documents, the script READMEs, the comments of config.example.toml and
pyproject.toml, and the issue and pull request forms. The legal sections
of the README (attribution and licence) stay exactly as they were, between
ste: off and ste: on markers. The SignPath attribution line, the one-line
description of MeshTerm, every code block, and every URL do not change.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-06 21:44:55 -04:00

137 lines
5.9 KiB
TOML

[build-system]
# Hatchling 1.26 is the first version that writes the PEP 639 fields below
# (`License-Expression`, `License-File`) into the metadata. An older version builds a
# wheel that says nothing about the licence, and it gives no warning.
requires = ["hatchling>=1.26"]
build-backend = "hatchling.build"
[project]
# This is only the name of the distribution. The import package and the console script stay
# `meshterm`. PyPI prohibits that name (refer to pypi/support#12162), but the app does not
# change because of this. The `[tool.hatch.build.targets.wheel]` section below makes the
# wheel contain 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"]
# There is no `License ::` entry, because PEP 639 does not permit one with 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. The 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",
# The version is pinned to one minor line. A formatter that is different on different
# machines is not a gate. Ruff 0.16 formats Python inside Markdown and 0.15 does not.
# With an unpinned `ruff>=0.4`, CI and a laptop disagreed about a tree with no errors.
"ruff>=0.16.6,<0.17",
# The node of the SPI radio. tests/test_radionode_live.py runs it with a fake radio.
# The library alone is pure Python on all systems. Only the `hardware` extra needs Linux.
"openhop-core>=1.1.3",
]
# A LoRa chip on this machine's own SPI bus (the uConsole AIO). A node that MeshTerm runs
# itself controls it (refer to meshterm/core/spiradio.py). It works only on Linux, so
# the other systems do not need it.
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"
# This is the one place where we write the version. `[project] version` is dynamic, so the
# package attribute and the distribution metadata cannot become different.
[tool.hatch.version]
path = "meshterm/__init__.py"
[tool.hatch.build.targets.wheel]
packages = ["meshterm"]
# The sdist is the source of the package. It is not the source of the repository. It has
# what a person needs to build and test the wheel. By default, Hatchling includes each file
# that git does not ignore. This included the Claude skills, the GitHub configuration, the
# PyInstaller spec, the shell scripts for the device (one of which has data under another
# licence), and the template of the developer environment. None of these builds, tests, or
# documents the package. The sdist keeps the package, the tests and their fixture, the
# manual, and the files that 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"
# The helper scripts for the Claude skills are not part of the package. Also exclude `docs/`.
# It has survey documents with dates. Ruff formats Python blocks inside Markdown, and the
# code in these documents is an excerpt that shows how a file looked on a past date. If
# ruff formats a quotation, it changes the record. The excerpts are fragments of calls and
# not complete programs. Thus the formatter would change them into something that never
# existed.
extend-exclude = [".claude", "docs"]
[tool.ruff.lint]
select = ["E", "F", "I", "UP", "B", "D"]
ignore = ["D203", "D213"] # select one style for the blank line before a class and for the multi-line summary
[tool.ruff.lint.pydocstyle]
convention = "google"
[tool.ruff.lint.flake8-bugbear]
# Typer declares CLI parameters when the default value calls these functions. The objects
# that they return are inert markers, and the command never changes them. B008 guards
# against this kind of change.
extend-immutable-calls = ["typer.Argument", "typer.Option"]
[tool.pytest.ini_options]
asyncio_mode = "auto"
testpaths = ["tests"]