fix: pair Lichfield bin headings with dates within their own card - #2187
fix: pair Lichfield bin headings with dates within their own card#2187alec-pinson wants to merge 1 commit into
Conversation
LichfieldDistrictCouncil built two page-wide lists and zipped them by
index:
bins = soup.find_all("h3", class_="bin-collection-tasks__heading")
dates = soup.find_all("p", class_="bin-collection-tasks__date")
for i in range(len(dates)):
bint = " ".join(bins[i].text.split()[2:4])
date = dates[i].text
That only holds while every heading has a matching date. Two things on
the page break it:
- The calendar download link ("Download your bin collection calendar")
reuses the bin-collection-tasks__heading class but is not a bin.
- A bin with no scheduled collection renders a
bin-collection-tasks__frequency ("Collected every Monday") instead of
a bin-collection-tasks__date. Food Waste Caddy is currently in this
state on at least some addresses.
When a dateless card appears before the others, every bin is shifted
onto the following bin's date and the last bin is dropped entirely.
This is silent - the output stays schema-valid, it is just wrong.
The repository's own test UPRN (100031694085) is affected. Ground truth
from the page:
Black Bin 30th July
Food Waste Caddy (no date - collected every Thursday)
Blue Bin 6th August
Brown Bin 6th August
Blue Bag 6th August
Before:
Black Bin 30/07/2026
Food Waste 06/08/2026 <- invented, the page shows no date
Blue Bin 06/08/2026
Brown Bin 06/08/2026
(Blue Bag missing)
After:
Black Bin 30/07/2026
Blue Bin 06/08/2026
Brown Bin 06/08/2026
Blue Bag 06/08/2026
Iterate the headings instead and read the date from the same card,
skipping cards that have no date.
Bin names now come from the heading with its visually-hidden "Your
next" / "collection" spans removed, rather than slicing words 2:4.
The slice truncated three-word names ("Food Waste Caddy" -> "Food
Waste"). Prefix/suffix stripping is kept as a fallback in case those
spans go away.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
📝 WalkthroughWalkthrough
ChangesLichfield bin parsing
Estimated code review effort: 2 (Simple) | ~10 minutes 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
uk_bin_collection/uk_bin_collection/councils/LichfieldDistrictCouncil.py (1)
40-71: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winAdd regression coverage for the card-local pairing.
Please add fixtures asserting that a dateless card does not shift subsequent dates, calendar headings are ignored, and multi-word names such as “Food Waste Caddy” are preserved.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@uk_bin_collection/uk_bin_collection/councils/LichfieldDistrictCouncil.py` around lines 40 - 71, The current card-local parsing logic lacks regression fixtures for its key pairing and heading-handling cases. Add fixtures and tests covering a dateless card, ensuring later cards retain their own dates; calendar download headings are ignored; and multi-word names such as “Food Waste Caddy” are preserved by bin_name.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@uk_bin_collection/uk_bin_collection/councils/LichfieldDistrictCouncil.py`:
- Around line 40-71: The current card-local parsing logic lacks regression
fixtures for its key pairing and heading-handling cases. Add fixtures and tests
covering a dateless card, ensuring later cards retain their own dates; calendar
download headings are ignored; and multi-word names such as “Food Waste Caddy”
are preserved by bin_name.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: d4dbe72c-67d7-4d1c-abcb-8a739bfc2652
📒 Files selected for processing (1)
uk_bin_collection/uk_bin_collection/councils/LichfieldDistrictCouncil.py
|
Re the nitpick asking for regression coverage on the card-local pairing: The principle is right, and arguably this bug is the argument for it — the mis-pairing was silent precisely because the shifted output stayed schema-valid. The existing checks can't catch that class of failure by construction. The obstacle is that there's no precedent for it here. As far as I can tell:
So adding fixtures for Lichfield alone would introduce an offline test pattern that none of the other 351 councils follow. That seemed like a maintainer decision rather than something to fold into a single-council bugfix, so I've left this PR as just the fix. @robbrad — happy to add offline fixture tests here (dateless card not shifting subsequent dates, calendar heading ignored, multi-word |
|
Thanks for this — the visually-hidden-span extraction approach for the bin name is cleaner than the original word-slicing and is exactly what got used. #2179 fixed the same underlying bug independently and also handled a case yours doesn't: a card with no date but a recognizable weekly frequency (e.g. Food Waste Caddy) now gets a derived next-occurrence date instead of being dropped from the output entirely, which matters for keeping that Home Assistant entity from going unavailable. Rather than pick one over the other, I synthesized both into a single fix in the consolidated "July Part 2" release: #2189 — your heading-text extraction combined with #2179's frequency fallback and year-rollover fix. Closing this one out — credited in the PR. Generated by Claude Code |
LichfieldDistrictCouncil zipped a page-wide heading list and a page-wide date list together by index. Two things on the current page break that: the calendar-download link reuses the heading class but has no date, and a bin with no scheduled collection (Food Waste Caddy) renders a "Collected every <day>" frequency instead of a date. Either one shifts every later bin onto the wrong date and drops the last bin. Iterate each card and read its own date instead of pairing by position. When a card has no date but does have a weekly frequency, derive the next occurrence of that weekday so the entity keeps reporting (previously it silently inherited a neighboring bin's date). Extract the bin name by removing the visually-hidden heading spans rather than slicing words, so three-word names like "Food Waste Caddy" survive; that value is then mapped back to "Food Waste" to preserve the existing Home Assistant entity identity. Also fix year rollover to compare against today's date directly instead of a month heuristic. Synthesizes PR robbrad#2179 by JasSmiths and PR robbrad#2187 by alec-pinson, which independently reported and fixed this bug.


What
LichfieldDistrictCouncilcollects two page-wide lists and zips them together by index:That holds only while every heading has a corresponding date element. Two things on the current page break the assumption:
Download your bin collection calendar) reuses thebin-collection-tasks__headingclass but is not a bin, so it padsbins.bin-collection-tasks__frequency(Collected every Monday) instead of abin-collection-tasks__date. Food Waste Caddy is in this state on at least some addresses.When a dateless card sits before the others, every bin is shifted onto the following bin's date and the final bin drops off the end of the loop. The failure is silent — output stays schema-valid, it's just wrong.
Reproduction
This affects the repo's own test UPRN for Lichfield,
100031694085. Ground truth from the page:Before this PR:
{"bins": [ {"type": "Black Bin", "collectionDate": "30/07/2026"}, {"type": "Food Waste", "collectionDate": "06/08/2026"}, {"type": "Blue Bin", "collectionDate": "06/08/2026"}, {"type": "Brown Bin", "collectionDate": "06/08/2026"} ]}Food Wasteis given a date the page never showed, andBlue Bagis missing entirely.After this PR:
{"bins": [ {"type": "Black Bin", "collectionDate": "30/07/2026"}, {"type": "Blue Bin", "collectionDate": "06/08/2026"}, {"type": "Brown Bin", "collectionDate": "06/08/2026"}, {"type": "Blue Bag", "collectionDate": "06/08/2026"} ]}On a second address (
394018646) the misalignment was more visible, because the dateless Food Waste Caddy card is first:How
visually-hiddenYour next/collectionspans removed, rather than slicing words[2:4]. The slice truncated three-word names (Food Waste Caddy→Food Waste). Prefix/suffix stripping is kept as a fallback should those spans ever go away.No change to the date parsing or year-rollover logic.
Notes
Reported downstream as bins going
unavailablein Home Assistant — once a bin stops appearing in the output the coordinator stops creating its entities. Likely related to #1905, which presented the same way and was closed as council-side; this looks like the underlying parser fragility that made the page change bite.Verified against the live site for both UPRNs above.
black --checkclean.Summary by CodeRabbit