API reference

This page documents the public surface exposed at the top of the restgdf namespace: the FeatureLayer and Directory entry points, the ArcGISTokenSession wrapper, and the migration helpers in restgdf.compat.

The pydantic response models (LayerMetadata, FeaturesResponse, CrawlReport and friends) live on Pydantic models. Internal utility modules are on Utilities.

The base pip install restgdf surface covers metadata/query helpers, raw-row iteration, crawl/auth utilities, and all pydantic models. Install restgdf[geo] for GeoDataFrame and pandas-backed APIs such as FeatureLayer.get_gdf(), sample_gdf(), head_gdf(), fieldtypes, get_value_counts(), and get_nested_count().

FeatureLayer

class restgdf.FeatureLayer(url, session, where='1=1', token=None, **kwargs)[source]

Bases: object

A class for interacting with an ArcGIS REST FeatureLayer.

Variables:
  • metadata (restgdf.LayerMetadata) – Pydantic-validated layer metadata (name, fields, max record count, advanced query capabilities, …). Replaces the pre-2.0 raw dict. Extra keys sent by the server are preserved via extra="allow" and reachable through metadata.model_extra.

  • name (str) – Convenience alias for metadata.name.

  • fields (tuple[str, ]) – Field names consumed by restgdf.

  • object_id_field (str) – Resolved object-id field name ("OBJECTID" when the server omits it).

  • count (int) – Feature count, validated via CountResponse at prep time.

async prep()[source]

Fetch and validate layer metadata from the server.

Populates metadata, name, fields, object_id_field, and count. Must be called before accessing any metadata attributes unless the instance was created via from_url() (which calls this method automatically).

Raises:

ValueError – If the URL does not point to a Feature Layer (e.g. a Table or Map Service root).

See also

from_url

Recommended constructor that calls prep automatically.

property fieldtypes: pandas.DataFrame

Return field metadata as a DataFrame when pandas is available.

async classmethod from_url(url, **kwargs)[source]

Create a prepared FeatureLayer from a URL.

This is the recommended constructor. It instantiates the class and calls prep() so all metadata attributes are immediately available on the returned instance.

Parameters:
  • url (str) – ArcGIS REST FeatureLayer endpoint URL (must end with a numeric layer ID).

  • **kwargs – Forwarded to __init__() — accepts session, where, token, and any extra HTTP request arguments.

Returns:

A fully prepared instance with metadata loaded.

Return type:

FeatureLayer

Raises:

ValueError – If url does not end with a number, conflicting tokens are provided, or the endpoint is not a Feature Layer.

See also

__init__

Low-level constructor (requires a manual prep call).

async get_oids()[source]

Return all object IDs matching the current WHERE filter.

Delegates to get_unique_values() using the resolved object_id_field.

Returns:

Sorted list of object ID values for the filtered feature set.

Return type:

list[int]

async sample_gdf(n=10)[source]

Get n random features as a GeoDataFrame.

async head_gdf(n=10)[source]

Get the n first features as a GeoDataFrame.

async get_gdf()[source]

Get a GeoDataFrame from an ArcGIS FeatureLayer.

The returned GeoDataFrame carries gdf.attrs["spatial_reference"] populated from the layer’s metadata envelope (R-65) when the layer advertises a spatial reference via extent.spatialReference or top-level spatialReference.

async iter_pages(*, order='request', max_concurrent_pages=None, on_truncation='raise', **kwargs)[source]

Yield raw ArcGIS query-page envelopes from this FeatureLayer.

Parameters:
  • order"request" (default) yields pages in submit order. "completion" yields pages as the underlying fetches complete (may reorder relative to the pagination plan).

  • max_concurrent_pages – Upper bound on concurrent in-flight page fetches. None (default) leaves concurrency unbounded.

  • on_truncation – Behavior when a page reports exceededTransferLimit=true:

    • "raise" (default) — raise restgdf.errors.RestgdfResponseError with context='exceededTransferLimit'.

    • "ignore" — log a restgdf.pagination warning and yield the truncated page anyway.

    • "split" — bisect the predicate’s OID list and recurse (max depth 32; irreducible partitions raise).

