@@ -151,6 +151,296 @@ For a new consumer repository:
1511514. Introduce modest thresholds in CI.
1521525. Raise thresholds over time as the repository matures.
153153
154+ ..
155+ ╓ ╖
156+ ║ .. The Following part has been generated by Copilot ║
157+ ╙ ╜
158+
159+ Metrics Needpie functions
160+ =========================
161+
162+ Overview
163+ --------
164+
165+ These helpers read values from a nested dictionary named ``CALCULATED_METRICS ``.
166+ A metric is selected by a **colon-separated path **, for example:
167+
168+ - ``overall_metrics:total ``
169+ - ``overall_metrics:with_test_link ``
170+ - ``types:bug:total ``
171+
172+ All resolved values are converted to ``int `` and appended to a mutable
173+ ``results `` list passed by the caller.
174+
175+ The ``needs `` parameter is accepted for integration compatibility, but it is not
176+ used by the current implementations.
177+
178+ Path format
179+ -----------
180+
181+ Paths are split using ``: `` and then resolved step by step.
182+
183+ Example:
184+
185+ .. code-block :: text
186+
187+ path = "overall_metrics:total"
188+
189+ is resolved like:
190+
191+ .. code-block :: python
192+
193+ current = CALCULATED_METRICS
194+ current = current[" overall_metrics" ]
195+ current = current[" total" ]
196+
197+ Function reference
198+ ------------------
199+
200+ _get_key_values(results, argument_paths)
201+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
202+
203+ Purpose
204+ ^^^^^^^
205+
206+ Internal helper that appends metric values for a list of paths.
207+
208+ Behavior
209+ ^^^^^^^^
210+
211+ 1. Iterate over each item in ``argument_paths ``.
212+ 2. Strip whitespace.
213+ 3. Skip empty paths.
214+ 4. Resolve the path inside ``CALCULATED_METRICS ``.
215+ 5. Convert to integer and append to ``results ``.
216+
217+ Notes
218+ ^^^^^
219+
220+ - Modifies ``results `` in place.
221+ - Does not return a new list.
222+ - Raises ``KeyError `` if a path key does not exist.
223+ - Raises ``ValueError `` if a resolved value cannot be converted to ``int ``.
224+
225+ get_metrics_with_overall_total_considered(...)
226+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
227+
228+ Purpose
229+ ^^^^^^^
230+
231+ Compute a remainder against global overall total.
232+
233+ Behavior
234+ ^^^^^^^^
235+
236+ 1. Append ``CALCULATED_METRICS["overall_metrics"]["total"] `` as first value.
237+ 2. Append each metric referenced by ``kwargs.values() ``.
238+ 3. Replace the first value with:
239+
240+ ``overall_total - sum(all other appended values) ``
241+
242+ Typical use case
243+ ^^^^^^^^^^^^^^^^
244+
245+ Use this when your pie/chart needs an "Other" bucket based on the global total.
246+
247+ Example
248+ ^^^^^^^
249+
250+ Assume:
251+
252+ .. code-block :: python
253+
254+ CALCULATED_METRICS = {
255+ " overall_metrics" : {
256+ " total" : 100 ,
257+ " with_test_link" : 30 ,
258+ " with_review" : 20 ,
259+ }
260+ }
261+
262+ Call:
263+
264+ .. code-block :: python
265+
266+ results = []
267+ get_metrics_with_overall_total_considered(
268+ needs = [],
269+ results = results,
270+ a = " overall_metrics:with_test_link" ,
271+ b = " overall_metrics:with_review" ,
272+ )
273+
274+ Result:
275+
276+ .. code-block :: python
277+
278+ # Step 1 append total: [100]
279+ # Step 2 append selected: [100, 30, 20]
280+ # Step 3 remainder: [50, 30, 20]
281+ results == [50 , 30 , 20 ]
282+
283+ get_metrics_with_custom_type_total_considered(...)
284+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
285+
286+ Purpose
287+ ^^^^^^^
288+
289+ Support custom total path if provided as the last kwarg value.
290+
291+ Behavior
292+ ^^^^^^^^
293+
294+ If the **last ** provided path ends with ``:total ``:
295+
296+ 1. Append that last path as baseline total.
297+ 2. Append all preceding paths as components.
298+ 3. Replace the first value with:
299+
300+ ``baseline_total - sum(components) ``
301+
302+ Otherwise:
303+
304+ - Append all provided paths directly (no subtraction).
305+
306+ Important ordering rule
307+ ^^^^^^^^^^^^^^^^^^^^^^^
308+
309+ The special total path must be the **last ** kwarg value, for example:
310+
311+ .. code-block :: python
312+
313+ get_metrics_with_custom_type_total_considered(
314+ needs = [],
315+ results = results,
316+ part_a = " types:feature:done" ,
317+ part_b = " types:feature:in_progress" ,
318+ total = " types:feature:total" , # must be last
319+ )
320+
321+ Example with custom total
322+ ^^^^^^^^^^^^^^^^^^^^^^^^^
323+
324+ Assume:
325+
326+ .. code-block :: python
327+
328+ CALCULATED_METRICS = {
329+ " types" : {
330+ " feature" : {
331+ " total" : 40 ,
332+ " done" : 10 ,
333+ " in_progress" : 5 ,
334+ }
335+ }
336+ }
337+
338+ Call:
339+
340+ .. code-block :: python
341+
342+ results = []
343+ get_metrics_with_custom_type_total_considered(
344+ needs = [],
345+ results = results,
346+ done = " types:feature:done" ,
347+ in_progress = " types:feature:in_progress" ,
348+ total = " types:feature:total" ,
349+ )
350+
351+ Result:
352+
353+ .. code-block :: python
354+
355+ # baseline total: 40
356+ # components: 10, 5
357+ # remainder: 40 - (10 + 5) = 25
358+ results == [25 , 10 , 5 ]
359+
360+ Example without custom total
361+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
362+
363+ Call:
364+
365+ .. code-block :: python
366+
367+ results = []
368+ get_metrics_with_custom_type_total_considered(
369+ needs = [],
370+ results = results,
371+ done = " types:feature:done" ,
372+ in_progress = " types:feature:in_progress" ,
373+ )
374+
375+ Result:
376+
377+ .. code-block :: python
378+
379+ # no subtraction mode
380+ results == [10 , 5 ]
381+
382+ get_just_metrics(...)
383+ ~~~~~~~~~~~~~~~~~~~~
384+
385+ Purpose
386+ ^^^^^^^
387+
388+ Append only the selected metric values.
389+
390+ Behavior
391+ ^^^^^^^^
392+
393+ - Interprets each kwarg value as a path.
394+ - Resolves and appends each value.
395+ - No total baseline and no remainder calculation.
396+
397+ Example
398+ ^^^^^^^
399+
400+ .. code-block :: python
401+
402+ results = []
403+ get_just_metrics(
404+ needs = [],
405+ results = results,
406+ a = " overall_metrics:with_test_link" ,
407+ b = " overall_metrics:with_review" ,
408+ )
409+ # results might become [30, 20]
410+
411+ How to use these functions correctly
412+ ------------------------------------
413+
414+ 1. Pass a mutable list in ``results `` (usually ``[] `` initially).
415+ 2. Provide metric paths through keyword argument values.
416+ 3. Use colon-separated keys (``a:b:c ``), not dot notation.
417+ 4. For custom-total mode, ensure the total path is the last kwarg value.
418+ 5. Expect in-place mutation of ``results ``.
419+
420+ Common pitfalls
421+ ---------------
422+
423+ - Empty kwargs in custom-total function can lead to index errors
424+ (because ``values[-1] `` is accessed).
425+ - Invalid paths raise ``KeyError ``.
426+ - Non-integer values raise ``ValueError `` during ``int(...) `` conversion.
427+ - ``print(results) `` currently causes side effects during execution; remove if
428+ quiet behavior is preferred in production.
429+
430+ Testing recommendations
431+ -----------------------
432+
433+ Add unit tests for:
434+
435+ - Basic path resolution with one and multiple paths.
436+ - Whitespace and empty-path handling.
437+ - Overall total remainder logic.
438+ - Custom total behavior when last path ends with ``:total ``.
439+ - Behavior when no custom total is provided.
440+ - Error handling for missing keys and non-integer values.
441+ - Empty ``kwargs `` behavior in custom-total function.
442+
443+
154444Related Guides
155445--------------
156446
0 commit comments