Skip to content
Open
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
8439bd9
test: replace OpenML fetches in tests with deterministic local synthe…
shamykyzer Mar 2, 2026
b662454
relaxed factory accuracy assetion
shamykyzer Mar 2, 2026
7a3ad0e
chore: enforce Ruff type annotations and mypy pre-commit checks added
shamykyzer Mar 6, 2026
be5543d
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Mar 6, 2026
ec98cae
fix: bug resolved for failed checks
shamykyzer Mar 10, 2026
0219599
chore: revert unrelated test changes and keep OpenML paths
shamykyzer Mar 10, 2026
6fd54b4
Merge branch 'main' into chore/enforce-type-hints
shamykyzer Mar 10, 2026
c04a211
Merge branch 'main' into chore/enforce-type-hints
shamykyzer Mar 10, 2026
12ebe87
chore: enforcing type hints attacks
shamykyzer Mar 11, 2026
2454cf6
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Mar 11, 2026
a0d36c0
fixed a failed check
shamykyzer Mar 11, 2026
e70663f
chore: enforce type hints across attacks, config, and safemodel modules
shamykyzer Mar 15, 2026
e36f09b
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Mar 15, 2026
dee7726
Merge branch 'main' into chore/enforce-type-hints
shamykyzer Mar 15, 2026
94b6210
comment out PD901 rule in pyproject.toml instead of deleting
shamykyzer Mar 15, 2026
61508a2
merge: resolve conflict in report.py with origin/main
shamykyzer Mar 19, 2026
d3422f9
chore: restore and add type hints across attack modules
shamykyzer Mar 19, 2026
1acdfd2
merge: resolve conflicts with origin/main
shamykyzer Mar 27, 2026
f10d503
style: pre-commit fixes
pre-commit-ci[bot] Mar 27, 2026
107401b
Merge branch 'main' into chore/enforce-type-hints
shamykyzer Mar 31, 2026
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
8 changes: 8 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,14 @@ repos:
args: ["--fix", "--show-fixes"]
- id: ruff-format

# Type checking (incremental rollout)
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.19.1
hooks:
- id: mypy
pass_filenames: false
args: ["--config-file=pyproject.toml"]

# Format docstrings
- repo: https://github.com/DanielNoord/pydocstringformatter
rev: v0.7.5
Expand Down
20 changes: 18 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ target-version = "py310"
extend-include = ["*.ipynb"]

lint.select = [
# "ANN", # flake8-annotations
"ANN", # flake8-annotations
"ARG", # flake8-unused-arguments
"B", # flake8-bugbear
"C4", # flake8-comprehensions
Expand Down Expand Up @@ -141,12 +141,13 @@ exclude = [
]

lint.ignore = [
"ANN401", # allow Any where interface is dynamic
"EM101", # raw-string-in-exception
"EM102", # f-string-in-exception
"PLC0206", # dict-index-missing-items
"S101", # allow asserts
"S301", # allow pickle
"PD901", # allow df for dataframe names
# "PD901", # allow df for dataframe names
]

[tool.ruff.lint.pep8-naming]
Expand All @@ -165,11 +166,26 @@ docstring-code-format = true
docstring-code-line-length = 80

[tool.ruff.lint.extend-per-file-ignores]
"examples/**/*" = ["ANN"]
"user_stories/**/*" = ["ANN"]
"tests/**/*" = ["S101", "PLR2004", "ANN"]
"sacroml/attacks/structural_attack.py" = ["PLR2004"]
"sacroml/safemodel/classifiers/new_model_template.py" = ["C901"]

[tool.mypy]
python_version = "3.10"
ignore_missing_imports = true
files = [
"sacroml/__init__.py",
"sacroml/attacks/__init__.py",
"sacroml/attacks/data.py",
"sacroml/config/__init__.py",
"sacroml/config/utils.py",
"sacroml/metrics.py",
"sacroml/safemodel/__init__.py",
"sacroml/version.py",
]

[tool.codespell]
ignore-words-list = [
"SOM",
Expand Down
4 changes: 2 additions & 2 deletions sacroml/attacks/attack.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ def _write_report(self, output: dict) -> None:
if self.write_report:
logger.info("Writing report: %s.json %s.pdf", dest, dest)
report.write_json(output, dest)
pdf_report = self._make_pdf(output)
pdf_report: FPDF | None = self._make_pdf(output)
if pdf_report is not None:
report.write_pdf(dest, pdf_report)

Expand All @@ -107,7 +107,7 @@ def __str__(self) -> str:
@classmethod
def _get_param_names(cls) -> list[str]:
"""Get parameter names."""
init_signature = inspect.signature(cls.__init__)
init_signature: inspect.Signature = inspect.signature(cls.__init__)
return [
p.name
for p in init_signature.parameters.values()
Expand Down
28 changes: 14 additions & 14 deletions sacroml/attacks/attack_report_formatter.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,9 +93,9 @@ class AnalysisModule:
"""Wrapper module for metrics analysis modules."""

def __init__(self) -> None:
self.immediate_rejection = []
self.support_rejection = []
self.support_release = []
self.immediate_rejection: list = []
self.support_rejection: list = []
self.support_release: list = []

def process_dict(self) -> dict:
"""Produce a risk summary output based on analysis in this module."""
Expand Down Expand Up @@ -127,7 +127,7 @@ def __init__(self, report: dict) -> None:
self.scores = []
self.reasons = []

def _is_instance_based_model(self, instance_based_model_score) -> bool:
def _is_instance_based_model(self, instance_based_model_score: int | float) -> bool:
if "model_name" in self.report:
if self.report["model_name"] == "SVC":
self.scores.append(instance_based_model_score)
Expand Down Expand Up @@ -185,7 +185,7 @@ def _statistically_significant_auc(
stat_sig_score: float,
mean_auc_score: float,
) -> None:
stat_sig_auc = []
stat_sig_auc: list[float] = []
for k in self.report:
if (
isinstance(self.report[k], dict)
Expand Down Expand Up @@ -263,7 +263,7 @@ def __str__(self) -> str:
class SummariseUnivariateMetricsModule(AnalysisModule):
"""Summarise a set of chosen univariate metrics from the output dictionary."""

def __init__(self, report: dict, metrics_list=None) -> None:
def __init__(self, report: dict, metrics_list: list[str] | None = None) -> None:
super().__init__()

if metrics_list is None:
Expand Down Expand Up @@ -447,18 +447,18 @@ class GenerateTextReport:
"""Generate a text report from a JSON input."""

def __init__(self) -> None:
self.text_out = []
self.target_yaml_filename = None
self.attack_json_filename = None
self.model_name_from_target = None
self.text_out: list = []
self.target_yaml_filename: str | None = None
self.attack_json_filename: str | None = None
self.model_name_from_target: str | None = None

self.immediate_rejection = []
self.support_rejection = []
self.support_release = []
self.immediate_rejection: list = []
self.support_rejection: list = []
self.support_release: list = []

def _process_target_yaml(self) -> None:
"""Create a summary of a target model YAML file."""
model_params_of_interest = [
model_params_of_interest: list[str] = [
"C",
"kernel",
"n_neighbors",
Expand Down
Loading
Loading