Repository navigation
Conversation
calculate_list_confusion_matrix, calculate_nested_field_metrics and calculate_single_nested_field_metrics only called each other, and their only way in was three StructuredModel wrappers that nothing calls. All six had zero executed lines across the full suite. Remove them, the HungarianHelper, NonMatchesHelper and List imports that only they used, and the refactoring notes that listed the wrappers. StructuredListComparator._calculate_nested_field_metrics is a separate, live method with the same name and is untouched. So are ConfusionMatrixCalculator.__init__, classify_field_for_confusion_matrix and StructuredModel._classify_field_for_confusion_matrix, which StructuredListComparator calls. The 1e-10 threshold window that algorithms/README.md and the HungarianMatcher.calculate_metrics docstring attribute to ConfusionMatrixCalculator lived in the deleted calculate_nested_field_metrics. The method that remains compares with a bare >=, so both now name only ThresholdHelper and ComparisonHelper. Also run ruff format on the calculator file, which only strips the trailing whitespace from 9 blank docstring lines. Closes awslabs#296
Security Scan ResultsASH Security Scan Report
Scan Metadata
SummaryScanner ResultsThe table below shows findings by scanner, with status based on severity thresholds and dependencies:
Top 2 HotspotsFiles with the highest number of security findings:
Detailed FindingsShow 4 actionable findingsFinding 1: SECRET-HEX-HIGH-ENTROPY-STRING
Description: Code Snippet: Finding 2: B108
Description: Code Snippet: Finding 3: B307
Description: Code Snippet: Finding 4: B307
Description: Code Snippet: Report generated by Automated Security Helper (ASH) at 2026-10-15T15:14:13+00:00 |
sromoam
left a comment
There was a problem hiding this comment.
Thanks @Thanatos9404, this is a clean removal, and welcome to the project. Nothing on ad19ac8 still references the six removed methods or the dropped imports, and the edits to algorithms/README.md and the hungarian.py docstring are accurate. CI is green.
Reviewing it turned up a few more dead paths of the same kind nearby, plus a threshold check on the remaining live path. None of that blocks this PR, so I've written them up in #395. If you'd like to take that one on too, it's yours.
* refactor(395): remove the remaining dead confusion-matrix paths StructuredModel._calculate_object_level_metrics has no caller. The one call site is inside StructuredListComparator, which does not inherit from StructuredModel and calls its own copy. ConfusionMatrixBuilder's calculator property and _calculator slot are never read. Both had zero executed lines across the full suite. Remove them, the HungarianHelper import that only the first used, and the docstrings that describe the builder as coordinating a ConfusionMatrixCalculator. classify_field_for_confusion_matrix now returns only the six counts. Its one caller, StructuredListComparator._handle_non_hierarchical_field, adds up those counts for every matched pair and primitive sub-field and never read the derived metrics that came with them. It is now a staticmethod that takes the ground truth model, so the StructuredModel wrapper no longer builds a ConfusionMatrixCalculator on every call. The StructuredModel branch in classify_field_for_confusion_matrix stays. is_structured_field_type does not recognise a list element sub-field annotated Union[A, B] or Any, so model values on such a field reach the classifier. Without the branch the default LevenshteinComparator would score the text of the two models, and a pair that scores 0.0 as models would count as a TP. A new test pins it. Also correct the StructuredModel size in the refactoring notes (2029 lines now, not ~1486), and name the shims #390 removed and what does their work now. Refs #395 * docs(395): say which StructuredModel shims remain The refactoring notes still said the private wrappers "were not removed" right above the paragraph listing the four that were. Say the ones that still have callers are kept as forwarding wrappers, and link the _calculate_object_level_metrics removal to #398 instead of the issue. Also stop listing ConfusionMatrixCalculator as the component that calculates the matrix in the ComparisonEngine, AggregateMetricsCalculator and DerivedMetricsCalculator docstrings, number the builder's inline step comments to match its docstring, and give the Levenshtein score in the model-valued sub-field test as about 0.96 (measured 0.9583). Refs #395 * docs(395): call the classified list sub-fields non-list, not primitive Model-valued sub-fields annotated Union or Any also reach the classifier, so "non-list" describes what it handles; simple list sub-fields still go through the element-level dispatch.
Pull Request
Issue Reference
Closes #296
Description of Changes
Removes the three
ConfusionMatrixCalculatormethods that nothing reaches, and the threeStructuredModelwrappers that were their only way in. Nothing that runs today changes: before this change all six had zero executed lines across the full suite.Changes Made
confusion_matrix_calculator.py: deletecalculate_list_confusion_matrix(lines 38-159),calculate_nested_field_metrics(244-556) andcalculate_single_nested_field_metrics(557-650). With the blank line between them that is the 530 lines from the re-verification comment. Drop theHungarianHelper,NonMatchesHelperandListimports, which only those methods used, and the "and lists of structured models" clause from the class docstring. The file goes from 650 to 117 lines.ruff formatalso strips the trailing whitespace from 9 blank docstring lines in the kept code, the cleanup the refactor: remove deprecated ComparableField(aggregate=) parameter (#226) #293 review set aside for Delete the superseded ConfusionMatrixCalculator nested and list methods (329 dead lines) and their StructuredModel wrappers #296.structured_model.py: delete the wrappers_calculate_list_confusion_matrix(:1504),_calculate_nested_field_metrics(:1526) and_calculate_single_nested_field_metrics(:1558), 80 lines.docs/structured_model_REFACTORING.md: drop the three rows from the Code Location Mapping table (378-380), and the two removed names from the "Legacy private methods are kept as delegating shims" paragraph (:159), which said they still exist.src/stickler/algorithms/README.mdand theHungarianMatcher.calculate_metricsdocstring: both saidConfusionMatrixCalculatoraccepts a score up to1e-10under the threshold. That tolerant test lived in the deletedcalculate_nested_field_metrics(old line 324). The method that remains,classify_field_for_confusion_matrix, uses a baresimilarity >= threshold, so both now name onlyThresholdHelperandComparisonHelper, which do use the tolerant test.No test changes.
Why These Changes Are Needed
These methods are a superseded copy of the list and nested metrics that
StructuredListComparatorcomputes today. They were kept as backward-compatibility shims, and nothing in the repository uses them any more. Removing them takes about 610 lines of unexecuted code out of the metrics path, and leaves one_calculate_nested_field_metricsinstead of two.Reachability check
Line numbers are on
devat 70e9afb. Each name was searched withgit grep -nover the whole checkout:src/,tests/,examples/(including all 11 notebooks),docs/andCHANGELOG.md. A search for indirect access (getattr/hasattr/mock.patchon these names, or the names as string literals) found none. Executed statements come fromcoverage jsonafter a fullcoverage run -m pytest tests/on unmodifieddev.devConfusionMatrixCalculator.calculate_list_confusion_matrixcalculate_nested_field_metrics(:343, :436, :490),calculate_single_nested_field_metrics(:614), wrapperStructuredModel._calculate_list_confusion_matrix(:1524)ConfusionMatrixCalculator.calculate_nested_field_metricscalculate_list_confusion_matrix(:145), wrapperStructuredModel._calculate_nested_field_metrics(:1554)ConfusionMatrixCalculator.calculate_single_nested_field_metricsStructuredModel._calculate_single_nested_field_metrics(:1580)StructuredModel._calculate_list_confusion_matrixStructuredModel._calculate_nested_field_metricsStructuredModel._calculate_single_nested_field_metricsThe three calculator methods only call each other, the three wrappers are their only entry points, and the wrappers have no callers.
The one call that looks like a caller is
structured_list_comparator.py:82,self._calculate_nested_field_metrics(...).StructuredListComparatordoes not inherit fromStructuredModel(class StructuredListComparator:at :21), so that call resolves to its own method at :209, which this PR keeps. It also passes five arguments, includingmatched_pairs; the wrapper took four.None of the six is public API. None is exported from any
__init__.pyor__all__. The API reference rendersStructuredModelthrough mkdocstrings withfilters: ["!^_[^_]", "^_compare$"](docs/mkdocs.yml), so the underscore wrappers never appeared there, and no:::directive rendersConfusionMatrixCalculator. The only docs that listed them were the refactoring notes edited here.Deliberately kept
StructuredListComparator._calculate_nested_field_metrics(structured_list_comparator.py:209): the live namesake, called from :82. 15/15 statements executed before and after.ConfusionMatrixCalculator.__init__andclassify_field_for_confusion_matrix: live throughstructured_list_comparator.py:511callingStructuredModel._classify_field_for_confusion_matrix(:1482), which callsclassify_field_for_confusion_matrix. Statements executed, the same before and after:classify_field_for_confusion_matrix26/29,__init__1/1.ConfusionMatrixBuilder.calculatoralso constructs aConfusionMatrixCalculatorand needs only__init__._classify_field_for_confusion_matrixwrapper and its row in the refactoring notes.Testing
signal.SIGALRM, plus two timing tests that fail only under coverage tracing; details below)Run on Windows, Python 3.12.5,
uv sync --frozen --extra llm --no-group docs(CI also installs thebertextra; its torch stack was not installed for this run).inspect.getfile(stickler)pointed at this checkout'ssrc/stickler/__init__.py.dev70e9afbconfusion_matrix_calculator.pystructured_model.pystructured_list_comparator.pysrc/totalMissed statements in
src/drop by exactly 164 (1174 to 1010), which is the body statement count of the six methods (29 + 100 + 26 + 3 x 3).Failures, the same 8 on both sides:
test_realistic_deep_nesting.py:AttributeError: module 'signal' has no attribute 'SIGALRM'(Windows has noSIGALRM). Linux CI runs them.test_deep_nesting_6_levels.py::test_performance_with_deep_nesting(35 s budget, 78.8 s on this branch) andtest_performance_benchmark.py::test_performance_simple_comparison(5 ms budget; 12.1 ms ondev, 5.3 ms on this branch). Without coverage both pass on this branch:uv run pytest tests/structured_object_evaluator/test_performance_benchmark.py tests/structured_object_evaluator/test_deep_nesting_6_levels.pygives 12 passed.Lint:
The same 16 findings before and after, all in
examples/notebooks/*.ipynbandexamples/scripts/llm_comparator_demo.py. None are insrc/ortests/. On the three changed Python files,uv run ruff checkpasses anduv run ruff format --checkreports them already formatted. The repo configures no type checker.Reviewers
@sromoam
Checklist
CHANGELOG.mdentry added under[Unreleased], or not needed becausenothing user-visible changed (see RELEASING.md): dead-code removal, no entry
Additional Notes
structured_model.pyhave moved since the re-verification comment (:1203 and :1229 there). On currentdev, the kept wrapper is at :1482 and the removed ones are at :1504, :1526 and :1558.src/stickler/algorithms/README.mda few lines below the sentence changed here. The two changes do not touch the same lines.By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.