geobox 1.4.2__py3-none-any.whl → 2.0.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. geobox/__init__.py +2 -2
  2. geobox/aio/__init__.py +63 -0
  3. geobox/aio/api.py +2640 -0
  4. geobox/aio/apikey.py +263 -0
  5. geobox/aio/attachment.py +339 -0
  6. geobox/aio/base.py +262 -0
  7. geobox/aio/basemap.py +196 -0
  8. geobox/aio/dashboard.py +342 -0
  9. geobox/aio/feature.py +527 -0
  10. geobox/aio/field.py +321 -0
  11. geobox/aio/file.py +522 -0
  12. geobox/aio/layout.py +341 -0
  13. geobox/aio/log.py +145 -0
  14. geobox/aio/map.py +1034 -0
  15. geobox/aio/model3d.py +415 -0
  16. geobox/aio/mosaic.py +696 -0
  17. geobox/aio/plan.py +315 -0
  18. geobox/aio/query.py +693 -0
  19. geobox/aio/raster.py +869 -0
  20. geobox/aio/route.py +63 -0
  21. geobox/aio/scene.py +342 -0
  22. geobox/aio/settings.py +194 -0
  23. geobox/aio/task.py +402 -0
  24. geobox/aio/tile3d.py +339 -0
  25. geobox/aio/tileset.py +672 -0
  26. geobox/aio/usage.py +243 -0
  27. geobox/aio/user.py +507 -0
  28. geobox/aio/vectorlayer.py +1363 -0
  29. geobox/aio/version.py +273 -0
  30. geobox/aio/view.py +983 -0
  31. geobox/aio/workflow.py +341 -0
  32. geobox/api.py +14 -15
  33. geobox/apikey.py +28 -1
  34. geobox/attachment.py +27 -1
  35. geobox/base.py +4 -4
  36. geobox/basemap.py +30 -1
  37. geobox/dashboard.py +27 -0
  38. geobox/feature.py +33 -13
  39. geobox/field.py +33 -21
  40. geobox/file.py +40 -46
  41. geobox/layout.py +28 -1
  42. geobox/log.py +31 -7
  43. geobox/map.py +34 -2
  44. geobox/model3d.py +31 -37
  45. geobox/mosaic.py +28 -7
  46. geobox/plan.py +29 -3
  47. geobox/query.py +39 -14
  48. geobox/raster.py +26 -13
  49. geobox/scene.py +26 -0
  50. geobox/settings.py +30 -1
  51. geobox/task.py +28 -6
  52. geobox/tile3d.py +27 -1
  53. geobox/tileset.py +26 -5
  54. geobox/usage.py +32 -1
  55. geobox/user.py +62 -6
  56. geobox/utils.py +34 -0
  57. geobox/vectorlayer.py +40 -4
  58. geobox/version.py +25 -1
  59. geobox/view.py +37 -17
  60. geobox/workflow.py +27 -1
  61. {geobox-1.4.2.dist-info → geobox-2.0.1.dist-info}/METADATA +4 -1
  62. geobox-2.0.1.dist-info/RECORD +68 -0
  63. geobox-1.4.2.dist-info/RECORD +0 -38
  64. {geobox-1.4.2.dist-info → geobox-2.0.1.dist-info}/WHEEL +0 -0
  65. {geobox-1.4.2.dist-info → geobox-2.0.1.dist-info}/licenses/LICENSE +0 -0
  66. {geobox-1.4.2.dist-info → geobox-2.0.1.dist-info}/top_level.txt +0 -0
