mvsep-cli 1.0.0__py3-none-any.whl
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.
- mvsep_cli/__init__.py +0 -0
- mvsep_cli/__main__.py +527 -0
- mvsep_cli/api.py +257 -0
- mvsep_cli/config.py +1179 -0
- mvsep_cli-1.0.0.dist-info/METADATA +160 -0
- mvsep_cli-1.0.0.dist-info/RECORD +9 -0
- mvsep_cli-1.0.0.dist-info/WHEEL +5 -0
- mvsep_cli-1.0.0.dist-info/entry_points.txt +2 -0
- mvsep_cli-1.0.0.dist-info/top_level.txt +1 -0
mvsep_cli/__init__.py
ADDED
|
File without changes
|
mvsep_cli/__main__.py
ADDED
|
@@ -0,0 +1,527 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
import argparse
|
|
3
|
+
import sys
|
|
4
|
+
import os
|
|
5
|
+
import time
|
|
6
|
+
|
|
7
|
+
from mvsep_cli.api import MVSEP_API
|
|
8
|
+
from mvsep_cli.config import Config, get_api_token
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def cmd_upload(args):
|
|
12
|
+
import sys
|
|
13
|
+
|
|
14
|
+
api = MVSEP_API(get_api_token())
|
|
15
|
+
config = Config()
|
|
16
|
+
|
|
17
|
+
output_format = (
|
|
18
|
+
args.output_format
|
|
19
|
+
if args.output_format is not None
|
|
20
|
+
else config.default_output_format
|
|
21
|
+
)
|
|
22
|
+
sep_type = args.sep_type if args.sep_type is not None else config.default_sep_type
|
|
23
|
+
|
|
24
|
+
print(f"Audio file: {args.audio_file}", flush=True)
|
|
25
|
+
print(f"Separation type: {sep_type}", flush=True)
|
|
26
|
+
print(f"Output format: {output_format}", flush=True)
|
|
27
|
+
print("Note: Uploading large file, please wait...", flush=True)
|
|
28
|
+
|
|
29
|
+
result = api.create_task(
|
|
30
|
+
audio_file=args.audio_file,
|
|
31
|
+
sep_type=sep_type,
|
|
32
|
+
output_format=output_format,
|
|
33
|
+
add_opt1=args.add_opt1,
|
|
34
|
+
add_opt2=args.add_opt2,
|
|
35
|
+
is_demo=args.is_demo,
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
hash_val = result["hash"]
|
|
39
|
+
print(f"\nTask created!", flush=True)
|
|
40
|
+
print(f"Hash: {hash_val}", flush=True)
|
|
41
|
+
print(f"Link: {result['link']}", flush=True)
|
|
42
|
+
print(f"\nUse following commands to check status:", flush=True)
|
|
43
|
+
print(f" mvsep status {hash_val}", flush=True)
|
|
44
|
+
print(f" mvsep wait {hash_val}", flush=True)
|
|
45
|
+
print(f" mvsep download {hash_val}", flush=True)
|
|
46
|
+
|
|
47
|
+
if args.wait:
|
|
48
|
+
interval = args.interval if args.interval is not None else config.poll_interval
|
|
49
|
+
print("\nWaiting for completion...")
|
|
50
|
+
try:
|
|
51
|
+
final_result = api.wait_for_completion(
|
|
52
|
+
hash_val, interval=interval, max_wait=args.timeout
|
|
53
|
+
)
|
|
54
|
+
status = final_result.get("status")
|
|
55
|
+
if status == "done":
|
|
56
|
+
output_dir = (
|
|
57
|
+
args.output_dir if args.output_dir else config.default_output_dir
|
|
58
|
+
)
|
|
59
|
+
if not output_dir:
|
|
60
|
+
output_dir = os.path.dirname(os.path.abspath(args.audio_file))
|
|
61
|
+
downloaded = api.download_results(hash_val, output_dir)
|
|
62
|
+
print(f"\nDownloaded {len(downloaded)} files:")
|
|
63
|
+
for f in downloaded:
|
|
64
|
+
print(f" - {f}")
|
|
65
|
+
return 0
|
|
66
|
+
except TimeoutError:
|
|
67
|
+
print(
|
|
68
|
+
f"\nTimeout, but task is still running. Use 'mvsep wait {hash_val}' to continue waiting."
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
return 0
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def cmd_status(args):
|
|
75
|
+
api = MVSEP_API(get_api_token())
|
|
76
|
+
|
|
77
|
+
result = api.get_status(args.hash)
|
|
78
|
+
status = result.get("status")
|
|
79
|
+
|
|
80
|
+
print(f"Task hash: {args.hash}")
|
|
81
|
+
print(f"Status: {status}")
|
|
82
|
+
|
|
83
|
+
if status == "done":
|
|
84
|
+
data = result.get("data", {})
|
|
85
|
+
print(f"Algorithm: {data.get('algorithm')}")
|
|
86
|
+
print(f"Output format: {data.get('output_format')}")
|
|
87
|
+
files = data.get("files", [])
|
|
88
|
+
print(f"Output files ({len(files)}):")
|
|
89
|
+
for f in files:
|
|
90
|
+
name = f.get("name") or "unknown"
|
|
91
|
+
url = f.get("url", "N/A")
|
|
92
|
+
print(f" - {name}: {url}")
|
|
93
|
+
elif status == "failed":
|
|
94
|
+
msg = result.get("data", {}).get("message", "Unknown error")
|
|
95
|
+
print(f"Error: {msg}")
|
|
96
|
+
elif status in ("waiting", "distributing"):
|
|
97
|
+
queue = result.get("data", {}).get("queue_count", "?")
|
|
98
|
+
order = result.get("data", {}).get("current_order", "?")
|
|
99
|
+
print(f"Queue count: {queue}")
|
|
100
|
+
print(f"Current order: {order}")
|
|
101
|
+
elif status == "processing":
|
|
102
|
+
print("Task is being processed...")
|
|
103
|
+
elif status == "merging":
|
|
104
|
+
chunks = result.get("data", {}).get("finished_chunks", "?")
|
|
105
|
+
total = result.get("data", {}).get("all_chunks", "?")
|
|
106
|
+
print(f"Merging: {chunks}/{total} chunks")
|
|
107
|
+
|
|
108
|
+
return 0 if status == "done" else 1
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def cmd_wait(args):
|
|
112
|
+
api = MVSEP_API(get_api_token())
|
|
113
|
+
config = Config()
|
|
114
|
+
|
|
115
|
+
interval = args.interval if args.interval is not None else config.poll_interval
|
|
116
|
+
|
|
117
|
+
print(f"Waiting for task {args.hash} to complete...")
|
|
118
|
+
print(f"Polling interval: {interval}s")
|
|
119
|
+
|
|
120
|
+
try:
|
|
121
|
+
result = api.wait_for_completion(
|
|
122
|
+
args.hash, interval=interval, max_wait=args.timeout
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
status = result.get("status")
|
|
126
|
+
|
|
127
|
+
if status == "done":
|
|
128
|
+
print("\nTask completed successfully!")
|
|
129
|
+
data = result.get("data", {})
|
|
130
|
+
print(f"Algorithm: {data.get('algorithm')}")
|
|
131
|
+
files = data.get("files", [])
|
|
132
|
+
print(f"Output files: {len(files)}")
|
|
133
|
+
return 0
|
|
134
|
+
elif status == "failed":
|
|
135
|
+
msg = result.get("data", {}).get("message", "Unknown error")
|
|
136
|
+
print(f"\nTask failed: {msg}")
|
|
137
|
+
return 1
|
|
138
|
+
else:
|
|
139
|
+
print(f"\nTask status: {status}")
|
|
140
|
+
return 1
|
|
141
|
+
|
|
142
|
+
except TimeoutError as e:
|
|
143
|
+
print(f"\nTimeout: {e}")
|
|
144
|
+
return 1
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
def cmd_download(args):
|
|
148
|
+
api = MVSEP_API(get_api_token())
|
|
149
|
+
config = Config()
|
|
150
|
+
|
|
151
|
+
output_dir = args.output_dir if args.output_dir else config.default_output_dir
|
|
152
|
+
|
|
153
|
+
print(f"Downloading results for {args.hash}...")
|
|
154
|
+
|
|
155
|
+
downloaded = api.download_results(args.hash, output_dir)
|
|
156
|
+
|
|
157
|
+
print(f"\nDownloaded {len(downloaded)} files:")
|
|
158
|
+
for f in downloaded:
|
|
159
|
+
print(f" - {f}")
|
|
160
|
+
|
|
161
|
+
return 0
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
def cmd_run(args):
|
|
165
|
+
api = MVSEP_API(get_api_token())
|
|
166
|
+
config = Config()
|
|
167
|
+
|
|
168
|
+
# Use args value if provided, otherwise use config default
|
|
169
|
+
output_format = (
|
|
170
|
+
args.output_format
|
|
171
|
+
if args.output_format is not None
|
|
172
|
+
else config.default_output_format
|
|
173
|
+
)
|
|
174
|
+
# sep_type is required, no default
|
|
175
|
+
sep_type = args.sep_type if args.sep_type is not None else None
|
|
176
|
+
interval = args.interval if args.interval is not None else config.poll_interval
|
|
177
|
+
|
|
178
|
+
if sep_type is None:
|
|
179
|
+
print(
|
|
180
|
+
"Error: sep_type is required. Use -t <type> or mvsep list to see available types."
|
|
181
|
+
)
|
|
182
|
+
return 1
|
|
183
|
+
|
|
184
|
+
print(f"Starting separation task for: {args.audio_file}")
|
|
185
|
+
print(f"Separation type: {sep_type}")
|
|
186
|
+
print(f"Output format: {output_format}")
|
|
187
|
+
|
|
188
|
+
result = api.create_task(
|
|
189
|
+
audio_file=args.audio_file,
|
|
190
|
+
sep_type=sep_type,
|
|
191
|
+
output_format=output_format,
|
|
192
|
+
add_opt1=args.add_opt1,
|
|
193
|
+
add_opt2=args.add_opt2,
|
|
194
|
+
is_demo=args.is_demo,
|
|
195
|
+
)
|
|
196
|
+
|
|
197
|
+
hash_value = result["hash"]
|
|
198
|
+
print(f"\nTask created! Hash: {hash_value}")
|
|
199
|
+
print("Waiting for completion...")
|
|
200
|
+
|
|
201
|
+
try:
|
|
202
|
+
final_result = api.wait_for_completion(
|
|
203
|
+
hash_value, interval=interval, max_wait=args.timeout
|
|
204
|
+
)
|
|
205
|
+
|
|
206
|
+
status = final_result.get("status")
|
|
207
|
+
|
|
208
|
+
if status == "done":
|
|
209
|
+
print("\nSeparation completed!")
|
|
210
|
+
|
|
211
|
+
output_dir = (
|
|
212
|
+
args.output_dir if args.output_dir else config.default_output_dir
|
|
213
|
+
)
|
|
214
|
+
if not output_dir:
|
|
215
|
+
output_dir = os.path.dirname(os.path.abspath(args.audio_file))
|
|
216
|
+
downloaded = api.download_results(hash_value, output_dir)
|
|
217
|
+
|
|
218
|
+
print(f"\nDownloaded {len(downloaded)} files:")
|
|
219
|
+
for f in downloaded:
|
|
220
|
+
print(f" - {f}")
|
|
221
|
+
|
|
222
|
+
return 0
|
|
223
|
+
else:
|
|
224
|
+
print(f"\nTask ended with status: {status}")
|
|
225
|
+
return 1
|
|
226
|
+
|
|
227
|
+
except TimeoutError as e:
|
|
228
|
+
print(f"\nTimeout: {e}")
|
|
229
|
+
return 1
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
def cmd_config(args):
|
|
233
|
+
config = Config()
|
|
234
|
+
|
|
235
|
+
if not args.subcommand:
|
|
236
|
+
print(
|
|
237
|
+
"Usage: mvsep config <show|set-token|set-mirror|set-output-dir|set-output-format|set-interval>"
|
|
238
|
+
)
|
|
239
|
+
print("\nCommands:")
|
|
240
|
+
print(" show Show current config")
|
|
241
|
+
print(" set-token <token> Set API token")
|
|
242
|
+
print(" set-mirror <mirror> Set mirror (main/mirror)")
|
|
243
|
+
print(" set-output-dir <dir> Set default output directory")
|
|
244
|
+
print(" set-output-format <val> Set default output format")
|
|
245
|
+
print(" set-interval <val> Set poll interval")
|
|
246
|
+
return 0
|
|
247
|
+
|
|
248
|
+
if args.subcommand == "show":
|
|
249
|
+
print(
|
|
250
|
+
f"API Token: {'*' * 8}{config.api_token[-4:] if config.api_token else 'Not set'}"
|
|
251
|
+
)
|
|
252
|
+
print(f"Mirror: {config.mirror} ({config.base_url})")
|
|
253
|
+
print(f"Default output_dir: {config.default_output_dir}")
|
|
254
|
+
print(f"Default output_format: {config.default_output_format}")
|
|
255
|
+
print(f"Poll interval: {config.poll_interval}s")
|
|
256
|
+
|
|
257
|
+
elif args.subcommand == "set-token":
|
|
258
|
+
if not args.token:
|
|
259
|
+
print("Error: Token required. Usage: mvsep config set-token <token>")
|
|
260
|
+
return 1
|
|
261
|
+
config.api_token = args.token
|
|
262
|
+
print("API token saved!")
|
|
263
|
+
|
|
264
|
+
elif args.subcommand == "set-mirror":
|
|
265
|
+
if not args.value:
|
|
266
|
+
print(
|
|
267
|
+
"Error: Mirror required. Usage: mvsep config set-mirror <main|mirror>"
|
|
268
|
+
)
|
|
269
|
+
return 1
|
|
270
|
+
try:
|
|
271
|
+
config.mirror = args.value
|
|
272
|
+
print(f"Mirror set to: {args.value} ({config.base_url})")
|
|
273
|
+
except ValueError as e:
|
|
274
|
+
print(f"Error: {e}")
|
|
275
|
+
return 1
|
|
276
|
+
|
|
277
|
+
elif args.subcommand == "set-output-dir":
|
|
278
|
+
config.default_output_dir = args.value
|
|
279
|
+
print(f"Default output_dir set to: {args.value}")
|
|
280
|
+
|
|
281
|
+
elif args.subcommand == "set-output-format":
|
|
282
|
+
config.default_output_format = args.value
|
|
283
|
+
print(f"Default output_format set to: {args.value}")
|
|
284
|
+
|
|
285
|
+
elif args.subcommand == "set-interval":
|
|
286
|
+
config.poll_interval = args.value
|
|
287
|
+
print(f"Poll interval set to: {args.value}s")
|
|
288
|
+
|
|
289
|
+
return 0
|
|
290
|
+
|
|
291
|
+
|
|
292
|
+
def cmd_history(args):
|
|
293
|
+
import json
|
|
294
|
+
from mvsep_cli.api import TASK_META_FILE
|
|
295
|
+
|
|
296
|
+
if not os.path.exists(TASK_META_FILE):
|
|
297
|
+
print("No task history found.")
|
|
298
|
+
return 0
|
|
299
|
+
|
|
300
|
+
with open(TASK_META_FILE, "r") as f:
|
|
301
|
+
meta = json.load(f)
|
|
302
|
+
|
|
303
|
+
if not meta:
|
|
304
|
+
print("No task history found.")
|
|
305
|
+
return 0
|
|
306
|
+
|
|
307
|
+
print(f"Task history ({len(meta)} tasks):")
|
|
308
|
+
print()
|
|
309
|
+
for hash_val, info in meta.items():
|
|
310
|
+
original_name = info.get("original_name", "unknown")
|
|
311
|
+
print(f" {hash_val}")
|
|
312
|
+
print(f" Original file: {original_name}")
|
|
313
|
+
print(f" Download: mvsep download {hash_val}")
|
|
314
|
+
print()
|
|
315
|
+
|
|
316
|
+
|
|
317
|
+
def cmd_list_types(args):
|
|
318
|
+
config = Config()
|
|
319
|
+
|
|
320
|
+
if args.models:
|
|
321
|
+
sep_type = args.models
|
|
322
|
+
model_opts = config.get_model_options(sep_type)
|
|
323
|
+
sep_name = config.SEP_TYPES.get(sep_type, "Unknown")
|
|
324
|
+
|
|
325
|
+
print(f"Separation type: {sep_type} - {sep_name}")
|
|
326
|
+
|
|
327
|
+
if not model_opts:
|
|
328
|
+
print("No additional model options for this separation type.")
|
|
329
|
+
return 0
|
|
330
|
+
|
|
331
|
+
for opt_key, opt_list in model_opts.items():
|
|
332
|
+
print(f"\n{opt_key}:")
|
|
333
|
+
for opt in opt_list:
|
|
334
|
+
print(f" {opt['value']:>3} - {opt['name']}")
|
|
335
|
+
return 0
|
|
336
|
+
|
|
337
|
+
if args.search:
|
|
338
|
+
keyword = args.search.lower()
|
|
339
|
+
results = [
|
|
340
|
+
(val, name)
|
|
341
|
+
for val, name in Config.SEP_TYPES.items()
|
|
342
|
+
if keyword in name.lower()
|
|
343
|
+
]
|
|
344
|
+
if results:
|
|
345
|
+
print(f"Search results for '{args.search}':")
|
|
346
|
+
for val, name in results:
|
|
347
|
+
print(f" {val}: {name}")
|
|
348
|
+
else:
|
|
349
|
+
print(f"No results found for '{args.search}'")
|
|
350
|
+
return 0
|
|
351
|
+
|
|
352
|
+
if args.popular:
|
|
353
|
+
print("Popular separation types:")
|
|
354
|
+
for val, name in Config.POPULAR_SEP_TYPES.items():
|
|
355
|
+
print(f" {val}: {name}")
|
|
356
|
+
elif args.formats:
|
|
357
|
+
print("All output formats:")
|
|
358
|
+
for val, name in Config.OUTPUT_FORMATS.items():
|
|
359
|
+
print(f" {val}: {name}")
|
|
360
|
+
else:
|
|
361
|
+
print("All separation types:")
|
|
362
|
+
for val, name in Config.SEP_TYPES.items():
|
|
363
|
+
print(f" {val}: {name}")
|
|
364
|
+
|
|
365
|
+
return 0
|
|
366
|
+
|
|
367
|
+
|
|
368
|
+
def main():
|
|
369
|
+
parser = argparse.ArgumentParser(
|
|
370
|
+
description="MVSEP CLI - Music separation tool",
|
|
371
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
372
|
+
)
|
|
373
|
+
|
|
374
|
+
subparsers = parser.add_subparsers(dest="command", help="Commands")
|
|
375
|
+
|
|
376
|
+
p_upload = subparsers.add_parser(
|
|
377
|
+
"upload", help="Upload audio and create separation task"
|
|
378
|
+
)
|
|
379
|
+
p_upload.add_argument("audio_file", help="Audio file to process")
|
|
380
|
+
p_upload.add_argument(
|
|
381
|
+
"-t",
|
|
382
|
+
"--sep-type",
|
|
383
|
+
type=int,
|
|
384
|
+
default=None,
|
|
385
|
+
help="Separation type (default: config value)",
|
|
386
|
+
)
|
|
387
|
+
p_upload.add_argument(
|
|
388
|
+
"-f",
|
|
389
|
+
"--output-format",
|
|
390
|
+
type=int,
|
|
391
|
+
default=None,
|
|
392
|
+
help="Output format (default: config value)",
|
|
393
|
+
)
|
|
394
|
+
p_upload.add_argument("--add-opt1", help="Additional option 1")
|
|
395
|
+
p_upload.add_argument("--add-opt2", help="Additional option 2")
|
|
396
|
+
p_upload.add_argument(
|
|
397
|
+
"--demo", dest="is_demo", action="store_true", help="Publish to demo page"
|
|
398
|
+
)
|
|
399
|
+
p_upload.add_argument(
|
|
400
|
+
"--wait", action="store_true", help="Wait for completion after upload"
|
|
401
|
+
)
|
|
402
|
+
p_upload.add_argument(
|
|
403
|
+
"-o",
|
|
404
|
+
"--output-dir",
|
|
405
|
+
type=str,
|
|
406
|
+
default=None,
|
|
407
|
+
help="Output directory for downloaded files",
|
|
408
|
+
)
|
|
409
|
+
p_upload.add_argument(
|
|
410
|
+
"-i", "--interval", type=int, default=None, help="Poll interval in seconds"
|
|
411
|
+
)
|
|
412
|
+
p_upload.add_argument("--timeout", type=int, help="Max wait time in seconds")
|
|
413
|
+
p_upload.set_defaults(func=cmd_upload)
|
|
414
|
+
|
|
415
|
+
p_status = subparsers.add_parser("status", help="Check task status")
|
|
416
|
+
p_status.add_argument("hash", help="Task hash")
|
|
417
|
+
p_status.set_defaults(func=cmd_status)
|
|
418
|
+
|
|
419
|
+
p_wait = subparsers.add_parser("wait", help="Wait for task completion")
|
|
420
|
+
p_wait.add_argument("hash", help="Task hash")
|
|
421
|
+
p_wait.add_argument(
|
|
422
|
+
"-i", "--interval", type=int, default=None, help="Poll interval in seconds"
|
|
423
|
+
)
|
|
424
|
+
p_wait.add_argument("--timeout", type=int, help="Max wait time in seconds")
|
|
425
|
+
p_wait.set_defaults(func=cmd_wait)
|
|
426
|
+
|
|
427
|
+
p_download = subparsers.add_parser("download", help="Download results")
|
|
428
|
+
p_download.add_argument("hash", help="Task hash")
|
|
429
|
+
p_download.add_argument("-o", "--output-dir", default=None, help="Output directory")
|
|
430
|
+
p_download.set_defaults(func=cmd_download)
|
|
431
|
+
|
|
432
|
+
p_run = subparsers.add_parser(
|
|
433
|
+
"run", help="Run full workflow (upload + wait + download)"
|
|
434
|
+
)
|
|
435
|
+
p_run.add_argument("audio_file", help="Audio file to process")
|
|
436
|
+
p_run.add_argument(
|
|
437
|
+
"-t",
|
|
438
|
+
"--sep-type",
|
|
439
|
+
type=int,
|
|
440
|
+
default=None,
|
|
441
|
+
help="Separation type (default: config value)",
|
|
442
|
+
)
|
|
443
|
+
p_run.add_argument(
|
|
444
|
+
"-f",
|
|
445
|
+
"--output-format",
|
|
446
|
+
type=int,
|
|
447
|
+
default=None,
|
|
448
|
+
help="Output format (default: config value)",
|
|
449
|
+
)
|
|
450
|
+
p_run.add_argument("--add-opt1", help="Additional option 1")
|
|
451
|
+
p_run.add_argument("--add-opt2", help="Additional option 2")
|
|
452
|
+
p_run.add_argument(
|
|
453
|
+
"--demo", dest="is_demo", action="store_true", help="Publish to demo page"
|
|
454
|
+
)
|
|
455
|
+
p_run.add_argument(
|
|
456
|
+
"-o", "--output-dir", type=str, default=None, help="Output directory"
|
|
457
|
+
)
|
|
458
|
+
p_run.add_argument(
|
|
459
|
+
"-i", "--interval", type=int, default=None, help="Poll interval in seconds"
|
|
460
|
+
)
|
|
461
|
+
p_run.add_argument("--timeout", type=int, help="Max wait time in seconds")
|
|
462
|
+
p_run.set_defaults(func=cmd_run)
|
|
463
|
+
|
|
464
|
+
p_config = subparsers.add_parser("config", help="Configuration management")
|
|
465
|
+
p_config_sub = p_config.add_subparsers(dest="subcommand", help="Config commands")
|
|
466
|
+
p_config_sub.add_parser("show", help="Show current config")
|
|
467
|
+
p_config_set = p_config_sub.add_parser("set-token", help="Set API token")
|
|
468
|
+
p_config_set.add_argument("token", help="API token")
|
|
469
|
+
|
|
470
|
+
p_set_dir = p_config_sub.add_parser(
|
|
471
|
+
"set-output-dir", help="Set default output directory"
|
|
472
|
+
)
|
|
473
|
+
p_set_dir.add_argument("value", type=str, help="Directory path")
|
|
474
|
+
|
|
475
|
+
p_set_mirror = p_config_sub.add_parser(
|
|
476
|
+
"set-mirror", help="Set mirror (main or mirror)"
|
|
477
|
+
)
|
|
478
|
+
p_set_mirror.add_argument("value", type=str, help="Mirror: main or mirror")
|
|
479
|
+
|
|
480
|
+
p_set_fmt = p_config_sub.add_parser(
|
|
481
|
+
"set-output-format", help="Set default output format"
|
|
482
|
+
)
|
|
483
|
+
p_set_fmt.add_argument("value", type=int, help="Value")
|
|
484
|
+
|
|
485
|
+
p_set_int = p_config_sub.add_parser("set-interval", help="Set poll interval")
|
|
486
|
+
p_set_int.add_argument("value", type=int, help="Value")
|
|
487
|
+
|
|
488
|
+
p_config.set_defaults(func=cmd_config)
|
|
489
|
+
|
|
490
|
+
p_list = subparsers.add_parser("list", help="List available options")
|
|
491
|
+
p_list.add_argument(
|
|
492
|
+
"--popular", action="store_true", help="Show popular separation types"
|
|
493
|
+
)
|
|
494
|
+
p_list.add_argument("--formats", action="store_true", help="Show output formats")
|
|
495
|
+
p_list.add_argument(
|
|
496
|
+
"--models",
|
|
497
|
+
type=int,
|
|
498
|
+
metavar="SEP_TYPE",
|
|
499
|
+
help="Show model options for a separation type",
|
|
500
|
+
)
|
|
501
|
+
p_list.add_argument(
|
|
502
|
+
"-s",
|
|
503
|
+
"--search",
|
|
504
|
+
type=str,
|
|
505
|
+
metavar="KEYWORD",
|
|
506
|
+
help="Search separation types by keyword",
|
|
507
|
+
)
|
|
508
|
+
p_list.set_defaults(func=cmd_list_types)
|
|
509
|
+
|
|
510
|
+
p_history = subparsers.add_parser("history", help="Show task history")
|
|
511
|
+
p_history.set_defaults(func=cmd_history)
|
|
512
|
+
|
|
513
|
+
args = parser.parse_args()
|
|
514
|
+
|
|
515
|
+
if not args.command:
|
|
516
|
+
parser.print_help()
|
|
517
|
+
return 1
|
|
518
|
+
|
|
519
|
+
try:
|
|
520
|
+
return args.func(args) or 0
|
|
521
|
+
except Exception as e:
|
|
522
|
+
print(f"Error: {e}", file=sys.stderr)
|
|
523
|
+
return 1
|
|
524
|
+
|
|
525
|
+
|
|
526
|
+
if __name__ == "__main__":
|
|
527
|
+
sys.exit(main())
|