@@ -38,8 +38,10 @@ def func(needs: list[NeedItem], results: list[int], **kwargs) -> None: ...
3838"""
3939
4040from __future__ import annotations
41+ from typing import Any
4142
4243from sphinx_needs .need_item import NeedItem
44+ from score_metrics .traceability_metrics import CALCULATED_METRICS
4345
4446
4547def _matches_source_selector (need : NeedItem , selector : str ) -> bool :
@@ -55,15 +57,15 @@ def _matches_source_selector(need: NeedItem, selector: str) -> bool:
5557
5658
5759def generic_pie_linked_items (
58- needs : list [NeedItem ], results : list [int ], ** kwargs : dict [ str , str | int | float ]
60+ needs : list [NeedItem ], results : list [int ], ** kwargs : Any
5961) -> None :
6062 """Count target IDs by whether they are linked by selected source needs.
6163
6264 Arguments are passed via ``arg1`` (target ID prefix), ``arg2`` (source
6365 selector prefix, matched against source ``type`` and ``id``), and ``arg3``
6466 (link field name, default ``complies``).
6567 """
66- results = []
68+ results . clear ()
6769 id_prefix = str (kwargs .get ("arg1" , "" ))
6870 source_selector = str (kwargs .get ("arg2" , "" ))
6971 link_field = str (kwargs .get ("arg3" , "complies" ))
@@ -90,14 +92,15 @@ def generic_pie_linked_items(
9092
9193
9294def generic_pie_items_by_tag (
93- needs : list [NeedItem ], results : list [int ], ** kwargs : dict [ str , str | int | float ]
95+ needs : list [NeedItem ], results : list [int ], ** kwargs : Any
9496) -> None :
9597 """Count tagged items split by whether selected source needs link them.
9698
9799 Arguments are passed via ``arg1`` (tag), ``arg2`` (source selector prefix,
98100 matched against source ``type`` and ``id``), and ``arg3`` (link field
99101 name, default ``complies``).
100102 """
103+ results .clear ()
101104 tag = str (kwargs .get ("arg1" , "" ))
102105 source_selector = str (kwargs .get ("arg2" , "" ))
103106 link_field = str (kwargs .get ("arg3" , "complies" ))
@@ -124,7 +127,7 @@ def generic_pie_items_by_tag(
124127
125128
126129def generic_pie_items_in_relationships (
127- needs : list [NeedItem ], results : list [int ], ** kwargs : dict [ str , str | int | float ]
130+ needs : list [NeedItem ], results : list [int ], ** kwargs : Any
128131) -> None :
129132 """Count items of a given type by how many container items reference them.
130133
@@ -143,6 +146,7 @@ def generic_pie_items_in_relationships(
143146 Appends to *results*:
144147 ``[not_referenced_count, referenced_once_count, referenced_multiple_count]``
145148 """
149+ results .clear ()
146150 container_type = str (kwargs .get ("arg1" , "" ))
147151 field = str (kwargs .get ("arg2" , "" ))
148152 item_type = str (kwargs .get ("arg3" , "" ))
@@ -167,9 +171,71 @@ def generic_pie_items_in_relationships(
167171 results .append (referenced_multiple )
168172
169173
170- def get_metrics_from_generated_json (
171- needs : list [NeedItem ], results : list [int ], ** kwargs : str | int | float
174+ def _get_key_values (results : list [int ], argument_paths : list [str ]):
175+ """Append integer metric values selected by colon-separated paths.
176+
177+ Each path is resolved against ``CALCULATED_METRICS`` (for example:
178+ ``"overall_metrics:total"``), converted to ``int``, and appended to
179+ ``results``.
180+ """
181+ metrics_json = CALCULATED_METRICS
182+ for raw_path in argument_paths :
183+ path = raw_path .strip ()
184+ if not path :
185+ continue
186+
187+ current : Any = metrics_json
188+ for key in path .split (":" ):
189+ current = current [key ]
190+
191+ results .append (int (current ))
192+
193+
194+ def get_metrics_with_overall_total_considered (
195+ needs : list [Any ], results : list [int ], ** kwargs : Any
196+ ) -> None :
197+ """Append selected metrics and compute remainder from overall total.
198+
199+ This function appends ``overall_metrics:total`` first, then appends all
200+ metrics referenced by ``kwargs`` values. Finally, it replaces the first
201+ appended value with the remainder after subtracting all other appended
202+ values.
203+ """
204+ results .clear ()
205+ metrics_json = CALCULATED_METRICS
206+ results .append (int (metrics_json ["overall_metrics" ]["total" ]))
207+ _get_key_values (results , [str (value ) for value in kwargs .values ()])
208+ results [0 ] -= sum (results [1 :])
209+ print (results )
210+
211+
212+ def get_metrics_with_custom_type_total_considered (
213+ needs : list [Any ], results : list [int ], ** kwargs : Any
172214) -> None :
173- metrics_json_path = str (kwargs .get ("arg1" , "_build/metrics.json" ))
174- # TODO: Read the Metrics.json and give back the data
175- results
215+ """Append selected metrics, optionally using a custom total path.
216+
217+ If the last kwarg value ends with ``":total"``, that path is used as
218+ baseline total and all preceding paths are treated as components; the first
219+ result becomes ``total - sum(components)``. Otherwise, all paths are simply
220+ appended as-is.
221+ """
222+ # Get the 'total' that was specified as the first value
223+
224+ results .clear ()
225+ values = [str (value ) for value in kwargs .values ()]
226+ if values [- 1 ].endswith (":total" ):
227+ _get_key_values (results , [values [- 1 ]]) # baseline total
228+ _get_key_values (results , values [:- 1 ]) # components
229+ results [0 ] -= sum (results [1 :])
230+ else :
231+ _get_key_values (results , values )
232+
233+
234+ def get_just_metrics (needs : list [Any ], results : list [int ], ** kwargs : Any ) -> None :
235+ """Append selected metric values without any total/remainder calculation.
236+
237+ All kwarg values are interpreted as colon-separated metric paths and
238+ appended to ``results`` in insertion order.
239+ """
240+ results .clear ()
241+ _get_key_values (results , [str (value ) for value in kwargs .values ()])
0 commit comments