trustbench 0.2.2__tar.gz → 0.2.3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (110) hide show
  1. {trustbench-0.2.2 → trustbench-0.2.3}/PKG-INFO +24 -8
  2. {trustbench-0.2.2 → trustbench-0.2.3}/README.md +23 -7
  3. {trustbench-0.2.2 → trustbench-0.2.3}/pyproject.toml +2 -1
  4. {trustbench-0.2.2 → trustbench-0.2.3}/pyproject.toml.orig +2 -1
  5. {trustbench-0.2.2 → trustbench-0.2.3}/src/trustbench/__init__.py +1 -1
  6. {trustbench-0.2.2 → trustbench-0.2.3}/src/trustbench/datasets/cifar10.py +1 -1
  7. {trustbench-0.2.2 → trustbench-0.2.3}/src/trustbench/evaluation/__init__.py +4 -6
  8. {trustbench-0.2.2 → trustbench-0.2.3}/src/trustbench/evaluation/distribution_shift.py +4 -4
  9. {trustbench-0.2.2 → trustbench-0.2.3}/src/trustbench/experiments/comparison.py +2 -2
  10. {trustbench-0.2.2 → trustbench-0.2.3}/src/trustbench/experiments/registry.py +15 -15
  11. {trustbench-0.2.2 → trustbench-0.2.3}/src/trustbench/registry/metrics.py +3 -3
  12. {trustbench-0.2.2 → trustbench-0.2.3}/src/trustbench/registry/plugins.py +2 -2
  13. {trustbench-0.2.2 → trustbench-0.2.3}/src/trustbench/robustness/evaluator.py +3 -3
  14. {trustbench-0.2.2 → trustbench-0.2.3}/src/trustbench/storage/filesystem.py +2 -2
  15. {trustbench-0.2.2 → trustbench-0.2.3}/src/trustbench/api/__init__.py +0 -0
  16. {trustbench-0.2.2 → trustbench-0.2.3}/src/trustbench/api/app.py +0 -0
  17. {trustbench-0.2.2 → trustbench-0.2.3}/src/trustbench/api/routes/experiments.py +0 -0
  18. {trustbench-0.2.2 → trustbench-0.2.3}/src/trustbench/benchmark.py +0 -0
  19. {trustbench-0.2.2 → trustbench-0.2.3}/src/trustbench/cli/__init__.py +0 -0
  20. {trustbench-0.2.2 → trustbench-0.2.3}/src/trustbench/cli/main.py +0 -0
  21. {trustbench-0.2.2 → trustbench-0.2.3}/src/trustbench/config/__init__.py +0 -0
  22. {trustbench-0.2.2 → trustbench-0.2.3}/src/trustbench/config/loader.py +0 -0
  23. {trustbench-0.2.2 → trustbench-0.2.3}/src/trustbench/config/schema.py +0 -0
  24. {trustbench-0.2.2 → trustbench-0.2.3}/src/trustbench/core/__init__.py +0 -0
  25. {trustbench-0.2.2 → trustbench-0.2.3}/src/trustbench/core/evaluator.py +0 -0
  26. {trustbench-0.2.2 → trustbench-0.2.3}/src/trustbench/core/exceptions.py +0 -0
  27. {trustbench-0.2.2 → trustbench-0.2.3}/src/trustbench/core/inference.py +0 -0
  28. {trustbench-0.2.2 → trustbench-0.2.3}/src/trustbench/core/protocols.py +0 -0
  29. {trustbench-0.2.2 → trustbench-0.2.3}/src/trustbench/core/reproducibility.py +0 -0
  30. {trustbench-0.2.2 → trustbench-0.2.3}/src/trustbench/core/results.py +0 -0
  31. {trustbench-0.2.2 → trustbench-0.2.3}/src/trustbench/datasets/__init__.py +0 -0
  32. {trustbench-0.2.2 → trustbench-0.2.3}/src/trustbench/datasets/base.py +0 -0
  33. {trustbench-0.2.2 → trustbench-0.2.3}/src/trustbench/datasets/memory.py +0 -0
  34. {trustbench-0.2.2 → trustbench-0.2.3}/src/trustbench/datasets/torch_dataset.py +0 -0
  35. {trustbench-0.2.2 → trustbench-0.2.3}/src/trustbench/evaluation/artifacts.py +0 -0
  36. {trustbench-0.2.2 → trustbench-0.2.3}/src/trustbench/evaluation/calibration.py +0 -0
  37. {trustbench-0.2.2 → trustbench-0.2.3}/src/trustbench/evaluation/classification.py +0 -0
  38. {trustbench-0.2.2 → trustbench-0.2.3}/src/trustbench/evaluation/error_detection.py +0 -0
  39. {trustbench-0.2.2 → trustbench-0.2.3}/src/trustbench/evaluation/fairness.py +0 -0
  40. {trustbench-0.2.2 → trustbench-0.2.3}/src/trustbench/evaluation/inference.py +0 -0
  41. {trustbench-0.2.2 → trustbench-0.2.3}/src/trustbench/evaluation/regression.py +0 -0
  42. {trustbench-0.2.2 → trustbench-0.2.3}/src/trustbench/evaluation/reproducibility.py +0 -0
  43. {trustbench-0.2.2 → trustbench-0.2.3}/src/trustbench/evaluation/retrieval.py +0 -0
  44. {trustbench-0.2.2 → trustbench-0.2.3}/src/trustbench/evaluation/runner.py +0 -0
  45. {trustbench-0.2.2 → trustbench-0.2.3}/src/trustbench/evaluation/segmentation.py +0 -0
  46. {trustbench-0.2.2 → trustbench-0.2.3}/src/trustbench/evaluation/selective.py +0 -0
  47. {trustbench-0.2.2 → trustbench-0.2.3}/src/trustbench/evaluation/streaming.py +0 -0
  48. {trustbench-0.2.2 → trustbench-0.2.3}/src/trustbench/evaluation/uncertainty.py +0 -0
  49. {trustbench-0.2.2 → trustbench-0.2.3}/src/trustbench/experiments/__init__.py +0 -0
  50. {trustbench-0.2.2 → trustbench-0.2.3}/src/trustbench/experiments/lineage.py +0 -0
  51. {trustbench-0.2.2 → trustbench-0.2.3}/src/trustbench/experiments/manager.py +0 -0
  52. {trustbench-0.2.2 → trustbench-0.2.3}/src/trustbench/experiments/schemas.py +0 -0
  53. {trustbench-0.2.2 → trustbench-0.2.3}/src/trustbench/metrics/__init__.py +0 -0
  54. {trustbench-0.2.2 → trustbench-0.2.3}/src/trustbench/metrics/calibration.py +0 -0
  55. {trustbench-0.2.2 → trustbench-0.2.3}/src/trustbench/metrics/classification.py +0 -0
  56. {trustbench-0.2.2 → trustbench-0.2.3}/src/trustbench/metrics/error_detection.py +0 -0
  57. {trustbench-0.2.2 → trustbench-0.2.3}/src/trustbench/metrics/regression.py +0 -0
  58. {trustbench-0.2.2 → trustbench-0.2.3}/src/trustbench/metrics/retrieval.py +0 -0
  59. {trustbench-0.2.2 → trustbench-0.2.3}/src/trustbench/metrics/segmentation.py +0 -0
  60. {trustbench-0.2.2 → trustbench-0.2.3}/src/trustbench/metrics/selective.py +0 -0
  61. {trustbench-0.2.2 → trustbench-0.2.3}/src/trustbench/metrics/uncertainty.py +0 -0
  62. {trustbench-0.2.2 → trustbench-0.2.3}/src/trustbench/models/__init__.py +0 -0
  63. {trustbench-0.2.2 → trustbench-0.2.3}/src/trustbench/models/base.py +0 -0
  64. {trustbench-0.2.2 → trustbench-0.2.3}/src/trustbench/models/checkpoint.py +0 -0
  65. {trustbench-0.2.2 → trustbench-0.2.3}/src/trustbench/models/densenet.py +0 -0
  66. {trustbench-0.2.2 → trustbench-0.2.3}/src/trustbench/models/dla.py +0 -0
  67. {trustbench-0.2.2 → trustbench-0.2.3}/src/trustbench/models/dla_simple.py +0 -0
  68. {trustbench-0.2.2 → trustbench-0.2.3}/src/trustbench/models/dpn.py +0 -0
  69. {trustbench-0.2.2 → trustbench-0.2.3}/src/trustbench/models/efficientnet.py +0 -0
  70. {trustbench-0.2.2 → trustbench-0.2.3}/src/trustbench/models/googlenet.py +0 -0
  71. {trustbench-0.2.2 → trustbench-0.2.3}/src/trustbench/models/jax.py +0 -0
  72. {trustbench-0.2.2 → trustbench-0.2.3}/src/trustbench/models/keras.py +0 -0
  73. {trustbench-0.2.2 → trustbench-0.2.3}/src/trustbench/models/lenet.py +0 -0
  74. {trustbench-0.2.2 → trustbench-0.2.3}/src/trustbench/models/mobilenet.py +0 -0
  75. {trustbench-0.2.2 → trustbench-0.2.3}/src/trustbench/models/mobilenetv2.py +0 -0
  76. {trustbench-0.2.2 → trustbench-0.2.3}/src/trustbench/models/onnx.py +0 -0
  77. {trustbench-0.2.2 → trustbench-0.2.3}/src/trustbench/models/pnasnet.py +0 -0
  78. {trustbench-0.2.2 → trustbench-0.2.3}/src/trustbench/models/preact_resnet.py +0 -0
  79. {trustbench-0.2.2 → trustbench-0.2.3}/src/trustbench/models/pytorch.py +0 -0
  80. {trustbench-0.2.2 → trustbench-0.2.3}/src/trustbench/models/regnet.py +0 -0
  81. {trustbench-0.2.2 → trustbench-0.2.3}/src/trustbench/models/resnet.py +0 -0
  82. {trustbench-0.2.2 → trustbench-0.2.3}/src/trustbench/models/resnext.py +0 -0
  83. {trustbench-0.2.2 → trustbench-0.2.3}/src/trustbench/models/senet.py +0 -0
  84. {trustbench-0.2.2 → trustbench-0.2.3}/src/trustbench/models/shufflenet.py +0 -0
  85. {trustbench-0.2.2 → trustbench-0.2.3}/src/trustbench/models/shufflenetv2.py +0 -0
  86. {trustbench-0.2.2 → trustbench-0.2.3}/src/trustbench/models/sklearn.py +0 -0
  87. {trustbench-0.2.2 → trustbench-0.2.3}/src/trustbench/models/vgg.py +0 -0
  88. {trustbench-0.2.2 → trustbench-0.2.3}/src/trustbench/registry/__init__.py +0 -0
  89. {trustbench-0.2.2 → trustbench-0.2.3}/src/trustbench/registry/corruptions.py +0 -0
  90. {trustbench-0.2.2 → trustbench-0.2.3}/src/trustbench/registry/datasets.py +0 -0
  91. {trustbench-0.2.2 → trustbench-0.2.3}/src/trustbench/registry/models.py +0 -0
  92. {trustbench-0.2.2 → trustbench-0.2.3}/src/trustbench/reporting/__init__.py +0 -0
  93. {trustbench-0.2.2 → trustbench-0.2.3}/src/trustbench/reporting/artifacts.py +0 -0
  94. {trustbench-0.2.2 → trustbench-0.2.3}/src/trustbench/reporting/hashing.py +0 -0
  95. {trustbench-0.2.2 → trustbench-0.2.3}/src/trustbench/reporting/html_report.py +0 -0
  96. {trustbench-0.2.2 → trustbench-0.2.3}/src/trustbench/reporting/plots.py +0 -0
  97. {trustbench-0.2.2 → trustbench-0.2.3}/src/trustbench/reporting/result_io.py +0 -0
  98. {trustbench-0.2.2 → trustbench-0.2.3}/src/trustbench/reporting/schema.py +0 -0
  99. {trustbench-0.2.2 → trustbench-0.2.3}/src/trustbench/reporting/tables.py +0 -0
  100. {trustbench-0.2.2 → trustbench-0.2.3}/src/trustbench/robustness/__init__.py +0 -0
  101. {trustbench-0.2.2 → trustbench-0.2.3}/src/trustbench/robustness/aggregation.py +0 -0
  102. {trustbench-0.2.2 → trustbench-0.2.3}/src/trustbench/robustness/corruptions.py +0 -0
  103. {trustbench-0.2.2 → trustbench-0.2.3}/src/trustbench/robustness/report.py +0 -0
  104. {trustbench-0.2.2 → trustbench-0.2.3}/src/trustbench/robustness/severity.py +0 -0
  105. {trustbench-0.2.2 → trustbench-0.2.3}/src/trustbench/storage/__init__.py +0 -0
  106. {trustbench-0.2.2 → trustbench-0.2.3}/src/trustbench/storage/base.py +0 -0
  107. {trustbench-0.2.2 → trustbench-0.2.3}/src/trustbench/storage/database.py +0 -0
  108. {trustbench-0.2.2 → trustbench-0.2.3}/src/trustbench/storage/models.py +0 -0
  109. {trustbench-0.2.2 → trustbench-0.2.3}/src/trustbench/storage/repositories.py +0 -0
  110. {trustbench-0.2.2 → trustbench-0.2.3}/src/trustbench/storage/sqlite.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: trustbench
