Source code for restgdf.adapters.stream

"""Core-install safe streaming adapters over ArcGIS pagination.

Thin async-iterator wrappers over the existing pagination helpers in
:mod:`restgdf.utils.getgdf`. Row-level and feature-batch-level iteration are
safe on a base install; ``iter_gdf_chunks`` requires the optional geo stack
and gates at call time via :func:`restgdf.utils.getgdf.chunk_generator`'s
internal call to :func:`restgdf.utils._optional.require_geo_stack`.

The public streaming surface (``stream_features``, ``stream_feature_batches``,
ordering guarantees, backpressure options) is planned to expand in phase-4a
under MASTER-PLAN BL-24. The names exposed here are the minimum viable set
that today's callers can depend on; their shape is compatible with the
planned BL-24 expansion.
"""

from __future__ import annotations

from collections.abc import AsyncIterator
from typing import TYPE_CHECKING, Any

from restgdf.utils.getgdf import (
    _feature_batch_generator,
    chunk_generator,
    row_dict_generator,
)

if TYPE_CHECKING:  # pragma: no cover - import-time only
    from restgdf._client._protocols import AsyncHTTPSession

__all__ = ["iter_feature_batches", "iter_gdf_chunks", "iter_rows"]


[docs] async def iter_feature_batches( url: str, session: AsyncHTTPSession, **kwargs: Any, ) -> AsyncIterator[list[dict[str, Any]]]: """Yield ArcGIS feature batches (lists of raw feature dicts) from ``url``. Thin wrapper around :func:`restgdf.utils.getgdf._feature_batch_generator`. Core-install safe — no pandas / geopandas dependency. Parameters ---------- url: Fully qualified ArcGIS FeatureServer/MapServer layer URL. session: An :class:`aiohttp.ClientSession` or :class:`restgdf.ArcGISTokenSession`. **kwargs: Forwarded to the underlying batch generator (``data``, ``where``, ``outFields``, ``token``, etc.). Yields ------ list[dict[str, Any]] One list of raw ArcGIS feature dicts per page. Examples -------- >>> import asyncio, aiohttp >>> from restgdf.adapters.stream import iter_feature_batches >>> async def demo(url): # doctest: +SKIP ... async with aiohttp.ClientSession() as s: ... async for batch in iter_feature_batches(url, s): ... print(len(batch)) See Also -------- :meth:`restgdf.FeatureLayer.stream_feature_batches` Preferred high-level entrypoint with ``order``, ``max_concurrent_pages``, and ``on_truncation`` knobs. """ async for batch in _feature_batch_generator(url, session, **kwargs): yield batch
[docs] async def iter_rows( url: str, session: AsyncHTTPSession, **kwargs: Any, ) -> AsyncIterator[dict[str, Any]]: """Yield row-shaped dicts from ``url``. Thin wrapper around :func:`restgdf.utils.getgdf.row_dict_generator`. Core-install safe — no pandas / geopandas dependency. Parameters ---------- url: Fully qualified ArcGIS FeatureServer/MapServer layer URL. session: An :class:`aiohttp.ClientSession` or :class:`restgdf.ArcGISTokenSession`. **kwargs: Forwarded to :func:`restgdf.utils.getgdf.row_dict_generator`. Yields ------ dict[str, Any] ``{**feature["attributes"], "geometry": feature.get("geometry")}`` per feature. Examples -------- >>> async for row in iter_rows(url, session): # doctest: +SKIP ... print(row["OBJECTID"], row["geometry"]) See Also -------- :meth:`restgdf.FeatureLayer.stream_rows` Preferred high-level entrypoint with streaming ordering and truncation-handling knobs. """ async for row in row_dict_generator(url, session, **kwargs): yield row
[docs] async def iter_gdf_chunks( url: str, session: AsyncHTTPSession, **kwargs: Any, ) -> AsyncIterator[Any]: """Yield ``GeoDataFrame`` chunks from ``url``. Requires the optional geo extra: ``pip install "restgdf[geo]"``. Thin wrapper around :func:`restgdf.utils.getgdf.chunk_generator`, which itself validates the optional geo stack via :func:`restgdf.utils._optional.require_geo_stack`. Parameters ---------- url: Fully qualified ArcGIS FeatureServer/MapServer layer URL. session: An :class:`aiohttp.ClientSession` or :class:`restgdf.ArcGISTokenSession`. **kwargs: Forwarded to :func:`restgdf.utils.getgdf.chunk_generator`. Yields ------ geopandas.GeoDataFrame One chunk per ArcGIS query page. Raises ------ restgdf.errors.OptionalDependencyError When ``pandas``, ``geopandas``, or ``pyogrio`` is missing. See Also -------- :meth:`restgdf.FeatureLayer.stream_gdf_chunks` Preferred high-level entrypoint. Each yielded chunk carries ``gdf.attrs["spatial_reference"]`` populated from layer metadata (R-65). """ async for chunk in chunk_generator(url, session, **kwargs): yield chunk