Source code for restgdf.directory.directory

import aiohttp
from typing import Optional, Union

from restgdf._models.crawl import CrawlReport, CrawlServiceEntry
from restgdf._models.responses import LayerMetadata
from restgdf.utils.getinfo import get_metadata
from restgdf.utils.crawl import fetch_all_data, safe_crawl  # noqa: F401
from restgdf.utils.token import ArcGISTokenSession


[docs] class Directory: """A class for interacting with ArcGIS Server directories. Attributes ---------- metadata : Optional[restgdf.LayerMetadata] Pydantic-validated root metadata populated by :meth:`prep`. ``None`` until ``prep`` (or :meth:`from_url`) has run. services : Optional[list[restgdf.CrawlServiceEntry]] Services discovered by the most recent :meth:`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 :meth:`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 :meth:`crawl` call. Use this when you need to inspect failures that were silently captured instead of raised. """ def __init__( self, url: str, session: Union[aiohttp.ClientSession, ArcGISTokenSession], token: Optional[str] = None, ): """A class for interacting with ArcGIS Server directories.""" self.url = url self.session = session self.token = token self.services: Optional[list[CrawlServiceEntry]] = None self.services_with_feature_count: Optional[list[CrawlServiceEntry]] = None self.metadata: Optional[LayerMetadata] = None self.report: Optional[CrawlReport] = None
[docs] async def prep(self): raw = await get_metadata(self.url, self.session, self.token) self.metadata = ( raw if isinstance(raw, LayerMetadata) else LayerMetadata.model_validate(raw) )
[docs] @classmethod async def from_url(cls, url: str, **kwargs) -> "Directory": """Create a Directory object from a url.""" self = cls(url, **kwargs) await self.prep() return self
[docs] async def crawl( self, return_feature_count: bool = False, ) -> list[CrawlServiceEntry]: if return_feature_count: if self.services_with_feature_count is None: report = await safe_crawl( self.session, self.url, self.token, return_feature_count=True, ) self.report = report self.services_with_feature_count = report.services self.services = self.services_with_feature_count return self.services_with_feature_count if self.services is None: report = await safe_crawl( self.session, self.url, self.token, return_feature_count=False, ) self.report = report self.services = report.services return self.services
[docs] def filter_directory_layers(self, layer_type: str) -> list[LayerMetadata]: if self.services is None: raise ValueError("You must call .crawl() before filtering layers.") matched: list[LayerMetadata] = [] for service in self.services: service_metadata = service.metadata if service_metadata is None: continue for layer in service_metadata.layers or []: if layer.type == layer_type: matched.append(layer) return matched
[docs] def feature_layers(self) -> list[LayerMetadata]: return self.filter_directory_layers("Feature Layer")
[docs] def rasters(self) -> list[LayerMetadata]: return self.filter_directory_layers("Raster Layer")