RemoteRF 0.0.7.48__tar.gz → 0.0.7.52__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.
- {remoterf-0.0.7.48/src/remoteRF.egg-info → remoterf-0.0.7.52}/PKG-INFO +1 -1
- {remoterf-0.0.7.48 → remoterf-0.0.7.52}/setup.py +5 -5
- remoterf-0.0.7.48/src/remoteRF/config/config_cli.py → remoterf-0.0.7.52/src/remoteRF/config/config.py +30 -69
- {remoterf-0.0.7.48 → remoterf-0.0.7.52}/src/remoteRF/core/acc_login.py +1 -1
- {remoterf-0.0.7.48 → remoterf-0.0.7.52}/src/remoteRF/core/version.py +1 -1
- remoterf-0.0.7.52/src/remoteRF/remoterf_cli.py +203 -0
- {remoterf-0.0.7.48 → remoterf-0.0.7.52/src/remoteRF.egg-info}/PKG-INFO +1 -1
- {remoterf-0.0.7.48 → remoterf-0.0.7.52}/src/remoteRF.egg-info/SOURCES.txt +2 -2
- remoterf-0.0.7.52/src/remoteRF.egg-info/entry_points.txt +2 -0
- remoterf-0.0.7.48/src/remoteRF/cli.py +0 -141
- remoterf-0.0.7.48/src/remoteRF.egg-info/entry_points.txt +0 -5
- {remoterf-0.0.7.48 → remoterf-0.0.7.52}/LICENSE +0 -0
- {remoterf-0.0.7.48 → remoterf-0.0.7.52}/MANIFEST.in +0 -0
- {remoterf-0.0.7.48 → remoterf-0.0.7.52}/README.md +0 -0
- {remoterf-0.0.7.48 → remoterf-0.0.7.52}/setup.cfg +0 -0
- {remoterf-0.0.7.48 → remoterf-0.0.7.52}/src/remoteRF/__init__.py +0 -0
- {remoterf-0.0.7.48 → remoterf-0.0.7.52}/src/remoteRF/common/__init__.py +0 -0
- {remoterf-0.0.7.48 → remoterf-0.0.7.52}/src/remoteRF/common/grpc/__init__.py +0 -0
- {remoterf-0.0.7.48 → remoterf-0.0.7.52}/src/remoteRF/common/grpc/grpc_pb2.py +0 -0
- {remoterf-0.0.7.48 → remoterf-0.0.7.52}/src/remoteRF/common/grpc/grpc_pb2_grpc.py +0 -0
- {remoterf-0.0.7.48 → remoterf-0.0.7.52}/src/remoteRF/common/utils/__init__.py +0 -0
- {remoterf-0.0.7.48 → remoterf-0.0.7.52}/src/remoteRF/common/utils/ansi_codes.py +0 -0
- {remoterf-0.0.7.48 → remoterf-0.0.7.52}/src/remoteRF/common/utils/api_token.py +0 -0
- {remoterf-0.0.7.48 → remoterf-0.0.7.52}/src/remoteRF/common/utils/list_string.py +0 -0
- {remoterf-0.0.7.48 → remoterf-0.0.7.52}/src/remoteRF/common/utils/process_arg.py +0 -0
- {remoterf-0.0.7.48 → remoterf-0.0.7.52}/src/remoteRF/config/__init__.py +0 -0
- {remoterf-0.0.7.48 → remoterf-0.0.7.52}/src/remoteRF/config/cert_fetcher.py +0 -0
- {remoterf-0.0.7.48 → remoterf-0.0.7.52}/src/remoteRF/core/__init__.py +0 -0
- {remoterf-0.0.7.48 → remoterf-0.0.7.52}/src/remoteRF/core/app.py +0 -0
- {remoterf-0.0.7.48 → remoterf-0.0.7.52}/src/remoteRF/core/grpc_acc.py +0 -0
- {remoterf-0.0.7.48 → remoterf-0.0.7.52}/src/remoteRF/core/grpc_client.py +0 -0
- {remoterf-0.0.7.48 → remoterf-0.0.7.52}/src/remoteRF/drivers/__init__.py +0 -0
- {remoterf-0.0.7.48 → remoterf-0.0.7.52}/src/remoteRF/drivers/adalm_pluto/__init__.py +0 -0
- {remoterf-0.0.7.48 → remoterf-0.0.7.52}/src/remoteRF/drivers/adalm_pluto/pluto_remote.py +0 -0
- {remoterf-0.0.7.48 → remoterf-0.0.7.52}/src/remoteRF.egg-info/dependency_links.txt +0 -0
- {remoterf-0.0.7.48 → remoterf-0.0.7.52}/src/remoteRF.egg-info/requires.txt +0 -0
- {remoterf-0.0.7.48 → remoterf-0.0.7.52}/src/remoteRF.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: remoterf
|
|
3
|
-
Version: 0.0.7.
|
|
3
|
+
Version: 0.0.7.52
|
|
4
4
|
Summary: A python API to remotely access signal centric hardware. Client-side only! Courtesy of Wireless Lab @ UCLA & Prof. Ian Roberts.
|
|
5
5
|
Author: Ethan Ge
|
|
6
6
|
Author-email: ethoGalaxy@gmail.com
|
|
@@ -6,7 +6,7 @@ with open("README.md", "r", encoding="utf-8") as fh:
|
|
|
6
6
|
|
|
7
7
|
setup(
|
|
8
8
|
name="remoterf",
|
|
9
|
-
version="0.0.7.
|
|
9
|
+
version="0.0.7.52",
|
|
10
10
|
author="Ethan Ge",
|
|
11
11
|
author_email="ethoGalaxy@gmail.com",
|
|
12
12
|
description="A python API to remotely access signal centric hardware. Client-side only! Courtesy of Wireless Lab @ UCLA & Prof. Ian Roberts.",
|
|
@@ -35,10 +35,10 @@ setup(
|
|
|
35
35
|
|
|
36
36
|
entry_points={
|
|
37
37
|
"console_scripts": [
|
|
38
|
-
"remoterf=remoteRF.
|
|
39
|
-
"remoterf-login=remoteRF.core.acc_login:main",
|
|
40
|
-
"remoterf-v=remoteRF.core.version:main",
|
|
41
|
-
"remoterf-config=remoteRF.config.config_cli:main",
|
|
38
|
+
"remoterf=remoteRF.remoterf_cli:main",
|
|
39
|
+
# "remoterf-login=remoteRF.core.acc_login:main",
|
|
40
|
+
# "remoterf-v=remoteRF.core.version:main",
|
|
41
|
+
# "remoterf-config=remoteRF.config.config_cli:main",
|
|
42
42
|
],
|
|
43
43
|
},
|
|
44
44
|
|
|
@@ -6,10 +6,13 @@ import os
|
|
|
6
6
|
import sys
|
|
7
7
|
import shutil
|
|
8
8
|
from pathlib import Path
|
|
9
|
-
from typing import Tuple
|
|
9
|
+
from typing import Optional, Sequence, Tuple
|
|
10
|
+
import argparse
|
|
10
11
|
|
|
11
12
|
from .cert_fetcher import fetch_and_save_ca_cert
|
|
12
13
|
|
|
14
|
+
|
|
15
|
+
|
|
13
16
|
# -----------------------------
|
|
14
17
|
# Local config locations
|
|
15
18
|
# -----------------------------
|
|
@@ -71,72 +74,19 @@ def _wipe_config(root: Path) -> None:
|
|
|
71
74
|
shutil.rmtree(root)
|
|
72
75
|
print(f"Wiped RemoteRF config: {root}")
|
|
73
76
|
|
|
74
|
-
def
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
"Fetches the server CA certificate and saves the gRPC target locally."
|
|
84
|
-
),
|
|
85
|
-
)
|
|
86
|
-
|
|
87
|
-
parser.add_argument(
|
|
88
|
-
"addr",
|
|
89
|
-
nargs="?",
|
|
90
|
-
help="Server address in host:port form. Example: 164.67.195.207:61005",
|
|
91
|
-
)
|
|
92
|
-
|
|
93
|
-
parser.add_argument(
|
|
94
|
-
"--wipe",
|
|
95
|
-
action="store_true",
|
|
96
|
-
help="Delete ALL existing RemoteRF config at ~/.config/remoterf and exit.",
|
|
97
|
-
)
|
|
98
|
-
|
|
99
|
-
parser.add_argument(
|
|
100
|
-
"--yes",
|
|
101
|
-
action="store_true",
|
|
102
|
-
help="Skip confirmation prompts (use with --wipe).",
|
|
103
|
-
)
|
|
104
|
-
|
|
105
|
-
args = parser.parse_args()
|
|
106
|
-
|
|
107
|
-
# ----- Wipe mode -----
|
|
108
|
-
if args.wipe:
|
|
109
|
-
root = _config_root()
|
|
110
|
-
if not args.yes:
|
|
111
|
-
if not _confirm_wipe(root):
|
|
112
|
-
print("Wipe aborted.")
|
|
113
|
-
sys.exit(1)
|
|
114
|
-
try:
|
|
115
|
-
_wipe_config(root)
|
|
116
|
-
sys.exit(0)
|
|
117
|
-
except Exception as e:
|
|
118
|
-
print(f"Error wiping config: {e}", file=sys.stderr)
|
|
119
|
-
sys.exit(1)
|
|
120
|
-
|
|
121
|
-
# ----- Normal configure mode -----
|
|
122
|
-
if not args.addr:
|
|
123
|
-
print(
|
|
124
|
-
"\nError: missing required argument: host:port\n\n"
|
|
125
|
-
"Usage:\n"
|
|
126
|
-
" remoterf-config <host:port>\n"
|
|
127
|
-
" remoterf-config --wipe [--yes]\n\n"
|
|
128
|
-
"Example:\n"
|
|
129
|
-
" remoterf-config 164.67.195.207:61005\n"
|
|
130
|
-
)
|
|
131
|
-
sys.exit(2)
|
|
77
|
+
def configure(host: str, port: int, cert_port: int) -> int:
|
|
78
|
+
# Basic validation
|
|
79
|
+
host = (host or "").strip()
|
|
80
|
+
if not host:
|
|
81
|
+
print("Error: host is empty", file=sys.stderr)
|
|
82
|
+
return 2
|
|
83
|
+
if port <= 0 or port > 65535:
|
|
84
|
+
print("Error: port out of range", file=sys.stderr)
|
|
85
|
+
return 2
|
|
132
86
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
except Exception as e:
|
|
136
|
-
print(f"Error: invalid addr '{args.addr}': {e}", file=sys.stderr)
|
|
137
|
-
sys.exit(2)
|
|
87
|
+
grpc_port = int(port)
|
|
88
|
+
cert_port = int(cert_port)
|
|
138
89
|
|
|
139
|
-
cert_port = grpc_port + 1
|
|
140
90
|
profile = "default"
|
|
141
91
|
timeout_sec = 3.0
|
|
142
92
|
overwrite = True
|
|
@@ -152,10 +102,9 @@ def main(argv=None) -> None:
|
|
|
152
102
|
timeout_sec=timeout_sec,
|
|
153
103
|
overwrite=overwrite,
|
|
154
104
|
)
|
|
155
|
-
|
|
156
105
|
if not fetched_ok:
|
|
157
106
|
print(f"Failed to fetch CA cert from {host}:{cert_port}.", file=sys.stderr)
|
|
158
|
-
|
|
107
|
+
return 1
|
|
159
108
|
|
|
160
109
|
env_file = _env_path()
|
|
161
110
|
_write_env_kv(env_file, {
|
|
@@ -170,5 +119,17 @@ def main(argv=None) -> None:
|
|
|
170
119
|
print(f" CA cert : {ca_out}")
|
|
171
120
|
print(f" env file : {env_file}")
|
|
172
121
|
|
|
173
|
-
|
|
174
|
-
|
|
122
|
+
def wipe_config(*, yes: bool = False) -> int:
|
|
123
|
+
"""
|
|
124
|
+
Optional helper if you want wipe behavior without argparse.
|
|
125
|
+
"""
|
|
126
|
+
root = _config_root()
|
|
127
|
+
if not yes and not _confirm_wipe(root):
|
|
128
|
+
print("Wipe aborted.")
|
|
129
|
+
return 1
|
|
130
|
+
try:
|
|
131
|
+
_wipe_config(root)
|
|
132
|
+
return 0
|
|
133
|
+
except Exception as e:
|
|
134
|
+
print(f"Error wiping config: {e}", file=sys.stderr)
|
|
135
|
+
return 1
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
# src/remoteRF/cli.py
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
import argparse
|
|
5
|
+
import sys
|
|
6
|
+
from typing import Optional, Sequence
|
|
7
|
+
|
|
8
|
+
import sys
|
|
9
|
+
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
|
|
12
|
+
def _config_root() -> Path:
|
|
13
|
+
return Path.home() / ".config" / "remoterf"
|
|
14
|
+
|
|
15
|
+
def _env_path() -> Path:
|
|
16
|
+
return _config_root() / ".env"
|
|
17
|
+
|
|
18
|
+
def _read_dotenv_kv(path: Path) -> dict[str, str]:
|
|
19
|
+
"""
|
|
20
|
+
Tiny dotenv reader (KEY=VALUE lines). Good enough for your use-case.
|
|
21
|
+
"""
|
|
22
|
+
out: dict[str, str] = {}
|
|
23
|
+
if not path.exists():
|
|
24
|
+
return out
|
|
25
|
+
|
|
26
|
+
for raw in path.read_text(encoding="utf-8").splitlines():
|
|
27
|
+
line = raw.strip()
|
|
28
|
+
if not line or line.startswith("#") or "=" not in line:
|
|
29
|
+
continue
|
|
30
|
+
k, v = line.split("=", 1)
|
|
31
|
+
k = k.strip()
|
|
32
|
+
v = v.strip().strip('"').strip("'")
|
|
33
|
+
out[k] = v
|
|
34
|
+
return out
|
|
35
|
+
|
|
36
|
+
def _ensure_config_present() -> tuple[bool, str]:
|
|
37
|
+
env_file = _env_path()
|
|
38
|
+
if not env_file.exists():
|
|
39
|
+
return (
|
|
40
|
+
False,
|
|
41
|
+
"RemoteRF is not configured.\n"
|
|
42
|
+
"Run:\n"
|
|
43
|
+
" remoterf --config --addr <host:port>\n"
|
|
44
|
+
"Example:\n"
|
|
45
|
+
" remoterf --config --addr 123.45.654.321:12321\n",
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
kv = _read_dotenv_kv(env_file)
|
|
49
|
+
addr = kv.get("REMOTERF_ADDR", "").strip()
|
|
50
|
+
ca = kv.get("REMOTERF_CA_CERT", "").strip()
|
|
51
|
+
|
|
52
|
+
if not addr or not ca:
|
|
53
|
+
return (
|
|
54
|
+
False,
|
|
55
|
+
"RemoteRF config is incomplete.\n"
|
|
56
|
+
f"Expected REMOTERF_ADDR and REMOTERF_CA_CERT in:\n {env_file}\n"
|
|
57
|
+
"Fix by re-running:\n"
|
|
58
|
+
" remoterf --config --addr <host:port>\n",
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
ca_path = Path(ca).expanduser()
|
|
62
|
+
if not ca_path.exists():
|
|
63
|
+
return (
|
|
64
|
+
False,
|
|
65
|
+
"RemoteRF config points to a missing CA certificate.\n"
|
|
66
|
+
f"REMOTERF_CA_CERT={ca}\n"
|
|
67
|
+
"Fix by re-running:\n"
|
|
68
|
+
" remoterf --config --addr <host:port>\n",
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
return True, ""
|
|
72
|
+
|
|
73
|
+
def print_help() -> None:
|
|
74
|
+
print(
|
|
75
|
+
"RemoteRF CLI Help\n"
|
|
76
|
+
"\n"
|
|
77
|
+
"Usage:\n"
|
|
78
|
+
" remoterf Show this help\n"
|
|
79
|
+
" remoterf -h | --help Show this help\n"
|
|
80
|
+
"\n"
|
|
81
|
+
" remoterf -l | --login Login / register\n"
|
|
82
|
+
" remoterf -v | --version Print version\n"
|
|
83
|
+
"\n"
|
|
84
|
+
" remoterf -c | --config [options]\n"
|
|
85
|
+
" -a, --addr, -addr <host:port> Set target server \n"
|
|
86
|
+
" -w, --wipe, -wipe Delete all local config\n"
|
|
87
|
+
" -y, --yes, -yes Skip wipe confirmation\n"
|
|
88
|
+
"\n"
|
|
89
|
+
"Examples:\n"
|
|
90
|
+
" remoterf --login\n"
|
|
91
|
+
" remoterf --version\n"
|
|
92
|
+
" remoterf --config --addr 123.45.654.321:12321\n"
|
|
93
|
+
" remoterf --config --wipe\n"
|
|
94
|
+
" remoterf --config --wipe --yes\n"
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
def main() -> int:
|
|
98
|
+
argv = list(sys.argv[1:])
|
|
99
|
+
|
|
100
|
+
# ---- Debug ----
|
|
101
|
+
# print(f"argc={len(argv)}")
|
|
102
|
+
# for i, a in enumerate(argv):
|
|
103
|
+
# print(f"argv[{i}] = {a!r}")
|
|
104
|
+
|
|
105
|
+
if len(argv) == 0 or argv[0] in ("--help", "-help", "-h"):
|
|
106
|
+
print_help()
|
|
107
|
+
return 0
|
|
108
|
+
|
|
109
|
+
if argv[0] in ("--login", "-login", "-l"):
|
|
110
|
+
ok, msg = _ensure_config_present()
|
|
111
|
+
if not ok:
|
|
112
|
+
print(msg)
|
|
113
|
+
return 2
|
|
114
|
+
|
|
115
|
+
from remoteRF.core.acc_login import main as _
|
|
116
|
+
return 0
|
|
117
|
+
|
|
118
|
+
if argv[0] in ("--version", "-version", "-v"):
|
|
119
|
+
from remoteRF.core.version import main as version_main
|
|
120
|
+
|
|
121
|
+
print("RemoteRF version:", end=" ")
|
|
122
|
+
version_main()
|
|
123
|
+
return 0
|
|
124
|
+
|
|
125
|
+
if argv[0] in ("--config", "-config", "-c"):
|
|
126
|
+
from remoteRF.config.config import configure, wipe_config
|
|
127
|
+
|
|
128
|
+
addr = None
|
|
129
|
+
wipe = False
|
|
130
|
+
yes = False
|
|
131
|
+
|
|
132
|
+
i = 1
|
|
133
|
+
while i < len(argv):
|
|
134
|
+
tok = argv[i]
|
|
135
|
+
|
|
136
|
+
if tok in ("--addr", "-a", "-addr"):
|
|
137
|
+
if i + 1 >= len(argv):
|
|
138
|
+
print("ERROR: missing required argument after --addr/-a/-addr")
|
|
139
|
+
return 2
|
|
140
|
+
addr = argv[i + 1]
|
|
141
|
+
i += 2
|
|
142
|
+
continue
|
|
143
|
+
|
|
144
|
+
if tok in ("--wipe", "-w", "-wipe"):
|
|
145
|
+
wipe = True
|
|
146
|
+
i += 1
|
|
147
|
+
continue
|
|
148
|
+
|
|
149
|
+
if tok in ("--yes", "-y", "-yes"):
|
|
150
|
+
yes = True
|
|
151
|
+
i += 1
|
|
152
|
+
continue
|
|
153
|
+
|
|
154
|
+
print(f"ERROR: unknown config argument: {tok!r}")
|
|
155
|
+
return 2
|
|
156
|
+
|
|
157
|
+
# Mirror remoterf-config behavior:
|
|
158
|
+
if wipe and addr is not None:
|
|
159
|
+
print("ERROR: cannot use --wipe and --addr together")
|
|
160
|
+
return 2
|
|
161
|
+
|
|
162
|
+
if wipe:
|
|
163
|
+
# wipe_config returns the proper exit code
|
|
164
|
+
return int(wipe_config(yes=yes))
|
|
165
|
+
|
|
166
|
+
if addr is not None:
|
|
167
|
+
# parse host:port (minimal, strict)
|
|
168
|
+
s = addr.strip()
|
|
169
|
+
if "://" in s:
|
|
170
|
+
s = s.split("://", 1)[1]
|
|
171
|
+
if ":" not in s:
|
|
172
|
+
print("ERROR: addr must be in 'host:port' form")
|
|
173
|
+
return 2
|
|
174
|
+
|
|
175
|
+
host, port_str = s.rsplit(":", 1)
|
|
176
|
+
host = host.strip()
|
|
177
|
+
try:
|
|
178
|
+
port = int(port_str.strip())
|
|
179
|
+
except Exception:
|
|
180
|
+
print("ERROR: port must be an integer")
|
|
181
|
+
return 2
|
|
182
|
+
|
|
183
|
+
# configure returns the proper exit code
|
|
184
|
+
cert_port = port + 1
|
|
185
|
+
configure(host, port, cert_port)
|
|
186
|
+
return 0
|
|
187
|
+
|
|
188
|
+
# No args -> same behavior as remoterf-config missing addr (exit code 2)
|
|
189
|
+
print(
|
|
190
|
+
"\nError: missing required argument: host:port\n\n"
|
|
191
|
+
"Usage:\n"
|
|
192
|
+
" remoterf --config --addr <host:port>\n"
|
|
193
|
+
" remoterf -c -a <host:port>\n"
|
|
194
|
+
" remoterf --config --wipe [--yes]\n\n"
|
|
195
|
+
"Example:\n"
|
|
196
|
+
" remoterf --config --addr 123.45.678.901:12345\n"
|
|
197
|
+
)
|
|
198
|
+
return 2
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
# fallback
|
|
202
|
+
print(f"ERROR: unknown command: {argv[0]!r}")
|
|
203
|
+
return 2
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: remoterf
|
|
3
|
-
Version: 0.0.7.
|
|
3
|
+
Version: 0.0.7.52
|
|
4
4
|
Summary: A python API to remotely access signal centric hardware. Client-side only! Courtesy of Wireless Lab @ UCLA & Prof. Ian Roberts.
|
|
5
5
|
Author: Ethan Ge
|
|
6
6
|
Author-email: ethoGalaxy@gmail.com
|
|
@@ -3,7 +3,7 @@ MANIFEST.in
|
|
|
3
3
|
README.md
|
|
4
4
|
setup.py
|
|
5
5
|
src/remoteRF/__init__.py
|
|
6
|
-
src/remoteRF/
|
|
6
|
+
src/remoteRF/remoterf_cli.py
|
|
7
7
|
src/remoteRF.egg-info/PKG-INFO
|
|
8
8
|
src/remoteRF.egg-info/SOURCES.txt
|
|
9
9
|
src/remoteRF.egg-info/dependency_links.txt
|
|
@@ -21,7 +21,7 @@ src/remoteRF/common/utils/list_string.py
|
|
|
21
21
|
src/remoteRF/common/utils/process_arg.py
|
|
22
22
|
src/remoteRF/config/__init__.py
|
|
23
23
|
src/remoteRF/config/cert_fetcher.py
|
|
24
|
-
src/remoteRF/config/
|
|
24
|
+
src/remoteRF/config/config.py
|
|
25
25
|
src/remoteRF/core/__init__.py
|
|
26
26
|
src/remoteRF/core/acc_login.py
|
|
27
27
|
src/remoteRF/core/app.py
|
|
@@ -1,141 +0,0 @@
|
|
|
1
|
-
# src/remoteRF/cli.py
|
|
2
|
-
from __future__ import annotations
|
|
3
|
-
|
|
4
|
-
import argparse
|
|
5
|
-
import sys
|
|
6
|
-
from typing import Optional, Sequence
|
|
7
|
-
|
|
8
|
-
from remoteRF.core.acc_login import main as login_main
|
|
9
|
-
from remoteRF.core.version import main as version_main
|
|
10
|
-
from remoteRF.config.config_cli import main as config_main
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
def build_parser() -> argparse.ArgumentParser:
|
|
14
|
-
p = argparse.ArgumentParser(
|
|
15
|
-
prog="remoterf",
|
|
16
|
-
formatter_class=argparse.RawTextHelpFormatter,
|
|
17
|
-
add_help=True,
|
|
18
|
-
description=(
|
|
19
|
-
"RemoteRF unified CLI\n\n"
|
|
20
|
-
"Examples:\n"
|
|
21
|
-
" remoterf --login\n"
|
|
22
|
-
" remoterf -l\n"
|
|
23
|
-
" remoterf --config --addr 164.67.195.207:61005\n"
|
|
24
|
-
" remoterf -c -a 164.67.195.207:61005\n"
|
|
25
|
-
" remoterf --config --wipe\n"
|
|
26
|
-
" remoterf -v\n"
|
|
27
|
-
),
|
|
28
|
-
)
|
|
29
|
-
|
|
30
|
-
mode = p.add_mutually_exclusive_group()
|
|
31
|
-
|
|
32
|
-
mode.add_argument("-l", "--login", action="store_true", help="Login / register (interactive).")
|
|
33
|
-
mode.add_argument("-c", "--config", action="store_true", help="Configure server target / CA cert.")
|
|
34
|
-
mode.add_argument("-v", "--version", action="store_true", help="Print version and exit.")
|
|
35
|
-
|
|
36
|
-
# These are only meaningful with --config, but we accept them at top-level
|
|
37
|
-
# so your UX works as requested.
|
|
38
|
-
p.add_argument(
|
|
39
|
-
"-a", "--addr", "-addr",
|
|
40
|
-
dest="addr",
|
|
41
|
-
default=None,
|
|
42
|
-
help="Server address (host:port). Used with --config / -c.",
|
|
43
|
-
)
|
|
44
|
-
|
|
45
|
-
p.add_argument(
|
|
46
|
-
"-w", "--wipe",
|
|
47
|
-
action="store_true",
|
|
48
|
-
help="Wipe local config (~/.config/remoterf). Used with --config / -c.",
|
|
49
|
-
)
|
|
50
|
-
|
|
51
|
-
p.add_argument(
|
|
52
|
-
"--yes",
|
|
53
|
-
action="store_true",
|
|
54
|
-
help="Skip confirmation prompts (use with --config --wipe).",
|
|
55
|
-
)
|
|
56
|
-
|
|
57
|
-
return p
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
def main(argv: Optional[Sequence[str]] = None) -> int:
|
|
61
|
-
argv = list(sys.argv[1:] if argv is None else argv)
|
|
62
|
-
|
|
63
|
-
parser = build_parser()
|
|
64
|
-
|
|
65
|
-
# No args => help panel
|
|
66
|
-
if len(argv) == 0:
|
|
67
|
-
parser.print_help()
|
|
68
|
-
return 0
|
|
69
|
-
|
|
70
|
-
args, extra = parser.parse_known_args(argv)
|
|
71
|
-
|
|
72
|
-
# --- Version ---
|
|
73
|
-
if args.version:
|
|
74
|
-
if extra:
|
|
75
|
-
parser.error(f"Unexpected arguments for --version: {' '.join(extra)}")
|
|
76
|
-
# If your version_main supports argv, pass [].
|
|
77
|
-
try:
|
|
78
|
-
version_main([])
|
|
79
|
-
except TypeError:
|
|
80
|
-
version_main()
|
|
81
|
-
return 0
|
|
82
|
-
|
|
83
|
-
# --- Login ---
|
|
84
|
-
if args.login:
|
|
85
|
-
if extra:
|
|
86
|
-
parser.error(f"Unexpected arguments for --login: {' '.join(extra)}")
|
|
87
|
-
try:
|
|
88
|
-
login_main([])
|
|
89
|
-
except TypeError:
|
|
90
|
-
login_main()
|
|
91
|
-
return 0
|
|
92
|
-
|
|
93
|
-
# --- Config ---
|
|
94
|
-
if args.config:
|
|
95
|
-
cfg_argv: list[str] = []
|
|
96
|
-
|
|
97
|
-
# Normalize to whatever config_cli expects.
|
|
98
|
-
# If your config_cli supports --wipe/--yes, pass them through.
|
|
99
|
-
if args.wipe:
|
|
100
|
-
cfg_argv.append("--wipe")
|
|
101
|
-
if args.yes:
|
|
102
|
-
cfg_argv.append("--yes")
|
|
103
|
-
|
|
104
|
-
# Address handling
|
|
105
|
-
if args.addr:
|
|
106
|
-
# If config_cli expects a positional addr, pass it positionally:
|
|
107
|
-
cfg_argv.append(args.addr)
|
|
108
|
-
# If your config_cli instead expects --addr, switch to:
|
|
109
|
-
# cfg_argv += ["--addr", args.addr]
|
|
110
|
-
|
|
111
|
-
# Preserve any extra args for config_cli (if you want)
|
|
112
|
-
cfg_argv += extra
|
|
113
|
-
|
|
114
|
-
# If neither addr nor wipe was supplied, show config help-like message.
|
|
115
|
-
if not args.addr and not args.wipe and len(extra) == 0:
|
|
116
|
-
# Call config_cli with --help if it supports it; otherwise print ours.
|
|
117
|
-
try:
|
|
118
|
-
config_main(["--help"])
|
|
119
|
-
except Exception:
|
|
120
|
-
parser.error("Config mode requires --addr <host:port> or --wipe.")
|
|
121
|
-
return 0
|
|
122
|
-
|
|
123
|
-
try:
|
|
124
|
-
config_main(cfg_argv)
|
|
125
|
-
except TypeError:
|
|
126
|
-
# Fallback if config_main does not accept argv; last resort:
|
|
127
|
-
old = sys.argv[:]
|
|
128
|
-
try:
|
|
129
|
-
sys.argv = ["remoterf-config", *cfg_argv]
|
|
130
|
-
config_main()
|
|
131
|
-
finally:
|
|
132
|
-
sys.argv = old
|
|
133
|
-
return 0
|
|
134
|
-
|
|
135
|
-
# If user passed only -a/-w without -c/--config, show help
|
|
136
|
-
parser.print_help()
|
|
137
|
-
return 0
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
if __name__ == "__main__":
|
|
141
|
-
raise SystemExit(main())
|
|
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
|