3
- Version: 0.2.2
3
+ Version: 0.2.3
4
4
  Summary: TrustBench: Evaluation framework for ML model reliability, robustness, and uncertainty.
5
5
  Keywords: machine-learning,evaluation,reliability,robustness,uncertainty,calibration,ood-detection,fairness
6
6
  Author: Uni-Creator
@@ -56,12 +56,11 @@ Description-Content-Type: text/markdown
56
56
 
57
57
  **ML Reliability, Robustness, Uncertainty & Fairness Evaluation Framework**
58
58
 
59
- [![PyPI version](https://img.shields.io/badge/pypi-v0.2.2-blue.svg)](https://pypi.org/project/trustbench/)
60
- [![Python Versions](https://img.shields.io/badge/python-3.11%20%7C%203.12-blue.svg)](https://pypi.org/project/trustbench/)
61
- [![License](https://img.shields.io/badge/license-Apache%202.0-green.svg)](https://github.com/Uni-Creator/trustbench/blob/main/LICENSE)
62
- [![CI Status](https://img.shields.io/badge/build-passing-brightgreen.svg)](https://github.com/Uni-Creator/trustbench/actions/workflows/ci.yml)
63
- [![Documentation](https://img.shields.io/badge/docs-mkdocs-blue.svg)](https://uni-creator.github.io/trustbench/)
64
- [![Tests](https://img.shields.io/badge/tests-204%20passed-success.svg)](https://github.com/Uni-Creator/trustbench/tree/main/tests)
59
+ [![PyPI version](https://img.shields.io/pypi/v/trustbench.svg)](https://pypi.org/project/trustbench/)
60
+ [![Python Versions](https://img.shields.io/pypi/pyversions/trustbench.svg)](https://pypi.org/project/trustbench/)
61
+ [![License](https://img.shields.io/github/license/Uni-Creator/trustbench.svg)](https://github.com/Uni-Creator/trustbench/blob/main/LICENSE)
62
+ [![CI Status](https://github.com/Uni-Creator/trustbench/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/Uni-Creator/trustbench/actions/workflows/ci.yml)
63
+ [![Documentation](https://github.com/Uni-Creator/trustbench/actions/workflows/docs.yml/badge.svg)](https://uni-creator.github.io/trustbench/)
65
64
 
66
65
  </div>
67
66
 
@@ -243,6 +242,23 @@ print(f"Pixel Accuracy: {result.metrics['pixel_accuracy']:.2%}")
243
242
 
244
243
  See [Metrics Documentation](https://github.com/Uni-Creator/trustbench/blob/main/docs/metrics.md) for mathematical derivations.
245
244
 
245
+ ### Metric Verification & Standards Compliance
246
+
247
+ To guarantee mathematical correctness and numerical fidelity, TrustBench metrics are rigorously tested directly against established reference implementations and peer-reviewed literature benchmarks on identical inputs:
248
+
249
+ | TrustBench Metric Domain | Reference Implementation / Peer-Reviewed Standard | Verification Test Suite |
250
+ | :--- | :--- | :--- |
251
+ | **Classification** (Acc, Balanced Acc, Macro-F1, Precision, Recall, Confusion Matrix) | `scikit-learn` (`sklearn.metrics`) | `tests/unit/test_metric_reference_benchmarks.py` |
252
+ | **Regression** (MAE, MSE, RMSE, $R^2$, MedAE, Max Error) | `scikit-learn` (`sklearn.metrics`) | `tests/unit/test_metric_reference_benchmarks.py` |
253
+ | **Calibration** (Brier Score, Negative Log-Likelihood) | `scikit-learn` (`brier_score_loss`, `log_loss`) | `tests/unit/test_metric_reference_benchmarks.py` |
254
+ | **Calibration** (Equal-width ECE, Adaptive Quantile ECE) | Guo et al. (2017), Naeini et al. (2015), Ding et al. (2020) | `tests/unit/test_metric_reference_benchmarks.py` |
255
+ | **Error Detection** (AUROC, AUPRC, FPR@95%TPR) | `scikit-learn` (`roc_auc_score`, `precision_recall_curve`, `auc`) | `tests/unit/test_metric_reference_benchmarks.py` |
256
+ | **Fairness & Bias** (Demographic Parity, Equalized Odds, Disparate Impact) | Fairlearn Mathematical Specification | `tests/unit/test_metric_reference_benchmarks.py` |
257
+ | **Selective Prediction** (Risk-Coverage, Optimal AURC, Excess AURC) | Geifman & El-Yaniv (2017) Analytical Bounds | `tests/unit/test_metric_reference_benchmarks.py` |
258
+
259
+ > [!NOTE]
260
+ > **Task Maturity**: Classification, Calibration, Robustness, Uncertainty, and Error Detection are core, production-verified pipelines with end-to-end integration tests. Specialized domain pipelines (Information Retrieval, Semantic Segmentation, and Algorithmic Fairness) and non-PyTorch adapters (Keras, JAX) are provided with protocol compliance tests and marked as experimental extensions.
261
+
246
262
  ---
247
263
 
248
264
  ## Tutorials & Examples
@@ -292,7 +308,7 @@ pytest
292
308
  ruff check .
293
309
 
294
310
  # Static type analysis
295
- mypy src/trustbench/core src/trustbench/reporting src/trustbench/metrics
311
+ mypy src/trustbench --ignore-missing-imports
296
312
  ```
297
313
 
298
314
  ---
@@ -4,12 +4,11 @@
4
4
 
5
5
  **ML Reliability, Robustness, Uncertainty & Fairness Evaluation Framework**
6
6
 
7
- [![PyPI version](https://img.shields.io/badge/pypi-v0.2.2-blue.svg)](https://pypi.org/project/trustbench/)
8
- [![Python Versions](https://img.shields.io/badge/python-3.11%20%7C%203.12-blue.svg)](https://pypi.org/project/trustbench/)
9
- [![License](https://img.shields.io/badge/license-Apache%202.0-green.svg)](https://github.com/Uni-Creator/trustbench/blob/main/LICENSE)
10
- [![CI Status](https://img.shields.io/badge/build-passing-brightgreen.svg)](https://github.com/Uni-Creator/trustbench/actions/workflows/ci.yml)
11
- [![Documentation](https://img.shields.io/badge/docs-mkdocs-blue.svg)](https://uni-creator.github.io/trustbench/)
12
- [![Tests](https://img.shields.io/badge/tests-204%20passed-success.svg)](https://github.com/Uni-Creator/trustbench/tree/main/tests)
7
+ [![PyPI version](https://img.shields.io/pypi/v/trustbench.svg)](https://pypi.org/project/trustbench/)
8
+ [![Python Versions](https://img.shields.io/pypi/pyversions/trustbench.svg)](https://pypi.org/project/trustbench/)
9
+ [![License](https://img.shields.io/github/license/Uni-Creator/trustbench.svg)](https://github.com/Uni-Creator/trustbench/blob/main/LICENSE)
10
+ [![CI Status](https://github.com/Uni-Creator/trustbench/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/Uni-Creator/trustbench/actions/workflows/ci.yml)
11
+ [![Documentation](https://github.com/Uni-Creator/trustbench/actions/workflows/docs.yml/badge.svg)](https://uni-creator.github.io/trustbench/)
13
12
 
14
13
  </div>
15
14
 
@@ -191,6 +190,23 @@ print(f"Pixel Accuracy: {result.metrics['pixel_accuracy']:.2%}")
191
190
 
192
191
  See [Metrics Documentation](https://github.com/Uni-Creator/trustbench/blob/main/docs/metrics.md) for mathematical derivations.
193
192
 
193
+ ### Metric Verification & Standards Compliance
194
+
195
+ To guarantee mathematical correctness and numerical fidelity, TrustBench metrics are rigorously tested directly against established reference implementations and peer-reviewed literature benchmarks on identical inputs:
196
+
197
+ | TrustBench Metric Domain | Reference Implementation / Peer-Reviewed Standard | Verification Test Suite |
198
+ | :--- | :--- | :--- |
199
+ | **Classification** (Acc, Balanced Acc, Macro-F1, Precision, Recall, Confusion Matrix) | `scikit-learn` (`sklearn.metrics`) | `tests/unit/test_metric_reference_benchmarks.py` |
200
+ | **Regression** (MAE, MSE, RMSE, $R^2$, MedAE, Max Error) | `scikit-learn` (`sklearn.metrics`) | `tests/unit/test_metric_reference_benchmarks.py` |
201
+ | **Calibration** (Brier Score, Negative Log-Likelihood) | `scikit-learn` (`brier_score_loss`, `log_loss`) | `tests/unit/test_metric_reference_benchmarks.py` |
202
+ | **Calibration** (Equal-width ECE, Adaptive Quantile ECE) | Guo et al. (2017), Naeini et al. (2015), Ding et al. (2020) | `tests/unit/test_metric_reference_benchmarks.py` |
203
+ | **Error Detection** (AUROC, AUPRC, FPR@95%TPR) | `scikit-learn` (`roc_auc_score`, `precision_recall_curve`, `auc`) | `tests/unit/test_metric_reference_benchmarks.py` |
204
+ | **Fairness & Bias** (Demographic Parity, Equalized Odds, Disparate Impact) | Fairlearn Mathematical Specification | `tests/unit/test_metric_reference_benchmarks.py` |
205
+ | **Selective Prediction** (Risk-Coverage, Optimal AURC, Excess AURC) | Geifman & El-Yaniv (2017) Analytical Bounds | `tests/unit/test_metric_reference_benchmarks.py` |
206
+
207
+ > [!NOTE]
208
+ > **Task Maturity**: Classification, Calibration, Robustness, Uncertainty, and Error Detection are core, production-verified pipelines with end-to-end integration tests. Specialized domain pipelines (Information Retrieval, Semantic Segmentation, and Algorithmic Fairness) and non-PyTorch adapters (Keras, JAX) are provided with protocol compliance tests and marked as experimental extensions.
209
+
194
210
  ---
195
211
 
196
212
  ## Tutorials & Examples
@@ -240,7 +256,7 @@ pytest
240
256
  ruff check .
241
257
 
242
258
  # Static type analysis
243
- mypy src/trustbench/core src/trustbench/reporting src/trustbench/metrics
259
+ mypy src/trustbench --ignore-missing-imports
244
260
  ```
245
261
 
246
262
  ---
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "trustbench"
3
- version = "0.2.2"
3
+ version = "0.2.3"
4
4
  description = "TrustBench: Evaluation framework for ML model reliability, robustness, and uncertainty."
5
5
  readme = "README.md"
6
6
  license = "Apache-2.0"
@@ -78,6 +78,7 @@ dev = [
78
78
  "httpx>=0.28.1",
79
79
  "mypy>=2.4.0",
80
80
  "pytest>=9.1.1",
81
+ "pytest-cov>=4.0.0",
81
82
  "ruff>=0.17.2",
82
83
  "fastapi>=0.100.0",
83
84
  "plotly>=5.0.0",
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "trustbench"
3
- version = "0.2.2"
3
+ version = "0.2.3"
4
4
  description = "TrustBench: Evaluation framework for ML model reliability, robustness, and uncertainty."
5
5
  readme = "README.md"
6
6
  license = "Apache-2.0"
@@ -97,6 +97,7 @@ dev = [
97
97
  "httpx>=0.28.1",
98
98
  "mypy>=2.4.0",
99
99
  "pytest>=9.1.1",
100
+ "pytest-cov>=4.0.0",
100
101
  "ruff>=0.17.2",
101
102
 
102
103
  # Dependencies required by the test suite
@@ -1,6 +1,6 @@
1
1
  """TrustBench: Evaluation framework for machine learning model reliability."""
2
2
 
3
- __version__ = "0.2.2"
3
+ __version__ = "0.2.3"
4
4
 
5
5
  from trustbench.benchmark import TrustBench
6
6
  from trustbench.core.evaluator import evaluate
@@ -84,7 +84,7 @@ def get_cifar10_validation_split(
84
84
 
85
85
  # Deterministic split indices
86
86
  generator = torch.Generator().manual_seed(seed)
87
- train_indices, val_indices = random_split(range(total_len), [train_len, val_size], generator=generator)
87
+ train_indices, val_indices = random_split(range(total_len), [train_len, val_size], generator=generator) # type: ignore[arg-type,var-annotated]
88
88
 
89
89
  train_subset = Subset(train_base, train_indices.indices)
90
90
  val_subset = Subset(val_base, val_indices.indices)
@@ -119,11 +119,10 @@ def __getattr__(name: str):
119
119
  save_experiment_artifacts,
120
120
  )
121
121
 
122
- exports = {
122
+ return {
123
123
  "load_experiment_artifacts": load_experiment_artifacts,
124
124
  "save_experiment_artifacts": save_experiment_artifacts,
125
- }
126
- return exports[name]
125
+ }[name]
127
126
  if name in {
128
127
  "IndexedDataset",
129
128
  "load_model_from_checkpoint",
@@ -137,13 +136,12 @@ def __getattr__(name: str):
137
136
  run_inference,
138
137
  )
139
138
 
140
- exports = {
139
+ return {
141
140
  "IndexedDataset": IndexedDataset,
142
141
  "load_model_from_checkpoint": load_model_from_checkpoint,
143
142
  "resolve_model_architecture": resolve_model_architecture,
144
143
  "run_inference": run_inference,
145
- }
146
- return exports[name]
144
+ }[name]
147
145
  if name in {"get_environment_info", "get_git_commit", "set_seed"}:
148
146
  from trustbench.core.reproducibility import (
149
147
  get_environment_info,
@@ -83,8 +83,8 @@ def compute_label_distribution_shift(
83
83
  counts_s = np.bincount(labels_s[labels_s >= 0], minlength=n_c)[:n_c]
84
84
  counts_t = np.bincount(labels_t[labels_t >= 0], minlength=n_c)[:n_c]
85
85
 
86
- priors_s = counts_s / max(1, np.sum(counts_s))
87
- priors_t = counts_t / max(1, np.sum(counts_t))
86
+ priors_s = counts_s / max(1.0, float(np.sum(counts_s)))
87
+ priors_t = counts_t / max(1.0, float(np.sum(counts_t)))
88
88
 
89
89
  tv = compute_tv_distance(priors_s, priors_t)
90
90
  js = float(jensenshannon(priors_s, priors_t))
@@ -177,8 +177,8 @@ def evaluate_distribution_shift(
177
177
  n_classes = clean_probs.shape[1] if clean_probs.ndim == 2 else int(max(np.max(clean_preds), np.max(shifted_preds)) + 1)
178
178
  counts_c = np.bincount(clean_preds[clean_preds >= 0], minlength=n_classes)[:n_classes]
179
179
  counts_s = np.bincount(shifted_preds[shifted_preds >= 0], minlength=n_classes)[:n_classes]
180
- marg_clean = counts_c / max(1, np.sum(counts_c))
181
- marg_shifted = counts_s / max(1, np.sum(counts_s))
180
+ marg_clean = counts_c / max(1.0, float(np.sum(counts_c)))
181
+ marg_shifted = counts_s / max(1.0, float(np.sum(counts_s)))
182
182
  pred_tv = compute_tv_distance(marg_clean, marg_shifted)
183
183
 
184
184
  # 2. Confidence & Entropy Shifts
@@ -148,13 +148,13 @@ class ExperimentComparator:
148
148
  Accepts experiment IDs (resolved via store or database session),
149
149
  or ExperimentRecord / dict objects directly.
150
150
  """
151
- records: list[ExperimentRecord | dict[str, Any]] = []
151
+ records: list[Any] = []
152
152
 
153
153
  for item in experiments:
154
154
  if isinstance(item, (ExperimentRecord, dict)):
155
155
  records.append(item)
156
156
  elif isinstance(item, str):
157
- rec = None
157
+ rec: Any = None
158
158
  if self.store is not None:
159
159
  rec = self.store.get(item)
160
160
  if rec is None and (self._session is not None or self.session_provided):
@@ -110,39 +110,39 @@ class ExperimentRegistry:
110
110
  repo.update_status(exp_model.id, status="completed", completed=True)
111
111
 
112
112
  # 3. Index Artifact Files
113
- for f in exp_path.iterdir():
114
- if f.is_file():
115
- art_type = f.stem
116
- csum = compute_file_sha256(f)
113
+ for file_item in exp_path.iterdir():
114
+ if file_item.is_file():
115
+ art_type = file_item.stem
116
+ csum = compute_file_sha256(file_item)
117
117
  repo.add_artifact(
118
118
  experiment_id=exp_model.id,
119
119
  artifact_type=art_type,
120
- file_path=str(f.resolve()),
120
+ file_path=str(file_item.resolve()),
121
121
  checksum=csum,
122
122
  )
123
123
 
124
124
  # Index corruption_results subfolder if present
125
125
  corruptions_dir = exp_path / "corruption_results"
126
126
  if corruptions_dir.is_dir():
127
- for f in corruptions_dir.iterdir():
128
- if f.is_file() and f.suffix == ".json":
127
+ for file_item in corruptions_dir.iterdir():
128
+ if file_item.is_file() and file_item.suffix == ".json":
129
129
  repo.add_artifact(
130
130
  experiment_id=exp_model.id,
131
- artifact_type=f"corruption_{f.stem}",
132
- file_path=str(f.resolve()),
133
- checksum=compute_file_sha256(f),
131
+ artifact_type=f"corruption_{file_item.stem}",
132
+ file_path=str(file_item.resolve()),
133
+ checksum=compute_file_sha256(file_item),
134
134
  )
135
135
 
136
136
  # Index predictions subfolder if present
137
137
  preds_dir = exp_path / "predictions"
138
138
  if preds_dir.is_dir():
139
- for f in preds_dir.iterdir():
140
- if f.is_file() and f.suffix == ".npz":
139
+ for file_item in preds_dir.iterdir():
140
+ if file_item.is_file() and file_item.suffix == ".npz":
141
141
  repo.add_artifact(
142
142
  experiment_id=exp_model.id,
143
- artifact_type=f"prediction_{f.stem}",
144
- file_path=str(f.resolve()),
145
- checksum=compute_file_sha256(f),
143
+ artifact_type=f"prediction_{file_item.stem}",
144
+ file_path=str(file_item.resolve()),
145
+ checksum=compute_file_sha256(file_item),
146
146
  )
147
147
 
148
148
  # 4. Extract and index scalar metrics
@@ -133,10 +133,10 @@ class MetricRegistry:
133
133
  raise MetricRegistrationError("Metric name must be a non-empty string.")
134
134
  metric_name = name.strip()
135
135
  else:
136
- metric_name = getattr(func, "__name__", None)
137
- if not metric_name or not isinstance(metric_name, str) or not metric_name.strip():
136
+ raw_name = getattr(func, "__name__", None)
137
+ if not raw_name or not isinstance(raw_name, str) or not raw_name.strip():
138
138
  raise MetricRegistrationError("Metric name must be a non-empty string.")
139
- metric_name = metric_name.strip()
139
+ metric_name = raw_name.strip()
140
140
 
141
141
  if not callable(func):
142
142
  raise MetricRegistrationError(f"Target metric {func!r} is not callable.")
@@ -9,7 +9,7 @@ from typing import Any
9
9
  try:
10
10
  CURRENT_VERSION = importlib.metadata.version("trustbench")
11
11
  except importlib.metadata.PackageNotFoundError:
12
- CURRENT_VERSION = "0.2.2"
12
+ CURRENT_VERSION = "0.2.3"
13
13
 
14
14
  logger = logging.getLogger(__name__)
15
15
 
@@ -164,7 +164,7 @@ class PluginManager:
164
164
  if hasattr(eps, "select"):
165
165
  matching_eps = eps.select(group=group)
166
166
  else:
167
- matching_eps = eps.get(group, [])
167
+ matching_eps = eps.get(group, []) # type: ignore[attr-defined,arg-type]
168
168
  except Exception as exc: # noqa: BLE001
169
169
  logger.warning("Error querying entry points for group %r: %s", group, exc)
170
170
  return dict(self._plugins)
@@ -109,8 +109,8 @@ class RobustnessEvaluator:
109
109
  base_seed=self.seed,
110
110
  )
111
111
 
112
- loader = DataLoader(
113
- corrupted_ds,
112
+ loader: Any = DataLoader(
113
+ corrupted_ds, # type: ignore[arg-type]
114
114
  batch_size=self.batch_size,
115
115
  shuffle=False,
116
116
  num_workers=self.num_workers,
@@ -261,7 +261,7 @@ class RobustnessEvaluator:
261
261
  # Save predictions NPZ: predictions/<c_type>.npz (if enabled)
262
262
  if save_predictions:
263
263
  npz_file = predictions_dir / f"{c_type}.npz"
264
- np.savez_compressed(npz_file, **npz_arrays)
264
+ np.savez_compressed(npz_file, **npz_arrays) # type: ignore[arg-type]
265
265
  del npz_arrays
266
266
 
267
267
  # Save config.json
@@ -55,7 +55,7 @@ def _atomic_write_npz(path: Path, data: dict[str, np.ndarray]) -> None:
55
55
  path.parent.mkdir(parents=True, exist_ok=True)
56
56
  tmp_path = path.with_suffix(path.suffix + f".tmp.{uuid.uuid4().hex[:8]}")
57
57
  with open(tmp_path, "wb") as f:
58
- np.savez_compressed(f, **data)
58
+ np.savez_compressed(f, **data) # type: ignore[arg-type]
59
59
  f.flush()
60
60
  os.fsync(f.fileno())
61
61
  os.replace(tmp_path, path)
@@ -184,7 +184,7 @@ class FilesystemExperimentStore:
184
184
  checkpoint_sha = meta.get("checkpoint_sha256") or cfg.get("checkpoint_sha256")
185
185
  dataset_fp = meta.get("dataset_fingerprint") or cfg.get("dataset_fingerprint")
186
186
 
187
- manifest = {
187
+ manifest: dict[str, Any] = {
188
188
  "id": exp_id,
189
189
  "name": name,
190
190
  "experiment_type": experiment_type,