Yields:

dict – The full raw response envelope for each page (features, objectIdFieldName, exceededTransferLimit, etc.).

Notes

When telemetry is enabled, emits exactly ONE INTERNAL parent span named feature_layer.stream wrapping the per-page loop (R-61). No per-page restgdf child spans are emitted.

async iter_features(*, order='request', max_concurrent_pages=None, on_truncation='raise', **kwargs)[source]

Yield one raw ArcGIS feature dict at a time.

Thin wrapper over iter_pages() that flattens each page’s features list. See iter_pages() for parameter semantics.

async stream_features(*, order='request', max_concurrent_pages=None, on_truncation='raise', **kwargs)

Yield one raw ArcGIS feature dict at a time.

Thin wrapper over iter_pages() that flattens each page’s features list. See iter_pages() for parameter semantics.

async stream_feature_batches(*, order='request', max_concurrent_pages=None, on_truncation='raise', **kwargs)[source]

Yield one list of raw feature dicts per page.

See iter_pages() for parameter semantics.

async stream_rows(*, order='request', max_concurrent_pages=None, on_truncation='raise', **kwargs)[source]

Yield row-shaped dicts (attributes plus raw geometry).

Each row is the layer feature’s attributes merged with a geometry key holding the ArcGIS geometry dict verbatim. See iter_pages() for parameter semantics.

async stream_gdf_chunks(**kwargs)[source]

Yield GeoDataFrame chunks; each chunk’s attrs carries spatial_reference (R-65).

Requires the optional geo stack (geopandas / pyogrio).

async get_df(resolve_domains=False)[source]

Get a pandas DataFrame from an ArcGIS FeatureLayer.

Tabular row view: attributes plus any raw geometry dict returned by the server, with no geopandas/pyogrio dependency. Raises restgdf.errors.OptionalDependencyError when pandas is not installed.

This is the pandas-only counterpart to get_gdf() — prefer it when callers only need tabular access and want to avoid the full geo dependency stack.

Parameters:

resolve_domains – When True, coded-value domain fields are post-processed so the DataFrame contains the human-readable name rather than the raw code. Codes absent from the domain’s codedValues table pass through unchanged. Range domains are not validated or coerced. Defaults to False — the historical behavior where the DataFrame faithfully mirrors the server payload. No additional HTTP traffic is issued; resolution uses the already-loaded FeatureLayer.metadata fetched during prep().

Examples

>>> df = await layer.get_df(resolve_domains=True)
>>> df["STATUS"].head().tolist()
['Active', 'Inactive', 'Active', ...]
async row_dict_generator(**kwargs)[source]

Asynchronously yield rows from a GeoDataFrame as dictionaries.

Deprecated since version 2.0: Use stream_rows() instead. This method emits a DeprecationWarning and continues to delegate to the module-level row_dict_generator helper for backwards compatibility with existing unittest.mock.patch targets. Scheduled for removal in a future release.

async get_unique_values(fields, sortby=None)[source]

Get unique values for one or more fields.

Results are cached per (fields, sortby) key for the lifetime of this instance.

Parameters:
  • fields (str or tuple of str) – A single field name (returns a list) or a tuple of field names (returns a DataFrame; requires the geo extra).

  • sortby (str or None, optional) – Field name to sort results by. When None, the server’s default ordering is used.

Returns:

A plain list when fields is a single string, or a DataFrame when fields is a tuple.

Return type:

list or DataFrame

Raises:

FieldDoesNotExistError – If any requested field is not present in the layer schema.

async get_value_counts(field)[source]

Get value counts for a single field.

Results are cached per field for the lifetime of this instance.

Parameters:

field (str) – The field name to compute value counts for.

Returns:

A pandas DataFrame with one row per distinct value and an associated count column.

Return type:

DataFrame

Raises:

FieldDoesNotExistError – If field is not present in the layer schema.

