Skip to content

feat: add postcode lookup for vale of glamorgan council#2066

Closed
InertiaUK wants to merge 2 commits into
robbrad:masterfrom
InertiaUK:feat/vale-of-glamorgan-postcode-lookup
Closed

feat: add postcode lookup for vale of glamorgan council#2066
InertiaUK wants to merge 2 commits into
robbrad:masterfrom
InertiaUK:feat/vale-of-glamorgan-postcode-lookup

Conversation

@InertiaUK
Copy link
Copy Markdown
Contributor

@InertiaUK InertiaUK commented May 12, 2026

Summary

  • Users can provide either UPRN or postcode + house number
  • UPRN takes priority when provided (backward compatible)
  • Uses iShareLIVE LocationSearch endpoint for postcode-to-address resolution
  • No need for OS Places API - the existing iShareLIVE platform has its own address search
  • Falls back to first result if no match found

Testing

  • UPRN path (backward compat): UPRN 64029020
  • Postcode + house number: CF63 4AE + paon 3
  • Tested via API end-to-end ✅

Summary by CodeRabbit

  • New Features
    • Vale of Glamorgan Council now accepts postcode and house number as input parameters; UPRN is no longer required.

Review Change Stack

Users can provide either UPRN or postcode + house number.
UPRN takes priority when provided (backward compatible).
Uses iShareLIVE LocationSearch endpoint for postcode-to-address
resolution, then matches by house number/name.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@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 27 minutes and 2 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: 9521c93b-efb8-4c17-b00b-bc2ea482f734

📥 Commits

Reviewing files that changed from the base of the PR and between 5708ad2 and f2d6756.

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

Walkthrough

The Vale of Glamorgan Council scraper is updated to accept postcode and house_number as primary inputs. When UPRN is missing, a LocationSearch API call resolves the address, and a _match_address helper selects the correct UPRN. Collection dates are built from LocalInfo JSONP data and calendar entries with robust error handling for invalid dates.

Changes

Address resolution and collection data flow

Layer / File(s) Summary
Test configuration update
uk_bin_collection/tests/input.json
Test input expectations updated to include postcode and house_number fields; wiki_note changed to reflect that UPRN is now optional.
Module constants and address resolution
uk_bin_collection/uk_bin_collection/councils/ValeofGlamorganCouncil.py
Module-level BASE_URL and HEADERS constants added; _match_address(results, uprn=None, paon=None) helper function introduced to select correct UPRN from LocationSearch results; parse_data rewritten to optionally call LocationSearch when UPRN is missing, then LocalInfo request with JSONP parsing to derive bin_week, weekly_collection, and weekly_dates.
Calendar parsing with error handling and weekly dates
uk_bin_collection/uk_bin_collection/councils/ValeofGlamorganCouncil.py
datetime conversion wrapped in try/except to skip invalid day entries via continue; weekly_dates entries appended to collections list alongside calendar-parsed dates; future dates filtered and sorted.

🎯 3 (Moderate) | ⏱️ ~22 minutes

🐰 A postcode now opens doors, no UPRN to hide,
_match_address finds the way far and wide,
Weekly collections dance with calendar dates,
Errors caught gently at parsing gates! 📅✨

🚥 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 clearly and concisely describes the main change: adding postcode lookup functionality for Vale of Glamorgan council. It directly reflects the primary objective and the significant user-facing enhancement in the changeset.
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.

@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 (f2d6756).

Additional details and impacted files
@@           Coverage Diff           @@
##           master    #2066   +/-   ##
=======================================
  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.

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: 1

🧹 Nitpick comments (1)
uk_bin_collection/uk_bin_collection/councils/ValeofGlamorganCouncil.py (1)

93-118: ⚡ Quick win

Hoist table_headers out of the inner loop and narrow the exception.

table_headers = table.find("tr").find_all("th") is recomputed for every day cell of every row even though the headers are fixed for the table — move it out of the loop. While there, the except Exception: continue swallows every error silently (Ruff BLE001/S112); narrow it to ValueError (the realistic failure for int(day) / datetime(...)) so genuine format changes still surface. Also note that table is obtained via chained .find(...).find("tbody") and will raise AttributeError if the council restructures the page — worth at least guarding with a clear error rather than letting it bubble as an opaque traceback.

♻️ Proposed refactor
-        table = soup.find("table", {"class": "TableStyle_Activities"}).find("tbody")
+        table_el = soup.find("table", {"class": "TableStyle_Activities"})
+        if table_el is None:
+            raise ValueError("Could not find collections table on schedule page")
+        table = table_el.find("tbody")
+        header_row = table.find("tr")
+        table_headers = header_row.find_all("th") if header_row else []
+        bin_type = (
+            table_headers[1].text.strip().replace(" collection date", "")
+            if len(table_headers) > 1 else ""
+        )
         for tr in soup.find_all("tr")[1:]:
             row = tr.find_all("td")
             month_and_year = row[0].text.split()
             ...
             for day in remove_alpha_characters(row[1].text.strip()).split():
                 try:
                     bin_date = datetime(collection_year, collection_month, int(day))
-                    table_headers = table.find("tr").find_all("th")
-                    collections.append(
-                        (
-                            table_headers[1]
-                            .text.strip()
-                            .replace(" collection date", ""),
-                            bin_date,
-                        )
-                    )
-                except Exception:
+                    collections.append((bin_type, bin_date))
+                except ValueError:
                     continue

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

🤖 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/ValeofGlamorganCouncil.py`
around lines 93 - 118, Hoist the table header lookup out of the inner day loop
and tighten error handling: first guard the table retrieval (the result of
soup.find("table", {"class": "TableStyle_Activities"}).find("tbody")) and raise
a clear exception if it's missing instead of letting an AttributeError bubble;
then compute table_headers = table.find("tr").find_all("th") once before
iterating rows/days; replace the broad except Exception: continue with except
ValueError: continue to only swallow parsing errors from int(day) /
datetime(...) so other unexpected issues surface; keep references to table,
table_headers, remove_alpha_characters, collections, and datetime to locate the
affected code.
🤖 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/ValeofGlamorganCouncil.py`:
- Around line 76-87: The two outbound HTTP calls in ValeofGlamorganCouncil (the
requests.get call that fetches BASE_URL/LocalInfo and the requests.get that
fetches schedule_url) are missing timeouts; update both calls to include
timeout=30 (matching the earlier LocationSearch call) while preserving existing
params/headers and verify=False on the schedule_page fetch so the requests use a
bounded timeout and cannot hang indefinitely.

---

Nitpick comments:
In `@uk_bin_collection/uk_bin_collection/councils/ValeofGlamorganCouncil.py`:
- Around line 93-118: Hoist the table header lookup out of the inner day loop
and tighten error handling: first guard the table retrieval (the result of
soup.find("table", {"class": "TableStyle_Activities"}).find("tbody")) and raise
a clear exception if it's missing instead of letting an AttributeError bubble;
then compute table_headers = table.find("tr").find_all("th") once before
iterating rows/days; replace the broad except Exception: continue with except
ValueError: continue to only swallow parsing errors from int(day) /
datetime(...) so other unexpected issues surface; keep references to table,
table_headers, remove_alpha_characters, collections, and datetime to locate the
affected code.
🪄 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: ee0b755e-96dd-47f1-a051-5a706ed65494

📥 Commits

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

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

Comment thread uk_bin_collection/uk_bin_collection/councils/ValeofGlamorganCouncil.py Outdated
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.

2 participants