Skip to main content

geopackage-toolkit

CI Docs License: MIT

Python toolkit for GeoPackage spatial data. Validate, query, and operate on spatial data without PostGIS or ArcGIS.

Zero compiled dependencies. Uses SpatiaLite (embedded in SQLite) for all spatial operations. One file format (.gpkg), one dependency chain, clean Python API.

from geopkgtoolkit import connect, validate_layers, count_in_zones

# Validate geometry health
report = validate_layers("data.gpkg", expected_srid=4326)
print(report.summary())

# Count buildings per administrative zone
con = connect("data.gpkg")
counts = count_in_zones(con, "buildings", "admin3")
for zone_id, count in counts[:5]:
    print(f"Zone {zone_id}: {count} buildings")

Why

GeoPackage is the OGC standard that replaces Shapefile. It's SQLite-based, supports vector + raster + tiles, and works everywhere. But the tooling around it is fractured:

  • ogr2ogr works but isn't Pythonic
  • GeoPandas adds heavy compiled dependencies
  • SpatiaLite has Windows quirks nobody documents
  • No single package covers validate-query-convert-publish

This toolkit fills that gap. Local-first, no server required.

Installation

pip install geopackage-toolkit

Prerequisites

SpatiaLite must be installed on your system:

OS Install
Windows Download from gaia-gis.it and set SPATIALITE_DIR env var
Ubuntu/Debian sudo apt install libspatialite-dev
macOS brew install libspatialite
Conda conda install -c conda-forge libspatialite

CLI

# Validate geometry health
geopkg validate data.gpkg --srid 4326

# Count features per zone
geopkg count data.gpkg --features buildings --zones admin3

# Show layer info
geopkg info data.gpkg

# Buffer features (output saved as new layer in same GeoPackage)
geopkg buffer data.gpkg --layer buildings --distance 100 --output buffered_buildings

# Clip a layer to a boundary
geopkg clip data.gpkg --source buildings --clip district_boundary --output clipped_buildings

# Spatial intersection of two layers
geopkg intersect data.gpkg --layer-a buildings --layer-b flood_zones --output buildings_in_flood

Python API

Validate

from geopkgtoolkit import validate_layers, validate_layer

# Validate all layers
report = validate_layers("data.gpkg", expected_srid=4326)
print(report.summary())
# GeoPackage: data.gpkg
# 9 layers, 685,968 features, 0 warnings
#   OSM_Buildings: 515,013 features, SRID=4326, OK
#   lbn_adm3: 1,627 features, SRID=4326, OK
#   ...

assert report.is_valid  # True if no warnings

# Validate a single layer
con = validate_layer(con, "buildings", expected_srid=4326)

Checks: null geometries, empty geometries, invalid geometries (self-intersections), SRID mismatches, bounding box sanity.

Query

from geopkgtoolkit import connect, count_in_zones, bbox_filter

con = connect("data.gpkg")

# Count features per zone (rtree-accelerated)
counts = count_in_zones(con, "buildings", "admin3")
# Returns: [(zone_fid, count), ...]

# Bounding box filter (rtree-accelerated)
fids = bbox_filter(con, "buildings", (35.4, 33.8, 35.6, 33.9))
# Returns: [fid, ...]

# Point-in-polygon classification
from geopkgtoolkit import points_in_polygons
result = points_in_polygons(con, "pois", "districts")
# Returns: [(point_fid, polygon_fid_or_None), ...]

Spatial Operations

from geopkgtoolkit import connect, buffer, clip, intersect

con = connect("data.gpkg")

# Buffer features by a distance (CRS units)
buffered = buffer(con, "buildings", distance=100, output_table="buffered_buildings")
# Creates new layer with buffered polygons

# Clip features to a boundary
clipped = clip(con, "buildings", "district_boundary", output_table="clipped_buildings")
# Creates new layer with features clipped to polygon boundary

# Spatial intersection of two layers
result = intersect(con, "buildings", "flood_zones", output_table="buildings_in_flood")
# Creates new layer with the intersection of two layers

All operations write results back to the same GeoPackage file. Attributes from both layers are preserved in intersection.

Connect

from geopkgtoolkit import connect

con = connect("data.gpkg")  # Auto-loads SpatiaLite
layers = con.execute("SELECT table_name FROM gpkg_geometry_columns").fetchall()
con.close()

How It Works

All spatial operations use SpatiaLite (embedded spatial SQL extension for SQLite) with GeoPackage's native rtree tables for spatial indexing. This means:

  • No server process (unlike PostGIS)
  • No compiled Python bindings (unlike GeoPandas/GDAL wheels)
  • Single .gpkg file per dataset
  • Works on Windows, Linux, macOS

Performance

Operation Method 500k features x 1k zones
count_in_zones rtree bbox + ST_Contains ~8 seconds
count_in_zones (no index) ST_Contains only >10 minutes
bbox_filter rtree lookup <1 second

The toolkit auto-creates rtree indexes when missing. First run builds the index, subsequent runs use it.

Roadmap

  • v0.1.0: Validate + Query modules
  • v0.2.0: Spatial operations (buffer, clip, intersect) with CLI commands
  • v0.3.0: Format conversion (Shapefile, GeoJSON, FlatGeobuf to/from GeoPackage)
  • v0.4.0: Config-driven batch pipeline
  • v0.5.0: Vector tile generation for web publishing
  • v1.0.0: Full toolkit with visualization and schema extraction

Contributing

Contributions welcome. Please open an issue first to discuss what you'd like to change.

License

MIT

Acknowledgments

Built on top of SpatiaLite by Alessandro Furieri and the GeoPackage OGC standard.

Download files

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

Source Distribution

geopackage_toolkit-0.2.0.tar.gz (34.7 kB view details)

Uploaded Source

Built Distribution

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

geopackage_toolkit-0.2.0-py3-none-any.whl (16.9 kB view details)

Uploaded Python 3

File details

Details for the file geopackage_toolkit-0.2.0.tar.gz.

File metadata

  • Download URL: geopackage_toolkit-0.2.0.tar.gz
  • Upload date:
  • Size: 34.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.11.0

File hashes

Hashes for geopackage_toolkit-0.2.0.tar.gz
Algorithm Hash digest
SHA256 44fdd7cf36f28277bfe2f327a1963b587d4c193c437f44465b795fd7aa40e767
MD5 d357bf4dbcfc53751fe9f78f5b272669
BLAKE2b-256 9af67855855bc2eb7d3a43c7b4b1c71f6245f7451b92aa4499f1f07bc32232c8

See more details on using hashes here.

File details

Details for the file geopackage_toolkit-0.2.0-py3-none-any.whl.

File metadata

File hashes

Hashes for geopackage_toolkit-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 facd3ba1e506ec147e18e6c9abda5cd9d6ff44cce16e9028ad97300889d53471
MD5 d7348d7784d4856cc203402500671d5f
BLAKE2b-256 033ccc877702e3f6c0da5ca609e6f09d37921557b1d5002e91e6068c6d37d1a2

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

0.2.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