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.

Metadata

Release files for matthewproctor-postcodes 2.0.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for matthewproctor-postcodes 2.0.0
File Size Uploaded Provenance Actions
matthewproctor_postcodes-2.0.0.tar.gz 10.6 kB Without provenance Details for matthewproctor_postcodes-2.0.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for matthewproctor-postcodes 2.0.0
File Interpreter ABI Platform Actions
matthewproctor_postcodes-2.0.0-py3-none-any.whl Python 3 none any Details for matthewproctor_postcodes-2.0.0-py3-none-any.whl

Total release size: 24.1 kB

Release files / matthewproctor_postcodes-2.0.0.tar.gz

Download URL matthewproctor_postcodes-2.0.0.tar.gz
Size 10.6 kB
Tags Source
SHA-256 checksum
How to use checksums
d5265a7379574866f4c61f8c567a8beed28dd1e90ae94dc8850eb1f3081449d2
BLAKE2b-256 checksum
How to use checksums
98782c241c63c487377a9f996a5862c25504c1702c421641c82ab10c3c8dc72a
Upload date
Uploaded using Trusted Publishing?
What is 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}

Release files / matthewproctor_postcodes-2.0.0-py3-none-any.whl

Download URL matthewproctor_postcodes-2.0.0-py3-none-any.whl
Size 13.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
4de52984d348ef38d6e081877632061e77addf4780acd51f0cd7acf0c406e0ca
BLAKE2b-256 checksum
How to use checksums
c0396424ba550e0e253ef48b6e027352e24cd4cc408119dd6d83a772b58555ea
Upload date
Uploaded using Trusted Publishing?
What is 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}

Security for matthewproctor-postcodes 2.0.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

2.0.0 This release

2 release files No provenance

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