async get_nested_count(fields)[source]

Get nested (cross-tabulated) value counts for multiple fields.

Results are cached per fields tuple for the lifetime of this instance.

Parameters:

fields (tuple of str) – Two or more field names to cross-tabulate.

Returns:

A pandas DataFrame with one row per unique combination of values across the requested fields and an associated count.

Return type:

DataFrame

Raises:

FieldDoesNotExistError – If any field in fields is not present in the layer schema.

async getoids()[source]

Deprecated alias for get_oids().

async samplegdf(n=10)[source]

Deprecated alias for sample_gdf().

async headgdf(n=10)[source]

Deprecated alias for head_gdf().

async getgdf()[source]

Deprecated alias for get_gdf().

async getuniquevalues(fields, sortby=None)[source]

Deprecated alias for get_unique_values().

async getvaluecounts(field)[source]

Deprecated alias for get_value_counts().

async getnestedcount(fields)[source]

Deprecated alias for get_nested_count().

async where(wherestr)[source]

Create a refined FeatureLayer bound to wherestr.

BL-46: when the current instance has already resolved its schema via prep(), the refined child reuses the parent’s cached metadata / name / fields / object_id_field so the expensive metadata GET (?f=json) is not re-issued. The feature-count POST is still issued, but scoped to the refined where_clause so refined.count is correct for the refined filter.

Directory

class restgdf.Directory(url, session, token=None)[source]

Bases: object

A class for interacting with ArcGIS Server directories.

Variables:
  • metadata (Optional[restgdf.LayerMetadata]) – Pydantic-validated root metadata populated by prep(). None until prep (or from_url()) has run.

  • services (Optional[list[restgdf.CrawlServiceEntry]]) – Services discovered by the most recent crawl() call. Each entry carries name, url, type, and a parsed metadata (LayerMetadata or None if that service’s metadata call failed).

  • services_with_feature_count (Optional[list[restgdf.CrawlServiceEntry]]) – Same as services but populated with feature counts when crawl() was invoked with return_feature_count=True.

  • report (Optional[restgdf.CrawlReport]) – The full crawl report (services + per-stage errors + root metadata) from the most recent crawl() call. Use this when you need to inspect failures that were silently captured instead of raised.

async prep()[source]

Fetch and validate directory metadata from the server.

Populates metadata with a LayerMetadata instance. Must be called before accessing metadata unless the instance was created via from_url().

async classmethod from_url(url, **kwargs)[source]

Create a prepared Directory from a URL.

This is the recommended constructor. It instantiates the class and calls prep() so metadata is immediately available.

Parameters:
  • url (str) – ArcGIS Server directory endpoint URL.

  • **kwargs – Forwarded to __init__() — accepts session and token.

Returns:

A fully prepared instance with metadata loaded.

Return type:

Directory

async crawl(return_feature_count=False)[source]

Discover all services under this directory recursively.

Results are cached — subsequent calls with the same return_feature_count value return the cached list without additional HTTP traffic.

Parameters:

return_feature_count (bool, default False) – When True, also fetches the feature count for each discovered layer (requires extra HTTP requests per layer).

Returns:

List of discovered service entries, each carrying name, url, type, and parsed metadata.

Return type:

list[CrawlServiceEntry]

Notes

After a successful call, the following instance attributes are populated:

  • services — the returned list.

  • report — the full CrawlReport.

  • services_with_feature_count — same as services when return_feature_count was True.

filter_directory_layers(layer_type)[source]

Filter discovered layers by type.

Parameters:

layer_type (str) – The layer type string to match (e.g. "Feature Layer", "Raster Layer").

Returns:

Metadata entries for layers whose type matches layer_type.

Return type:

list[LayerMetadata]

Raises:

ValueError – If crawl() has not been called yet.

See also

feature_layers

Shortcut for filter_directory_layers("Feature Layer").

rasters

Shortcut for filter_directory_layers("Raster Layer").

feature_layers()[source]

Return all Feature Layer metadata from the crawl.

