pgntui 0.2.1__tar.gz → 0.2.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {pgntui-0.2.1 → pgntui-0.2.2}/PKG-INFO +1 -1
- {pgntui-0.2.1 → pgntui-0.2.2}/packaging/homebrew/pgntui.rb +1 -1
- {pgntui-0.2.1 → pgntui-0.2.2}/packaging/winget/phobic.pgntui.yaml +2 -2
- {pgntui-0.2.1 → pgntui-0.2.2}/pyproject.toml +4 -1
- {pgntui-0.2.1 → pgntui-0.2.2}/src/pgntui/__init__.py +1 -1
- pgntui-0.2.2/src/pgntui/examples/containers/main.json +14 -0
- pgntui-0.2.2/src/pgntui/examples/signals/anchor_light.json +12 -0
- pgntui-0.2.2/src/pgntui/examples/signals/bilge_alarm.json +10 -0
- pgntui-0.2.2/src/pgntui/examples/signals/target_heading.json +14 -0
- {pgntui-0.2.1 → pgntui-0.2.2}/tests/test_example_workspace.py +25 -3
- {pgntui-0.2.1 → pgntui-0.2.2}/tests/test_signals_loader.py +21 -11
- {pgntui-0.2.1 → pgntui-0.2.2}/tests/test_smoke.py +1 -1
- pgntui-0.2.1/src/pgntui/examples/containers/main.json +0 -11
- {pgntui-0.2.1 → pgntui-0.2.2}/.github/workflows/ci.yml +0 -0
- {pgntui-0.2.1 → pgntui-0.2.2}/.github/workflows/release.yml +0 -0
- {pgntui-0.2.1 → pgntui-0.2.2}/.gitignore +0 -0
- {pgntui-0.2.1 → pgntui-0.2.2}/LICENSE +0 -0
- {pgntui-0.2.1 → pgntui-0.2.2}/README.md +0 -0
- {pgntui-0.2.1 → pgntui-0.2.2}/docs/superpowers/plans/2026-06-04-pgntui-implementation.md +0 -0
- {pgntui-0.2.1 → pgntui-0.2.2}/docs/superpowers/specs/2026-06-04-pgntui-design.md +0 -0
- {pgntui-0.2.1 → pgntui-0.2.2}/src/pgntui/__main__.py +0 -0
- {pgntui-0.2.1 → pgntui-0.2.2}/src/pgntui/app.py +0 -0
- {pgntui-0.2.1 → pgntui-0.2.2}/src/pgntui/config.py +0 -0
- {pgntui-0.2.1 → pgntui-0.2.2}/src/pgntui/containers/__init__.py +0 -0
- {pgntui-0.2.1 → pgntui-0.2.2}/src/pgntui/containers/loader.py +0 -0
- {pgntui-0.2.1 → pgntui-0.2.2}/src/pgntui/containers/screen.py +0 -0
- {pgntui-0.2.1 → pgntui-0.2.2}/src/pgntui/debug/__init__.py +0 -0
- {pgntui-0.2.1 → pgntui-0.2.2}/src/pgntui/debug/tab.py +0 -0
- {pgntui-0.2.1 → pgntui-0.2.2}/src/pgntui/decode/__init__.py +0 -0
- {pgntui-0.2.1 → pgntui-0.2.2}/src/pgntui/decode/canboat.py +0 -0
- {pgntui-0.2.1 → pgntui-0.2.2}/src/pgntui/decode/pgns.json +0 -0
- {pgntui-0.2.1 → pgntui-0.2.2}/src/pgntui/decode/router.py +0 -0
- {pgntui-0.2.1 → pgntui-0.2.2}/src/pgntui/drivers/__init__.py +0 -0
- {pgntui-0.2.1 → pgntui-0.2.2}/src/pgntui/drivers/actisense.py +0 -0
- {pgntui-0.2.1 → pgntui-0.2.2}/src/pgntui/drivers/base.py +0 -0
- {pgntui-0.2.1 → pgntui-0.2.2}/src/pgntui/drivers/replay.py +0 -0
- {pgntui-0.2.1 → pgntui-0.2.2}/src/pgntui/examples/__init__.py +0 -0
- {pgntui-0.2.1 → pgntui-0.2.2}/src/pgntui/examples/config.toml +0 -0
- {pgntui-0.2.1 → pgntui-0.2.2}/src/pgntui/examples/signals/depth.json +0 -0
- {pgntui-0.2.1 → pgntui-0.2.2}/src/pgntui/examples/signals/engine_rpm.json +0 -0
- {pgntui-0.2.1 → pgntui-0.2.2}/src/pgntui/examples/signals/speed.json +0 -0
- {pgntui-0.2.1 → pgntui-0.2.2}/src/pgntui/examples/signals/water_temp.json +0 -0
- {pgntui-0.2.1 → pgntui-0.2.2}/src/pgntui/logging/__init__.py +0 -0
- {pgntui-0.2.1 → pgntui-0.2.2}/src/pgntui/logging/csv.py +0 -0
- {pgntui-0.2.1 → pgntui-0.2.2}/src/pgntui/recording/__init__.py +0 -0
- {pgntui-0.2.1 → pgntui-0.2.2}/src/pgntui/recording/reader.py +0 -0
- {pgntui-0.2.1 → pgntui-0.2.2}/src/pgntui/recording/writer.py +0 -0
- {pgntui-0.2.1 → pgntui-0.2.2}/src/pgntui/replay_mode.py +0 -0
- {pgntui-0.2.1 → pgntui-0.2.2}/src/pgntui/signals/__init__.py +0 -0
- {pgntui-0.2.1 → pgntui-0.2.2}/src/pgntui/signals/base.py +0 -0
- {pgntui-0.2.1 → pgntui-0.2.2}/src/pgntui/signals/widgets.py +0 -0
- {pgntui-0.2.1 → pgntui-0.2.2}/src/pgntui/themes/__init__.py +0 -0
- {pgntui-0.2.1 → pgntui-0.2.2}/src/pgntui/themes/builtin/__init__.py +0 -0
- {pgntui-0.2.1 → pgntui-0.2.2}/src/pgntui/themes/builtin/amber-crt.json +0 -0
- {pgntui-0.2.1 → pgntui-0.2.2}/src/pgntui/themes/builtin/dark.json +0 -0
- {pgntui-0.2.1 → pgntui-0.2.2}/src/pgntui/themes/builtin/green-phosphor.json +0 -0
- {pgntui-0.2.1 → pgntui-0.2.2}/src/pgntui/themes/builtin/light.json +0 -0
- {pgntui-0.2.1 → pgntui-0.2.2}/src/pgntui/themes/builtin/mono-ascii.json +0 -0
- {pgntui-0.2.1 → pgntui-0.2.2}/src/pgntui/themes/builtin/rainbow-disco.json +0 -0
- {pgntui-0.2.1 → pgntui-0.2.2}/src/pgntui/themes/loader.py +0 -0
- {pgntui-0.2.1 → pgntui-0.2.2}/tests/__init__.py +0 -0
- {pgntui-0.2.1 → pgntui-0.2.2}/tests/fixtures/__init__.py +0 -0
- {pgntui-0.2.1 → pgntui-0.2.2}/tests/fixtures/e2e_containers/engine.json +0 -0
- {pgntui-0.2.1 → pgntui-0.2.2}/tests/fixtures/e2e_containers/nav.json +0 -0
- {pgntui-0.2.1 → pgntui-0.2.2}/tests/fixtures/e2e_session.pgnlog +0 -0
- {pgntui-0.2.1 → pgntui-0.2.2}/tests/fixtures/e2e_signals/engine_rpm.json +0 -0
- {pgntui-0.2.1 → pgntui-0.2.2}/tests/fixtures/e2e_signals/wind_speed.json +0 -0
- {pgntui-0.2.1 → pgntui-0.2.2}/tests/fixtures/frames.py +0 -0
- {pgntui-0.2.1 → pgntui-0.2.2}/tests/fixtures/sample.pgnlog +0 -0
- {pgntui-0.2.1 → pgntui-0.2.2}/tests/test_actisense_driver.py +0 -0
- {pgntui-0.2.1 → pgntui-0.2.2}/tests/test_app_empty_welcome.py +0 -0
- {pgntui-0.2.1 → pgntui-0.2.2}/tests/test_app_frame_loop.py +0 -0
- {pgntui-0.2.1 → pgntui-0.2.2}/tests/test_app_on_write.py +0 -0
- {pgntui-0.2.1 → pgntui-0.2.2}/tests/test_app_quit_binding.py +0 -0
- {pgntui-0.2.1 → pgntui-0.2.2}/tests/test_app_record_toggle.py +0 -0
- {pgntui-0.2.1 → pgntui-0.2.2}/tests/test_app_shell.py +0 -0
- {pgntui-0.2.1 → pgntui-0.2.2}/tests/test_builtin_themes.py +0 -0
- {pgntui-0.2.1 → pgntui-0.2.2}/tests/test_canboat.py +0 -0
- {pgntui-0.2.1 → pgntui-0.2.2}/tests/test_cli.py +0 -0
- {pgntui-0.2.1 → pgntui-0.2.2}/tests/test_config.py +0 -0
- {pgntui-0.2.1 → pgntui-0.2.2}/tests/test_container_screen.py +0 -0
- {pgntui-0.2.1 → pgntui-0.2.2}/tests/test_containers_loader.py +0 -0
- {pgntui-0.2.1 → pgntui-0.2.2}/tests/test_csv_logger.py +0 -0
- {pgntui-0.2.1 → pgntui-0.2.2}/tests/test_debug_tab.py +0 -0
- {pgntui-0.2.1 → pgntui-0.2.2}/tests/test_drivers_base.py +0 -0
- {pgntui-0.2.1 → pgntui-0.2.2}/tests/test_e2e_replay.py +0 -0
- {pgntui-0.2.1 → pgntui-0.2.2}/tests/test_main_replay.py +0 -0
- {pgntui-0.2.1 → pgntui-0.2.2}/tests/test_packaging.py +0 -0
- {pgntui-0.2.1 → pgntui-0.2.2}/tests/test_recording_writer.py +0 -0
- {pgntui-0.2.1 → pgntui-0.2.2}/tests/test_replay_driver.py +0 -0
- {pgntui-0.2.1 → pgntui-0.2.2}/tests/test_replay_mode.py +0 -0
- {pgntui-0.2.1 → pgntui-0.2.2}/tests/test_router.py +0 -0
- {pgntui-0.2.1 → pgntui-0.2.2}/tests/test_signals_base.py +0 -0
- {pgntui-0.2.1 → pgntui-0.2.2}/tests/test_themes_loader.py +0 -0
- {pgntui-0.2.1 → pgntui-0.2.2}/tests/test_widgets_analog_in.py +0 -0
- {pgntui-0.2.1 → pgntui-0.2.2}/tests/test_widgets_analog_out.py +0 -0
- {pgntui-0.2.1 → pgntui-0.2.2}/tests/test_widgets_digital_in.py +0 -0
- {pgntui-0.2.1 → pgntui-0.2.2}/tests/test_widgets_digital_out.py +0 -0
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
class Pgntui < Formula
|
|
4
4
|
desc "Cross-platform TUI for NMEA 2000 with canboat decoding"
|
|
5
5
|
homepage "https://github.com/phobicdotno/pgntui"
|
|
6
|
-
url "https://files.pythonhosted.org/packages/source/p/pgntui/pgntui-0.2.
|
|
6
|
+
url "https://files.pythonhosted.org/packages/source/p/pgntui/pgntui-0.2.2.tar.gz"
|
|
7
7
|
sha256 "REPLACE_ON_RELEASE"
|
|
8
8
|
license "MIT"
|
|
9
9
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Stub manifest for microsoft/winget-pkgs PR
|
|
2
2
|
PackageIdentifier: phobic.pgntui
|
|
3
|
-
PackageVersion: 0.2.
|
|
3
|
+
PackageVersion: 0.2.2
|
|
4
4
|
PackageLocale: en-US
|
|
5
5
|
Publisher: phobic
|
|
6
6
|
PackageName: pgntui
|
|
@@ -15,7 +15,7 @@ Tags: [nmea, marine, tui, terminal]
|
|
|
15
15
|
Installers:
|
|
16
16
|
- Architecture: x64
|
|
17
17
|
InstallerType: portable
|
|
18
|
-
InstallerUrl: https://github.com/phobicdotno/pgntui/releases/download/v0.2.
|
|
18
|
+
InstallerUrl: https://github.com/phobicdotno/pgntui/releases/download/v0.2.2/pgntui-windows-x86_64.exe
|
|
19
19
|
InstallerSha256: REPLACE_ON_RELEASE
|
|
20
20
|
ManifestType: singleton
|
|
21
21
|
ManifestVersion: 1.6.0
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "pgntui"
|
|
7
|
-
version = "0.2.
|
|
7
|
+
version = "0.2.2"
|
|
8
8
|
description = "Cross-platform TUI for NMEA 2000 with canboat decoding and pluggable drivers"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.11"
|
|
@@ -64,6 +64,9 @@ packages = ["src/pgntui"]
|
|
|
64
64
|
"src/pgntui/examples/signals/speed.json" = "pgntui/examples/signals/speed.json"
|
|
65
65
|
"src/pgntui/examples/signals/depth.json" = "pgntui/examples/signals/depth.json"
|
|
66
66
|
"src/pgntui/examples/signals/water_temp.json" = "pgntui/examples/signals/water_temp.json"
|
|
67
|
+
"src/pgntui/examples/signals/target_heading.json" = "pgntui/examples/signals/target_heading.json"
|
|
68
|
+
"src/pgntui/examples/signals/bilge_alarm.json" = "pgntui/examples/signals/bilge_alarm.json"
|
|
69
|
+
"src/pgntui/examples/signals/anchor_light.json" = "pgntui/examples/signals/anchor_light.json"
|
|
67
70
|
|
|
68
71
|
[tool.ruff]
|
|
69
72
|
line-length = 100
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "main",
|
|
3
|
+
"title": "Main",
|
|
4
|
+
"cols": 12,
|
|
5
|
+
"signals": [
|
|
6
|
+
{"ref": "engine_rpm", "row": 0, "col": 0, "w": 3},
|
|
7
|
+
{"ref": "speed", "row": 0, "col": 3, "w": 3},
|
|
8
|
+
{"ref": "depth", "row": 0, "col": 6, "w": 3},
|
|
9
|
+
{"ref": "water_temp", "row": 0, "col": 9, "w": 3},
|
|
10
|
+
{"ref": "target_heading", "row": 1, "col": 0, "w": 12},
|
|
11
|
+
{"ref": "bilge_alarm", "row": 2, "col": 0, "w": 6},
|
|
12
|
+
{"ref": "anchor_light", "row": 2, "col": 6, "w": 6}
|
|
13
|
+
]
|
|
14
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "target_heading",
|
|
3
|
+
"type": "analog_out",
|
|
4
|
+
"title": "Target Heading",
|
|
5
|
+
"unit": "rad",
|
|
6
|
+
"pgn": 65360,
|
|
7
|
+
"field": "Target Heading Magnetic",
|
|
8
|
+
"min": 0,
|
|
9
|
+
"max": 6.2832,
|
|
10
|
+
"decimals": 2,
|
|
11
|
+
"write_pgn": 65360,
|
|
12
|
+
"write_field": "Target Heading Magnetic",
|
|
13
|
+
"log": false
|
|
14
|
+
}
|
|
@@ -6,7 +6,7 @@ from pathlib import Path
|
|
|
6
6
|
|
|
7
7
|
from pgntui.__main__ import main
|
|
8
8
|
from pgntui.containers.loader import load_container
|
|
9
|
-
from pgntui.signals.base import load_signals_dir
|
|
9
|
+
from pgntui.signals.base import AnalogIn, AnalogOut, DigitalIn, DigitalOut, load_signals_dir
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
def test_example_creates_expected_files(tmp_path: Path) -> None:
|
|
@@ -18,8 +18,17 @@ def test_example_creates_expected_files(tmp_path: Path) -> None:
|
|
|
18
18
|
assert (ws / "containers").is_dir()
|
|
19
19
|
signals = load_signals_dir(ws / "signals")
|
|
20
20
|
ids = {s.id for s in signals}
|
|
21
|
-
#
|
|
22
|
-
|
|
21
|
+
# Seven shipped defaults: four analog readouts plus one of each remaining
|
|
22
|
+
# widget kind so the scaffold exercises the full UI surface.
|
|
23
|
+
assert ids == {
|
|
24
|
+
"engine_rpm",
|
|
25
|
+
"speed",
|
|
26
|
+
"depth",
|
|
27
|
+
"water_temp",
|
|
28
|
+
"target_heading",
|
|
29
|
+
"bilge_alarm",
|
|
30
|
+
"anchor_light",
|
|
31
|
+
}
|
|
23
32
|
# Containers reference signal ids that exist.
|
|
24
33
|
main_container = load_container(ws / "containers" / "main.json", ids)
|
|
25
34
|
refs = {p.ref for p in main_container.signals}
|
|
@@ -27,6 +36,19 @@ def test_example_creates_expected_files(tmp_path: Path) -> None:
|
|
|
27
36
|
assert main_container.cols == 12
|
|
28
37
|
|
|
29
38
|
|
|
39
|
+
def test_example_includes_all_four_widget_types(tmp_path: Path) -> None:
|
|
40
|
+
"""Scaffolded workspace must contain at least one signal of each kind."""
|
|
41
|
+
ws = tmp_path / "ws"
|
|
42
|
+
rc = main(["--workspace", str(ws), "--example"])
|
|
43
|
+
assert rc == 0
|
|
44
|
+
signals = load_signals_dir(ws / "signals")
|
|
45
|
+
kinds = {type(s) for s in signals}
|
|
46
|
+
assert AnalogIn in kinds
|
|
47
|
+
assert AnalogOut in kinds
|
|
48
|
+
assert DigitalIn in kinds
|
|
49
|
+
assert DigitalOut in kinds
|
|
50
|
+
|
|
51
|
+
|
|
30
52
|
def test_example_refuses_when_workspace_non_empty(tmp_path: Path, capsys) -> None: # type: ignore[no-untyped-def]
|
|
31
53
|
ws = tmp_path / "ws"
|
|
32
54
|
ws.mkdir()
|
|
@@ -6,28 +6,38 @@ from importlib import resources
|
|
|
6
6
|
|
|
7
7
|
import pytest
|
|
8
8
|
|
|
9
|
-
from pgntui.signals.base import AnalogIn, AnalogOut, DigitalIn, DigitalOut, load_signal
|
|
9
|
+
from pgntui.signals.base import AnalogIn, AnalogOut, DigitalIn, DigitalOut, Signal, load_signal
|
|
10
10
|
|
|
11
|
+
_EXAMPLE_EXPECTED: dict[str, type[Signal]] = {
|
|
12
|
+
"engine_rpm": AnalogIn,
|
|
13
|
+
"speed": AnalogIn,
|
|
14
|
+
"depth": AnalogIn,
|
|
15
|
+
"water_temp": AnalogIn,
|
|
16
|
+
"target_heading": AnalogOut,
|
|
17
|
+
"bilge_alarm": DigitalIn,
|
|
18
|
+
"anchor_light": DigitalOut,
|
|
19
|
+
}
|
|
11
20
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
["engine_rpm", "speed", "depth", "water_temp"],
|
|
15
|
-
)
|
|
21
|
+
|
|
22
|
+
@pytest.mark.parametrize("name", sorted(_EXAMPLE_EXPECTED))
|
|
16
23
|
def test_each_example_signal_loads(name: str, tmp_path) -> None: # type: ignore[no-untyped-def]
|
|
17
|
-
"""Every bundled signal JSON parses into
|
|
24
|
+
"""Every bundled signal JSON parses into the expected Signal subclass."""
|
|
18
25
|
src = resources.files("pgntui.examples.signals").joinpath(f"{name}.json")
|
|
19
26
|
target = tmp_path / f"{name}.json"
|
|
20
27
|
with src.open("rb") as fh:
|
|
21
28
|
target.write_bytes(fh.read())
|
|
22
29
|
sig = load_signal(target)
|
|
23
|
-
|
|
24
|
-
# digital example, extend this assertion.
|
|
25
|
-
assert isinstance(sig, AnalogIn)
|
|
30
|
+
assert isinstance(sig, _EXAMPLE_EXPECTED[name])
|
|
26
31
|
assert sig.id == name
|
|
27
32
|
assert sig.pgn > 0
|
|
28
33
|
assert sig.field
|
|
29
|
-
|
|
30
|
-
|
|
34
|
+
if isinstance(sig, AnalogIn | AnalogOut):
|
|
35
|
+
assert sig.min < sig.max
|
|
36
|
+
if isinstance(sig, AnalogIn):
|
|
37
|
+
assert sig.smoothing >= 0
|
|
38
|
+
if isinstance(sig, AnalogOut | DigitalOut):
|
|
39
|
+
assert sig.write_pgn > 0
|
|
40
|
+
assert sig.write_field
|
|
31
41
|
|
|
32
42
|
|
|
33
43
|
def test_signal_load_round_trip_all_types(tmp_path) -> None: # type: ignore[no-untyped-def]
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"id": "main",
|
|
3
|
-
"title": "Main",
|
|
4
|
-
"cols": 12,
|
|
5
|
-
"signals": [
|
|
6
|
-
{"ref": "engine_rpm", "row": 0, "col": 0, "w": 6},
|
|
7
|
-
{"ref": "speed", "row": 0, "col": 6, "w": 6},
|
|
8
|
-
{"ref": "depth", "row": 1, "col": 0, "w": 6},
|
|
9
|
-
{"ref": "water_temp", "row": 1, "col": 6, "w": 6}
|
|
10
|
-
]
|
|
11
|
-
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|