Source code for shapelib.adapters.read_file
"""Adapter for reading geospatial files from local or remote storage."""
from pathlib import Path
from typing import Any
from shapelib.core.cloud.cloud_path import CloudPath
from shapelib.core.geometries.base import BaseShapes
from shapelib.factories.geo_file_factory import GeoFileFactory
[docs]
def read_file(path: str | Path, *, keep_z: bool = False, **kwargs: Any) -> BaseShapes:
"""
Read a geospatial file from local or remote storage.
This function automatically detects whether the path is a local file or
a remote URL and routes to the appropriate handler. Supports local files,
HTTPS URLs (including presigned S3 URLs), and s3:// protocol.
Parameters
----------
path : str | Path
The path to the geospatial file. Can be:
- A local file path (string or Path object)
- An HTTPS URL (including presigned AWS S3 URLs)
- An S3 URL (s3://bucket/key)
keep_z : bool, optional
Keep the Z coordinate of 3-D geometries. Defaults to False, which
flattens every geometry to 2-D. Turn it on when Z is data, such as the
elevation of each vertex of a contour line; it is kept by the copies,
filters and reprojections of the returned object too.
**kwargs : Any
Additional arguments passed to the file handler (e.g., layer name
for GeoPackage files).
Returns
-------
BaseShapes
A geometry object (Polygons, Lines, Points, or Empty) containing
the file's data with full spatial functionality.
Raises
------
FileNotFoundError
If the file (local or remote) does not exist.
ValueError
If the file format is not supported.
ConnectionError
If a remote file cannot be accessed.
PermissionError
If access to the file is denied.
Examples
--------
Read a local shapefile:
>>> polygons = read_file("/path/to/shapefile.shp")
>>> print(polygons.get_total_area())
Read from a presigned S3 URL (streaming for FlatGeobuf):
>>> lines = read_file(
... "https://bucket.s3.amazonaws.com/file.fgb?X-Amz-Signature=..."
... )
Read using S3 protocol (requires AWS credentials in environment):
>>> points = read_file("s3://my-bucket/data/points.gpkg")
Keep the elevation of 3-D contour lines:
>>> contours = read_file("/path/to/contours.fgb", keep_z=True)
>>> bool(contours.has_z.all())
True
Big-O
-----
Local: O(n) where n is file size.
Remote streaming (.fgb, .gpkg, .geojson): O(n) with range requests.
Remote download (.shp, .kml, .sqlite): O(n) + network latency.
Notes
-----
For remote files, the handler selection is based on file extension:
- Streaming (vsicurl): .fgb, .geojson, .json, .gpkg
- Download to temp: .shp, .kml, .sqlite
AWS credentials for s3:// protocol should be set via environment
variables: AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY.
Presigned HTTPS URLs include credentials and don't require env vars.
"""
cloud_path = CloudPath.from_string(str(path))
if cloud_path.is_remote:
return _read_remote(cloud_path, keep_z=keep_z, **kwargs)
return GeoFileFactory.get_handler(path=Path(path), keep_z=keep_z, **kwargs)
def _read_remote(cloud_path: CloudPath, *, keep_z: bool = False, **kwargs: Any) -> BaseShapes:
"""
Read from remote storage using GeoCloudFactory.
Parameters
----------
cloud_path : CloudPath
The parsed cloud path.
keep_z : bool, optional
Keep the Z coordinate of 3-D geometries (default False).
**kwargs : Any
Additional arguments.
Returns
-------
BaseShapes
The geometry object.
"""
# Import here to trigger handler registration
import shapelib.core.cloud.handlers # noqa: F401 - registers handlers
from shapelib.factories.geo_cloud_factory import GeoCloudFactory
return GeoCloudFactory.get_handler(cloud_path.raw_path, keep_z=keep_z, **kwargs)