Convenience wrapper around filter_directory_layers("Feature Layer").

Returns:

Metadata for every discovered Feature Layer.

Return type:

list[LayerMetadata]

rasters()[source]

Return all Raster Layer metadata from the crawl.

Convenience wrapper around filter_directory_layers("Raster Layer").

Returns:

Metadata for every discovered Raster Layer.

Return type:

list[LayerMetadata]

Token session

class restgdf.ArcGISTokenSession(session, credentials=None, token_url='https://www.arcgis.com/sharing/rest/generateToken', token_refresh_threshold=60, token=None, expires=None, verify_ssl=True, config=None)[source]

Bases: object

Wrap an aiohttp session with ArcGIS token refresh behavior.

Construction knobs (token_url, token_refresh_threshold, credentials) are validated via TokenSessionConfig in __post_init__() so a bogus scheme or zero-length username fails fast with RestgdfResponseError rather than surfacing as a 401 or an aiohttp error deep in the request path.

session: ClientSession
credentials: AGOLUserPass | None = None
token_url: str = 'https://www.arcgis.com/sharing/rest/generateToken'
token_refresh_threshold: int = 60
token: str | None = None
expires: int | float | None = None
verify_ssl: bool = True
config: TokenSessionConfig | None = None
property token_request_payload: dict

Return the payload for the token request.

property expires_at: datetime | None

Return the token expiry as a tz-aware UTC datetime.

ArcGIS returns expires in either seconds or milliseconds since the Unix epoch — values above 1e11 are treated as milliseconds and divided by 1000. Returns None when no expiry is set.

property auth_headers: dict[str, str]

Return authentication headers with the token if available.

update_headers(headers=None)[source]

Return headers merged with the active token.

update_dict(input_dict=None)[source]

Return a request payload/query dict merged with the active token.

async update_token()[source]

Update the token by making a request to the token URL.

The /generateToken payload is validated against TokenResponse (strict tier) so malformed/error envelopes raise RestgdfResponseError instead of KeyError deep in caller code paths.

Retries up to _MAX_TOKEN_RETRIES times with exponential backoff (base _BASE_BACKOFF_S) on transient network errors. Deterministic errors (bad credentials, content-type mismatches, validation failures) are re-raised immediately. After exhausting retries, raises TokenRefreshFailedError.

Emits structured log events: * auth.refresh.start — before the POST * auth.refresh.success — after successful token update * auth.refresh.failure — on any exception

token_needs_update()[source]

Check if the token needs to be updated.

async update_token_if_needed()[source]

Ensure the token is valid and refresh if necessary.

BL-03: concurrent callers racing on an expired token collapse onto a single /generateToken POST via a lazily-initialized per-instance asyncio.Lock with a double-checked token_needs_update() inside the lock (plan.md §3c R-18, kickoff phase-1a §10.4). The lock is created here — not in __post_init__ — so instances constructed outside a running event loop (e.g. at import time or inside a sync test) never trigger DeprecationWarning: There is no current event loop.

async get(url, params=None, headers=None, **kwargs)[source]

Make a GET request to the specified URL with the token.

async post(url, data=None, headers=None, **kwargs)[source]

Make a POST request to the specified URL with the token.

property closed: bool

Return True when the underlying aiohttp.ClientSession is closed.

Delegating lets ArcGISTokenSession satisfy the internal AsyncHTTPSession transport Protocol uniformly with aiohttp.ClientSession (R-71).

async close()[source]

Close the underlying aiohttp.ClientSession.

Mirrors aiohttp.ClientSession.close() so token sessions and raw aiohttp sessions are interchangeable through the internal AsyncHTTPSession transport Protocol. Idempotent: closing an already-closed session is a no-op.

Errors

exception restgdf.RestgdfResponseError(message, *, model_name='', context='', raw=None, url=None, status_code=None, request_id=None)[source]

Bases: RestgdfError, ValueError

Raised when validated ArcGIS response handling must fail fast.

