Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
6e1bb1d
ruff config
paulinek13 Nov 11, 2025
639691d
FIX D213 multi-line-summary-second-line
paulinek13 Nov 11, 2025
6a09901
FIX D411 no-blank-line-before-section (D410 is also fixed now)
paulinek13 Nov 11, 2025
daa1bab
FIX D209 new-line-after-last-paragraph
paulinek13 Nov 11, 2025
3a0f1a7
FIX D214 overindented-section
paulinek13 Nov 11, 2025
b3c8e76
FIX D301 escape-sequence-in-docstring
paulinek13 Nov 11, 2025
57b6adb
FIX D300 triple-single-quotes
paulinek13 Nov 11, 2025
90b00b2
FIX D403 first-word-uncapitalized
paulinek13 Nov 11, 2025
c082e73
FIX D416 missing-section-name-colon
paulinek13 Nov 11, 2025
bad6e38
FIX D415 missing-terminal-punctuation
paulinek13 Nov 11, 2025
7ea8b7d
update ruff version and add ruff-check hook to pre-commit
paulinek13 Nov 11, 2025
9b58913
FIX D202 blank-line-after-function
paulinek13 Nov 11, 2025
a4242ff
add missing D202 to args
paulinek13 Nov 11, 2025
0cae9c8
important config fix
paulinek13 Nov 12, 2025
f21b7b7
update comment
paulinek13 Nov 12, 2025
c9eb071
use ruff's F401 instead of pylint
paulinek13 Nov 12, 2025
9863041
Merge branch 'main' into docs/1176/ruff_first_pr
romanlutz Nov 13, 2025
f904ac3
make the config simpler
paulinek13 Nov 15, 2025
23567dc
restore 7_batch_scorer
paulinek13 Nov 15, 2025
ef05920
fix 7_batch_scorer
paulinek13 Nov 15, 2025
3731488
use google convention
paulinek13 Nov 15, 2025
722cfc0
don't use `noqa: D415` if not really needed
paulinek13 Nov 15, 2025
3c75893
Merge branch 'main' into docs/1176/ruff_first_pr
paulinek13 Nov 15, 2025
037d1ad
ignore D301
paulinek13 Nov 16, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 6 additions & 7 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,12 @@ repos:
name: Import Sort (Jupyter Notebooks)
args: [--profile=black]

- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.14.4
hooks:
- id: ruff-check
name: ruff-check

- repo: https://github.com/PyCQA/flake8
rev: 7.1.2
hooks:
Expand All @@ -67,13 +73,6 @@ repos:
additional_dependencies: ['requests']
exclude: (release_process.md|git.md|^doc/deployment/|tests|pyrit/prompt_converter/morse_converter.py|.github|pyrit/prompt_converter/emoji_converter.py|pyrit/score/markdown_injection.py|^pyrit/datasets/|^pyrit/auxiliary_attacks/gcg/)

- repo: https://github.com/pycqa/pylint
rev: v3.3.7
hooks:
- id: pylint
args: [--disable=all, --enable=unused-import]
exclude: NOTICE.txt

- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.15.0
hooks:
Expand Down
13 changes: 5 additions & 8 deletions doc/code/scoring/7_batch_scorer.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,7 @@
{
"cell_type": "markdown",
"id": "0",
"metadata": {
"lines_to_next_cell": 0
},
"metadata": {},
"source": [
"# 7. Batch Scoring\n",
"\n",
Expand Down Expand Up @@ -133,10 +131,9 @@
}
],
"source": [
"# pylint: disable=W0611\n",
"from pyrit.memory import CentralMemory\n",
"from pyrit.prompt_target import OpenAIChatTarget\n",
"from pyrit.score import (\n",
"from pyrit.score import ( # noqa: F401\n",
" AzureContentFilterScorer,\n",
" BatchScorer,\n",
" ContentClassifierPaths,\n",
Expand Down Expand Up @@ -205,12 +202,11 @@
}
],
"source": [
"# pylint: disable=W0611\n",
"import uuid\n",
"\n",
"from pyrit.memory import CentralMemory\n",
"from pyrit.prompt_target import OpenAIChatTarget\n",
"from pyrit.score import (\n",
"from pyrit.score import ( # noqa: F401\n",
" AzureContentFilterScorer,\n",
" BatchScorer,\n",
" ContentClassifierPaths,\n",
Expand Down Expand Up @@ -256,7 +252,8 @@
],
"metadata": {
"jupytext": {
"cell_metadata_filter": "-all"
"cell_metadata_filter": "-all",
"main_language": "python"
},
"language_info": {
"codemirror_mode": {
Expand Down
6 changes: 2 additions & 4 deletions doc/code/scoring/7_batch_scorer.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,9 @@
# Once the prompts are in the database (which again, is often automatic) we can use `BatchScorer` to score them with whatever scorers we want. It works in parallel with batches.

# %%
# pylint: disable=W0611
from pyrit.memory import CentralMemory
from pyrit.prompt_target import OpenAIChatTarget
from pyrit.score import (
from pyrit.score import ( # noqa: F401
AzureContentFilterScorer,
BatchScorer,
ContentClassifierPaths,
Expand Down Expand Up @@ -113,12 +112,11 @@
# - Converted Value SHA256

# %%
# pylint: disable=W0611
import uuid

from pyrit.memory import CentralMemory
from pyrit.prompt_target import OpenAIChatTarget
from pyrit.score import (
from pyrit.score import ( # noqa: F401
AzureContentFilterScorer,
BatchScorer,
ContentClassifierPaths,
Expand Down
35 changes: 35 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ dev = [
"pytest-cov>=6.1.1",
"pytest-timeout>=2.4.0",
"respx>=0.22.0",
"ruff>=0.14.4",
"sphinxcontrib-mermaid>=1.0.0",
"types-PyYAML>=6.0.12.20250516",
"types-requests>=2.31.0.20250515",
Expand Down Expand Up @@ -174,6 +175,9 @@ formats = "ipynb,py:percent"

[tool.ruff]
line-length = 120

[tool.ruff.lint]
preview = true
fixable = [
"A",
"B",
Expand Down Expand Up @@ -220,3 +224,34 @@ fixable = [
"UP",
"YTT",
]
select = [
"D", # https://docs.astral.sh/ruff/rules/#pydocstyle-d
"DOC", # https://docs.astral.sh/ruff/rules/#pydoclint-doc
"F401", # unused-import
]
ignore = [
"D100", # Missing docstring in public module
"D200", # One-line docstring should fit on one line
"D205", # 1 blank line required between summary line and description
"D212", # Multi-line docstring summary should start at the first line
"D301", # Use r""" if any backslashes in a docstring
"DOC502", # Raised exception is not explicitly raised
]
extend-select = [
"D204", # 1 blank line required after class docstring
"D213", # Multi-line docstring summary should start at the second line
"D401", # First line of docstring should be in imperative mood
"D404", # First word of the docstring should not be "This"
]

[tool.ruff.lint.per-file-ignores]
# Ignore D and DOC rules everywhere except for the pyrit/ directory
"!pyrit/**.py" = ["D", "DOC"]
# Temporary ignores for pyrit/ subdirectories until issue #1176
# https://github.com/Azure/PyRIT/issues/1176 is fully resolved
# TODO: Remove these ignores once the issues are fixed
"pyrit/{analytics,auth,auxiliary_attacks,chat_message_normalizer,cli,common,datasets,embedding,exceptions,executor,memory,models,prompt_converter,prompt_normalizer,prompt_target,scenarios,score,setup,ui}/**/*.py" = ["D101", "D102", "D103", "D104", "D105", "D106", "D107", "D401", "D404", "D417", "D418", "DOC102", "DOC201", "DOC202", "DOC402", "DOC501"]
"pyrit/__init__.py" = ["D104"]

[tool.ruff.lint.pydocstyle]
convention = "google"
3 changes: 1 addition & 2 deletions pyrit/analytics/conversation_analytics.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ def get_prompt_entries_with_same_converted_content(
self, *, chat_message_content: str
) -> list[ConversationMessageWithSimilarity]:
"""
Retrieves chat messages that have the same converted content
Retrieves chat messages that have the same converted content.

Args:
chat_message_content (str): The content of the chat message to find similar messages for.
Expand Down Expand Up @@ -68,7 +68,6 @@ def get_similar_chat_messages_by_embedding(
List[ConversationMessageWithSimilarity]: A list of ConversationMessageWithSimilarity objects representing
the similar chat messages based on embedding similarity.
"""

all_embdedding_memory = self.memory_interface.get_all_embeddings()
similar_messages = []

Expand Down
1 change: 0 additions & 1 deletion pyrit/analytics/result_analysis.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ def analyze_results(attack_results: list[AttackResult]) -> dict:
"By_attack_identifier": dict[str, AttackStats]
}
"""

if not attack_results:
raise ValueError("attack_results cannot be empty")

Expand Down
24 changes: 16 additions & 8 deletions pyrit/auth/azure_auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ def _set_default_token(self) -> None:
self.token = self.access_token.token

def refresh_token(self) -> str:
"""Refresh the access token if it is expired.
"""
Refresh the access token if it is expired.

Returns:
A token
Expand Down Expand Up @@ -79,7 +80,8 @@ def get_access_token_from_azure_cli(*, scope: str, tenant_id: str = ""):


def get_access_token_from_azure_msi(*, client_id: str, scope: str):
"""Connect to an AOAI endpoint via managed identity credential attached to an Azure resource.
"""
Connect to an AOAI endpoint via managed identity credential attached to an Azure resource.
For proper setup and configuration of MSI
https://learn.microsoft.com/en-us/entra/identity/managed-identities-azure-resources/overview.

Expand All @@ -100,7 +102,8 @@ def get_access_token_from_azure_msi(*, client_id: str, scope: str):


def get_access_token_from_msa_public_client(*, client_id: str, scope: str):
"""Uses MSA account to connect to an AOAI endpoint via interactive login. A browser window
"""
Uses MSA account to connect to an AOAI endpoint via interactive login. A browser window
will open and ask for login credentials.

Args:
Expand All @@ -120,7 +123,8 @@ def get_access_token_from_msa_public_client(*, client_id: str, scope: str):


def get_access_token_from_interactive_login(scope: str) -> str:
"""Connects to an OpenAI endpoint with an interactive login from Azure. A browser window will
"""
Connects to an OpenAI endpoint with an interactive login from Azure. A browser window will
open and ask for login credentials. The token will be scoped for Azure Cognitive services.

Returns:
Expand All @@ -135,7 +139,8 @@ def get_access_token_from_interactive_login(scope: str) -> str:


def get_token_provider_from_default_azure_credential(scope: str) -> Callable[[], str]:
"""Connect to an AOAI endpoint via default Azure credential.
"""
Connect to an AOAI endpoint via default Azure credential.

Returns:
Authentication token provider
Expand All @@ -149,7 +154,8 @@ def get_token_provider_from_default_azure_credential(scope: str) -> Callable[[],


def get_default_scope(endpoint: str) -> str:
"""Get the default scope for the given endpoint.
"""
Get the default scope for the given endpoint.

Args:
endpoint (str): The endpoint to get the scope for.
Expand All @@ -170,12 +176,13 @@ def get_default_scope(endpoint: str) -> str:
def get_speech_config(resource_id: Union[str, None], key: Union[str, None], region: str):
"""
Get the speech config using key/region pair (for key auth scenarios) or resource_id/region pair
(for Entra auth scenarios)
(for Entra auth scenarios).

Args:
resource_id (Union[str, None]): The resource ID to get the token for.
key (Union[str, None]): The Azure Speech key
region (str): The region to get the token for.

Returns:
The speech config based on passed in args

Expand Down Expand Up @@ -207,7 +214,8 @@ def get_speech_config(resource_id: Union[str, None], key: Union[str, None], regi


def get_speech_config_from_default_azure_credential(resource_id: str, region: str):
"""Get the speech config for the given resource ID and region.
"""
Get the speech config for the given resource ID and region.

Args:
resource_id (str): The resource ID to get the token for.
Expand Down
Loading
Loading