Pydantic models¶
The base pip install restgdf install exposes every ArcGIS response and config object as a
pydantic BaseModel. These classes are the single source of
truth for payload shape and are re-exported from restgdf directly. Use
restgdf.compat.as_dict() if you need a plain dict during a migration.
Model relationships¶
The models nest in a natural hierarchy that mirrors the ArcGIS REST API response structure:
FeatureLayer.metadata → LayerMetadata
│ ├── .fields → list[FieldSpec]
│ ├── .extent → dict (raw spatial extent)
│ └── .advanced_query_capabilities → AdvancedQueryCapabilities
│
FeatureLayer.get_gdf() internally parses → FeaturesResponse
│ ├── .features → list[Feature]
│ └── .exceeded_transfer_limit → bool
│
Directory.crawl() → list[CrawlServiceEntry]
│ ├── .metadata → LayerMetadata | None
│ └── .name, .url, .type
│
Directory.report → CrawlReport
├── .services → list[CrawlServiceEntry]
└── .errors → list[CrawlError]
Use model.model_dump(by_alias=True) to round-trip any model back to ArcGIS
camelCase JSON. Use restgdf.compat.as_dict() for a plain dict during
migration.
Response envelopes¶
- pydantic model restgdf.LayerMetadata[source]¶
Bases:
PermissiveModelPolymorphic ArcGIS REST metadata envelope.
The same endpoint family (
GET <url>?f=json) returns per-layer metadata (name,fields,maxRecordCount, …), service roots (services,folders), sub-layer descriptors (id), and restgdf-enriched payloads (url,feature_count). All variants parse into this single permissive model; missing fields default toNonerather than raise.Field aliases accept either camelCase (native ArcGIS) or snake_case (Python-native) input via
AliasChoices, andmodel_dump(by_alias=True)round-trips back to camelCase so downstream serialization stays ArcGIS-compatible.- Fields:
advanced_query_capabilities (dict[str, Any] | None)advanced_query_capabilities_typed (restgdf._models.responses.AdvancedQueryCapabilities | None)feature_count (int | None)fields (list[restgdf._models.responses.FieldSpec] | None)folders (list[str] | None)id (int | None)layers (list[restgdf._models.responses.LayerMetadata] | None)max_record_count (int | None)name (str | None)services (list[dict[str, Any]] | None)supports_pagination (bool | None)type (str | None)url (str | None)
- pydantic model restgdf.ServiceInfo[source]¶
Bases:
PermissiveModelRoot
GET <services_root>?f=jsonenvelope.A narrower permissive view over the subset of keys a services-root crawl consumes (
servicesandfolders). UnlikeLayerMetadata, this model does not enrich nestedservicesentries into typed objects — the crawl report keeps them as raw dicts so per-service merge keys (name,type) survive unchanged.- Fields:
folders (list[str] | None)layers (list[restgdf._models.responses.LayerMetadata] | None)services (list[dict[str, Any]] | None)url (str | None)
- pydantic model restgdf.FieldSpec[source]¶
Bases:
PermissiveModelA field descriptor entry in a layer’s
fieldslist.Real ArcGIS servers emit an open-ended set of keys here (
sqlType,defaultValue,modelName, …). Permissive tier preserves them viaextra="allow"while declaring the handful of keys restgdf actually consumes.- Fields:
alias (str | None)domain (dict | None)editable (bool | None)length (int | None)name (str | None)nullable (bool | None)type (str | None)
- pydantic model restgdf.Feature[source]¶
Bases:
PermissiveModelA single feature in
FeaturesResponse.features.attributesis declared as a dict but not typed further — ArcGIS layer schemas are dynamic.geometryis optional because non- spatial tables andreturnGeometry=falsequeries omit it.- Fields:
attributes (dict[str, Any] | None)geometry (dict[str, Any] | None)
- pydantic model restgdf.FeaturesResponse[source]¶
Bases:
PermissiveModelEnvelope for
?f=jsonfeature queries.Permissive tier: only the envelope keys restgdf consumes are declared.
featuresis kept as alist[dict]rather thanlist[Feature]on purpose — validating every feature of a large batch with pydantic would be expensive and returns no value to the downstream GeoPandas reader, which consumes raw ArcGIS JSON. Callers that need typed features can validate them explicitly viaFeature.- Fields:
exceeded_transfer_limit (bool | None)features (list[dict[str, Any]])fields (list[restgdf._models.responses.FieldSpec] | None)object_id_field_name (str | None)
- pydantic model restgdf.CountResponse[source]¶
Bases:
StrictModelEnvelope for
?returnCountOnly=truequery results.Strict tier: ArcGIS always returns
countfor this query shape, so a missing/ill-typed key signals a protocol-level incident (for example an HTML error page bodied as JSON)._parse_response()surfaces those asRestgdfResponseError.- Fields:
count (int)
- pydantic model restgdf.ObjectIdsResponse[source]¶
Bases:
StrictModelEnvelope for
?returnIdsOnly=truequery results.Strict tier. The response is operation-critical: chunked pagination in
restgdf.utils.getgdfrequires both the OID field name and the full id list. A zero-row match produces{"objectIdFieldName": "OBJECTID", "objectIds": null}in the wild; theobject_idsvalidator below coerces thatNoneto an empty list so consumers can unconditionally iterate.- Fields:
object_id_field_name (str)object_ids (list[int])
- Validators:
_coerce_null_to_empty»object_ids
- pydantic model restgdf.TokenResponse[source]¶
Bases:
StrictModelEnvelope for ArcGIS
/generateTokenresponses.Strict tier: token refresh is operation-critical; a missing
tokenorexpireskey means a token cannot be used and any downstream request will fail authentication. ArcGIS also returns error envelopes through this same endpoint ({"error": {...}}); those fail validation here and surface asRestgdfResponseError, leaving the original payload onexc.rawfor operator triage.- Fields:
expires (int)ssl (bool | None)token (str)
- pydantic model restgdf.ErrorInfo[source]¶
Bases:
PermissiveModelInner error payload:
{"code": int, "message": str, ...}.ArcGIS error payloads routinely carry diagnostic extras (
messageCode,errorCode,details) that restgdf does not need but should not strip away.- Fields:
code (int | None)details (list[str] | None)message (str | None)
- pydantic model restgdf.ErrorResponse[source]¶
Bases:
StrictModelTop-level JSON error envelope:
{"error": {...}}.Strict tier: callers branching on
isinstance(obj, ErrorResponse)need theerrorkey to actually be present. Missing-key drift on this envelope indicates a protocol-level bug, not vendor variance.- Fields:
error (restgdf._models.responses.ErrorInfo)
Crawl models¶
- pydantic model restgdf.CrawlReport[source]¶
Bases:
PermissiveModelAggregated result of a directory crawl.
Unlike the legacy
fetch_all_datareturn shape (which short-circuits to{"error": exc}on the first failure),CrawlReportalways returns partial successes alongside captured errors.- Fields:
errors (list[restgdf._models.crawl.CrawlError])metadata (restgdf._models.responses.LayerMetadata | None)services (list[restgdf._models.crawl.CrawlServiceEntry])
- pydantic model restgdf.CrawlServiceEntry[source]¶
Bases:
PermissiveModelA service entry in
CrawlReport.services.metadatais theLayerMetadatareturned byservice_metadatafor this service. It isNonewhen theservice_metadatacall failed; in that case a correspondingCrawlErroris recorded inCrawlReport.errors.- Fields:
metadata (restgdf._models.responses.LayerMetadata | None)name (str | None)type (str | None)url (str | None)
- pydantic model restgdf.CrawlError[source]¶
Bases:
PermissiveModelA single failure captured during
safe_crawl().stageidentifies where the failure occurred. Standard stages emitted bysafe_crawlare:"base_metadata"— the rootget_metadatacall failed."folder_metadata"— a per-folderget_metadatacall failed."service_metadata"— a per-serviceservice_metadatacall failed.
exceptionpreserves the originalBaseExceptionso callers can re-raise; it is excluded from the defaultmodel_dump()output for JSON safety.- Fields:
exception (BaseException | None)message (str | None)stage (str | None)url (str | None)
Credentials and session config¶
- pydantic model restgdf.AGOLUserPass[source]
Bases:
StrictModelArcGIS Online / Enterprise credentials used to mint tokens.
passwordis stored aspydantic.SecretStr. Callcreds.password.get_secret_value()only at the HTTP-POST boundary; never store or log the unwrapped value.- Fields:
expiration (int)password (pydantic.types.SecretStr)referer (str | None)username (str)
- pydantic model restgdf.TokenSessionConfig[source]
Bases:
StrictModelValidated configuration for
ArcGISTokenSession.token_urlis intentionally a plainstrwith a custom validator rather thanpydantic.AnyHttpUrl. ArcGIS Enterprise deployments commonly run plain HTTP on internal networks, andAnyHttpUrlnormalizes/rejects real-world URLs (for example it appends trailing slashes and may reject edge cases). Accepting anyhttp://orhttps://string matches the behavior ArcGIS clients need.- Refresh semantics (BL-04 / R-36, R-37):
refresh_leeway_seconds(default120) — how far in advance of the token’s expiry the session eagerly refreshes.clock_skew_seconds(default30, capped at30when derived from the legacy alias) — extra padding for client / server clock drift.
refresh_threshold_secondsis retained as a deprecation-warning alias. Reads returnrefresh_leeway_seconds + clock_skew_seconds; writes via the constructor kwarg split the supplied total intoclock_skew_seconds = min(30, total)andrefresh_leeway_seconds = total - clock_skew_seconds.- Fields:
clock_skew_seconds (int)credentials (restgdf._models.credentials.AGOLUserPass)header_name (str)referer (str | None)refresh_leeway_seconds (int)token (pydantic.types.SecretStr | None)token_url (str)transport (Literal['header', 'body', 'query'])verify_ssl (bool)
- Validators:
_check_token_url_scheme»token_url_translate_legacy_refresh_threshold»all fields
Runtime settings¶
- pydantic model restgdf.Settings[source]¶
Bases:
BaseModelValidated runtime configuration for restgdf.
The model is frozen: treat a
Settingsinstance as immutable. To change runtime configuration, mutate the environment (or pass an explicit mapping), then callreset_settings_cache()and re-fetch viaget_settings().- Fields:
chunk_size (int)default_headers_json (str | None)log_level (str)max_concurrent_requests (int)refresh_threshold_seconds (int)timeout_seconds (float)token_url (str)user_agent (str)
- Validators:
_check_token_url_scheme»token_url_normalize_log_level»log_level