Skip to content

Commit 5ec5bc9

Browse files
committed
refactor: generalize verbose table and fix stale test regex
1 parent 68905b1 commit 5ec5bc9

File tree

2 files changed

+40
-27
lines changed

2 files changed

+40
-27
lines changed

garak/command.py

Lines changed: 39 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,28 @@ def _tier_name(tier_value):
169169
return ""
170170

171171

172+
def _truncate(text, max_len=80):
173+
"""Truncate text to max_len, appending '...' if needed."""
174+
if len(text) > max_len:
175+
return text[:max_len - 3] + "..."
176+
return text
177+
178+
179+
# Column definitions per plugin type for verbose table output.
180+
# Each entry is (column_name, extractor_fn(info_dict) -> str).
181+
# "name" and "active" are always included and handled separately.
182+
_PLUGIN_TABLE_COLUMNS = {
183+
"probes": [
184+
("tier", lambda info: _tier_name(info.get("tier")) if info.get("tier") is not None else ""),
185+
("description", lambda info: _truncate(info.get("description", ""))),
186+
],
187+
# Future plugin types can define their own extra columns here, e.g.:
188+
# "detectors": [
189+
# ("description", lambda info: _truncate(info.get("description", ""))),
190+
# ],
191+
}
192+
193+
172194
def print_plugins(prefix: str, color, selected_plugins=None, verbose=0):
173195
"""
174196
Print plugins for a category (probes/detectors/generators/buffs).
@@ -203,8 +225,8 @@ def print_plugins(prefix: str, color, selected_plugins=None, verbose=0):
203225

204226
sorted_items = sorted(short, key=lambda x: x[0])
205227

206-
if verbose >= 1 and prefix == "probes":
207-
_print_probes_table(sorted_items, prefix)
228+
if verbose >= 1 and prefix in _PLUGIN_TABLE_COLUMNS:
229+
_print_plugins_table(sorted_items, prefix)
208230
else:
209231
# plain text output (default)
210232
for item in sorted_items:
@@ -218,42 +240,33 @@ def print_plugins(prefix: str, color, selected_plugins=None, verbose=0):
218240
print()
219241

220242

221-
def _print_probes_table(sorted_items, prefix):
222-
"""Render probes as a markdown table with name, active, tier, description."""
243+
def _print_plugins_table(sorted_items, prefix):
244+
"""Render plugins as a markdown table with name, active, and type-specific columns."""
223245
from py_markdown_table.markdown_table import markdown_table
224246
from garak._plugins import plugin_info as get_plugin_info
225247

248+
extra_columns = _PLUGIN_TABLE_COLUMNS.get(prefix, [])
249+
226250
table_data = []
227251
for item in sorted_items:
228252
plugin_name, active = item[0], item[1]
229253
full_name = item[2] if len(item) > 2 else None
230254

231255
is_module_header = "." not in plugin_name
232256

257+
row = {"name": plugin_name}
258+
233259
if is_module_header:
234-
active_str = "🌟"
235-
tier_str = ""
236-
desc_str = ""
260+
row["active"] = "🌟"
261+
for col_name, _ in extra_columns:
262+
row[col_name] = ""
237263
else:
238-
active_str = "✅" if active else "💤"
239-
if full_name:
240-
info = get_plugin_info(full_name)
241-
tier_val = info.get("tier", None)
242-
tier_str = _tier_name(tier_val) if tier_val is not None else ""
243-
desc_str = info.get("description", "")
244-
# Truncate long descriptions
245-
if len(desc_str) > 80:
246-
desc_str = desc_str[:77] + "..."
247-
else:
248-
tier_str = ""
249-
desc_str = ""
250-
251-
table_data.append({
252-
"name": plugin_name,
253-
"active": active_str,
254-
"tier": tier_str,
255-
"description": desc_str,
256-
})
264+
row["active"] = "✅" if active else "💤"
265+
info = get_plugin_info(full_name) if full_name else {}
266+
for col_name, extractor in extra_columns:
267+
row[col_name] = extractor(info)
268+
269+
table_data.append(row)
257270

258271
print(f"{prefix}:")
259272
print(

tests/cli/test_cli.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ def test_probe_list(capsys):
2222
output = ANSI_ESCAPE.sub("", result.out)
2323
for line in output.strip().split("\n"):
2424
assert re.match(
25-
r"^probes: [a-z0-9_]+(\.[A-Za-z0-9_]+)?(\tTier [1239])?( 🌟)?( 💤)?$", line
25+
r"^probes: [a-z0-9_]+(\.[A-Za-z0-9_]+)?( 🌟)?( 💤)?$", line
2626
) or line.startswith(f"{__app__} {__description__}")
2727

2828

0 commit comments

Comments
 (0)