Matthew Proctor Postcodes
Typed Python 3.12+ lookup API for Matthew Proctor Australian and New Zealand postcode CSV datasets.
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 ofAUSMatthewProctorPostcodeInforows.lookup_postcode("110", "NZL")returns a read-only sequence ofNZLMatthewProctorPostcodeInforows.- 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 forexcept*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
TypedDicttypes 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 to30.0.download_if_missing: whether to download the source CSV when it is not already present locally. Defaults toTrue.
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)
| 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)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| 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.