Skip to main content

psgc-core

psgc-core is the small rules engine that sits between raw PSGC data and the applications that need to use it correctly.

Its job is not to download PSGC data, parse Excel workbooks, store records, or build UI. Its job is to answer the recurring domain questions every downstream consumer asks once it already has a PSGC code:

  • is this a region, province, city, municipality, sub-municipality, or barangay?
  • what is this record's parent?
  • what are its ancestors?
  • does NCR, HUC placement, or Manila sub-municipality logic change the answer?

Without a shared package, those rules get reimplemented across apps and drift over time. psgc-core exists so the tricky parts of PSGC behavior live in one tested place.

Why this package exists

Most systems that consume PSGC data do not just display a 10-digit code. They need to derive hierarchy.

Typical downstream work looks like this:

  • grouping schools, offices, or datasets by region or province/HUC
  • building breadcrumbs and drilldown navigation
  • validating incoming PSGC identifiers
  • computing parent filters from a locality or barangay row
  • handling PSGC edge cases consistently across reports and services

Those tasks sound simple until the exceptions matter:

  • NCR localities do not sit under a province layer
  • highly urbanized city placements can parent directly to the region
  • Manila SubMun rows are children of Manila city
  • some barangay parent derivation needs the municipality-collapse fallback

psgc-core isolates those rules as pure functions so every host application can reuse the same behavior.

Where it fits

This repository is intentionally narrow.

  • ../deped-psgc creates cleaned PSGC tabular data from the PSA workbook
  • psgc-core interprets PSGC codes and geo values from that data
  • downstream apps use both: the exported dataset plus the shared rule helpers

In practical terms, the flow is:

  1. deped-psgc reads the official PSGC Excel workbook and writes a cleaned CSV.
  2. Each CSV row carries fields such as id, name, and geo.
  3. A downstream app reads those rows and calls psgc-core to derive hierarchy, labels, parent codes, and ancestor chains.

That separation matters because the workbook-export logic and the hierarchy rules change for different reasons. Parsing the source file is one concern; applying PSGC structure rules correctly everywhere is another.

Example Use Case

Assume ../deped-psgc has already exported a row like this:

id=1380601001
name=Barangay 649
geo=Bgy

An application usually needs more than the raw row:

from psgc_core import ancestor_codes, candidate_parent_code, kind_label

row = {
    "id": "1380601001",
    "geo": "Bgy",
}

parent = candidate_parent_code(row["id"], row["geo"])
ancestors = ancestor_codes(row["id"], row["geo"])
label = kind_label(row["geo"])

print(label)
print(parent)
print(ancestors)

Output:

"Barangay"
"1380601000"
["1300000000", "1380600000", "1380601000"]

That is the value of the package:

  • the app does not need to embed Manila-specific PSGC logic itself
  • the same parent/ancestor behavior is reused everywhere
  • tests live beside the rules instead of being copied into each consumer

Package Scope

psgc-core owns only pure PSGC rules:

  • code normalization and validation
  • geo alias normalization into canonical types
  • stable kind labels and hierarchy ranks
  • suffix-based geographic classification
  • parent-code and ancestor derivation
  • explicit handling for NCR, HUC placement, Manila sub-municipalities, and the barangay municipality-collapse edge case

It does not own:

  • workbook parsing
  • CSV export
  • persistence
  • framework integration
  • query building
  • UI rendering

Install

uv pip install -e .

Public API

from psgc_core import (
    GeoType,
    NormalizedKind,
    ancestor_codes,
    candidate_parent_code,
    infer_geo,
    is_huc_placement,
    is_manila_submun,
    is_ncr,
    kind_label,
    kind_rank,
    muni_code,
    normalize_geo,
    normalize_code,
    normalized_kind,
    provhuc_code,
    region_code,
    validate_code,
)

Notes

  • infer_geo() is suffix-based. It can distinguish Reg, Prov, locality-shape codes (Mun), and Bgy.
  • candidate_parent_code() and ancestor_codes() use the provided geo type to preserve City and SubMun behavior where suffix-only inference is insufficient.
  • normalize_geo() accepts the aliases used by current host apps: reg, region, prov, province, city, mun, municipality, submun, submunicipal, submunicipality, bgy, brgy, and barangay.
  • normalized_kind(), kind_label(), and kind_rank() are the canonical package-level helpers for PSGC tree UIs and summaries.

Release files for psgc-core 0.0.1

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

Source distribution (sdist)

Source distribution for psgc-core 0.0.1
File Size Uploaded
psgc_core-0.0.1.tar.gz 13.1 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for psgc-core 0.0.1
File Interpreter ABI Platform
psgc_core-0.0.1-py3-none-any.whl Python 3 none any Details

Total release size: 19.7 kB

Release files / psgc_core-0.0.1.tar.gz

Download URL psgc_core-0.0.1.tar.gz
Size 13.1 kB
Tags Source
SHA-256 checksum
How to use checksums
3cd9873c014fd0c60d2485648cac4d418c1f9ab2644e5337e1d712464347c5e9
BLAKE2b-256 checksum
How to use checksums
118eff0e788cdec9bf9eb54e1531086d1ed1186d07ec63b2fa5dc524cfb60393
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.10.9 {"installer":{"name":"uv","version":"0.10.9","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release files / psgc_core-0.0.1-py3-none-any.whl

Download URL psgc_core-0.0.1-py3-none-any.whl
Size 6.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
83028d7f1451ac67f7f54850b9cac21d703b60ac920b0ee447811e8265acedb2
BLAKE2b-256 checksum
How to use checksums
65cb4f4bd84da0eb7c4339e99c57129d094e3bb0b0cc3a019e0de9c6f7d1bafb
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.10.9 {"installer":{"name":"uv","version":"0.10.9","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release history Release notifications | RSS feed

This release

0.0.1 This release

2 release 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