Version: dev

shapefile_reader

Stable type · Native arrays and readers

Tier: stable · Kind: type · Topic: Native arrays and readers

PythonJuliaRust
ShapefileReaderShapefileReaderShapefileReader

Python

class ShapefileReader
ShapefileReader.formats() -> List[str]
ShapefileReader.extensions() -> List[str]
ShapefileReader.open(blob_path: Any) -> Any
ShapefileReader.read_native(handle: Any, variables: Optional[Sequence[str]] = None, select: Optional[Any] = None, *, member: Optional[str] = None, numeric_columns: Optional[Sequence[str]] = None, nvert_max: Optional[int] = None, **_: Any) -> NativeDataset

The active shapefile reader — an ESRI shapefile as a feature table.

Decode is delegated to pyshp (shapefile), imported lazily so a base install stays lean, mirroring the Julia Shapefile.jl extension and the Rust shapefile crate. Nothing about the format is re-implemented here; what this reader owns is the mapping onto the NATIVE-ARRAY contract.

One row per PART. A shapefile record may carry several parts — a polygon’s outer ring plus its holes, a county’s mainland plus its islands, a multi-part route. The op that consumes this geometry (polygon_intersection_area, intersect_polygon) takes ONE ring, so a reader that surfaced only the first part would silently drop the islands. Each part therefore becomes one row of the index axis, with the record’s .dbf attributes REPLICATED across its parts and shape_index / part_index / n_parts naming where the row came from. A layer whose records are all single-part (the common case) decodes 1:1.

Variables:

geometry float64[index, vertex, xy] — the vertex rings, right-PADDED to the longest part by REPEATING the final vertex. That padding is the rectangular-vertex-storage convention esm-spec §8.6.1 pins: a binding evaluates such a ring as its deduplicated form, so a short ring padded this way has the same area as the ring itself. A Null shape’s row is all NaN. Vertices are kept exactly as stored — the explicit closing vertex of a shapefile ring is NOT dropped (§8.6.1 makes dropping it the kernel’s job) and no winding is normalized. shape_type, crs_wkt str[meta] — one-element string fields: the layer’s shape type, and the .prj WKT verbatim when the archive carries one (crs_wkt is absent otherwise). The native CRS is DECLARED, not acted on — reprojection is ESD’s job, never the reader’s. They are fields rather than field attrs because the Rust NativeField has no attrs, and the cross-language native-array equality check compares fields. n_vertices int64[index] — real vertices in the part, before padding. shape_index, part_index, n_parts int64[index] — the 0-based record index in the .shp, the 0-based part index inside it, and its part count. xmin, ymin, xmax, ymax float64[index] — the parent RECORD’s stored bounding box (a Point’s own coordinate where the format stores no box), replicated to its parts. On disk, not computed: it is the shapefile’s own broad-phase envelope. one field per .dbf column [index], replicated to parts. Numeric (N/F) columns become float64 with a blank as NaN; L becomes bool; D and C stay str. A row whose deletion flag is * is dropped, and no other flag byte means deleted (spec/conformance.md §3).

READER-ONLY (Risk R3): no reprojection, no unit conversion, no ring orientation fix, no polygon/hole classification, no name remap.

reader_kwargs: member="path/in/zip" names the .shp inside a zip blob (sidecars are the same stem with .dbf/.shx/.prj); it never enters the cache key. numeric_columns=[...] parses the named C columns as float64 — the CSVReader/FF10Reader spelling, for a text-typed code column (a FIPS GEOID) a model wants as a number.

Members

  • read_native — Decode a shapefile blob into a one-row-per-part feature table.

Source

Julia

struct ShapefileReader <: Reader
ShapefileReader()
ShapefileReader()

The shapefile format reader — an ESRI shapefile as a feature table.

Decode is delegated to Shapefile.jl, loaded LAZILY via a weakdep extension (EarthSciIOShapefileExt, active on using Shapefile) — mirroring the Python reader’s lazy pyshp import and the Rust shapefile crate. Calling read_native without using Shapefile throws a clear install hint.

One row per PART. A shapefile record may carry several parts — a polygon’s outer ring plus its holes, a county’s mainland plus its islands. The op that consumes this geometry (polygon_intersection_area, intersect_polygon) takes ONE ring, so a reader that surfaced only the first part would silently drop the islands. Each part becomes one row of the index axis, with the record’s .dbf attributes REPLICATED across its parts; a single-part layer decodes 1:1.

Variables: geometry (Float64[index, vertex, xy], right-PADDED to the longest part by REPEATING the final vertex — the esm-spec §8.6.1 rectangular-storage convention, which a binding evaluates as the deduplicated ring; a Null shape’s row is all NaN), shape_type and — when the archive carries a .prj — crs_wkt (String[meta], one element each: the layer’s shape type and the projection WKT verbatim; the native CRS is DECLARED, not acted on), n_vertices/shape_index/part_index/ n_parts (Int64[index]), xmin/ymin/xmax/ymax (Float64[index], the parent record’s STORED bounding box replicated to its parts) and one field per .dbf column (N/F -> Float64 with blank as NaN, L -> Bool, D/C -> String). A row whose deletion flag is * is dropped, and no other flag byte means deleted (spec/conformance.md §3).

READER-ONLY (Risk R3): no reprojection, no unit conversion, no ring orientation fix, no polygon/hole classification, no name remap.

reader_kwargs: member="path/in/zip" names the .shp inside a zip blob (sidecars are the same stem with .dbf/.shx/.prj); it never enters the cache key. numeric_columns=[...] parses the named C columns as Float64 — the CSVReader/FF10Reader spelling, for a text-typed code column (a FIPS GEOID) a model wants as a number. nvert_max=N pads geometry to exactly N vertex slots instead of to the longest part, so a DOCUMENT declares the vertex-axis length rather than inheriting a number the file happens to have (a longer part is an error naming it, never a silent truncation). variables=[...] restricts the returned fields.

Source

Rust

pub struct ShapefileReader {
    /* private fields */
}

impl ShapefileReader { pub fn new() -> Self }

impl ShapefileReader { pub fn member(self, member: impl Into<String>) -> Self }

impl ShapefileReader { pub fn numeric_columns<I, S>(self, columns: I) -> Self where I: IntoIterator<Item = S>, S: Into<String> }

impl ShapefileReader { pub fn nvert_max(self, n: usize) -> Self }

The shapefile format reader. See the module docs for the decode contract.

Source · Rust docs