Skip to main content

improved esri rest io for geopandas

Project description

restgdf

improved esri rest io for geopandas

PyPI version Python versions Downloads License

CI Publish to PyPI coverage

Read the Docs llms.txt Ask DeepWiki

Pydantic v2 pre-commit Ruff Checked with mypy Code style: black security: bandit

What's new in 2.0

restgdf 2.0 is a major release built on pydantic 2.13. See MIGRATION.md for the full breaking-changes table and code-rewrite recipes.

  • Typed responses. FeatureLayer.metadata, Directory.metadata / .services / .report, and helpers like get_metadata, safe_crawl now return pydantic models instead of raw dicts.
  • Validated envelopes. get_feature_count, get_object_ids, and token refresh surface malformed ArcGIS payloads as a typed RestgdfResponseError (with model_name, context, raw).
  • Schema-drift observability. Vendor variance in permissive payloads (metadata, crawl) is logged through the opt-in restgdf.schema_drift logger instead of silently KeyError-ing.
  • Redacted credentials. AGOLUserPass.password is a pydantic.SecretStr so passwords are never in repr() or logs.
  • Centralized settings. Settings / get_settings() reads RESTGDF_* environment variables (chunk size, timeout, user agent, token URL, refresh threshold, etc.).
  • Migration helpers. restgdf.compat.as_dict and as_json_dict convert any returned model back to a plain dict during a transitional upgrade window.
  • Deprecated shim. restgdf._types.* still imports the legacy TypedDict names, but they now re-export the pydantic classes and emit DeprecationWarning. The shim will be removed in 3.x.
  • Dependency bump. pydantic>=2.13.3,<3 is a new required dependency.

gpd.read_file(url, driver="ESRIJSON") does not account for max record count limitations

so if you read a service with 100000 features but there's a limit of 1000 records per query, then your gdf will only have 1000 features

these functions use asyncio to read all features from a service, not limited by max record count

keyword arguments to FeatureLayer.getgdf are passed on to aiohttp.ClientSession.post; include query parameters like where and token in the data dict when needed

this enables enhanced control over queries and supports either direct data={"token": "..."} usage or a reusable ArcGISTokenSession

Usage

pip install restgdf
import asyncio

from aiohttp import ClientSession

from restgdf import FeatureLayer


beaches_url = r"https://maps1.vcgov.org/arcgis/rest/services/Beaches/MapServer/6"

zipcodes_url = "https://services.arcgis.com/P3ePLMYs2RVChkJx/ArcGIS/rest/services/USA_ZIP_Codes_2016/FeatureServer/0"

async def main():
    async with ClientSession() as session:
        beaches = await FeatureLayer.from_url(beaches_url, session=session)
        beaches_gdf = await beaches.getgdf()

        daytona = await beaches.where("LOWER(City) LIKE 'daytona%'")
        daytona_gdf = await daytona.getgdf()

        oh_zipcodes = await FeatureLayer.from_url(zipcodes_url, where="STATE = 'OH'", session=session)
        oh_zipcodes_gdf = await oh_zipcodes.getgdf()

    return beaches_gdf, daytona_gdf, oh_zipcodes_gdf


beaches_gdf, daytona_gdf, oh_zipcodes_gdf = asyncio.run(main())

print(beaches_gdf.shape)
# (243, 10)

print(daytona_gdf.shape)
# (83, 10)

print(oh_zipcodes_gdf.shape)
# (1026, 8)

Token authentication

import asyncio

from aiohttp import ClientSession

from restgdf import AGOLUserPass, ArcGISTokenSession, FeatureLayer


secured_url = "https://example.com/arcgis/rest/services/Secured/FeatureServer/0"


async def main():
    async with ClientSession() as base_session:
        token_session = ArcGISTokenSession(
            session=base_session,
            credentials=AGOLUserPass(
                username="my-username",
                password="my-password",
            ),
        )
        layer = await FeatureLayer.from_url(secured_url, session=token_session)
        return await layer.getgdf()


secured_gdf = asyncio.run(main())

If you already have a token, you can pass it with token="..." or data={"token": "..."}.

Typed responses

Every response is a pydantic model. Attribute access replaces dict indexing, and model_dump(by_alias=True) round-trips back to ArcGIS camelCase:

import asyncio

from aiohttp import ClientSession

from restgdf import FeatureLayer


async def main():
    async with ClientSession() as session:
        fl = await FeatureLayer.from_url(beaches_url, session=session)
        md = fl.metadata                      # restgdf.LayerMetadata
        return md.name, md.max_record_count, md.model_dump(by_alias=True)


name, max_record_count, arcgis_dict = asyncio.run(main())

Need a plain dict during a transitional migration? Use restgdf.compat.as_dict(md). See MIGRATION.md for the full 1.x → 2.0 rewrite table.

Documentation

Full docs live at https://restgdf.readthedocs.io/ (hosted by Read the Docs).

Docs for humans and LLMs

Every page is published in three formats so you can feed it to a teammate or to a language model without any preprocessing:

Format URL
Rendered HTML https://restgdf.readthedocs.io/en/latest/
Plain Markdown (per page) append .md to any page — e.g. https://restgdf.readthedocs.io/en/latest/quickstart.html.md
llms.txt index https://restgdf.readthedocs.io/en/latest/llms.txt
llms-full.txt (all pages) https://restgdf.readthedocs.io/en/latest/llms-full.txt
Ask DeepWiki https://deepwiki.com/joshuasundance-swca/restgdf

Point your coding agent or RAG pipeline at llms-full.txt for the entire reference in a single file, or at llms.txt for a concise table of contents.

Uses

Project details


Download files

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

Source Distribution

restgdf-2.0.0.tar.gz (70.3 kB view details)

Uploaded Source

Built Distribution

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

restgdf-2.0.0-py3-none-any.whl (46.0 kB view details)

Uploaded Python 3

File details

Details for the file restgdf-2.0.0.tar.gz.

File metadata

  • Download URL: restgdf-2.0.0.tar.gz
  • Upload date:
  • Size: 70.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for restgdf-2.0.0.tar.gz
Algorithm Hash digest
SHA256 c4cabed380c37ee5d780ab6a3a99cf36a5509504777d7a354e3db74f2729fd4f
MD5 1901c56e742411144e5ca3b2956c1202
BLAKE2b-256 07816ca3b4117e3add6b94008c3490bbede3012a1b1686342a01bfeb2b18ef22

See more details on using hashes here.

Provenance

The following attestation bundles were made for restgdf-2.0.0.tar.gz:

Publisher: publish_on_pypi.yml on joshuasundance-swca/restgdf

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file restgdf-2.0.0-py3-none-any.whl.

File metadata

  • Download URL: restgdf-2.0.0-py3-none-any.whl
  • Upload date:
  • Size: 46.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for restgdf-2.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 45d93209038d44a0eb090d4b1e6bda96b472ef3157965d462da2f5200df5e07b
MD5 b2a536e2a408d27231c84d4af0dd754a
BLAKE2b-256 1290e4e5aa6710d10381a0951cbf9c978cb505c5ef50adea8cc8f191bdd80550

See more details on using hashes here.

Provenance

The following attestation bundles were made for restgdf-2.0.0-py3-none-any.whl:

Publisher: publish_on_pypi.yml on joshuasundance-swca/restgdf

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page