-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathpyproject.toml
More file actions
215 lines (193 loc) · 7.89 KB
/
Copy pathpyproject.toml
File metadata and controls
215 lines (193 loc) · 7.89 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
[project]
name = "rigplane"
version = "2.11.1"
description = "Multi-vendor radio control library and Web UI with native providers and planned Hamlib-backed CAT coverage"
readme = "README.md"
license = "MIT"
requires-python = ">=3.11"
dependencies = [
"aiohttp>=3.13.3",
"pyserial>=3.5",
"pyserial-asyncio>=0.6",
"opuslib",
"sounddevice",
"numpy",
"platformdirs>=4.2",
]
authors = [
{ name = "Sergey Morozik", email = "morozsm@gmail.com" },
]
keywords = ["rigplane", "ham-radio", "amateur-radio", "transceiver", "icom", "yaesu", "xiegu", "lab599", "ci-v", "cat", "rigctld", "ic-7610", "ic-7300", "ic-705", "ftx-1"]
classifiers = [
"Development Status :: 5 - Production/Stable",
"Intended Audience :: Developers",
"License :: OSI Approved :: MIT License",
"Topic :: Communications :: Ham Radio",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
]
[project.urls]
Homepage = "https://rigplane.dev/"
Documentation = "https://rigplane.dev/"
Repository = "https://github.com/rigplane/rigplane-core"
Issues = "https://github.com/rigplane/rigplane-core/issues"
[project.scripts]
rigplane = "rigplane.cli:main"
# Deprecated alias of `rigplane` — prints DeprecationWarning then forwards.
icom-lan = "icom_lan._cli_shim:main"
[project.optional-dependencies]
# `audio` and `bridge` extras are kept as no-op aliases for backwards
# compatibility — `opuslib`, `sounddevice`, and `numpy` are now part of
# the core dependencies (#1090). New users should run `pip install rigplane`.
audio = []
bridge = []
scope = [
"pillow>=10.0",
]
dsp = ["scipy>=1.11"]
webrtc = ["aiortc>=1.9"]
tls = ["cryptography>=41.0"]
# Dev/build-only: pydantic drives the public-state JSON-Schema → TypeScript
# codegen (MOR-881). It must NEVER enter the runtime `dependencies` above —
# core stays zero-runtime-dep. Only the conformance test and the
# `scripts/gen_state_types.py` generator import it; `state_schema.py` is never
# imported on the live request path.
# `jsonschema` drives the consumer-driven contract (CDC) runner (MOR-883):
# `scripts/run_consumer_contracts.py` validates the real producer artifacts
# against consumer-authored expectations. Like `pydantic`, it is DEV/CI-only and
# must NEVER enter the runtime `dependencies` above — core stays zero-runtime-dep.
# Only the runner and its conformance test import it.
codegen = ["pydantic>=2.13,<3", "jsonschema>=4.0"]
dev = ["pytest", "pytest-asyncio", "pytest-cov", "pytest-timeout", "pytest-xdist", "ruff", "mypy", "pydantic>=2.13,<3", "jsonschema>=4.0"]
[dependency-groups]
dev = [
"import-linter>=2.0,<3",
"mkdocs-material>=9.7.3",
"mkdocstrings[python]>=1.0.3",
"mypy>=1.18.1",
# Dev/build-only — drives MOR-881 state-payload codegen + conformance test.
# NOT a runtime dependency (core stays zero-runtime-dep).
"pydantic>=2.13,<3",
# Dev/build-only — drives the MOR-883 consumer-driven contract runner.
# NOT a runtime dependency (core stays zero-runtime-dep).
"jsonschema>=4.0",
"pytest>=8.0",
"pytest-asyncio>=1.3.0",
"pytest-cov>=7.0.0",
"pytest-timeout>=2.0",
"pytest-xdist>=3.6",
"ruff>=0.15.2",
"types-pyserial>=3.5",
]
[tool.hatch.build.targets.wheel]
packages = ["src/rigplane", "src/icom_lan"]
# The web UI is placed at src/rigplane/web/static exclusively via the custom
# build hook's force-include (see hatch_build.py). When building a wheel from an
# sdist (uv build's default sdist->wheel chain), the sdist has already
# materialized src/rigplane/web/static on disk; exclude it from normal project
# file selection so the force-include is the single source and the tree is not
# bundled twice.
exclude = ["src/rigplane/web/static"]
[tool.hatch.build.targets.wheel.force-include]
"rigs" = "rigplane/rigs"
# Builds the Svelte web UI during packaging (if not prebuilt) and force-includes
# the result at src/rigplane/web/static for BOTH wheel and sdist targets, so
# source/git installs are self-contained. See hatch_build.py.
[tool.hatch.build.hooks.custom]
path = "hatch_build.py"
[tool.pytest.ini_options]
asyncio_mode = "auto"
asyncio_default_fixture_loop_scope = "function"
markers = [
"integration: tests requiring real radio hardware (skip if not configured)",
"hardware: opt-in tests that may key a real transmitter or require attached devices",
"e2e: end-to-end tests for PCM API and CLI audio workflows",
"slow: marks tests as slow (deselect with '-m \"not slow\"')",
"validation_hardware: real-radio validation runs; requires explicit env opt-in",
]
testpaths = ["tests"]
python_files = ["test_*.py"]
python_classes = ["Test*"]
python_functions = ["test_*"]
addopts = "-v --tb=short -m 'not slow'"
[tool.ruff]
target-version = "py311"
[tool.ruff.lint]
select = ["E4", "E7", "E9", "F", "TID251"]
[tool.ruff.lint.per-file-ignores]
"tests/*" = ["TID251"]
# Build/codegen scripts may import tier-3 internals (e.g. the state-payload
# schema for TypeScript codegen, MOR-881). They are dev/build-only, never
# shipped in the wheel.
"scripts/**" = ["TID251"]
# CLI is the orchestrator that composes tier-3 web and rigctld servers (issue-blessed).
"src/rigplane/cli/**" = ["TID251"]
# Package entry point dispatches to cli.main.
"src/rigplane/__main__.py" = ["TID251"]
# Backwards-compat shim — re-exports rigplane internals; banned-imports
# checks for tier-3 boundaries don't apply to a deprecated alias package.
"src/icom_lan/**" = ["TID251", "F401", "F403"]
[tool.ruff.lint.flake8-tidy-imports.banned-api]
"rigplane.radio.IcomRadio".msg = "Use radio_protocol.Radio in web/ modules (and capability protocols) instead of IcomRadio."
"rigplane.web".msg = "tier 3 — internal; do not import outside web/ subtree (tests are exempt)."
"rigplane.rigctld".msg = "tier 3 — internal; do not import outside rigctld/ subtree (tests are exempt)."
"rigplane.cli".msg = "tier 3 — internal; do not import outside cli + tests."
[tool.mypy]
python_version = "3.11"
follow_imports = "skip"
# Backwards-compat shim — pure re-export façade, no semantic content to type-check.
[[tool.mypy.overrides]]
module = ["icom_lan", "icom_lan.*"]
follow_imports = "skip"
warn_unused_ignores = false
[[tool.mypy.overrides]]
module = ["rigplane.web.*"]
strict = true
follow_imports = "skip"
warn_unused_ignores = false
# Codegen-only contract schema (MOR-881). Under the global ``follow_imports =
# skip`` policy pydantic's ``BaseModel`` resolves to ``Any``, so strict mypy
# reports "cannot subclass BaseModel (has type Any)". The module is dev/build-
# only (never on the runtime import path) and is covered by the conformance
# test + the codegen drift gate, so suppress that single ``misc`` diagnostic
# rather than wiring the pydantic mypy plugin into the strict web boundary.
[[tool.mypy.overrides]]
module = ["rigplane.web.state_schema"]
disable_error_code = ["misc"]
[[tool.mypy.overrides]]
module = ["cryptography", "cryptography.*"]
ignore_missing_imports = true
[[tool.mypy.overrides]]
module = ["scipy", "scipy.*"]
ignore_missing_imports = true
# ``Pillow`` is an optional dep behind ``[scope]``; suppress the missing-stubs
# error so ``mypy src/`` is clean regardless of whether Pillow is installed.
[[tool.mypy.overrides]]
module = ["PIL", "PIL.*"]
ignore_missing_imports = true
# Audio / DSP deps without published type stubs. ``numpy``, ``sounddevice``
# and ``opuslib`` ship with the core install since #1090; ``scipy`` is still
# behind the ``[dsp]`` extra. Ignore missing stubs so mypy runs cleanly.
[[tool.mypy.overrides]]
module = [
"numpy",
"numpy.*",
"sounddevice",
"sounddevice.*",
"opuslib",
"opuslib.*",
]
ignore_missing_imports = true
[[tool.mypy.overrides]]
module = [
"rigplane.cli",
"rigplane.web.radio_poller",
"rigplane.web.handlers.control",
"rigplane.rigctld.routing",
"rigplane.rigctld.handler",
]
disable_error_code = ["attr-defined"]