Skip to main content

Matthew Proctor Postcodes

Typed Python 3.12+ lookup API for Matthew Proctor Australian and New Zealand postcode CSV datasets.

Python UV Hatchling Ruff Pytest PyPI

Package CI Package CD

Quick Start

Install the package:

pip install matthewproctor-postcodes

Look up a postcode:

from matthewproctor_postcodes import lookup_postcode

entries = lookup_postcode("3004", "AUS")

for entry in entries:
    print(entry["locality"], entry.get("RA_2021_NAME"))

Install development dependencies:

uv sync --refresh

Run local checks:

make lint
make test

Format code:

make format

Behaviour

  • lookup_postcode("3004", "AUS") returns a read-only sequence of AUSMatthewProctorPostcodeInfo rows.
  • lookup_postcode("110", "NZL") returns a read-only sequence of NZLMatthewProctorPostcodeInfo rows.
  • Country codes are normalized to uppercase alpha-3 values.
  • A lookup returns every locality for a postcode.
  • Unknown but well-formed postcodes return an empty sequence.
  • Postcodes are normalized to four decimal digits, so "110" is looked up as "0110".
  • Invalid postcodes raise InvalidPostcodeError; values must be one to four decimal digits.
  • Unsupported countries raise UnsupportedCountryError.
  • Failed downloads from every configured source raise DatasetDownloadError, preserving the original per-source exceptions for except* handling.
  • A local CSV is preferred; a missing CSV is downloaded and saved atomically.
  • Each country database is loaded lazily once, then reused as an in-memory index.
  • Row models are lightweight TypedDict types that use the known source CSV headers.

Installation

pip install matthewproctor-postcodes

For local development from a checkout:

uv sync --refresh

Storage

Set MATTHEWPROCTOR_POSTCODES to control where files are read and downloaded:

export MATTHEWPROCTOR_POSTCODES=data/matthewproctor

This produces:

data/matthewproctor/australian_postcodes.csv
data/matthewproctor/newzealand_postcodes.csv

If the environment variable is absent, the default is data/matthewproctor relative to the current working directory.

For an enterprise image, bake either CSV into that path and pass download_if_missing=False.

Usage

from matthewproctor_postcodes import lookup_postcode

aus_entries = lookup_postcode("3004", "AUS")
nz_entries = lookup_postcode("110", "NZL")

print([entry["locality"] for entry in aus_entries])
print([entry["locality"] for entry in nz_entries])

lookup_postcode() is the top-level public API and returns a collections.abc.Sequence so callers can safely consume country-specific row types through the shared MatthewProctorPostcodeInfo union. Convert it with list(...) if your code needs to mutate or serialize a concrete list object:

entries = list(lookup_postcode("3004", "AUS"))

Lookup Options

lookup_postcode() accepts these keyword arguments:

  • request_timeout_seconds: HTTP timeout used when a missing CSV must be downloaded. Defaults to 30.0.
  • download_if_missing: whether to download the source CSV when it is not already present locally. Defaults to True.

Storage is configured with MATTHEWPROCTOR_POSTCODES:

import os

from matthewproctor_postcodes import lookup_postcode

os.environ["MATTHEWPROCTOR_POSTCODES"] = "/app/data/matthewproctor"

entries = lookup_postcode(
    "3004",
    "AUS",
    request_timeout_seconds=10.0,
    download_if_missing=False,
)

Lifecycle options only affect an attempt to load an unloaded database. Once a country database has loaded, later calls use the same in-memory index and do not make another request. A failed call with download_if_missing=False does not poison the database; a later call with downloads enabled may still load it.

Exception classes and lower-level helpers are available from their owning modules:

from matthewproctor_postcodes.exceptions import DatasetDownloadError
from matthewproctor_postcodes.normalization import normalize_postcode

Database classes are available from matthewproctor_postcodes.databases for advanced use, and MatthewProctorDatabaseType is available from matthewproctor_postcodes.models.

DatasetDownloadError is an ExceptionGroup, so callers can either handle the whole download failure or selectively handle grouped source failures:

import httpx

try:
    lookup_postcode("3000", "AUS")
except* httpx.TimeoutException as errors:
    for error in errors.exceptions:
        print(error)

Source Schemas

The Australian CSV is australian_postcodes.csv. It includes the prescribed Australia Post postcode ranges for NSW, ACT, VIC, QLD, SA, WA, TAS, and NT, including LVR and PO Box ranges.

Common Australian fields include:

id,postcode,locality,state,long,lat,dc,type,status,sa3,sa3name,sa4,sa4name,region,
Lat_precise,Long_precise,SA1_CODE_2021,SA1_NAME_2021,SA2_CODE_2021,SA2_NAME_2021,
SA3_CODE_2021,SA3_NAME_2021,SA4_CODE_2021,SA4_NAME_2021,RA_2011,RA_2016,RA_2021,
RA_2021_NAME,MMM_2015,MMM_2019,ced,altitude,chargezone,phn_code,phn_name,
lgaregion,lgacode,electorate,electoraterating,sed_code,sed_name

The New Zealand CSV is newzealand_postcodes.csv and currently uses:

postcode,locality,region,long,lat,territory,island

The source datasets may add fields over time. Unknown extra CSV fields are preserved in returned row dictionaries, while the exported TypedDict models document the fields known by this package. Returned rows also include a database field injected by this package with the source MatthewProctorDatabaseType.

Development

This package uses uv, ruff, pytest, and hatchling. It targets Python 3.12 or newer.

CI/CD

Package CI runs on pull requests and pushes to main with:

uv run ruff format --check .
uv run ruff check .
uv run pytest -vv

Package publishing is handled by .github/workflows/package-cd.yaml. Run it manually or publish a GitHub Release.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

matthewproctor_postcodes-2.0.0.tar.gz (10.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

matthewproctor_postcodes-2.0.0-py3-none-any.whl (13.5 kB view details)

Uploaded Python 3

File details

Details for the file matthewproctor_postcodes-2.0.0.tar.gz.

File metadata

  • Download URL: matthewproctor_postcodes-2.0.0.tar.gz
  • Upload date:
  • Size: 10.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.12.1 {"installer":{"name":"uv","version":"0.12.1","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for matthewproctor_postcodes-2.0.0.tar.gz
Algorithm Hash digest
SHA256 d5265a7379574866f4c61f8c567a8beed28dd1e90ae94dc8850eb1f3081449d2
MD5 f5e6da26c520cf69d0491934b99aeed2
BLAKE2b-256 98782c241c63c487377a9f996a5862c25504c1702c421641c82ab10c3c8dc72a

See more details on using hashes here.

File details

Details for the file matthewproctor_postcodes-2.0.0-py3-none-any.whl.

File metadata

  • Download URL: matthewproctor_postcodes-2.0.0-py3-none-any.whl
  • Upload date:
  • Size: 13.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.12.1 {"installer":{"name":"uv","version":"0.12.1","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for matthewproctor_postcodes-2.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 4de52984d348ef38d6e081877632061e77addf4780acd51f0cd7acf0c406e0ca
MD5 d13136de3d157f5f0db31ac4cbb51e1c
BLAKE2b-256 c0396424ba550e0e253ef48b6e027352e24cd4cc408119dd6d83a772b58555ea

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

2.0.0 This release

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page