Skip to content

Commit 5c71efb

Browse files
ValbuenaVCVictor Valbuena
andauthored
MAINT Scenario Namespace & Directory Changes (microsoft#1197)
Co-authored-by: Victor Valbuena <vvalbuena@microsoft.com>
1 parent 48ebd5c commit 5c71efb

37 files changed

Lines changed: 197 additions & 132 deletions

doc/api.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -531,10 +531,10 @@ API Reference
531531
TrueFalseScoreAggregator
532532
TrueFalseScorer
533533

534-
:py:mod:`pyrit.scenarios`
534+
:py:mod:`pyrit.scenario`
535535
=========================
536536

537-
.. automodule:: pyrit.scenarios
537+
.. automodule:: pyrit.scenario
538538
:no-members:
539539
:no-inherited-members:
540540

doc/code/front_end/1_pyrit_scan.ipynb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,7 @@
247247
"\n",
248248
"You need a single scenario to run, you need two things:\n",
249249
"\n",
250-
"1. A Scenario. Many are defined in `pyrit.scenarios.scenarios`. But you can also define your own in initialization_scripts.\n",
250+
"1. A Scenario. Many are defined in `pyrit.scenario.scenarios`. But you can also define your own in initialization_scripts.\n",
251251
"2. Initializers (which can be supplied via `--initializers` or `--initialization-scripts`). Scenarios often don't need many arguments, but they can be configured in different ways. And at the very least, most need an `objective_target` (the thing you're running a scan against).\n",
252252
"3. Scenario Strategies (optional). These are supplied by the `--scenario-strategies` flag and tell the scenario what to test, but they are always optional. Also note you can obtain these by running `--list-scenarios`\n",
253253
"\n",
@@ -413,8 +413,8 @@
413413
"source": [
414414
"# my_custom_scenarios.py\n",
415415
"from pyrit.common.apply_defaults import apply_defaults\n",
416-
"from pyrit.scenarios import Scenario\n",
417-
"from pyrit.scenarios.scenario_strategy import ScenarioStrategy\n",
416+
"from pyrit.scenario import Scenario\n",
417+
"from pyrit.scenario.scenario_strategy import ScenarioStrategy\n",
418418
"\n",
419419
"\n",
420420
"class MyCustomStrategy(ScenarioStrategy):\n",

doc/code/front_end/1_pyrit_scan.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@
5959
#
6060
# You need a single scenario to run, you need two things:
6161
#
62-
# 1. A Scenario. Many are defined in `pyrit.scenarios.scenarios`. But you can also define your own in initialization_scripts.
62+
# 1. A Scenario. Many are defined in `pyrit.scenario.scenarios`. But you can also define your own in initialization_scripts.
6363
# 2. Initializers (which can be supplied via `--initializers` or `--initialization-scripts`). Scenarios often don't need many arguments, but they can be configured in different ways. And at the very least, most need an `objective_target` (the thing you're running a scan against).
6464
# 3. Scenario Strategies (optional). These are supplied by the `--scenario-strategies` flag and tell the scenario what to test, but they are always optional. Also note you can obtain these by running `--list-scenarios`
6565
#
@@ -124,8 +124,8 @@
124124

125125
# %%
126126
# my_custom_scenarios.py
127-
from pyrit.scenarios import Scenario
128-
from pyrit.scenarios.scenario_strategy import ScenarioStrategy
127+
from pyrit.scenario import Scenario
128+
from pyrit.scenario.scenario_strategy import ScenarioStrategy
129129

130130

131131
class MyCustomStrategy(ScenarioStrategy):

doc/code/scenarios/scenarios.ipynb

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@
4141
"\n",
4242
"## Creating Custom Scenarios\n",
4343
"\n",
44-
"To create a custom scenario, extend the `Scenario` base class. See [`FoundryScenario`](../../../pyrit/scenarios/scenarios/foundry_scenario.py) for an example.\n",
44+
"To create a custom scenario, extend the `Scenario` base class. See [`FoundryScenario`](../../../pyrit/scenario/scenarios/foundry_scenario.py) for an example.\n",
4545
"\n",
4646
"## Using Scenarios\n",
4747
"\n",
@@ -64,7 +64,7 @@
6464
{
6565
"data": {
6666
"application/vnd.jupyter.widget-view+json": {
67-
"model_id": "a1dd9e091cb741e59cd9408027ba6e2e",
67+
"model_id": "a99d236b595c4934ad564e9562190ff0",
6868
"version_major": 2,
6969
"version_minor": 0
7070
},
@@ -101,7 +101,7 @@
101101
"\u001b[1m 🎯 Target Information\u001b[0m\n",
102102
"\u001b[36m • Target Type: OpenAIChatTarget\u001b[0m\n",
103103
"\u001b[36m • Target Model: gpt4o\u001b[0m\n",
104-
"\u001b[36m • Target Endpoint: https://pyrit-github-pipeline.openai.azure.com/openai/deployments/gpt-40/chat/completions?api-version=2024-10-21\u001b[0m\n",
104+
"\u001b[36m • Target Endpoint: https://pyrit-japan-test.openai.azure.com/openai/deployments/gpt-4o-japan-nilfilter/chat/completions?api-version=2024-10-21\u001b[0m\n",
105105
"\n",
106106
"\u001b[1m 📊 Scorer Information\u001b[0m\n",
107107
"\u001b[36m • Scorer Type: TrueFalseCompositeScorer\u001b[0m\n",
@@ -118,7 +118,7 @@
118118
"\u001b[1m 📈 Summary\u001b[0m\n",
119119
"\u001b[32m • Total Strategies: 4\u001b[0m\n",
120120
"\u001b[32m • Total Attack Results: 8\u001b[0m\n",
121-
"\u001b[32m • Overall Success Rate: 12%\u001b[0m\n",
121+
"\u001b[32m • Overall Success Rate: 0%\u001b[0m\n",
122122
"\u001b[32m • Unique Objectives: 2\u001b[0m\n",
123123
"\n",
124124
"\u001b[1m\u001b[36m▼ Per-Strategy Breakdown\u001b[0m\n",
@@ -130,7 +130,7 @@
130130
"\n",
131131
"\u001b[1m 🔸 Strategy: base64\u001b[0m\n",
132132
"\u001b[33m • Number of Results: 2\u001b[0m\n",
133-
"\u001b[33m • Success Rate: 50%\u001b[0m\n",
133+
"\u001b[32m • Success Rate: 0%\u001b[0m\n",
134134
"\n",
135135
"\u001b[1m 🔸 Strategy: binary\u001b[0m\n",
136136
"\u001b[33m • Number of Results: 2\u001b[0m\n",
@@ -147,8 +147,9 @@
147147
],
148148
"source": [
149149
"from pyrit.prompt_target import OpenAIChatTarget\n",
150-
"from pyrit.scenarios import FoundryScenario, FoundryStrategy, ScenarioCompositeStrategy\n",
151-
"from pyrit.scenarios.printer.console_printer import ConsoleScenarioResultPrinter\n",
150+
"from pyrit.scenario.core import ScenarioCompositeStrategy\n",
151+
"from pyrit.scenario.printer.console_printer import ConsoleScenarioResultPrinter\n",
152+
"from pyrit.scenario.scenarios import FoundryScenario, FoundryStrategy\n",
152153
"from pyrit.setup import IN_MEMORY, initialize_pyrit\n",
153154
"\n",
154155
"initialize_pyrit(\n",
@@ -174,10 +175,8 @@
174175
"\n",
175176
"\n",
176177
"# Create a scenario from the pre-configured Foundry scenario\n",
177-
"foundry_scenario = FoundryScenario(\n",
178-
" objectives=objectives\n",
179-
")\n",
180-
"await foundry_scenario.initialize_async( # type: ignore\n",
178+
"foundry_scenario = FoundryScenario(objectives=objectives)\n",
179+
"await foundry_scenario.initialize_async( # type: ignore\n",
181180
" objective_target=objective_target,\n",
182181
" scenario_strategies=scenario_strategies,\n",
183182
" max_concurrency=10,\n",
@@ -186,8 +185,8 @@
186185
"print(f\"Created scenario: {foundry_scenario.name}\")\n",
187186
"\n",
188187
"# Execute the entire scenario\n",
189-
"foundry_results = await foundry_scenario.run_async() # type: ignore\n",
190-
"await printer.print_summary_async(foundry_results) # type: ignore"
188+
"foundry_results = await foundry_scenario.run_async() # type: ignore\n",
189+
"await printer.print_summary_async(foundry_results) # type: ignore"
191190
]
192191
},
193192
{
@@ -226,7 +225,7 @@
226225
"name": "python",
227226
"nbconvert_exporter": "python",
228227
"pygments_lexer": "ipython3",
229-
"version": "3.12.11"
228+
"version": "3.11.14"
230229
}
231230
},
232231
"nbformat": 4,

doc/code/scenarios/scenarios.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@
4545
#
4646
# ## Creating Custom Scenarios
4747
#
48-
# To create a custom scenario, extend the `Scenario` base class. See [`FoundryScenario`](../../../pyrit/scenarios/scenarios/foundry_scenario.py) for an example.
48+
# To create a custom scenario, extend the `Scenario` base class. See [`FoundryScenario`](../../../pyrit/scenario/scenarios/foundry_scenario.py) for an example.
4949
#
5050
# ## Using Scenarios
5151
#
@@ -54,8 +54,9 @@
5454

5555
# %%
5656
from pyrit.prompt_target import OpenAIChatTarget
57-
from pyrit.scenarios import FoundryScenario, FoundryStrategy, ScenarioCompositeStrategy
58-
from pyrit.scenarios.printer.console_printer import ConsoleScenarioResultPrinter
57+
from pyrit.scenario.core import ScenarioCompositeStrategy
58+
from pyrit.scenario.printer.console_printer import ConsoleScenarioResultPrinter
59+
from pyrit.scenario.scenarios import FoundryScenario, FoundryStrategy
5960
from pyrit.setup import IN_MEMORY, initialize_pyrit
6061

6162
initialize_pyrit(

doc/code/setup/2_resiliency.ipynb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@
156156
],
157157
"source": [
158158
"from pyrit.prompt_target import OpenAIChatTarget\n",
159-
"from pyrit.scenarios import FoundryScenario, FoundryStrategy\n",
159+
"from pyrit.scenario import FoundryScenario, FoundryStrategy\n",
160160
"from pyrit.setup import IN_MEMORY, initialize_pyrit\n",
161161
"\n",
162162
"initialize_pyrit(memory_db_type=IN_MEMORY)\n",

doc/code/setup/2_resiliency.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@
124124

125125
# %%
126126
from pyrit.prompt_target import OpenAIChatTarget
127-
from pyrit.scenarios import FoundryScenario, FoundryStrategy
127+
from pyrit.scenario import FoundryScenario, FoundryStrategy
128128
from pyrit.setup import IN_MEMORY, initialize_pyrit
129129

130130
initialize_pyrit(memory_db_type=IN_MEMORY)

pyrit/cli/frontend_core.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,7 @@ async def run_scenario_async(
214214
Note:
215215
Initializers from PyRITContext will be run before the scenario executes.
216216
"""
217-
from pyrit.scenarios.printer.console_printer import ConsoleScenarioResultPrinter
217+
from pyrit.scenario.printer.console_printer import ConsoleScenarioResultPrinter
218218
from pyrit.setup import initialize_pyrit
219219

220220
# Ensure context is initialized first (loads registries)

pyrit/cli/pyrit_shell.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -296,7 +296,7 @@ def do_print_scenario(self, arg):
296296
print(f"\n{'#' * 80}")
297297
print(f"Scenario Run #{idx}: {command}")
298298
print(f"{'#' * 80}")
299-
from pyrit.scenarios.printer.console_printer import (
299+
from pyrit.scenario.printer.console_printer import (
300300
ConsoleScenarioResultPrinter,
301301
)
302302

@@ -313,7 +313,7 @@ def do_print_scenario(self, arg):
313313
command, result = self._scenario_history[scenario_num - 1]
314314
print(f"\nScenario Run #{scenario_num}: {command}")
315315
print("=" * 80)
316-
from pyrit.scenarios.printer.console_printer import (
316+
from pyrit.scenario.printer.console_printer import (
317317
ConsoleScenarioResultPrinter,
318318
)
319319

pyrit/cli/scenario_registry.py

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
Scenario registry for discovering and instantiating PyRIT scenarios.
88
99
This module provides functionality to discover all available Scenario subclasses
10-
from the pyrit.scenarios.scenarios module and from user-defined initialization scripts.
10+
from the pyrit.scenario.scenarios module and from user-defined initialization scripts.
1111
1212
PERFORMANCE OPTIMIZATION:
1313
This module uses lazy imports to minimize overhead during CLI operations:
@@ -35,7 +35,7 @@
3535
# Lazy import to avoid loading heavy scenario modules when just listing scenarios
3636
if TYPE_CHECKING:
3737
from pyrit.cli.frontend_core import ScenarioInfo
38-
from pyrit.scenarios.scenario import Scenario
38+
from pyrit.scenario.core import Scenario
3939

4040
logger = logging.getLogger(__name__)
4141

@@ -45,7 +45,7 @@ class ScenarioRegistry:
4545
Registry for discovering and managing available scenarios.
4646
4747
This class discovers all Scenario subclasses from:
48-
1. Built-in scenarios in pyrit.scenarios.scenarios module
48+
1. Built-in scenarios in pyrit.scenario.scenarios module
4949
2. User-defined scenarios from initialization scripts (set via globals)
5050
5151
Scenarios are identified by their simple name (e.g., "encoding_scenario", "foundry_scenario").
@@ -65,15 +65,15 @@ def _ensure_discovered(self) -> None:
6565

6666
def _discover_builtin_scenarios(self) -> None:
6767
"""
68-
Discover all built-in scenarios from pyrit.scenarios.scenarios module.
68+
Discover all built-in scenarios from pyrit.scenario.scenarios module.
6969
7070
This method dynamically imports all modules in the scenarios package
7171
and registers any Scenario subclasses found.
7272
"""
73-
from pyrit.scenarios.scenario import Scenario
73+
from pyrit.scenario.core import Scenario
7474

7575
try:
76-
import pyrit.scenarios.scenarios as scenarios_package
76+
import pyrit.scenario.scenarios as scenarios_package
7777

7878
# Get the path to the scenarios package
7979
package_file = scenarios_package.__file__
@@ -94,7 +94,7 @@ def _discover_builtin_scenarios(self) -> None:
9494

9595
try:
9696
# Import the module
97-
full_module_name = f"pyrit.scenarios.scenarios.{module_name}"
97+
full_module_name = f"pyrit.scenario.scenarios.{module_name}"
9898
module = importlib.import_module(full_module_name)
9999

100100
# Find all Scenario subclasses in the module
@@ -121,7 +121,7 @@ def discover_user_scenarios(self) -> None:
121121
122122
User scenarios will override built-in scenarios with the same name.
123123
"""
124-
from pyrit.scenarios.scenario import Scenario
124+
from pyrit.scenario.core import Scenario
125125

126126
try:
127127
# Check the global namespace for Scenario subclasses
@@ -142,8 +142,8 @@ def discover_user_scenarios(self) -> None:
142142
# Look for Scenario subclasses in the module
143143
for name, obj in inspect.getmembers(module, inspect.isclass):
144144
if issubclass(obj, Scenario) and obj is not Scenario:
145-
# Check if this is a user-defined class (not from pyrit.scenarios.scenarios)
146-
if not obj.__module__.startswith("pyrit.scenarios.scenarios"):
145+
# Check if this is a user-defined class (not from pyrit.scenario.scenarios)
146+
if not obj.__module__.startswith("pyrit.scenario.scenarios"):
147147
# Convert class name to snake_case for scenario name
148148
scenario_name = self._class_name_to_scenario_name(obj.__name__)
149149
self._scenarios[scenario_name] = obj

0 commit comments

Comments
 (0)