Skip to content

feat: WestMorlandAndFurness - add postcode + house number lookup#2064

Open
InertiaUK wants to merge 2 commits into
robbrad:masterfrom
InertiaUK:feat/westmorland-postcode-lookup
Open

feat: WestMorlandAndFurness - add postcode + house number lookup#2064
InertiaUK wants to merge 2 commits into
robbrad:masterfrom
InertiaUK:feat/westmorland-postcode-lookup

Conversation

@InertiaUK
Copy link
Copy Markdown
Contributor

@InertiaUK InertiaUK commented May 12, 2026

Summary

  • Users can now provide either UPRN or postcode + house number — whichever they have.
  • UPRN takes priority when provided (backward compatible with existing users).
  • When only postcode + house number is given, the scraper searches the council's LocalGov Drupal page, parses the address dropdown, and resolves the UPRN automatically.
  • Falls back to first address if no house number match found.

How it works

  1. If UPRN provided → use directly (existing behavior, unchanged)
  2. If no UPRN → GET /waste-collection-schedule/find?postcode=X → parse <select name="uprn"> → match by house number in option text → use matched UPRN with existing /view/{uprn} page

Testing

  • UPRN path (backward compat): LA9 4QU + UPRN 100110698636
  • Postcode + house number: LA9 4QU + paon 23
  • API end-to-end via bin-resolve-v2.php ✅

Summary by CodeRabbit

  • New Features
    • Search bin collections by postcode and house number (UPRN now optional)
    • More reliable schedule lookup using the council's base schedule source
    • Improved extraction of bin types for displayed collection days

Review Change Stack

@codecov
Copy link
Copy Markdown

codecov Bot commented May 12, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 86.67%. Comparing base (8ecf878) to head (e79dc18).

Additional details and impacted files
@@           Coverage Diff           @@
##           master    #2064   +/-   ##
=======================================
  Coverage   86.67%   86.67%           
=======================================
  Files           9        9           
  Lines        1141     1141           
=======================================
  Hits          989      989           
  Misses        152      152           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 12, 2026

Warning

Review limit reached

@InertiaUK, we couldn't start this review because you've used your available PR reviews for now.

Your plan currently allows 2 reviews/hour. Refill in 28 minutes and 45 seconds.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After more review capacity refills, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than trial, open-source, and free plans. In all cases, review capacity refills continuously over time.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 0cc4ef05-8c75-4b38-bc0f-b3c811082f74

📥 Commits

Reviewing files that changed from the base of the PR and between ab9f683 and e79dc18.

📒 Files selected for processing (1)
  • uk_bin_collection/uk_bin_collection/councils/WestMorlandAndFurness.py
📝 Walkthrough

Walkthrough

Westmorland & Furness waste collection parser now resolves UPRNs from postcode/house_number input via a new _resolve_uprn helper, constructs schedule URLs from a BASE_URL, and extracts per-day bin types from the waste-collection__day--type element. Test input fixture updated to accept postcode and house_number; UPRN is accepted but optional.

Changes

Postcode-Based UPRN Resolution

Layer / File(s) Summary
UPRN resolution contract and implementation
uk_bin_collection/tests/input.json, uk_bin_collection/uk_bin_collection/councils/WestMorlandAndFurness.py
Adds BASE_URL and _resolve_uprn which posts to the postcode lookup endpoint, parses <select name="uprn"> options and optionally matches PAON to choose a UPRN. parse_data now accepts postcode, house_number/paon, and optional uprn, calls _resolve_uprn, builds the schedule detail URL from BASE_URL + uprn, and fetches the schedule page. Test fixture updated to require postcode and house_number, and wiki_note now indicates UPRN is accepted but not required.
Bin type extraction update
uk_bin_collection/uk_bin_collection/councils/WestMorlandAndFurness.py
Per-day bin type extraction now reads text from the waste-collection__day--type span instead of using the previous colour-based selector.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • dp247

Poem

🐇 I sniff the postcode, hop to find the code,
The lookup lists the homes in row and node,
I pick the UPRN with a twitch and a cheer,
Then read the bins and their collection near,
Hooray — tidy streets from this small rabbit's ode!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: adding postcode and house number lookup capability to the WestMorlandAndFurness scraper, replacing the prior UPRN-only requirement.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (1)
uk_bin_collection/tests/input.json (1)

2719-2721: ⚡ Quick win

This fixture still bypasses the new postcode lookup path.

Because uprn is still populated, _resolve_uprn(...) returns early and never exercises the postcode + house-number resolution added in this PR. If this entry is meant to cover the new branch, remove uprn here or add a second postcode-only fixture.

🤖 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/tests/input.json` around lines 2719 - 2721, The fixture
with postcode "LA9 4QU" still includes an uprn so _resolve_uprn(...) returns
early and never exercises the new postcode + house-number lookup; either remove
the "uprn" field from that fixture to force the postcode lookup branch or add a
separate postcode-only fixture (same postcode and "house_number": "23" but no
uprn) so the postcode+house-number resolution path is exercised by tests.
🤖 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.

Inline comments:
In `@uk_bin_collection/uk_bin_collection/councils/WestMorlandAndFurness.py`:
- Around line 48-53: The parse_data method currently extracts paon from kwargs
but not house_number, causing _resolve_uprn to miss address matches; update
parse_data to also read house_number = kwargs.get("house_number") (and/or
fallback to paon if needed) and pass it into the call to _resolve_uprn (e.g.,
_resolve_uprn(user_postcode, uprn=user_uprn, paon=user_paon or house_number) or
by passing a house_number parameter if _resolve_uprn supports it) so the
postcode-based resolution uses the provided house_number from fixtures.
- Around line 57-64: The request to fetch the schedule at URI (the
requests.get(URI) call used before creating soup) lacks a timeout and doesn't
call response.raise_for_status(), so add an explicit timeout argument to
requests.get and immediately call response.raise_for_status() after receiving
the response (and let exceptions propagate or wrap them with a clear message)
before passing response.text to BeautifulSoup; update the code around the URI
variable, the requests.get(URI) invocation, and the creation of soup to include
these safeguards.
- Around line 34-44: The PAON lookup currently uses a broad substring match and
then silently returns options[0][0] on miss; update the logic in
WestMorlandAndFurness.py (the block using paon, paon_norm and options) to only
accept precise matches (e.g., exact token match or startswith with a separator
like " " or "," for text_upper against paon_norm) and remove the loose `if
paon_norm in text.upper()` fallback, and instead raise a clear exception (e.g.,
ValueError) when no option matches rather than returning options[0][0]; ensure
the raised exception includes the paon_norm and available option texts for
debugging.

---

Nitpick comments:
In `@uk_bin_collection/tests/input.json`:
- Around line 2719-2721: The fixture with postcode "LA9 4QU" still includes an
uprn so _resolve_uprn(...) returns early and never exercises the new postcode +
house-number lookup; either remove the "uprn" field from that fixture to force
the postcode lookup branch or add a separate postcode-only fixture (same
postcode and "house_number": "23" but no uprn) so the postcode+house-number
resolution path is exercised by tests.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 61789da9-42e2-4ef2-b27d-3e5e4fb9bf67

📥 Commits

Reviewing files that changed from the base of the PR and between 8ecf878 and c5eafaf.

📒 Files selected for processing (2)
  • uk_bin_collection/tests/input.json
  • uk_bin_collection/uk_bin_collection/councils/WestMorlandAndFurness.py

Comment on lines +34 to +44
if paon:
paon_norm = str(paon).strip().upper()
for val, text in options:
text_upper = text.upper()
if text_upper.startswith(paon_norm + " ") or text_upper.startswith(paon_norm + ","):
return val
for val, text in options:
if paon_norm in text.upper():
return val

return options[0][0]
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Don’t silently resolve to a different property when PAON lookup misses.

Line 44 falls back to the first address, and Lines 40-42 also allow a broad substring match. On multi-address postcodes that can return another household’s UPRN instead of failing fast.

Suggested fix
+import re
+
     if paon:
         paon_norm = str(paon).strip().upper()
         for val, text in options:
             text_upper = text.upper()
             if text_upper.startswith(paon_norm + " ") or text_upper.startswith(paon_norm + ","):
                 return val
         for val, text in options:
-            if paon_norm in text.upper():
+            if re.search(rf"(?<!\w){re.escape(paon_norm)}(?!\w)", text.upper()):
                 return val
+        raise ValueError(f"No address matching '{paon}' for postcode: {postcode}")
 
     return options[0][0]

Based on learnings: prefer explicit failures (raise exceptions on unexpected formats) over silent defaults or swallowed errors.

🤖 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/WestMorlandAndFurness.py` around
lines 34 - 44, The PAON lookup currently uses a broad substring match and then
silently returns options[0][0] on miss; update the logic in
WestMorlandAndFurness.py (the block using paon, paon_norm and options) to only
accept precise matches (e.g., exact token match or startswith with a separator
like " " or "," for text_upper against paon_norm) and remove the loose `if
paon_norm in text.upper()` fallback, and instead raise a clear exception (e.g.,
ValueError) when no option matches rather than returning options[0][0]; ensure
the raised exception includes the paon_norm and available option texts for
debugging.

UPRN is no longer required. Searches council LocalGov Drupal page by
postcode to resolve UPRN from address dropdown. Backward compatible.
@InertiaUK InertiaUK force-pushed the feat/westmorland-postcode-lookup branch from c5eafaf to ab9f683 Compare May 12, 2026 15:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant