Skip to content
This repository was archived by the owner on Jan 23, 2026. It is now read-only.

Commit e06ca8e

Browse files
Migrate all driver descriptions to DriverClickGroup decorator
Replace @click.group decorators with DriverClickGroup in all drivers, and use it to provide server-side driver description In cli() use: base = DriverClickGroup(self, help="...") The CLI client will retrieve customized driver's description via GetReport() from the exporter. When there's no customization it falls back to locally provided default in help=.
1 parent 240cb81 commit e06ca8e

File tree

11 files changed

+30
-57
lines changed
  • packages
    • jumpstarter-driver-composite/jumpstarter_driver_composite
    • jumpstarter-driver-flashers/jumpstarter_driver_flashers
    • jumpstarter-driver-gpiod/jumpstarter_driver_gpiod
    • jumpstarter-driver-network/jumpstarter_driver_network
    • jumpstarter-driver-opendal/jumpstarter_driver_opendal
    • jumpstarter-driver-power/jumpstarter_driver_power
    • jumpstarter-driver-probe-rs/jumpstarter_driver_probe_rs
    • jumpstarter-driver-pyserial/jumpstarter_driver_pyserial
    • jumpstarter-driver-ridesx/jumpstarter_driver_ridesx
    • jumpstarter-driver-shell/jumpstarter_driver_shell
    • jumpstarter-driver-snmp/jumpstarter_driver_snmp

11 files changed

+30
-57
lines changed

packages/jumpstarter-driver-composite/jumpstarter_driver_composite/client.py

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from rich import traceback
66

77
from jumpstarter.client import DriverClient
8+
from jumpstarter.client.decorators import DriverClickGroup
89

910

1011
def _opt_log_level_callback(ctx, param, value):
@@ -34,18 +35,14 @@ def close(self):
3435
v.close()
3536