Variables:
  • model_name – The pydantic model class name associated with the failed parse (for example "CountResponse" or "LayerMetadata").

  • context – A short identifier describing where the response came from (for example the request URL or a helper name). Used by operators triaging ArcGIS vendor variance.

  • raw – The raw JSON-decoded payload that failed validation. Kept on the exception so callers can log or re-raise without re-reading the response body.

Canonical exception taxonomy for restgdf 3.0.

This module defines the public exception hierarchy used by every public entry point in restgdf. All domain-specific exceptions derive from RestgdfError so callers can catch “any restgdf failure” with a single except RestgdfError block while still being able to discriminate between transport, schema, auth, pagination, configuration, and conversion failures via the more specific subclasses.

Several classes multi-inherit from a builtin exception in addition to their restgdf-specific parent. This is deliberate and preserves backward-compat:

  • ConfigurationError(RestgdfError, ValueError) keeps except ValueError callers working while restgdf 3.x stabilizes (R-09).

  • OptionalDependencyError(ConfigurationError, ModuleNotFoundError) keeps except ImportError / except ModuleNotFoundError working when optional pandas/geopandas/pyogrio dependencies are missing.

  • RestgdfResponseError(RestgdfError, ValueError) keeps the 2.x except ValueError contract around typed response validation.

  • PaginationError(ArcGISServiceError, IndexError) preserves the 2.x “looks like an IndexError” contract around cursor exhaustion.

  • AuthenticationError(RestgdfResponseError, PermissionError) lets callers treat auth failures as PermissionError when appropriate.

  • RestgdfTimeoutError(TransportError, TimeoutError) keeps except TimeoutError callers working on request timeouts without shadowing the builtin TimeoutError symbol.

Hierarchy:

RestgdfError(Exception)
+-- ConfigurationError(RestgdfError, ValueError)
|   +-- OptionalDependencyError(ConfigurationError, ModuleNotFoundError)
+-- RestgdfResponseError(RestgdfError, ValueError)
|   +-- SchemaValidationError(RestgdfResponseError)
|   |   +-- FieldDoesNotExistError(SchemaValidationError)
|   +-- ArcGISServiceError(RestgdfResponseError)
|   |   +-- PaginationError(ArcGISServiceError, IndexError)
|   +-- AuthenticationError(RestgdfResponseError, PermissionError)
|       +-- InvalidCredentialsError(AuthenticationError)
|       +-- TokenExpiredError(AuthenticationError)
|       +-- TokenRequiredError(AuthenticationError)
|       +-- TokenRefreshFailedError(AuthenticationError)
|       +-- AuthNotAttachedError(AuthenticationError)
+-- TransportError(RestgdfError)
|   +-- RestgdfTimeoutError(TransportError, TimeoutError)
|   +-- RateLimitError(TransportError)
+-- OutputConversionError(RestgdfError)
exception restgdf.errors.ArcGISServiceError(message, *, model_name='', context='', raw=None, url=None, status_code=None, request_id=None)[source]

Bases: RestgdfResponseError

Raised when the ArcGIS service returns an explicit {"error": ...} envelope.

exception restgdf.errors.AuthNotAttachedError(message, *, context=None, attempt=None, cause=None, model_name='AuthenticationError', raw=None)[source]

Bases: _AuthSubtypeBase

Raised when a 499 is observed — the library did not attach auth to the request.

Per R-14 no retry is attempted; the error propagates immediately to the caller. This is semantically distinct from TokenExpiredError (498) which does trigger a single-flight refresh.

exception restgdf.errors.AuthenticationError(message, *, model_name='', context='', raw=None, url=None, status_code=None, request_id=None)[source]

Bases: RestgdfResponseError, PermissionError

Raised when ArcGIS auth (token, creds, scope) is invalid or expired.

Multi-inherits PermissionError so except PermissionError in application code can treat restgdf auth failures uniformly with local-filesystem permission failures.

exception restgdf.errors.ConfigurationError[source]

Bases: RestgdfError, ValueError

Raised when restgdf configuration (env vars, Settings, kwargs) is invalid.

