The plugin system exposes both a high-level PluginLoader class and low-level functions for programmatic use.
PluginLoader (High-Level)
Constructor
from barangay.plugin_loader import PluginLoader
loader = PluginLoader(
env=True, # Read BARANGAY_PLUGINS_DIR env var?
config_file=None, # Explicit config file path
extra_dirs=["/path/to/my/plugins"], # Additional plugin directories
)
| Parameter | Type | Default | Description |
|---|---|---|---|
env |
bool |
True |
Read BARANGAY_PLUGINS_DIR environment variable |
config_file |
str \| Path \| None |
None |
Explicit path to a barangay.yaml config file |
extra_dirs |
list[str \| Path] \| None |
None |
Additional plugin directories (highest priority) |
Methods
enable_plugin(name)
Enable a plugin by name. Sets the in-memory config.
loader = PluginLoader(env=True)
loader.enable_plugin("psgc-aux-data")
disable_plugin(name)
Disable a plugin by name.
loader.disable_plugin("sample_elevation")
add_plugin_dir(path)
Add a plugin directory at highest priority. Reloads config automatically.
loader.add_plugin_dir("/path/to/my/plugins")
loader.enable_plugin("my_custom_plugin")
build_index(as_of=None)
Build the plugin index for a given date. Returns a dict[str, dict[str, dict[str, Any]]] mapping psgc_id to plugin data.
plugin_index = loader.build_index() # current date
plugin_index = loader.build_index(as_of="2025-08-29") # historical
enrich_flat(flat_data, as_of=None)
Builds the index then enriches flat records. Each record gets an "extensions" list.
from barangay import barangay_flat
from barangay.plugin_loader import PluginLoader
loader = PluginLoader(env=True)
loader.enable_plugin("psgc-aux-data")
enriched = loader.enrich_flat([r.model_dump() for r in barangay_flat])
for r in enriched:
if r.get("extensions"):
print(r["name"], r["extensions"][0]["data"])
break
Bangsamoro Autonomous Region In Muslim Mindanao (BARMM) {'correspondence_code': '0150000000', 'old_names': None, 'city_class': None, 'income_classification': None, 'urban_rural': None, 'population': 4545486, 'status': None}
Each enriched record contains an extensions list. Each extension has:
{
"field_group": "psgc-aux-data", # plugin name
"metadata": PluginExtensionMetadata( # Pydantic model
name="psgc-aux-data",
description="Supplementary PSGC data...",
version="0.1.0",
repository="https://github.com/bendlikeabamboo/psgc-aux-data-repository",
format="json",
as_of="2026-04-13",
),
"data": { # the actual plugin fields
"correspondence_code": "0150000000",
"old_names": None,
"city_class": None,
"income_classification": None,
"urban_rural": None,
"population": 4545486,
"status": None,
}
}
enrich_extended(node, as_of=None)
Builds the index then recursively enriches tree nodes. Walks the components tree and attaches extensions to each matching node.
from barangay import barangay_extended
from barangay.plugin_loader import PluginLoader
loader = PluginLoader(env=True)
loader.enable_plugin("psgc-aux-data")
enriched = loader.enrich_extended(barangay_extended.model_dump())
# Access NCR region node
for comp in enriched.get("components", []):
if comp.get("name") == "National Capital Region (NCR)":
ext = comp["extensions"][0]
print(f"{comp['name']}: population={ext['data']['population']}")
break
National Capital Region (NCR): population=14001751
Extensions propagate recursively — every node in the tree (region, province, city, barangay) that has a matching psgc_id in the plugin index gets its extensions populated.
Low-Level Functions
build_plugin_index()
Builds the plugin index using the default configuration (enabled plugins from config files).
from barangay.plugin_loader import build_plugin_index, enrich_flat
from barangay import barangay_flat
plugin_index = build_plugin_index()
enriched = enrich_flat([r.model_dump() for r in barangay_flat], plugin_index)
| Parameter | Type | Default | Description |
|---|---|---|---|
as_of |
str \| None |
None |
Historical date (YYYY-MM-DD) |
plugin_config |
dict \| None |
None |
Override plugin enable/disable config |
plugin_dirs |
list[Path] \| None |
None |
Override plugin source directories |
enrich_flat(flat_data, plugin_index)
Attaches an extensions list to each flat record where the psgc_id matches.
from barangay.plugin_loader import build_plugin_index, enrich_flat
from barangay import barangay_flat
plugin_index = build_plugin_index()
enriched = enrich_flat([r.model_dump() for r in barangay_flat], plugin_index)
enrich_extended(node, plugin_index)
Recursively walks the tree and attaches extensions to matching nodes.
from barangay.plugin_loader import build_plugin_index, enrich_extended
from barangay import barangay_extended
plugin_index = build_plugin_index()
enriched = enrich_extended(barangay_extended.model_dump(), plugin_index)
resolve_plugin_sources()
Returns the ordered list of plugin source directories.
from barangay.plugin_loader import resolve_plugin_sources
dirs = resolve_plugin_sources(env=True)
for d in dirs:
print(d)
/home/user/projects/barangay/barangay/plugins
load_plugin_config()
Reads and merges all plugins.yaml from every source directory. Higher-priority overrides enabled status.
from barangay.plugin_loader import resolve_plugin_sources, load_plugin_config
dirs = resolve_plugin_sources(env=True)
config = load_plugin_config(dirs)
print(config)
{'sample_elevation': False, 'sample_population': False, 'sample_schools': False, 'sample_elevation_time': False, 'psgc-aux-data': True}
load_manifest()
Reads and validates a plugin's manifest.yaml.
from barangay.plugin_loader import resolve_plugin_sources, load_manifest
dirs = resolve_plugin_sources(env=True)
manifest = load_manifest("psgc-aux-data", dirs)
print(manifest["name"], manifest["format"], manifest["repository"])
psgc-aux-data json https://github.com/bendlikeabamboo/psgc-aux-data-repository
load_plugin_data()
Loads a plugin's data file and returns it as a psgc_id-keyed dict.
from barangay.plugin_loader import load_plugin_data, load_manifest, resolve_plugin_sources
dirs = resolve_plugin_sources(env=True)
manifest = load_manifest("sample_elevation", dirs)
data = load_plugin_data(manifest, plugin_dirs=dirs)
Pydantic Models
PluginExtensionMetadata
Metadata attached to each extension.
from barangay.models import PluginExtensionMetadata
meta = PluginExtensionMetadata(
name="psgc-aux-data",
description="Supplementary PSGC data...",
version="0.1.0",
repository="https://github.com/user/repo",
format="json",
as_of="2026-04-13",
)
| Field | Type | Description |
|---|---|---|
name |
str |
Plugin name |
description |
str \| None |
Plugin description |
version |
str \| None |
Plugin version |
repository |
str \| None |
Remote repository URL |
format |
str \| None |
Data format (csv, json, parquet) |
as_of |
str \| None |
Resolved date for time-aware plugins |
PluginExtension
A single extension entry on a record.
from barangay.models import PluginExtension, PluginExtensionMetadata
ext = PluginExtension(
field_group="psgc-aux-data",
metadata=PluginExtensionMetadata(name="psgc-aux-data"),
data={"population": 4545486, "old_names": None},
)
| Field | Type | Description |
|---|---|---|
field_group |
str |
Plugin name (used as namespace) |
metadata |
PluginExtensionMetadata |
Plugin metadata |
data |
dict \| list[dict] |
Scalar data (dict) or array data (list) |
Exceptions
| Exception | Raised When |
|---|---|
PluginManifestError |
Manifest is missing required fields, not found, or invalid |
PluginDataError |
Data file cannot be read or remote fetch fails |