This commit is contained in:
nose
2025-12-05 03:42:57 -08:00
parent 5e4df11dbf
commit 5482ee5586
20 changed files with 911 additions and 223 deletions

174
CLI.py
View File

@@ -407,24 +407,27 @@ def _get_cmdlet_names() -> List[str]:
return []
def _import_cmd_module(mod_name: str):
"""Import a cmdlet/native module from cmdlets or cmdnats packages."""
for package in ("cmdlets", "cmdnats", None):
try:
qualified = f"{package}.{mod_name}" if package else mod_name
return import_module(qualified)
except ModuleNotFoundError:
continue
except Exception:
continue
return None
def _get_cmdlet_args(cmd_name: str) -> List[str]:
"""Get list of argument flags for a cmdlet (with - and -- prefixes)."""
try:
# Try to load CMDLET object from the module
mod_name = cmd_name.replace("-", "_")
# Try importing as cmdlet first, then as root-level module
data = None
try:
mod = import_module(f"cmdlets.{mod_name}")
mod = _import_cmd_module(mod_name)
if mod:
data = getattr(mod, "CMDLET", None)
except (ModuleNotFoundError, ImportError):
try:
# Try root-level modules like search_soulseek
mod = import_module(mod_name)
data = getattr(mod, "CMDLET", None)
except (ModuleNotFoundError, ImportError):
pass
if data:
# If CMDLET is an object (not dict), use build_flag_registry if available
@@ -458,25 +461,56 @@ def _get_arg_choices(cmd_name: str, arg_name: str) -> List[str]:
"""Get list of valid choices for a specific cmdlet argument."""
try:
mod_name = cmd_name.replace("-", "_")
try:
mod = import_module(f"cmdlets.{mod_name}")
data = getattr(mod, "CMDLET", None)
if data:
args_list = data.get("args", []) if isinstance(data, dict) else getattr(data, "args", [])
for arg in args_list:
normalized_arg = arg_name.lstrip("-")
# Dynamic storage backends: use current config to enumerate available storages
if normalized_arg == "storage":
try:
from helper.file_storage import FileStorage
storage = FileStorage(_load_cli_config())
backends = storage.list_backends()
if backends:
return backends
except Exception:
pass
# Dynamic search providers
if normalized_arg == "provider":
try:
from helper.search_provider import list_providers
providers = list_providers(_load_cli_config())
available = [name for name, is_ready in providers.items() if is_ready]
provider_choices = sorted(available) if available else sorted(providers.keys())
except Exception:
provider_choices = []
try:
from helper.metadata_search import list_metadata_providers
meta_providers = list_metadata_providers(_load_cli_config())
meta_available = [n for n, ready in meta_providers.items() if ready]
meta_choices = sorted(meta_available) if meta_available else sorted(meta_providers.keys())
except Exception:
meta_choices = []
merged = sorted(set(provider_choices + meta_choices))
if merged:
return merged
mod = _import_cmd_module(mod_name)
data = getattr(mod, "CMDLET", None) if mod else None
if data:
args_list = data.get("args", []) if isinstance(data, dict) else getattr(data, "args", [])
for arg in args_list:
if isinstance(arg, dict):
arg_obj_name = arg.get("name", "")
else:
arg_obj_name = getattr(arg, "name", "")
if arg_obj_name == arg_name:
# Found matching arg, get choices
if isinstance(arg, dict):
arg_obj_name = arg.get("name", "")
return arg.get("choices", [])
else:
arg_obj_name = getattr(arg, "name", "")
if arg_obj_name == arg_name:
# Found matching arg, get choices
if isinstance(arg, dict):
return arg.get("choices", [])
else:
return getattr(arg, "choices", [])
except ModuleNotFoundError:
pass
return getattr(arg, "choices", [])
return []
except Exception:
return []
@@ -1575,43 +1609,40 @@ def _show_cmdlet_list():
from cmdlets import REGISTRY
import os
# Collect unique commands by scanning cmdlet modules
cmdlet_info = {}
cmdlets_dir = os.path.join(os.path.dirname(__file__), "cmdlets")
# Iterate through cmdlet files
for filename in os.listdir(cmdlets_dir):
if filename.endswith(".py") and not filename.startswith("_"):
mod_name = filename[:-3]
try:
mod = import_module(f"cmdlets.{mod_name}")
if hasattr(mod, "CMDLET"):
cmdlet = getattr(mod, "CMDLET")
# Extract name, aliases, and args
if hasattr(cmdlet, "name"):
cmd_name = cmdlet.name
aliases = []
if hasattr(cmdlet, "aliases"):
aliases = cmdlet.aliases
# Extract argument names
arg_names = []
if hasattr(cmdlet, "args"):
for arg in cmdlet.args:
if hasattr(arg, "name"):
arg_names.append(arg.name)
elif isinstance(arg, dict):
arg_names.append(arg.get("name", ""))
# Store info (skip if already seen)
if cmd_name not in cmdlet_info:
cmdlet_info[cmd_name] = {
"aliases": aliases,
"args": arg_names,
}
except Exception:
# If we can't import the module, try to get info from REGISTRY
pass
base_dir = os.path.dirname(__file__)
def _collect_cmdlets_from_dir(folder: str, package: str) -> None:
if not os.path.isdir(folder):
return
for filename in os.listdir(folder):
if filename.endswith(".py") and not filename.startswith("_") and filename != "__init__.py":
mod_name = filename[:-3]
try:
mod = import_module(f"{package}.{mod_name}")
if hasattr(mod, "CMDLET"):
cmdlet = getattr(mod, "CMDLET")
if hasattr(cmdlet, "name"):
cmd_name = cmdlet.name
aliases = getattr(cmdlet, "aliases", []) if hasattr(cmdlet, "aliases") else []
arg_names = []
if hasattr(cmdlet, "args"):
for arg in cmdlet.args:
if hasattr(arg, "name"):
arg_names.append(arg.name)
elif isinstance(arg, dict):
arg_names.append(arg.get("name", ""))
if cmd_name not in cmdlet_info:
cmdlet_info[cmd_name] = {
"aliases": aliases,
"args": arg_names,
}
except Exception:
pass
_collect_cmdlets_from_dir(os.path.join(base_dir, "cmdlets"), "cmdlets")
_collect_cmdlets_from_dir(os.path.join(base_dir, "cmdnats"), "cmdnats")
# Also check root-level cmdlets (search_*, etc)
# Note: search_libgen, search_soulseek, and search_debrid are consolidated into search-file with providers
@@ -1700,14 +1731,11 @@ def _show_cmdlet_help(cmd_name: str):
"""Display help for a cmdlet."""
try:
mod_name = cmd_name.replace("-", "_")
try:
mod = import_module(f"cmdlets.{mod_name}")
data = getattr(mod, "CMDLET", None)
if data:
_print_metadata(cmd_name, data)
return
except ModuleNotFoundError:
pass
mod = _import_cmd_module(mod_name)
data = getattr(mod, "CMDLET", None) if mod else None
if data:
_print_metadata(cmd_name, data)
return
from cmdlets import REGISTRY
cmd_fn = REGISTRY.get(cmd_name)