@@ -80,7 +80,7 @@ dev = [
8080 " jupyter-book>=2.0.0" ,
8181 " jupytext>=1.17.1" ,
8282 " matplotlib>=3.10.0" ,
83- " mypy>=1.16.0 " ,
83+ " ty>=0.0.32 " ,
8484 " mock-alchemy>=0.2.6" ,
8585 " pandas>=2.2.0" ,
8686 " pre-commit>=4.2.0" ,
@@ -167,17 +167,33 @@ pythonpath = ["."]
167167asyncio_default_fixture_loop_scope = " function"
168168asyncio_mode = " auto"
169169
170- [tool .mypy ]
171- plugins = []
172- ignore_missing_imports = true
173- strict = true
174- follow_imports = " silent"
175- disable_error_code = [" empty-body" ]
170+ [tool .ty ]
171+ [tool .ty .rules ]
172+ all = " error"
173+ # Suppress errors for missing third-party stubs
174+ unresolved-import = " ignore"
175+ # Tolerate None attribute access
176+ possibly-missing-attribute = " ignore"
177+ # Allow existing type: ignore comments without matching errors
178+ unused-ignore-comment = " warn"
179+ unused-type-ignore-comment = " warn"
180+ # Allow empty function bodies during development
181+ empty-body = " ignore"
182+
183+ [tool .ty .analysis ]
184+ respect-type-ignore-comments = true
185+ # Treat colorama as Any — it has no type stubs and uses a dynamic pattern
186+ # (class attrs are int, __init__ converts to str via setattr) that ty can't follow
187+ replace-imports-with-any = [" colorama.**" ]
188+
189+ [tool .ty .src ]
176190exclude = [" doc/code/" , " pyrit/auxiliary_attacks/" ]
177191
178- [[tool .mypy .overrides ]]
179- module = " pyrit.prompt_target.hugging_face.*"
180- disallow_untyped_calls = false
192+ # Relax type checking for HuggingFace module
193+ [[tool .ty .overrides ]]
194+ include = [" pyrit/prompt_target/hugging_face/**" ]
195+ [tool .ty .overrides .rules ]
196+ invalid-argument-type = " warn"
181197
182198[tool .uv ]
183199constraint-dependencies = [
@@ -297,8 +313,10 @@ select = [
297313 " UP" , # https://docs.astral.sh/ruff/rules/#pyupgrade-up
298314 " W" , # https://docs.astral.sh/ruff/rules/#pycodestyle-w
299315 " YTT" , # https://docs.astral.sh/ruff/rules/#flake8-2020-ytt
316+ " ANN" , # https://docs.astral.sh/ruff/rules/#flake8-annotations-ann
300317]
301318ignore = [
319+ " ANN401" , # any-type (too strict — many legitimate uses of Any)
302320 " B903" , # class-as-data-structure (test helper classes use @apply_defaults pattern)
303321 " D100" , # Missing docstring in public module
304322 " D200" , # One-line docstring should fit on one line
@@ -331,12 +349,12 @@ notice-rgx = "Copyright \\(c\\) Microsoft Corporation\\.\\s*\\n.*Licensed under
331349# Ignore copyright, import-location (E402), line length (E501), type-checking, and blanket type-ignore (PGH003) rules in doc/ directory
332350# E402: notebooks have imports in code cells, not at top of file
333351# E501: markdown comments in notebooks can exceed line length
334- # PGH003: blanket type: ignore in notebooks (not mypy -checked)
352+ # PGH003: blanket type: ignore in notebooks (not type -checked)
335353# A: notebook code commonly uses builtins like id, dir, display
336354# ERA001: jupytext markdown cells look like commented-out code
337355# LOG: notebooks use root logger for convenience
338356# PLE1142: top-level await is valid in Jupyter notebooks
339- "doc/**" = [" CPY001" , " TCH" , " E402" , " E501" , " PGH003" , " A" , " ERA001" , " LOG" , " PLE1142" ]
357+ "doc/**" = [" ANN " , " CPY001" , " TCH" , " E402" , " E501" , " PGH003" , " A" , " ERA001" , " LOG" , " PLE1142" ]
340358"pyrit/{auxiliary_attacks,ui}/**/*.py" = [" B905" , " D101" , " D102" , " D103" , " D104" , " D105" , " D106" , " D107" , " D401" , " D404" , " D417" , " D418" , " DOC102" , " DOC201" , " DOC202" , " DOC402" , " DOC501" , " N" , " PERF" , " SIM101" , " SIM108" ]
341359# Backend API routes raise HTTPException handled by FastAPI, not true exceptions
342360"pyrit/backend/**/*.py" = [" DOC501" , " B008" ]
@@ -346,7 +364,11 @@ notice-rgx = "Copyright \\(c\\) Microsoft Corporation\\.\\s*\\n.*Licensed under
346364"pyrit/ui/**/*.py" = [" D" , " DOC201" , " DOC501" ]
347365"pyrit/__init__.py" = [" D104" ]
348366# Allow broad pytest.raises(Exception) in tests
349- "tests/**/*.py" = [" B017" ]
367+ "tests/**/*.py" = [" ANN" , " B017" ]
368+ # Infrastructure/utility scripts — not part of the library API
369+ "build_scripts/**/*.py" = [" ANN" ]
370+ "docker/**/*.py" = [" ANN" ]
371+ "frontend/dev.py" = [" ANN" ]
350372
351373[tool .ruff .lint .pydocstyle ]
352374convention = " google"
0 commit comments