Multi-inherits ValueError through 3.x so existing except ValueError callers continue to catch misconfiguration. The ValueError base will be dropped in 3.1+.

exception restgdf.errors.FieldDoesNotExistError(field_name=None, *, context=None, message=None)[source]

Bases: SchemaValidationError

A referenced field is absent from the ArcGIS layer metadata (BL-09).

Replaces the 2.x FIELDDOESNOTEXIST IndexError singleton per plan.md §3c R-02. Callers previously catching IndexError must migrate to except FieldDoesNotExistError (or the parent SchemaValidationError / RestgdfResponseError). No compat shim.

Variables:
  • field_name (:py:class:`str | tuple[str`, :py:class:`...] | None`) – The field(s) that failed resolution.

  • context (str) – Call-site identifier (e.g. "FeatureLayer.get_unique_values"); defaults to "FieldDoesNotExistError" when the caller passes None, matching the parent RestgdfResponseError contract where context is always a non-None string.

exception restgdf.errors.InvalidCredentialsError(message, *, context=None, attempt=None, cause=None, model_name='AuthenticationError', raw=None)[source]

Bases: _AuthSubtypeBase

Raised on 400 / bad credentials from /generateToken.

Inherits AuthenticationErrorPermissionError.

exception restgdf.errors.OptionalDependencyError[source]

Bases: ConfigurationError, ModuleNotFoundError

Raised when an optional dependency (pandas/geopandas/pyogrio) is absent.

Multi-inherits ModuleNotFoundError so existing except ImportError / except ModuleNotFoundError call sites keep working when restgdf[geo] is not installed.

exception restgdf.errors.OutputConversionError[source]

Bases: RestgdfError

Raised when converting validated ArcGIS data to a GeoDataFrame / DataFrame fails.

exception restgdf.errors.PaginationInconsistencyWarning[source]

Bases: UserWarning

Emitted when an ArcGIS batch response is self-inconsistent (R-73).

Specifically: a page that returns zero features and sets exceededTransferLimit=true is an ArcGIS-side pagination bug — the cursor cannot advance (offset-based pagination needs at least one row per page to progress) but the service simultaneously insists more rows exist. Left un-flagged this produces a silently-truncated result set.

Multi-inherits UserWarning so callers can silence or escalate it via warnings (e.g. warnings.filterwarnings("error", category=PaginationInconsistencyWarning)).

exception restgdf.errors.PaginationError(*args, batch_index=None, page_size=None)[source]

Bases: ArcGISServiceError, IndexError

Raised when cursor-based pagination cannot advance or exceeds limits.

Multi-inherits IndexError so legacy call sites that used except IndexError around pagination exhaustion keep working.

Variables:
  • batch_index – The zero-based batch index at which pagination failed, if known.

  • page_size – The page size in effect when pagination failed, if known.

exception restgdf.errors.RateLimitError(*args, retry_after=None, url=None, status_code=None)[source]

Bases: TransportError

Raised when the ArcGIS service signals a rate limit / throttle.

Variables:

retry_after – Optional seconds to wait before retrying, parsed from a Retry-After header or service envelope. None when the service did not supply a hint.

exception restgdf.errors.RestgdfError[source]

Bases: Exception

Base class for every exception raised by restgdf.

exception restgdf.errors.RestgdfResponseError(message, *, model_name='', context='', raw=None, url=None, status_code=None, request_id=None)[source]

Bases: RestgdfError, ValueError

Raised when validated ArcGIS response handling must fail fast.

Variables:
  • model_name – The pydantic model class name associated with the failed parse (for example "CountResponse" or "LayerMetadata").

  • context – A short identifier describing where the response came from (for example the request URL or a helper name). Used by operators triaging ArcGIS vendor variance.

  • raw – The raw JSON-decoded payload that failed validation. Kept on the exception so callers can log or re-raise without re-reading the response body.

exception restgdf.errors.RestgdfTimeoutError(*args, url=None, status_code=None, timeout_kind=None)[source]

