Repository navigation
Commit a73bfef
fix(compare): skip malformed compare_list entries instead of crashing, with one shared check (#5488)
* fix(compare): skip a compare_list entry with no id instead of crashing (#5472)
Compare.run_all() indexed tariff["id"] directly, so a compare_list entry
missing its id line raised KeyError every 5-minute cycle - and because the
crash skipped predbat.py's compare_active reset, the comparison (and the
crash) kept re-triggering until the config was fixed.
The id lookup and its warning are now in their own get_tariff_id() method,
so the guard can be tested directly rather than only by inspecting run_all()'s
source text (code review for #5472 found the source-inspection test alone
would pass a guard that checked the wrong field, e.g. tariff.get("name")).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
* test(compare): behavioural tests for the id-less skip and compare_active reset (#5472)
Replace T28's source-text check with a run_all() run against the real
fixture (run_single/save_yaml stubbed) showing only the valid tariff is
compared and persisted. Extract the compare_active set/clear into
PredBat.run_comparison() so T29 can make run_all() raise and check the
flag is cleared, without driving all of update_pred(). Both tests fail
with the fixes reverted.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(compare): validate compare_list once, skipping every malformed entry (#5472)
get_tariff_id() only caught a missing id. A non-dict entry, a duplicate
id or a nameless entry still misbehaved in run_all(), and an unquoted
numeric id (YAML int) still crashed publish_data() building the sensor
name - every cycle, via publish_only(). Replace it with module-level
compare_entry_problem()/valid_compare_list(), which run_all(),
publish_only() and load_yaml() use to drop bad entries (warning with
the entry's position) and normalise ids to strings. load_yaml() also
str()s stored keys so a numeric key saved earlier can't crash startup.
T29 now restores compare_active on the shared fixture.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(web): share compare.py's compare_list rules in the editor and compare page (#5472)
_validate_compare_list() now applies compare_entry_problem(), so the
apps.yaml editor refuses exactly what a comparison would skip - now
including a blank id and a numeric id clashing with the same id quoted.
html_compare() reads valid_compare_list(), so a malformed entry no
longer crashes the page and a numeric id finds its string-keyed result.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(compare): one check_compare_list() for engine, editor and page (#5472)
Review follow-up. check_compare_list() returns the usable entries plus a
message per skipped one, so web.py's validator no longer re-implements
the loop. It also covers a compare_list that isn't a list (was a
TypeError every cycle via publish_only), strips padded ids so ' agile'
can't sidestep the duplicate check, and str()s a numeric name, which
otherwise crashed publish_data() - and, once saved, every startup.
The Compare page now says why an entry was skipped instead of dropping
it silently or claiming nothing is configured. Tests now assert the
run_all() warnings and the editor's refusal reasons.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(compare): reject a non-mapping config, blank name; report every problem (#5472)
Second review round. check_compare_list() now skips an entry whose
config: isn't a mapping (it crashed run_all() outside the per-tariff
try) and treats an empty config: as no overrides; strips the name so a
blank one is refused like a blank id. publish_data() str()s a stored
name so one saved as a number can't stop startup. The editor lists
every compare_list problem at once rather than one per save.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(compare): keep treating an empty config: list or string as no overrides (#5472)
Third review round. The previous commit skipped any entry whose config:
wasn't a mapping, which wrongly dropped working tariffs with config: []
or "" (both always meant no overrides). Only a non-empty non-mapping
config - which crashed run_all()'s override snapshot - is skipped now,
and the comment names that real crash site. T28 now drives a list
config through run_all() itself.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(compare): spell out which config: values mean no overrides (#5472)
Review follow-up. Only None, "", [] and {} count as an empty config:
and are dropped; any other non-mapping (false, 0, a string, a list) is
skipped with a warning instead of silently losing the overrides.
check_compare_list()'s docstring now states the shape it guarantees,
and the comment names where a list config really crashed (overrides
looked up by key in run_all()/fetch_config()).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* test(compare): pin which config: values are kept, dropped or skipped (#5472)
Review follow-up. One EMPTY_COMPARE_CONFIG tuple now decides both the
skip and the drop, rather than a tuple in one place and truthiness in
the other. T27 checks the reason each config entry was skipped, and
adds a mapping config, which must survive as the tariff's overrides -
nothing tested that, so a check skipping or dropping every config would
have passed.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>1 parent 0bca948 commit a73bfef
6 files changed
Lines changed: 361 additions & 35 deletions
File tree
- apps/predbat
- tests
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
27 | 27 | | |
28 | 28 | | |
29 | 29 | | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
30 | 89 | | |
31 | 90 | | |
32 | 91 | | |
| |||
483 | 542 | | |
484 | 543 | | |
485 | 544 | | |
486 | | - | |
| 545 | + | |
| 546 | + | |
| 547 | + | |
487 | 548 | | |
488 | 549 | | |
489 | 550 | | |
490 | 551 | | |
491 | | - | |
| 552 | + | |
492 | 553 | | |
493 | 554 | | |
494 | 555 | | |
| |||
512 | 573 | | |
513 | 574 | | |
514 | 575 | | |
515 | | - | |
| 576 | + | |
| 577 | + | |
516 | 578 | | |
517 | 579 | | |
518 | 580 | | |
| |||
539 | 601 | | |
540 | 602 | | |
541 | 603 | | |
542 | | - | |
| 604 | + | |
543 | 605 | | |
544 | 606 | | |
545 | 607 | | |
| |||
597 | 659 | | |
598 | 660 | | |
599 | 661 | | |
600 | | - | |
| 662 | + | |
601 | 663 | | |
602 | 664 | | |
603 | 665 | | |
| |||
672 | 734 | | |
673 | 735 | | |
674 | 736 | | |
675 | | - | |
| 737 | + | |
| 738 | + | |
676 | 739 | | |
677 | 740 | | |
678 | 741 | | |
| |||
684 | 747 | | |
685 | 748 | | |
686 | 749 | | |
687 | | - | |
| 750 | + | |
688 | 751 | | |
689 | 752 | | |
690 | 753 | | |
691 | | - | |
| 754 | + | |
692 | 755 | | |
693 | 756 | | |
694 | 757 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1070 | 1070 | | |
1071 | 1071 | | |
1072 | 1072 | | |
| 1073 | + | |
| 1074 | + | |
| 1075 | + | |
| 1076 | + | |
| 1077 | + | |
| 1078 | + | |
| 1079 | + | |
| 1080 | + | |
| 1081 | + | |
1073 | 1082 | | |
1074 | 1083 | | |
1075 | 1084 | | |
| |||
1431 | 1440 | | |
1432 | 1441 | | |
1433 | 1442 | | |
1434 | | - | |
1435 | | - | |
1436 | | - | |
| 1443 | + | |
1437 | 1444 | | |
1438 | 1445 | | |
1439 | 1446 | | |
| |||
0 commit comments