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/base.py ADDED
@@ -0,0 +1,262 @@
1
+ from typing import Any, List, Dict, Callable, TYPE_CHECKING, Union
2
+ from urllib.parse import urljoin, urlencode
3
+ from datetime import datetime
4
+
5
+ from ..utils import clean_data
6
+ from ..base import Base as SyncBase
7
+
8
+ if TYPE_CHECKING:
9
+ from .user import User
10
+ from .task import Task
11
+ from . import AsyncGeoboxClient
12
+
13
+
14
+ class AsyncBase(SyncBase):
15
+ BASE_ENDPOINT = ''
16
+
17
+ def __init__(self, api, **kwargs):
18
+ """
19
+ Initialize the Base class.
20
+
21
+ Args:
22
+ api (AsyncGeoboxClient): The AsyncGeoboxClient client
23
+ uuid (str, optional): The UUID of the resource
24
+ data (dict, optional): The data of the resource
25
+ """
26
+ super().__init__(api, **kwargs)
27
+
28
+
29
+ @classmethod
30
+ async def _get_list(cls, api: 'AsyncGeoboxClient', endpoint: str, params: dict = {},
31
+ factory_func: Callable = None, geojson: bool = False) -> Union[List['Base'], int]:
32
+ """Get a list of resources with optional filtering and pagination"""
33
+ query_string = urlencode(clean_data(params)) if params else ''
34
+ endpoint = urljoin(endpoint, f'?{query_string}')
35
+ response = await api.get(endpoint)
36
+
37
+ if params.get('return_count'):
38
+ return cls._get_count(response)
39
+
40
+ if not response:
41
+ return []
42
+
43
+ if geojson:
44
+ return cls._handle_geojson_response(api, response, factory_func)
45
+
46
+ return [factory_func(api, item) for item in response]
47
+
48
+
49
+ @classmethod
50
+ async def _get_list_by_ids(cls, api: 'AsyncGeoboxClient', endpoint: str, params: dict = None, factory_func: Callable = None) -> List['Base']:
51
+ """
52
+ Internal method to get a list of resources by their IDs.
53
+
54
+ Args:
55
+ api (AsyncGeoboxClient): The AsyncGeoboxClient client
56
+ endpoint (str): The endpoint of the resource
57
+ params (dict): Additional parameters for filtering and pagination
58
+ factory_func (Callable): A function to create the resource object
59
+
60
+ Returns:
61
+ List[Base]: The list of resource objects
62
+ """
63
+ params = clean_data(params)
64
+ query_string = urlencode(params)
65
+ endpoint = urljoin(endpoint, f'?{query_string}')
66
+ response = await api.get(endpoint)
67
+ return [factory_func(api, item) for item in response]
68
+
69
+
70
+ @classmethod
71
+ async def _get_detail(cls, api: 'AsyncGeoboxClient', endpoint: str, uuid: str, params: dict = {}, factory_func: Callable = None) -> 'Base':
72
+ """
73
+ Internal method to get a single resource by UUID.
74
+
75
+ Args:
76
+ api (AsyncGeoboxClient): The AsyncGeoboxClient client
77
+ uuid (str): The UUID of the resource
78
+ params (dict): Additional parameters for filtering and pagination
79
+ factory_func (Callable): A function to create the resource object
80
+
81
+ Returns:
82
+ Base: The resource object
83
+ """
84
+ query_strings = urlencode(clean_data(params))
85
+ endpoint = urljoin(endpoint, f'{uuid}/?{query_strings}')
86
+ response = await api.get(endpoint)
87
+ return factory_func(api, response)
88
+
89
+
90
+ @classmethod
91
+ async def _create(cls, api: 'AsyncGeoboxClient', endpoint: str, data: dict, factory_func: Callable = None) -> 'Base':
92
+ """
93
+ Internal method to create a resource.
94
+
95
+ Args:
96
+ api (AsyncGeoboxClient): The AsyncGeoboxClient client
97
+ data (dict): The data to create the resource with
98
+ factory_func (Callable): A function to create the resource object
99
+
100
+ Returns:
101
+ Base: The created resource object
102
+ """
103
+ data = clean_data(data)
104
+ response = await api.post(endpoint, data)
105
+ return factory_func(api, response)
106
+
107
+
108
+ async def _update(self, endpoint: str, data: dict, clean: bool = True) -> Dict:
109
+ """
110
+ Update the resource.
111
+
112
+ Args:
113
+ data (dict): The data to update the resource with
114
+ """
115
+ if clean:
116
+ data = clean_data(data)
117
+
118
+ response = await self.api.put(endpoint, data)
119
+ self._update_properties(response)
120
+ return response
121
+
122
+
123
+ async def delete(self, endpoint: str) -> None:
124
+ """
125
+ Delete the resource.
126
+ """
127
+ await self.api.delete(endpoint)
128
+ self.uuid = None
129
+ self.endpoint = None
130
+
131
+
132
+ async def _share(self, endpoint: str, users: List['User']) -> None:
133
+ """
134
+ Internal method to share the resource with the given user IDs.
135
+
136
+ Args:
137
+ users (List[User]): The user objects to share the resource with
138
+ """
139
+ data = {"user_ids": [user.user_id for user in users]}
140
+ endpoint = urljoin(endpoint, f'share/')
141
+ await self.api.post(endpoint, data, is_json=False)
142
+
143
+
144
+ async def _unshare(self, endpoint: str, users: List['User']) -> None:
145
+ """
146
+ Internal method to unshare the resource with the given user IDs.
147
+
148
+ Args:
149
+ users (List[User]): The user objects to unshare the resource with
150
+ """
151
+ data = {"user_ids": [user.user_id for user in users]}
152
+ endpoint = urljoin(endpoint, f'unshare/')
153
+ await self.api.post(endpoint, data, is_json=False)
154
+
155
+
156
+ async def _get_shared_users(self, endpoint: str, params: dict = None) -> List['User']:
157
+ """
158
+ Internal method to get the users that the resource is shared with.
159
+
160
+ Args:
161
+ endpoint (str): resource endpoint
162
+ params (dict): Additional parameters for filtering and pagination
163
+
164
+ Returns:
165
+ List[User]: The users that the resource is shared with
166
+ """
167
+ from .user import User
168
+
169
+ params = clean_data(params)
170
+ query_strings = urlencode(params)
171
+ endpoint = urljoin(endpoint, f'shared-with-users/?{query_strings}')
172
+ response = await self.api.get(endpoint)
173
+ return [User(self.api, item['id'], item) for item in response]
174
+
175
+
176
+ async def _get_settings(self, endpoint: str) -> Dict:
177
+ """
178
+ Internal method to get the settings of the resource.
179
+
180
+ Args:
181
+ endpoint (str): The endpoint of the resource
182
+ """
183
+ endpoint = urljoin(endpoint, f'settings/?f=json')
184
+ return await self.api.get(endpoint)
185
+
186
+
187
+ async def _set_settings(self, endpoint: str, data: dict) -> None:
188
+ """
189
+ Internal method to set the settings of the resource.
190
+
191
+ Args:
192
+ endpoint (str): The endpoint of the resource
193
+ data (dict): The data to set the settings with
194
+ """
195
+ endpoint = urljoin(endpoint, f'settings/')
196
+ return await self.api.put(endpoint, data)
197
+
198
+
199
+ async def _get_task(self, response, error_message: str) -> List['Task']:
200
+ from .task import Task # avoid circular dependency
201
+
202
+ if len(response) == 1 and isinstance(response, list) and response[0].get('task_id'):
203
+ result = [await self.api.get_task(response[0].get('task_id'))]
204
+ elif len(response) == 2 and isinstance(response, list) and (response[0].get('task_id') and response[1].get('task_id')):
205
+ result = [await self.api.get_task(item.get('task_id')) for item in response]
206
+ elif len(response) == 1 and isinstance(response, dict) and response.get('task_id'):
207
+ result = [await self.api.get_task(response.get('task_id'))]
208
+ else:
209
+ raise ValueError(error_message)
210
+
211
+ return result
212
+
213
+
214
+ async def _seed_cache(self, endpoint: str, data: dict) -> List['Task']:
215
+ """
216
+ Internal method to cache seed the resource.
217
+
218
+ Args:
219
+ endpoint (str): The endpoint of the resource
220
+ data (dict): The data to cache seed with
221
+ """
222
+ if data['workers'] not in [1, 2, 4, 8, 12, 16, 20, 24]:
223
+ raise ValueError("workers must be in [1, 2, 4, 8, 12, 16, 20, 24]")
224
+
225
+ data = clean_data(data)
226
+ endpoint = urljoin(endpoint, f'cache/seed/')
227
+ response = await self.api.post(endpoint, data)
228
+ return await self._get_task(response, 'Failed to seed cache')
229
+
230
+ async def _clear_cache(self, endpoint: str) -> None:
231
+ """
232
+ Internal method to clear the cache of the resource.
233
+
234
+ Args:
235
+ endpoint (str): The endpoint of the resource
236
+ """
237
+ endpoint = urljoin(endpoint, f'cache/clear/')
238
+ await self.api.post(endpoint)
239
+
240
+
241
+ async def _cache_size(self, endpoint: str) -> int:
242
+ """
243
+ Internal method to get the size of the cache of the resource.
244
+
245
+ Args:
246
+ endpoint (str): The endpoint of the resource
247
+ """
248
+ endpoint = urljoin(endpoint, f'cache/size/')
249
+ return await self.api.post(endpoint)
250
+
251
+
252
+ async def _update_cache(self, endpoint: str, data: Dict = {}) -> List['Task']:
253
+ """
254
+ Internal method to update the cache of the resource.
255
+
256
+ Args:
257
+ endpoint (str): The endpoint of the resource
258
+ """
259
+ data = clean_data(data)
260
+ endpoint = urljoin(endpoint, 'cache/update/')
261
+ response = await self.api.post(endpoint, data)
262
+ return await self._get_task(response, 'Failed to update cache')
geobox/aio/basemap.py ADDED
@@ -0,0 +1,196 @@
1
+ from typing import List, Dict, Optional, TYPE_CHECKING
2
+ from urllib.parse import urljoin, urlencode
3
+
4
+ from .base import AsyncBase
5
+ from ..exception import NotFoundError
6
+ from ..utils import clean_data
7
+
8
+ if TYPE_CHECKING:
9
+ from . import AsyncGeoboxClient
10
+ from ..api import GeoboxClient as SyncGeoboxClient
11
+ from ..basemap import Basemap as SyncBasemap
12
+
13
+
14
+ class Basemap(AsyncBase):
15
+
16
+ BASE_ENDPOINT = 'basemaps/'
17
+
18
+ def __init__(self,
19
+ api: 'AsyncGeoboxClient',
20
+ data: Optional[Dict] = {}):
21
+ """
22
+ Initialize a basemap instance.
23
+
24
+ Args:
25
+ api (AsyncGeoboxClient): The AsyncGeoboxClient instance for making requests.
26
+ data (Dict): The data of the basemap.
27
+ """
28
+ super().__init__(api, data=data)
29
+ self.endpoint = f"{self.BASE_ENDPOINT}{self.data.get('name')}/"
30
+
31
+
32
+ @classmethod
33
+ async def get_basemaps(cls, api: 'AsyncGeoboxClient') -> List['Basemap']:
34
+ """
35
+ [async] Get a list of basemaps
36
+
37
+ Args:
38
+ api (AsyncGeoboxClient): The AsyncGeoboxClient instance for making requests.
39
+
40
+ Returns:
41
+ List[BaseMap]: list of basemaps.
42
+
43
+ Example:
44
+ >>> from geobox.aio import AsyncGeoboxClient
45
+ >>> from geobox.aio.basemap import Basemap
46
+ >>> async with AsyncGeoboxClient() as client:
47
+ >>> basemaps = await Basemap.get_basemaps(client)
48
+ or
49
+ >>> basemaps = await client.get_basemaps()
50
+ """
51
+ response = await api.get(cls.BASE_ENDPOINT)
52
+ if not response:
53
+ return []
54
+
55
+ items = []
56
+ for item in response:
57
+ response[item]['name'] = item
58
+ items.append(response[item])
59
+
60
+ return [cls(api, item) for item in items]
61
+
62
+
63
+ @classmethod
64
+ async def get_basemap(cls, api: 'AsyncGeoboxClient', name: str) -> 'Basemap':
65
+ """
66
+ [async] Get a basemap object
67
+
68
+ Args:
69
+ api (AsyncGeoboxClient): The AsyncGeoboxClient instance for making requests.
70
+ name: the basemap name
71
+
72
+ Returns:
73
+ Basemap: the basemap object
74
+
75
+ Raises:
76
+ NotFoundError: if the base,ap with the specified name not found
77
+
78
+ Example:
79
+ >>> from geobox.aio import AsyncGeoboxClient
80
+ >>> from geobox.aio.basemap import Basemap
81
+ >>> async with AsyncGeoboxClient() as client:
82
+ >>> basemap = await Basemap.get_basemap(client, name='test')
83
+ or
84
+ >>> basemap = await client.get_basemap(name='test')
85
+ """
86
+ response = await cls.get_basemaps(api)
87
+ basemap = [basemap for basemap in response if basemap.name == name]
88
+ if not basemap:
89
+ raise NotFoundError(f'Basemap with name "{name}" not found.')
90
+
91
+ return basemap[0]
92
+
93
+
94
+ @property
95
+ def thumbnail(self) -> str:
96
+ """
97
+ Get the thumbnail url of the basemap
98
+
99
+ Returns:
100
+ str: the thumbnail url
101
+ """
102
+ return super().thumbnail()
103
+
104
+
105
+ @property
106
+ def wmts(self) -> str:
107
+ """
108
+ Get the wmts url of the basemap
109
+
110
+ Returns:
111
+ str: the wmts url
112
+ """
113
+ endpoint = urljoin(self.api.base_url, f'{self.endpoint}wmts/')
114
+
115
+ if not self.api.access_token and self.api.apikey:
116
+ endpoint = f"{endpoint}?apikey={self.api.apikey}"
117
+
118
+ return endpoint
119
+
120
+
121
+ @property
122
+ async def server_url(self) -> str:
123
+ """
124
+ [async] Get the server url of the basemap
125
+
126
+ Returns:
127
+ str: the server url
128
+ """
129
+ endpoint = f'{self.api.base_url}{self.BASE_ENDPOINT}server_url'
130
+ return await self.api.get(endpoint)
131
+
132
+
133
+ @property
134
+ async def proxy_url(self) -> str:
135
+ """
136
+ [async] Get the proxy url of the basemap
137
+
138
+ Returns:
139
+ str: the proxy url
140
+ """
141
+ endpoint = f'{self.api.base_url}{self.BASE_ENDPOINT}proxy_url'
142
+ return await self.api.get(endpoint)
143
+
144
+
145
+ @classmethod
146
+ async def proxy_basemap(cls, api: 'response', url: str) -> None:
147
+ """
148
+ [async] Proxy the basemap
149
+
150
+ Args:
151
+ api (GeoboxClient): The GeoboxClient instance for making requests.
152
+ url (str): the proxy server url.
153
+
154
+ Returns:
155
+ None
156
+
157
+ Example:
158
+ >>> from geobox.aio import AsyncGeoboxClient
159
+ >>> from geobox.aio.basemap import Basemap
160
+ >>> async with AsyncGeoboxClient() as client:
161
+ >>> await Basemap.proxy_basemap(client, url='proxy_server_url')
162
+ or
163
+ >>> await client.proxy_basemap(url='proxy_server_url')
164
+ """
165
+ param = clean_data({
166
+ 'url': url
167
+ })
168
+ query_string = urlencode(param)
169
+ endpoint = urljoin(cls.BASE_ENDPOINT, f"?{query_string}")
170
+ await api.get(endpoint)
171
+
172
+
173
+ def to_sync(self, sync_client: 'SyncGeoboxClient') -> 'SyncBasemap':
174
+ """
175
+ Switch to sync version of the basemap instance to have access to the sync methods
176
+
177
+ Args:
178
+ sync_client (SyncGeoboxClient): The sync version of the GeoboxClient instance for making requests.
179
+
180
+ Returns:
181
+ geobox.basemap.Basemap: the sync instance of the basemap.
182
+
183
+ Example:
184
+ >>> from geobox import Geoboxclient
185
+ >>> from geobox.aio import AsyncGeoboxClient
186
+ >>> from geobox.aio.basemap import Basemap
187
+ >>> client = GeoboxClient()
188
+ >>> async with AsyncGeoboxClient() as async_client:
189
+ >>> basemap = await Basemap.get_basemap(async_client, name='test')
190
+ or
191
+ >>> basemap = await async_client.get_basemap(name='test')
192
+ >>> sync_basemap = basemap.to_sync(client)
193
+ """
194
+ from ..basemap import Basemap as SyncBasemap
195
+
196
+ return SyncBasemap(api=sync_client, data=self.data)