geobox/aio/field.py ADDED
@@ -0,0 +1,321 @@
1
+ from urllib.parse import urljoin
2
+ from typing import Optional, Dict, TYPE_CHECKING, Any
3
+
4
+ from .base import AsyncBase
5
+ from ..utils import clean_data
6
+ from ..enums import FieldType
7
+
8
+ if TYPE_CHECKING:
9
+ from .api import AsyncGeoboxClient
10
+ from .vectorlayer import VectorLayer
11
+ from ..api import GeoboxClient as SyncGeoboxClient
12
+ from ..field import Field as SyncField
13
+
14
+
15
+ class Field(AsyncBase):
16
+
17
+ def __init__(self,
18
+ layer: 'VectorLayer',
19
+ data_type: 'FieldType',
20
+ field_id: int = None,
21
+ data: Optional[Dict] = {}):
22
+ """
23
+ Constructs all the necessary attributes for the Field object.
24
+
25
+ Args:
26
+ layer (VectorLayer): The vector layer that the field belongs to.
27
+ data_type (FieldType): type of the field
28
+ field_id (int): the id of the field
29
+ data (Dict, optional): The data of the field.
30
+ """
31
+ super().__init__(api=layer.api, data=data)
32
+ self.layer = layer
33
+ self.field_id = field_id
34
+ if not isinstance(data_type, FieldType):
35
+ raise ValueError("data_type must be a FieldType instance")
36
+ self.data_type = data_type
37
+ self.endpoint = urljoin(layer.endpoint, f'fields/{self.id}/') if self.data.get('id') else None
38
+
39
+
40
+ def __repr__(self) -> str:
41
+ """
42
+ Return a string representation of the field.
43
+
44
+ Returns:
45
+ str: The string representation of the field.
46
+ """
47
+ return f"Field(id={self.id}, name={self.name}, data_type={self.data_type})"
48
+
49
+
50
+ def __getattr__(self, name: str) -> Any:
51
+ """
52
+ Get an attribute from the resource.
53
+
54
+ Args:
55
+ name (str): The name of the attribute
56
+ """
57
+ if name == 'datatype':
58
+ return FieldType(self.data['datatype'])
59
+ return super().__getattr__(name)
60
+
61
+
62
+ @property
63
+ def domain(self) -> Dict:
64
+ """
65
+ Domain property
66
+
67
+ Returns:
68
+ Dict: domain data
69
+ """
70
+ return self.data.get('domain')
71
+
72
+
73
+ @domain.setter
74
+ def domain(self, value: Dict) -> None:
75
+ """
76
+ Domain property setter
77
+
78
+ Returns:
79
+ None
80
+ """
81
+ self.data['domain'] = value
82
+
83
+
84
+ @classmethod
85
+ async def create_field(cls, api: 'AsyncGeoboxClient', layer: 'VectorLayer', name: str, data_type: 'FieldType', data: Dict = {}) -> 'Field':
86
+ """
87
+ [async] Create a new field
88
+
89
+ Args:
90
+ api (AsyncGeoboxClient): The AsyncGeoboxClient instance for making requests.
91
+ layer (VectorLayer): field's layer
92
+ name (str): name of the field
93
+ data_type (FieldType): type of the field
94
+ data (Dict, optional): the data of the field
95
+
96
+ Returns:
97
+ Field: the created field object
98
+
99
+ Example:
100
+ >>> from geobox.aio import AsyncGeoboxClient
101
+ >>> from geobox.aio.vectorlayer import VectorLayer
102
+ >>> from geobox.aio.field import Field
103
+ >>> async with AsyncGeoboxClient() as client:
104
+ >>> layer = await client.get_layer(uuid="12345678-1234-5678-1234-567812345678")
105
+ >>> field = await Field.create_field(client, layer=layer, name='test', data_type=FieldType.Integer)
106
+ """
107
+ data.update({
108
+ "name": name,
109
+ "datatype": data_type.value
110
+ })
111
+ endpoint = urljoin(layer.endpoint, 'fields/')
112
+ return await super()._create(api, endpoint, data, factory_func=lambda api, item: Field(layer, data_type, item['id'], item))
113
+
114
+
115
+ async def save(self) -> None:
116
+ """
117
+ [async] Save the field. Creates a new field if field_id is None, updates existing field otherwise.
118
+
119
+ Returns:
120
+ None
121
+
122
+ Example:
123
+ >>> from geobox.aio import AsyncGeoboxClient
124
+ >>> from geobox.aio.field import Field
125
+ >>> async with AsyncGeoboxClient() as client:
126
+ >>> layer = await client.get_vector(uuid="12345678-1234-5678-1234-567812345678")
127
+ >>> field = Field(layer=layer, data_type=FieldType.String)
128
+ >>> await field.save()
129
+ """
130
+ data = clean_data({
131
+ "name": self.name,
132
+ "datatype": FieldType(self.data_type).value,
133
+ "display_name": self.data.get("display_name"),
134
+ "description": self.data.get("description"),
135
+ "domain": self.data.get("domain"),
136
+ "width": self.data.get("width"),
137
+ "hyperlink": self.data.get("hyperlink")
138
+ })
139
+
140
+ try:
141
+ if self.id:
142
+ response = await self.layer.api.put(self.endpoint, data)
143
+ except AttributeError:
144
+ endpoint = urljoin(self.layer.endpoint, 'fields/')
145
+ response = await self.layer.api.post(endpoint, data)
146
+ self.id = response['id']
147
+ self.endpoint = urljoin(self.layer.endpoint, f'fields/{self.id}/')
148
+
149
+ self._update_properties(response)
150
+
151
+
152
+ async def delete(self) -> None:
153
+ """
154
+ [async] Delete the field.
155
+
156
+ Returns:
157
+ None
158
+
159
+ Example:
160
+ >>> from geobox.aio import AsyncGeoboxClient
161
+ >>> from geobox.aio.field import Field
162
+ >>> async with AsyncGeoboxClient() as client:
163
+ >>> layer = await client.get_vector(uuid="12345678-1234-5678-1234-567812345678")
164
+ >>> field = await layer.get_field(name='test')
165
+ >>> await field.delete()
166
+ """
167
+ await super().delete(self.endpoint)
168
+ self.field_id = None
169
+
170
+
171
+ async def update(self, **kwargs) -> Dict:
172
+ """
173
+ [async] Update the field.
174
+
175
+ Keyword Args:
176
+ name (str): The name of the field.
177
+ display_name (str): The display name of the field.
178
+ description (str): The description of the field.
179
+ domain (Dict): the domain of the field
180
+ width (int): The width of the field.
181
+ hyperlink (bool): the hyperlink field.
182
+
183
+ Returns:
184
+ Dict: The updated data.
185
+
186
+ Example:
187
+ >>> from geobox.aio import AsyncGeoboxClient
188
+ >>> from geobox.aio.field import Field
189
+ >>> async with AsyncGeoboxClient() as client:
190
+ >>> layer = await client.get_vector(uuid="12345678-1234-5678-1234-567812345678")
191
+ >>> field = await layer.get_field(name='test')
192
+ >>> field.update(name="my_field", display_name="My Field", description="My Field Description")
193
+ """
194
+ data = {
195
+ "name": kwargs.get('name'),
196
+ "display_name": kwargs.get('display_name'),
197
+ "description": kwargs.get('description'),
198
+ "domain": kwargs.get('domain'),
199
+ "hyperlink": kwargs.get('hyperlink')
200
+ }
201
+ return await super()._update(self.endpoint, data)
202
+
203
+
204
+ async def get_field_unique_values(self) -> Dict:
205
+ """
206
+ [async] Get the unique values of the field.
207
+
208
+ Returns:
209
+ Dict: The response data.
210
+
211
+ Example:
212
+ >>> from geobox.aio import AsyncGeoboxClient
213
+ >>> from geobox.aio.field import Field
214
+ >>> async with AsyncGeoboxClient() as client:
215
+ >>> layer = await client.get_vector(uuid="12345678-1234-5678-1234-567812345678")
216
+ >>> field = await layer.get_field(name='test')
217
+ >>> await field.get_field_unique_values()
218
+ """
219
+ endpoint = urljoin(self.endpoint, 'distinct/')
220
+ return await self.layer.api.get(endpoint)
221
+
222
+
223
+ async def get_field_unique_values_numbers(self) -> int:
224
+ """
225
+ [async] Get the count of unique values of the field.
226
+
227
+ Returns:
228
+ int: The count of the field unique values.
229
+
230
+ Example:
231
+ >>> from geobox.aio import AsyncGeoboxClient
232
+ >>> from geobox.aio.field import Field
233
+ >>> async with AsyncGeoboxClient() as client:
234
+ >>> layer = await client.get_vector(uuid="12345678-1234-5678-1234-567812345678")
235
+ >>> field = awaitlayer.get_field(name='test')
236
+ >>> await field.get_field_unique_values_numbers()
237
+ """
238
+ endpoint = urljoin(self.endpoint, 'distinctCount/')
239
+ return await self.layer.api.get(endpoint)
240
+
241
+
242
+ async def get_field_statistic(self, func: str) -> Dict:
243
+ """
244
+ [async] Get the statistic of the field.
245
+
246
+ Args:
247
+ func (str): The function to apply to the field. values are: min, max, avg
248
+
249
+ Returns:
250
+ Dict: The response data.
251
+
252
+ Example:
253
+ >>> from geobox.aio import AsyncGeoboxClient
254
+ >>> from geobox.aio.field import Field
255
+ >>> async with AsyncGeoboxClient() as client:
256
+ >>> layer = await client.get_vector(uuid="12345678-1234-5678-1234-567812345678")
257
+ >>> field = await layer.get_field(name='test')
258
+ >>> await field.get_field_statistic(func='avg')
259
+ """
260
+ endpoint = urljoin(self.endpoint, f'stats/?func_type={func}')
261
+ return await self.layer.api.get(endpoint)
262
+
263
+
264
+ async def update_domain(self, range_domain: Dict = None, list_domain: Dict = None) -> Dict:
265
+ """
266
+ [async] Update field domian values
267
+
268
+ Args:
269
+ range_domain (Dict): a dictionary with min and max keys.
270
+ list_domain (Dict): a dictionary containing the domain codes and values.
271
+
272
+ Returns:
273
+ Dict: the updated field domain
274
+
275
+ Example:
276
+ >>> from geobox.aio import AsyncGeoboxClient
277
+ >>> async with AsyncGeoboxClient() as client:
278
+ >>> field = await client.get_vector(uuid="12345678-1234-5678-1234-567812345678").get_fields()[0]
279
+ >>> range_d = {'min': 1, 'max': 10}
280
+ >>> list_d = {'1': 'value1', '2': 'value2'}
281
+ >>> await field.update_domain(range_domain = range_d, list_domain=list_d)
282
+ {'min': 1, 'max': 10, 'items: {'1': 'value1', '2': 'value2'}}
283
+ """
284
+ if not self.domain:
285
+ self.domain = {'min': None, 'max': None, 'items': {}}
286
+
287
+ if range_domain:
288
+ self.domain['min'] = range_domain['min']
289
+ self.domain['max'] = range_domain['max']
290
+
291
+ if list_domain:
292
+ self.domain['items'] = {**self.domain['items'], **list_domain}
293
+
294
+ await self.save()
295
+ return self.domain
296
+
297
+
298
+ def to_sync(self, sync_client: 'SyncGeoboxClient') -> 'SyncField':
299
+ """
300
+ Switch to sync version of the field instance to have access to the sync methods
301
+
302
+ Args:
303
+ sync_client (SyncGeoboxClient): The sync version of the GeoboxClient instance for making requests.
304
+
305
+ Returns:
306
+ geobox.field.Field: the sync instance of the field.
307
+
308
+ Example:
309
+ >>> from geobox import Geoboxclient
310
+ >>> from geobox.aio import AsyncGeoboxClient
311
+ >>> from geobox.aio.field import Field
312
+ >>> client = GeoboxClient()
313
+ >>> async with AsyncGeoboxClient() as async_client:
314
+ >>> layer = await async_client.get_vector(uuid="12345678-1234-5678-1234-567812345678")
315
+ >>> field = await layer.get_field(name='test')
316
+ >>> sync_field = field.to_sync(client)
317
+ """
318
+ from ..field import Field as SyncField
319
+
320
+ sync_layer = self.layer.to_sync(sync_client=sync_client)
321
+ return SyncField(layer=sync_layer, data_type=self.data_type, field_id=self.field_id, data=self.data)