Files
MeshTerm/pyproject.toml
T
Jean-Pierre MartineauandClaude Fable 5.1 8b80a88f03 The sdist is the package's source, not the repository's
Hatchling's default sdist is everything git does not ignore, which packed the
Claude skills, the GitHub configuration, the PyInstaller spec, the device-side
scripts and the developer environment template into an archive whose only job
is to build and test the wheel. An exclude list keeps the package, the tests
and their fixture, the manual and the files a build reads. The build backend
floor is hatchling 1.26, the first to write the PEP 639 licence fields into the
metadata; an older one built a wheel that said nothing about the licence.
Workflow comments that reasoned from a private repo's metered minutes are
reworded for the public one, a skill's usage line stops naming one machine's
venv, and the scheduler's lock file is ignored in the tree rather than only in
one clone's info/exclude.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-12 19:02:02 -04:00

124 lines
5.2 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-based MeshCore client for your terminal. Supports USB, Bluetooth and TCP companion connection. 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",
"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)
"PyYAML>=6.0", # the preferences file (meshterm.core.preferences)
"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 for 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",
]
[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/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"]