|
64 | 64 |
|
65 | 65 |
|
66 | 66 | class FPBCLIError(Exception): |
67 | | - """CLI specific errors""" |
| 67 | + """CLI-specific error. ``exit_code`` defaults to 1. |
68 | 68 |
|
69 | | - pass |
| 69 | + Raise the ``AmbiguousServerError`` subclass when more than one server |
| 70 | + matches a discovery handle so main() can exit ``2`` (the documented |
| 71 | + ladder code for "needs disambiguation"). |
| 72 | + """ |
| 73 | + |
| 74 | + exit_code = 1 |
| 75 | + |
| 76 | + |
| 77 | +class AmbiguousServerError(FPBCLIError): |
| 78 | + """Multi-match on discovery handle / mDNS browse; exits ``2``.""" |
| 79 | + |
| 80 | + exit_code = 2 |
70 | 81 |
|
71 | 82 |
|
72 | 83 | class DeviceState(DeviceStateBase): |
@@ -1378,7 +1389,7 @@ def _resolve_handle_to_url(value: str, *, source: str) -> str: |
1378 | 1389 | for s in matches: |
1379 | 1390 | msg.append(f" {s.handle} {s.url}") |
1380 | 1391 | msg.append("Be more specific (use 'host:port' form).") |
1381 | | - raise FPBCLIError("\n".join(msg)) |
| 1392 | + raise AmbiguousServerError("\n".join(msg)) |
1382 | 1393 |
|
1383 | 1394 | chosen = matches[0] |
1384 | 1395 | if kind == "host_port": |
@@ -1546,16 +1557,14 @@ def resolve_connection_plan(args) -> ConnectionPlan: |
1546 | 1557 | _classify_url(s.url, token=token, source="mdns"), port, baudrate |
1547 | 1558 | ) |
1548 | 1559 |
|
1549 | | - print( |
1550 | | - "Multiple FPBInject servers discovered; pass --server-url to choose:", |
1551 | | - file=sys.stderr, |
1552 | | - ) |
| 1560 | + lines = [ |
| 1561 | + "Multiple FPBInject servers discovered; pass -s <handle> to choose:", |
| 1562 | + ] |
1553 | 1563 | for s in servers: |
1554 | | - print( |
1555 | | - f" {s.url} version={s.version} auth={s.auth} device={s.device}", |
1556 | | - file=sys.stderr, |
| 1564 | + lines.append( |
| 1565 | + f" -s {s.handle} version={s.version} auth={s.auth} device={s.device}" |
1557 | 1566 | ) |
1558 | | - sys.exit(2) |
| 1567 | + raise AmbiguousServerError("\n".join(lines)) |
1559 | 1568 |
|
1560 | 1569 |
|
1561 | 1570 | def resolve_server_url(args): |
@@ -1596,12 +1605,12 @@ def resolve_server_url(args): |
1596 | 1605 | ) |
1597 | 1606 | return s.url |
1598 | 1607 | print( |
1599 | | - "Multiple FPBInject servers discovered; pass --server-url to choose:", |
| 1608 | + "Multiple FPBInject servers discovered; pass -s <handle> to choose:", |
1600 | 1609 | file=sys.stderr, |
1601 | 1610 | ) |
1602 | 1611 | for s in servers: |
1603 | 1612 | print( |
1604 | | - f" {s.url} version={s.version} auth={s.auth} device={s.device}", |
| 1613 | + f" -s {s.handle} version={s.version} auth={s.auth} device={s.device}", |
1605 | 1614 | file=sys.stderr, |
1606 | 1615 | ) |
1607 | 1616 | sys.exit(2) |
@@ -2062,16 +2071,21 @@ def main(): |
2062 | 2071 | plan = resolve_connection_plan(args) |
2063 | 2072 | cli = FPBCLI( |
2064 | 2073 | verbose=args.verbose, |
| 2074 | + port=args.port, |
| 2075 | + baudrate=args.baudrate, |
2065 | 2076 | elf_path=elf_path, |
2066 | 2077 | compile_commands=args.compile_commands, |
2067 | 2078 | tx_chunk_size=args.tx_chunk_size, |
2068 | 2079 | tx_chunk_delay=args.tx_chunk_delay, |
2069 | 2080 | max_retries=args.max_retries, |
| 2081 | + direct=args.direct, |
| 2082 | + server_url=plan.server_url, |
| 2083 | + token=args.token, |
2070 | 2084 | plan=plan, |
2071 | 2085 | ) |
2072 | 2086 | except FPBCLIError as e: |
2073 | 2087 | print(f"Error: {e}", file=sys.stderr) |
2074 | | - sys.exit(1) |
| 2088 | + sys.exit(e.exit_code) |
2075 | 2089 | args.server_url = plan.server_url |
2076 | 2090 |
|
2077 | 2091 | try: |
@@ -2139,7 +2153,7 @@ def main(): |
2139 | 2153 | cli.server_stop(port) |
2140 | 2154 | except FPBCLIError as e: |
2141 | 2155 | cli.output_error(str(e)) |
2142 | | - sys.exit(1) |
| 2156 | + sys.exit(e.exit_code) |
2143 | 2157 | except KeyboardInterrupt: |
2144 | 2158 | print("\nInterrupted by user", file=sys.stderr) |
2145 | 2159 | sys.exit(130) |
|
0 commit comments