3637
def cli(self):
37-
@click.group
38-
@click.option(
38+
base = DriverClickGroup(self, help="Generic composite device")
39+
base.add_option(
3940
"--log-level",
40-
"log_level",
4141
type=click.Choice(["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"]),
4242
help="Set the log level",
4343
expose_value=False,
4444
callback=_opt_log_level_callback,
4545
)
46-
def base():
47-
"""Generic composite device"""
48-
pass
4946

5047
for k, v in self.children.items():
5148
if hasattr(v, "cli"):

packages/jumpstarter-driver-flashers/jumpstarter_driver_flashers/client.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
from jumpstarter_driver_flashers.bundle import FlasherBundleManifestV1Alpha1
2323

24+
from jumpstarter.client.decorators import DriverClickGroup
2425
from jumpstarter.common.exceptions import ArgumentError
2526

2627
debug_console_option = click.option("--console-debug", is_flag=True, help="Enable console debug mode")
@@ -750,10 +751,7 @@ def _validate_bearer_token(self, token: str | None) -> str | None:
750751
return token
751752

752753
def cli(self):
753-
@click.group
754-
def base():
755-
"""Software-defined flasher interface"""
756-
pass
754+
base = DriverClickGroup(self, help="Software-defined flasher interface")
757755

758756
@base.command()
759757
@click.argument("file")

packages/jumpstarter-driver-gpiod/jumpstarter_driver_gpiod/client.py

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from jumpstarter_driver_power.client import PowerClient
66

77
from jumpstarter.client import DriverClient
8+
from jumpstarter.client.decorators import DriverClickGroup
89

910

1011
class PinState(Enum):
@@ -34,10 +35,7 @@ def read(self):
3435
return PinState(int(self.call("read_pin")))
3536

3637
def cli(self):
37-
@click.group()
38-
def gpio():
39-
"""GPIO power control commands."""
40-
pass
38+
gpio = DriverClickGroup(self, help="GPIO power control commands.")
4139

4240
for cmd in super().cli().commands.values():
4341
gpio.add_command(cmd)
@@ -79,10 +77,7 @@ def read(self):
7977
return PinState(int(self.call("read_pin")))
8078

8179
def cli(self):
82-
@click.group()
83-
def gpio():
84-
"""GPIO input commands."""
85-
pass
80+
gpio = DriverClickGroup(self, help="GPIO input commands.")
8681

8782
@gpio.command()
8883
def read():

packages/jumpstarter-driver-network/jumpstarter_driver_network/client.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
from .driver import DbusNetwork
1313
from jumpstarter.client import DriverClient
1414
from jumpstarter.client.core import DriverMethodNotImplemented
15+
from jumpstarter.client.decorators import DriverClickGroup
1516

1617

1718
class NetworkClient(DriverClient):
@@ -20,10 +21,7 @@ def address(self):
2021
return self.call("address")
2122

2223
def cli(self):
23-
@click.group
24-
def base():
25-
"""Generic Network Connection"""
26-
pass
24+
base = DriverClickGroup(self, help="Generic Network Connection")
2725

2826
@base.command()
2927
@click.option("--address", default="localhost", show_default=True)

packages/jumpstarter-driver-opendal/jumpstarter_driver_opendal/client.py

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
from .adapter import OpendalAdapter
2020
from .common import Capability, HashAlgo, Metadata, Mode, PathBuf, PresignedRequest
2121
from jumpstarter.client import DriverClient
22+
from jumpstarter.client.decorators import DriverClickGroup
2223
from jumpstarter.common.exceptions import ArgumentError
2324
from jumpstarter.streams.encoding import Compression
2425

@@ -413,9 +414,7 @@ def cli(self): # noqa: C901
413414
arg_dst = click.argument("dst", type=click.Path())
414415
opt_expire_second = click.option("--expire-second", type=int, required=True)
415416

416-
@click.group
417-
def base():
418-
"""Opendal Storage"""
417+
base = DriverClickGroup(self, help="Opendal Storage")
419418

420419
@base.command
421420
@arg_path
@@ -548,10 +547,7 @@ def dump(
548547
...
549548

550549
def cli(self):
551-
@click.group
552-
def base():
553-
"""Generic flasher interface"""
554-
pass
550+
base = DriverClickGroup(self, help="Generic flasher interface")
555551

556552
@base.command()
557553
@click.argument("file", nargs=-1, required=False)
@@ -716,7 +712,7 @@ def read_local_file(self, filepath):
716712

717713
def cli(self, base=None):
718714
if base is None:
719-
base = click.group(lambda: None)
715+
base = DriverClickGroup(self, help="Storage operations")
720716

721717
@base.command()
722718
def host():

packages/jumpstarter-driver-power/jumpstarter_driver_power/client.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
from .common import PowerReading
77
from jumpstarter.client import DriverClient
8+
from jumpstarter.client.decorators import DriverClickGroup
89

910

1011
class PowerClient(DriverClient):
@@ -35,10 +36,7 @@ def read(self) -> Generator[PowerReading, None, None]:
3536
yield PowerReading.model_validate(v, strict=True)
3637

3738
def cli(self):
38-
@click.group
39-
def base():
40-
"""Generic power"""
41-
pass
39+
base = DriverClickGroup(self, help="Generic power")
4240

4341
@base.command()
4442
def on():

packages/jumpstarter-driver-probe-rs/jumpstarter_driver_probe_rs/client.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
from opendal import Operator
77

88
from jumpstarter.client import DriverClient
9+
from jumpstarter.client.decorators import DriverClickGroup
910
from jumpstarter.common.exceptions import ArgumentError
1011

1112

@@ -60,10 +61,7 @@ def read(self, width: int, address: int, words: int) -> list[int]:
6061
return [int(data, 16) for data in data_strs]
6162

6263
def cli(self): # noqa: C901
63-
@click.group
64-
def base():
65-
"""probe-rs client"""
66-
pass
64+
base = DriverClickGroup(self, help="probe-rs client")
6765

6866
@base.command()
6967
def info():

packages/jumpstarter-driver-pyserial/jumpstarter_driver_pyserial/client.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
from .console import Console
88
from jumpstarter.client import DriverClient
9+
from jumpstarter.client.decorators import DriverClickGroup
910

1011

1112
class PySerialClient(DriverClient):
@@ -36,10 +37,7 @@ def pexpect(self):
3637
yield adapter
3738

3839
def cli(self):
39-
@click.group
40-
def base():
41-
"""Serial port client"""
42-
pass
40+
base = DriverClickGroup(self, help="Serial port client")
4341

4442
@base.command()
4543
def start_console():

packages/jumpstarter-driver-ridesx/jumpstarter_driver_ridesx/client.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,13 @@
22
from pathlib import Path
33
from typing import Dict, Optional
44

5-
import click
65
from jumpstarter_driver_composite.client import CompositeClient
76
from jumpstarter_driver_opendal.client import FlasherClient, operator_for_path
87
from jumpstarter_driver_power.client import PowerClient
98
from opendal import Operator
109

10+
from jumpstarter.client.decorators import DriverClickGroup
11+
1112
PROMPT = "CMD >> "
1213

1314

@@ -102,9 +103,7 @@ def flash(
102103
def cli(self):
103104
generic_cli = FlasherClient.cli(self)
104105

105-
@click.group()
106-
def storage():
107-
pass
106+
storage = DriverClickGroup(self, help="RideSX storage operations")
108107

109108
for name, cmd in generic_cli.commands.items():
110109
storage.add_command(cmd, name=name)

packages/jumpstarter-driver-shell/jumpstarter_driver_shell/client.py

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import click
55

66
from jumpstarter.client import DriverClient
7+
from jumpstarter.client.decorators import DriverClickGroup
78

89

910
@dataclass(kw_only=True)
@@ -41,10 +42,7 @@ def execute(*args, **kwargs):
4142

4243
def cli(self):
4344
"""Create CLI interface for dynamically configured shell methods"""
44-
@click.group
45-
def base():
46-
"""Shell command executor"""
47-
pass
45+
base = DriverClickGroup(self, help="Shell command executor")
4846

4947
# Get available methods from the driver
5048
if self._methods is None:
@@ -80,12 +78,12 @@ def method_command(args, env):
8078
except Exception:
8179
description = f"Execute the {method_name} shell method"
8280

83-
# Decorate and register the command
84-
method_command.__doc__ = description
81+
# Decorate and register the command with help text
8582
method_command = click.argument('args', nargs=-1, type=click.UNPROCESSED)(method_command)
8683
method_command = click.option('--env', '-e', multiple=True,
8784
help='Environment variables in KEY=VALUE format')(method_command)
8885
method_command = group.command(
8986
name=method_name,
87+
help=description,
9088
context_settings={"ignore_unknown_options": True, "allow_interspersed_args": False},
9189
)(method_command)

0 commit comments

Comments
 (0)