|
1 | | -from collections import OrderedDict |
2 | | -from typing import List, Dict |
| 1 | +from typing import Dict, Iterable, List |
3 | 2 |
|
4 | 3 | from geopandas import GeoDataFrame |
| 4 | +from pandas import DataFrame, concat |
5 | 5 |
|
6 | | -from .base import Base |
| 6 | +from ._base import Base |
7 | 7 | from .layer import Layer |
8 | 8 |
|
9 | 9 |
|
10 | 10 | class Service(Base): |
11 | | - def __init__(self, url, **kwargs): |
12 | | - super(Service, self).__init__(url, **kwargs) |
| 11 | + def __init__(self, url): |
| 12 | + self.url = url |
| 13 | + super(Service, self).__init__(self.url) |
13 | 14 |
|
14 | | - @property |
15 | | - def layers(self) -> List[dict]: |
16 | | - return self.meta['layers'] |
17 | | - |
18 | | - @property |
19 | | - def tables(self) -> List[dict]: |
20 | | - return self.meta['tables'] |
21 | | - |
22 | | - def to_gdfs(self, include_tables: bool = True, **kwargs) -> Dict[str, GeoDataFrame]: |
| 15 | + def layers(self, include_tables: bool = True) -> DataFrame: |
23 | 16 | """ |
24 | | - Export a complete ArcGIS Server Map or Feature service to GeoDataFrames |
| 17 | + Get Service layers. |
25 | 18 |
|
26 | | - :param include_tables: whether to include attribute-only tables |
27 | | - :param kwargs: extra keyword arguments provided to pyesridump's EsriDumper class |
| 19 | + :param include_tables: include Service tables |
28 | 20 | :return: |
29 | 21 | """ |
30 | | - layers = [layer for layer in self.layers if layer['type'] != 'Group Layer'] |
31 | | - gdfs = OrderedDict( |
32 | | - {layer['name']: Layer(f'{self.url}/{layer["id"]}', **kwargs).to_gdf() |
33 | | - for layer in sorted(layers, key=lambda _: _['name'])} |
| 22 | + layers = DataFrame( |
| 23 | + data=[ |
| 24 | + {**layer, "url": f'{self.url}/{layer["id"]}'} |
| 25 | + for layer in self.meta["layers"] |
| 26 | + ] |
34 | 27 | ) |
35 | | - if self.tables and include_tables: |
36 | | - gdfs.update({table['name']: Layer(f'{self.url}/{table["id"]}').to_gdf() for table in self.tables}) |
| 28 | + layers.set_index("id", inplace=True) |
| 29 | + |
| 30 | + if include_tables and self.meta["tables"]: |
| 31 | + tables = DataFrame( |
| 32 | + data=[ |
| 33 | + {**table, "url": f'{self.url}/{table["id"]}'} |
| 34 | + for table in self.meta["tables"] |
| 35 | + ] |
| 36 | + ) |
| 37 | + tables.set_index("id", inplace=True) |
| 38 | + layers = concat([layers, tables]) |
| 39 | + |
| 40 | + return layers |
| 41 | + |
| 42 | + def to_gpkg( |
| 43 | + self, |
| 44 | + filename: str, |
| 45 | + index: bool = True, |
| 46 | + schema: dict = None, |
| 47 | + include_tables: bool = True, |
| 48 | + **kwargs, |
| 49 | + ) -> str: |
| 50 | + """ |
| 51 | + Export an ArcGIS Server Map or Feature service to geopackage |
| 52 | +
|
| 53 | + :param filename: File path or file handle to write to. |
| 54 | + :param index: If True, write index into one or more columns (for MultiIndex). |
| 55 | + Default None writes the index into one or more columns only if |
| 56 | + the index is named, is a MultiIndex, or has a non-integer data |
| 57 | + type. If False, no index is written. |
| 58 | + :param schema: If specified, the schema dictionary is passed to Fiona to |
| 59 | + better control how the file is written. |
| 60 | + :param include_tables: include Service tables |
| 61 | + :param kwargs: extra keyword arguments provided to the EsriDumper class |
| 62 | + :return: provided filename |
| 63 | + """ |
| 64 | + layers = self.layers(include_tables).to_dict(orient="records") |
| 65 | + for layer in layers: |
| 66 | + if layer["type"] in self._supported_types: |
| 67 | + Layer(layer["url"], **kwargs).to_gdf().to_file( |
| 68 | + filename, |
| 69 | + driver="GPKG", |
| 70 | + index=index, |
| 71 | + schema=schema, |
| 72 | + layer=layer["name"], |
| 73 | + ) |
| 74 | + return filename |
| 75 | + |
| 76 | + def to_gdfs( |
| 77 | + self, include_tables: bool = True, **kwargs |
| 78 | + ) -> List[Dict[str, GeoDataFrame]]: |
| 79 | + """ |
| 80 | + Export an ArcGIS Server Map or Feature service to GeoDataFrames |
| 81 | +
|
| 82 | + :param include_tables: include Service tables |
| 83 | + :param kwargs: extra keyword arguments provided to the EsriDumper class |
| 84 | + :return: list of dicts with layer names and layer GeoDataFrames |
| 85 | + """ |
| 86 | + layers = self.layers(include_tables).to_dict(orient="records") |
| 87 | + gdfs = [] |
| 88 | + for layer in layers: |
| 89 | + if layer["type"] in self._supported_types: |
| 90 | + gdfs.append( |
| 91 | + { |
| 92 | + "name": layer["name"], |
| 93 | + "gdf": Layer(layer["url"], **kwargs).to_gdf(), |
| 94 | + } |
| 95 | + ) |
37 | 96 | return gdfs |
0 commit comments