Skip to content

Conversation

@rlundeen2
Copy link
Contributor

@rlundeen2 rlundeen2 commented Nov 14, 2025

  • Added pyrit_shell (debated on making it pyrit_scan without parameters. I prefer this way but we could go either)
  • Refactored frontend core so both pyrit_scan and pyrit_shell could use shared code
  • Added arguments for more params max-retries max-concurrency and memory-labels
  • Various perf improvements via lazy module loading (5x speedup for help, 2x speedup for list-initializers). But some things are slow, which is why pyrit_shell is nice
  • Most importantly, cool ascii art banner
image

Tests updated. Docs incorporated.

Copy link
Contributor

@ValbuenaVC ValbuenaVC left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great! At the moment I can only think of stylistic changes. It's great to have this feature (and the cool ASCII art)

Comment on lines +324 to +352
def format_scenario_info(*, scenario_info: dict[str, Any]) -> None:
"""
Print formatted information about a scenario.

Args:
scenario_info: Dictionary containing scenario information.
"""
_print_header(text=scenario_info["name"])
print(f" Class: {scenario_info['class_name']}")

description = scenario_info.get("description", "")
if description:
print(" Description:")
print(_format_wrapped_text(text=description, indent=" "))

if scenario_info.get("aggregate_strategies"):
agg_strategies = scenario_info["aggregate_strategies"]
print(" Aggregate Strategies:")
formatted = _format_wrapped_text(text=", ".join(agg_strategies), indent=" - ")
print(formatted)

if scenario_info.get("all_strategies"):
strategies = scenario_info["all_strategies"]
print(f" Available Strategies ({len(strategies)}):")
formatted = _format_wrapped_text(text=", ".join(strategies), indent=" ")
print(formatted)

if scenario_info.get("default_strategy"):
print(f" Default Strategy: {scenario_info['default_strategy']}")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor stylistic choice, but these functions could take kwargs since that's already a dictionary

Suggested change
def format_scenario_info(*, scenario_info: dict[str, Any]) -> None:
"""
Print formatted information about a scenario.
Args:
scenario_info: Dictionary containing scenario information.
"""
_print_header(text=scenario_info["name"])
print(f" Class: {scenario_info['class_name']}")
description = scenario_info.get("description", "")
if description:
print(" Description:")
print(_format_wrapped_text(text=description, indent=" "))
if scenario_info.get("aggregate_strategies"):
agg_strategies = scenario_info["aggregate_strategies"]
print(" Aggregate Strategies:")
formatted = _format_wrapped_text(text=", ".join(agg_strategies), indent=" - ")
print(formatted)
if scenario_info.get("all_strategies"):
strategies = scenario_info["all_strategies"]
print(f" Available Strategies ({len(strategies)}):")
formatted = _format_wrapped_text(text=", ".join(strategies), indent=" ")
print(formatted)
if scenario_info.get("default_strategy"):
print(f" Default Strategy: {scenario_info['default_strategy']}")
def format_scenario_info(**kwargs) -> None:
"""
Print formatted information about a scenario.
Args:
kwargs: Dictionary containing scenario information.
"""
_print_header(text=kwargs["name"])
print(f" Class: {kwargs['class_name']}")
description = kwargs.get("description", "")
if description:
print(" Description:")
print(_format_wrapped_text(text=description, indent=" "))
if kwargs.get("aggregate_strategies"):
agg_strategies = kwargs["aggregate_strategies"]
print(" Aggregate Strategies:")
formatted = _format_wrapped_text(text=", ".join(agg_strategies), indent=" - ")
print(formatted)
if kwargs.get("all_strategies"):
strategies = kwargs["all_strategies"]
print(f" Available Strategies ({len(strategies)}):")
formatted = _format_wrapped_text(text=", ".join(strategies), indent=" ")
print(formatted)
if kwargs.get("default_strategy"):
print(f" Default Strategy: {kwargs['default_strategy']}")

ValueError: If value is not a valid integer or violates constraints.
"""
try:
int_value = int(value)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want to add stronger parsing? There may be some unexpected behaviors, e.g. if value = True, then int(value) == 1

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The type annotation should be enough to constrain value to str anyway but I'm wondering if there's an edge case where this would break

return int_value


def _argparse_validator(validator_func):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
def _argparse_validator(validator_func):
def _argparse_validator(validator_func: Callable):

- Reuse the same validation logic in both argparse and non-argparse contexts

Args:
validator_func: Function that raises ValueError on invalid input.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
validator_func: Function that raises ValueError on invalid input.
validator_func (Callable): Function that raises ValueError on invalid input.

functools has some utilities that might help here, but I'm not too familiar

import logging
import sys
from pathlib import Path
from typing import TYPE_CHECKING, Any, Optional, Sequence
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
from typing import TYPE_CHECKING, Any, Optional, Sequence
from typing import TYPE_CHECKING, Any, Callable, Optional, Sequence

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants