Hide POIs, show overlay state, remove zoom button, rotate vpn

This commit is contained in:
Andras Schmelczer 2026-07-15 21:58:05 +01:00
parent 35276d34fa
commit bce34b73de
32 changed files with 1137 additions and 186 deletions

View file

@ -162,6 +162,89 @@ def test_epc_council_by_postcode_null_latest_tenure_counts_as_ex_council() -> No
]
def test_epc_council_shares_exclude_unmatched_listing_seed_rows(tmp_path) -> None:
# The council shares must describe the DWELLING universe, so `_build`
# aggregates them before splicing listings in. An unmatched listing appends a
# seed row, which is not a dwelling: it would both pad the denominator and,
# having no latest_tenure_status, count as ex-council.
#
# This pins the two aggregates against each other to show what the ordering
# buys. It does not exercise `_build`, whose 15 parquet inputs no test in this
# file fixtures, so it cannot catch the call being moved back after the
# splice; the server warns at boot if the columns go missing entirely.
listings_path = tmp_path / "listings.parquet"
arcgis_path = tmp_path / "arcgis.parquet"
# A number-less listing on an unknown street matches no dwelling, so it is
# spliced in as its own seed row.
_sample_listings_frame().with_columns(
pl.lit("Juniper Crescent").alias("Address per Property Register"),
).write_parquet(listings_path)
_stub_arcgis(arcgis_path)
# Two real dwellings in SW1A 1AA: one ever-council and still social.
# % Council housing = 1/2 = 50.0; % Ex-council = 0/2 = 0.0.
wide = pl.LazyFrame(
{
"postcode": ["SW1A 1AA", "SW1A 1AA"],
"pp_address": ["Old Cottage High Street", "New Cottage High Street"],
"pp_property_type": ["Terraced", "Terraced"],
"duration": ["Freehold", "Freehold"],
"total_floor_area": [120.0, 110.0],
"number_habitable_rooms": [4, 4],
"latest_price": [750_000, 700_000],
"epc_address": ["Old Cottage High Street", "New Cottage High Street"],
"current_energy_rating": ["C", "C"],
"potential_energy_rating": ["B", "B"],
"floor_height": [2.4, 2.4],
"construction_age_band": [1930, 1930],
"is_construction_date_approximate": [1, 1],
"was_council_house": ["Yes", "No"],
"latest_tenure_status": ["Rented (social)", "Owner-occupied"],
# `_build` has always attached this by the time it aggregates, and
# `_fill_property_level_no_defaults` defaults it alongside council.
LISTED_BUILDING_FEATURE: [None, None],
},
schema={
"postcode": pl.Utf8,
"pp_address": pl.Utf8,
"pp_property_type": pl.Utf8,
"duration": pl.Utf8,
"total_floor_area": pl.Float64,
"number_habitable_rooms": pl.Int16,
"latest_price": pl.Int64,
"epc_address": pl.Utf8,
"current_energy_rating": pl.Utf8,
"potential_energy_rating": pl.Utf8,
"floor_height": pl.Float64,
"construction_age_band": pl.UInt16,
"is_construction_date_approximate": pl.UInt8,
"was_council_house": pl.Utf8,
"latest_tenure_status": pl.Utf8,
LISTED_BUILDING_FEATURE: pl.Utf8,
},
)
dwelling_shares = _epc_council_by_postcode(
_fill_property_level_no_defaults(wide)
).collect()
assert dwelling_shares.to_dicts() == [
{"postcode": "SW1A 1AA", "% Council housing": 50.0, "% Ex-council": 0.0}
]
spliced = _integrate_listings(wide, listings_path, arcgis_path, epc_path=None)
spliced_shares = _epc_council_by_postcode(
_fill_property_level_no_defaults(spliced)
).collect()
# The seed row pads the denominator to 3, understating the council share as
# 1/3 and disagreeing with postcode.parquet for the same postcode. That is
# exactly why the aggregate is taken before the splice.
assert spliced.collect().height == 3
assert spliced_shares.to_dicts() == [
{"postcode": "SW1A 1AA", "% Council housing": 33.3, "% Ex-council": 0.0}
]
def test_epc_council_columns_are_area_level_and_survive_the_split() -> None:
# The EPC council shares are postcode-level AREA columns: they must route to
# the postcode output and NOT appear in the property output. The per-property