HTTP: prefer pip-system-certs/certifi_win32 bundle; use init-time verify in retries; add tests

This commit is contained in:
2026-01-05 13:09:24 -08:00
parent 1f765cffda
commit ac1d1d634f
12 changed files with 19424 additions and 2371 deletions

238
cmdlet/select_item.py Normal file
View File

@@ -0,0 +1,238 @@
from __future__ import annotations
from typing import Any, Dict, List, Sequence
from . import _shared as sh
from SYS.logger import log, debug
from SYS import pipeline as ctx
from SYS.result_table_api import ResultModel
from SYS.result_table_adapters import get_provider
from SYS.result_table_renderers import RichRenderer
Cmdlet = sh.Cmdlet
CmdletArg = sh.CmdletArg
parse_cmdlet_args = sh.parse_cmdlet_args
normalize_result_input = sh.normalize_result_input
CMDLET = Cmdlet(
name="select",
summary="Select items from a piped result set (interactive or via -select) and emit the selected item(s).",
usage="select -select <n|1-3|1,3> [-multi] [-run-cmd <name>]",
arg=[
CmdletArg("select", type="string", description="Selection string (e.g., 1, 2-4)", alias="s"),
CmdletArg("multi", type="flag", description="Allow multiple selections."),
CmdletArg("interactive", type="flag", description="Prompt interactively for selection."),
CmdletArg("run-cmd", type="string", description="Cmdlet to invoke with selected items (each)"),
],
detail=[
"Accepts piped input from provider-table or other sources and emits the selected item(s) as dicts.",
"If -run-cmd is provided, invokes the named cmdlet for each selected item with selector args and the item as piped input.",
],
)
def _parse_selection(selection: str, max_len: int) -> List[int]:
"""Parse a selection string like '1', '1-3', '1,3,5-7' into 0-based indices."""
if not selection:
return []
parts = [p.strip() for p in str(selection).split(",") if p.strip()]
indices = set()
for part in parts:
if "-" in part:
try:
a, b = part.split("-", 1)
start = int(a.strip())
end = int(b.strip())
if start > end:
start, end = end, start
for i in range(start, end + 1):
if 1 <= i <= max_len:
indices.add(i - 1)
except Exception:
raise ValueError(f"Invalid range: {part}")
else:
try:
v = int(part)
if 1 <= v <= max_len:
indices.add(v - 1)
except Exception:
raise ValueError(f"Invalid selection: {part}")
return sorted(indices)
def _dict_to_result_model(d: Dict[str, Any]) -> ResultModel:
if isinstance(d, ResultModel):
return d
# Allow dicts or objects with attributes
title = d.get("title") or d.get("name") or (d.get("path") and str(d.get("path")).split("/")[-1])
return ResultModel(
title=str(title) if title is not None else "",
path=d.get("path") if d.get("path") is not None else None,
ext=d.get("ext") if d.get("ext") is not None else None,
size_bytes=d.get("size_bytes") if d.get("size_bytes") is not None else None,
metadata=d.get("metadata") or {},
source=d.get("source") or None,
)
def _run(result: Any, args: Sequence[str], config: Dict[str, Any]) -> int:
parsed = parse_cmdlet_args(args, CMDLET)
select_raw = parsed.get("select")
allow_multi = bool(parsed.get("multi", False))
interactive = bool(parsed.get("interactive", False))
run_cmd = parsed.get("run-cmd")
inputs = normalize_result_input(result)
if not inputs:
log("No input provided to select; pipe provider-table output or use a cmdlet that emits items.", file=sys.stderr)
return 1
# Model-ize items
rows = [_dict_to_result_model(item if isinstance(item, dict) else item) for item in inputs]
# Attempt to detect provider from first item
provider = None
first_src = inputs[0].get("source") if isinstance(inputs[0], dict) else None
if first_src:
try:
provider = get_provider(first_src)
except Exception:
provider = None
# Columns: ask provider for column spec if available, else build minimal columns
if provider:
cols = provider.get_columns(rows)
else:
# Minimal columns built from available keys
from SYS.result_table_api import title_column, ext_column
cols = [title_column()]
if any(r.ext for r in rows):
cols.append(ext_column())
# Render table to console
try:
table = RichRenderer().render(rows, cols, None)
try:
from rich.console import Console
Console().print(table)
except Exception:
for r in rows:
print(" ".join(str((c.extractor(r) or "")) for c in cols))
except Exception as exc:
log(f"Rendering failed: {exc}", file=sys.stderr)
return 1
# Determine selection indices
indices: List[int] = []
if select_raw:
try:
indices = _parse_selection(str(select_raw), len(rows))
except ValueError as exc:
log(str(exc), file=sys.stderr)
return 1
elif interactive:
# Prompt user (single index only unless multi)
try:
from rich.prompt import Prompt
prompt_text = "Select item(s) (e.g., 1 or 1,3-5)"
if not allow_multi:
prompt_text += " (single)"
choice = Prompt.ask(prompt_text).strip()
indices = _parse_selection(choice, len(rows))
except Exception as exc:
log(f"Interactive selection failed: {exc}", file=sys.stderr)
return 1
else:
log("No selection requested. Use -select or -interactive.", file=sys.stderr)
return 1
if not indices:
log("No valid selection indices provided", file=sys.stderr)
return 1
# Build selected items and emit
selected_items: List[Dict[str, Any]] = []
for idx in indices:
try:
raw = inputs[idx] if idx < len(inputs) else None
if isinstance(raw, dict):
selected = dict(raw)
elif isinstance(raw, ResultModel):
selected = {
"title": raw.title,
"path": raw.path,
"ext": raw.ext,
"size_bytes": raw.size_bytes,
"metadata": raw.metadata or {},
"source": raw.source,
}
else:
# try to call to_dict or fallback
try:
selected = raw.to_dict()
except Exception:
selected = {"title": getattr(raw, "title", str(raw))}
# Ensure selection args exist
if not selected.get("_selection_args"):
if provider:
try:
sel_args = provider.selection_args(rows[idx])
selected["_selection_args"] = sel_args
except Exception:
selected["_selection_args"] = []
else:
# fallback
if selected.get("path"):
selected["_selection_args"] = ["-path", selected.get("path")]
else:
selected["_selection_args"] = ["-title", selected.get("title") or ""]
selected_items.append(selected)
except Exception:
continue
# Emit selected items so downstream cmdlets can consume them
try:
for itm in selected_items:
ctx.emit(itm)
except Exception:
pass
# Optionally run follow-up cmdlet for each selected item
if run_cmd:
try:
from cmdlet import ensure_cmdlet_modules_loaded, get as get_cmdlet
ensure_cmdlet_modules_loaded()
cmd_fn = get_cmdlet(run_cmd)
if not cmd_fn:
log(f"Follow-up cmdlet not found: {run_cmd}", file=sys.stderr)
return 1
exit_code = 0
for itm in selected_items:
sel_args = itm.get("_selection_args") or []
# Invoke follow-up cmdlet with the selected item as piped input
try:
ret = cmd_fn(itm, sel_args, config or {})
except Exception as exc:
log(f"Follow-up cmdlet raised: {exc}", file=sys.stderr)
ret = 1
if ret != 0:
exit_code = ret
return exit_code
except Exception as exc:
log(f"Failed to invoke follow-up cmdlet: {exc}", file=sys.stderr)
return 1
return 0
CMDLET.exec = _run
CMDLET.register()