Bases: TransportError, TimeoutError

Raised when a request times out.

Named RestgdfTimeoutError (not TimeoutError) to avoid shadowing the builtin. Multi-inherits TimeoutError so except TimeoutError callers continue to match.

Variables:

timeout_kind – One of "total", "connect", or "read", indicating which timeout budget was exceeded. None when unknown.

exception restgdf.errors.SchemaValidationError(message, *, model_name='', context='', raw=None, url=None, status_code=None, request_id=None)[source]

Bases: RestgdfResponseError

Raised when an ArcGIS response envelope fails schema validation.

Does not multi-inherit IndexError: R-02 explicitly forbids the transitional SchemaValidationError(IndexError, ...) shim that earlier drafts of the plan proposed.

exception restgdf.errors.TokenExpiredError(message='Token expired (Esri 498)', *, code=498, context=None, attempt=None, cause=None)[source]

Bases: _AuthSubtypeBase

Raised when ArcGIS returns error code 498 (Invalid Token).

Variables:

code (int) – Always 498.

exception restgdf.errors.TokenRefreshFailedError(message, *, context=None, attempt=None, cause=None, model_name='AuthenticationError', raw=None)[source]

Bases: _AuthSubtypeBase

Raised after the bounded-retry ladder for /generateToken is exhausted.

Variables:

attempt (int | None) – The final attempt number at which the refresh was abandoned.

exception restgdf.errors.TokenRequiredError(message, *, context=None, attempt=None, cause=None, model_name='AuthenticationError', raw=None)[source]

Bases: _AuthSubtypeBase

Raised when ArcGIS returns error code 499 (Token Required).

Semantically: the service demands a token but the request did not carry one (or the wrong transport was chosen).

exception restgdf.errors.TransportError(*args, url=None, status_code=None)[source]

Bases: RestgdfError

Raised for network/HTTP transport-layer failures (connection, DNS, …).

Variables:
  • url – The URL that was being requested when the failure occurred.

  • status_code – The HTTP status code, if one was received before the transport failure. None for pre-connect failures (DNS, refused, …).

Runtime settings

See Pydantic models for the Settings model; the helpers below read it from the environment.

restgdf.get_settings()[source]

Return the process-wide cached Settings instance.

Deprecated since version phase-2a: Use restgdf.get_config() and restgdf.Config. This shim constructs a Settings from the cached Config and emits a single DeprecationWarning per process.

Migration helpers

Compatibility helpers for the 1.x → 2.x migration.

Downstream code that indexed the legacy dict-based public surface (for example metadata["name"], crawl_result["services"]) needs a short-term way to keep working during its own upgrade window. These helpers convert the 2.x pydantic models back into plain Python structures on demand.

They are migration aids, not the primary API — prefer direct attribute access (metadata.name) and model_dump() in new code. These helpers will stay available for the 2.x series but may be removed in 3.x.

restgdf.compat.as_dict(obj)[source]

Return a plain Python dict view of a restgdf pydantic model.

If obj is a pydantic.BaseModel instance, returns obj.model_dump(mode="python", by_alias=False) — a dict keyed by the model’s Python (snake_case) field names, with nested models also recursively dumped.

If obj is anything else (already-a-dict, None, primitive, list), it is returned unchanged. This lets migration code wrap heterogeneous values uniformly:

for entry in report.services:
    row = as_dict(entry)   # dict whether entry is model or already dict
    save(row["name"], row.get("url"))

This helper is intentionally conservative: it does not recurse into containers of models and does not coerce by_alias=True. Callers that need the ArcGIS-native camelCase round-trip should call model_dump() explicitly.

restgdf.compat.as_json_dict(obj)[source]

Return a JSON-safe dict view of a restgdf pydantic model.

Like as_dict(), but uses model_dump(mode="json") so every nested value is a JSON-serializable primitive (SecretStr"**********" placeholder, datetime → ISO string, etc.). Handy for structured logging of a model without carrying unserializable objects into the log record.

Non-model values are returned unchanged.