geobox 2.1.0__py3-none-any.whl → 2.2.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 (70) hide show
  1. geobox/__init__.py +61 -63
  2. geobox/aio/__init__.py +61 -63
  3. geobox/aio/api.py +491 -574
  4. geobox/aio/apikey.py +263 -263
  5. geobox/aio/attachment.py +341 -339
  6. geobox/aio/base.py +261 -262
  7. geobox/aio/basemap.py +196 -196
  8. geobox/aio/dashboard.py +340 -342
  9. geobox/aio/feature.py +35 -35
  10. geobox/aio/field.py +315 -321
  11. geobox/aio/file.py +72 -72
  12. geobox/aio/layout.py +340 -341
  13. geobox/aio/log.py +23 -23
  14. geobox/aio/map.py +1033 -1034
  15. geobox/aio/model3d.py +415 -415
  16. geobox/aio/mosaic.py +696 -696
  17. geobox/aio/plan.py +314 -314
  18. geobox/aio/query.py +693 -693
  19. geobox/aio/raster.py +88 -454
  20. geobox/aio/{analysis.py → raster_analysis.py} +153 -170
  21. geobox/aio/route.py +4 -4
  22. geobox/aio/scene.py +340 -342
  23. geobox/aio/settings.py +18 -18
  24. geobox/aio/task.py +404 -402
  25. geobox/aio/tile3d.py +337 -339
  26. geobox/aio/tileset.py +102 -103
  27. geobox/aio/usage.py +52 -51
  28. geobox/aio/user.py +506 -507
  29. geobox/aio/vector_tool.py +1968 -0
  30. geobox/aio/vectorlayer.py +316 -414
  31. geobox/aio/version.py +272 -273
  32. geobox/aio/view.py +1019 -983
  33. geobox/aio/workflow.py +340 -341
  34. geobox/api.py +14 -98
  35. geobox/apikey.py +262 -262
  36. geobox/attachment.py +336 -337
  37. geobox/base.py +384 -384
  38. geobox/basemap.py +194 -194
  39. geobox/dashboard.py +339 -341
  40. geobox/enums.py +31 -1
  41. geobox/feature.py +31 -10
  42. geobox/field.py +320 -320
  43. geobox/file.py +4 -4
  44. geobox/layout.py +339 -340
  45. geobox/log.py +4 -4
  46. geobox/map.py +1031 -1032
  47. geobox/model3d.py +410 -410
  48. geobox/mosaic.py +696 -696
  49. geobox/plan.py +313 -313
  50. geobox/query.py +691 -691
  51. geobox/raster.py +5 -368
  52. geobox/{analysis.py → raster_analysis.py} +108 -128
  53. geobox/scene.py +341 -342
  54. geobox/settings.py +194 -194
  55. geobox/task.py +399 -400
  56. geobox/tile3d.py +337 -338
  57. geobox/tileset.py +4 -4
  58. geobox/usage.py +3 -3
  59. geobox/user.py +503 -503
  60. geobox/vector_tool.py +1968 -0
  61. geobox/vectorlayer.py +5 -110
  62. geobox/version.py +272 -272
  63. geobox/view.py +981 -981
  64. geobox/workflow.py +338 -339
  65. {geobox-2.1.0.dist-info → geobox-2.2.1.dist-info}/METADATA +15 -1
  66. geobox-2.2.1.dist-info/RECORD +72 -0
  67. geobox-2.1.0.dist-info/RECORD +0 -70
  68. {geobox-2.1.0.dist-info → geobox-2.2.1.dist-info}/WHEEL +0 -0
  69. {geobox-2.1.0.dist-info → geobox-2.2.1.dist-info}/licenses/LICENSE +0 -0
  70. {geobox-2.1.0.dist-info → geobox-2.2.1.dist-info}/top_level.txt +0 -0
geobox/aio/map.py CHANGED
@@ -1,1034 +1,1033 @@
1
- from typing import Dict, List, Optional, Union, TYPE_CHECKING
2
- from urllib.parse import urljoin, urlencode
3
-
4
- from .base import AsyncBase
5
- from .model3d import Model
6
- from .file import File
7
- from .feature import Feature
8
- from ..utils import clean_data, join_url_params
9
-
10
- if TYPE_CHECKING:
11
- from . import AsyncGeoboxClient
12
- from .user import User
13
- from .task import Task
14
- from .attachment import Attachment
15
- from ..api import GeoboxClient as SyncGeoboxClient
16
- from ..map import Map as SyncMap
17
-
18
-
19
- class Map(AsyncBase):
20
-
21
- BASE_ENDPOINT = 'maps/'
22
-
23
- def __init__(self,
24
- api: 'AsyncGeoboxClient',
25
- uuid: str,
26
- data: Optional[Dict] = {}):
27
- """
28
- Initialize a Map instance.
29
-
30
- Args:
31
- api (AsyncGeoboxClient): The AsyncGeoboxClient instance for making requests.
32
- name (str): The name of the map.
33
- uuid (str): The unique identifier for the map.
34
- data (Dict, optional): The data of the map.
35
- """
36
- self.map_layers = {
37
- 'layers': []
38
- }
39
- super().__init__(api, uuid=uuid, data=data)
40
-
41
-
42
- @classmethod
43
- async def get_maps(cls, api: 'AsyncGeoboxClient', **kwargs) -> Union[List['Map'], int]:
44
- """
45
- [async] Get list of maps with optional filtering and pagination.
46
-
47
- Args:
48
- api (AsyncGeoboxClient): The AsyncGeoboxClient instance for making requests.
49
-
50
- Keyword Args:
51
- q (str): query filter based on OGC CQL standard. e.g. "field1 LIKE '%GIS%' AND created_at > '2021-01-01'"
52
- search (str): search term for keyword-based searching among search_fields or all textual fields if search_fields does not have value. NOTE: if q param is defined this param will be ignored.
53
- search_fields (str): comma separated list of fields for searching.
54
- order_by (str): comma separated list of fields for sorting results [field1 A|D, field2 A|D, …]. e.g. name A, type D. NOTE: "A" denotes ascending order and "D" denotes descending order.
55
- return_count (bool): Whether to return total count. default is False.
56
- skip (int): Number of items to skip. default is 0.
57
- limit (int): Number of items to return. default is 10.
58
- user_id (int): Specific user. privileges required.
59
- shared (bool): Whether to return shared maps. default is False.
60
-
61
- Returns:
62
- List[Map] | int: A list of Map instances or the total number of maps.
63
-
64
- Example:
65
- >>> from geobox.aio import AsyncGeoboxClient
66
- >>> from geobox.aio.map import Map
67
- >>> async with AsyncGeoboxClient() as client:
68
- >>> maps = await Map.get_maps(client, q="name LIKE '%My Map%'")
69
- or
70
- >>> maps = await client.get_maps(q="name LIKE '%My Map%'")
71
- """
72
- params = {
73
- 'f': 'json',
74
- 'q': kwargs.get('q'),
75
- 'search': kwargs.get('search'),
76
- 'search_fields': kwargs.get('search_fields'),
77
- 'order_by': kwargs.get('order_by'),
78
- 'return_count': kwargs.get('return_count', False),
79
- 'skip': kwargs.get('skip', 0),
80
- 'limit': kwargs.get('limit', 10),
81
- 'user_id': kwargs.get('user_id'),
82
- 'shared': kwargs.get('shared', False)
83
- }
84
- return await super()._get_list(api, cls.BASE_ENDPOINT, params, factory_func=lambda api, item: Map(api, item['uuid'], item))
85
-
86
-
87
- @classmethod
88
- async def create_map(cls,
89
- api: 'AsyncGeoboxClient',
90
- name: str,
91
- display_name: str = None,
92
- description: str = None,
93
- extent: List[float] = None,
94
- thumbnail: str = None,
95
- style: Dict = None,
96
- user_id: int = None) -> 'Map':
97
- """
98
- [async] Create a new map.
99
-
100
- Args:
101
- api (AsyncGeoboxClient): The AsyncGeoboxClient instance for making requests.
102
- name (str): The name of the map.
103
- display_name (str, optional): The display name of the map.
104
- description (str, optional): The description of the map.
105
- extent (List[float], optional): The extent of the map.
106
- thumbnail (str, optional): The thumbnail of the map.
107
- style (Dict, optional): The style of the map.
108
- user_id (int, optional): Specific user. privileges required.
109
-
110
- Returns:
111
- Map: The newly created map instance.
112
-
113
- Raises:
114
- ValidationError: If the map data is invalid.
115
-
116
- Example:
117
- >>> from geobox.aio import AsyncGeoboxClient
118
- >>> from geobox.aio.map import Map
119
- >>> async with AsyncGeoboxClient() as client:
120
- >>> map = await Map.create_map(client, name="my_map", display_name="My Map", description="This is a description of my map", extent=[10, 20, 30, 40], thumbnail="https://example.com/thumbnail.png", style={"type": "style"})
121
- or
122
- >>> map = await client.create_map(name="my_map", display_name="My Map", description="This is a description of my map", extent=[10, 20, 30, 40], thumbnail="https://example.com/thumbnail.png", style={"type": "style"})
123
- """
124
- data = {
125
- "name": name,
126
- "display_name": display_name,
127
- "description": description,
128
- "extent": extent,
129
- "thumbnail": thumbnail,
130
- "style": style,
131
- "user_id": user_id,
132
- }
133
- return await super()._create(api, cls.BASE_ENDPOINT, data, factory_func=lambda api, item: Map(api, item['uuid'], item))
134
-
135
-
136
- @classmethod
137
- async def get_map(cls, api: 'AsyncGeoboxClient', uuid: str, user_id: int = None) -> 'Map':
138
- """
139
- [async] Get a map by its UUID.
140
-
141
- Args:
142
- api (AsyncGeoboxClient): The AsyncGeoboxClient instance for making requests.
143
- uuid (str): The UUID of the map to get.
144
- user_id (int, optional): Specific user. privileges required.
145
-
146
- Returns:
147
- Map: The map object.
148
-
149
- Raises:
150
- NotFoundError: If the map with the specified UUID is not found.
151
-
152
- Example:
153
- >>> from geobox.aio import AsyncGeoboxClient
154
- >>> from geobox.aio.map import Map
155
- >>> async with AsyncGeoboxClient() as client:
156
- >>> map = await Map.get_map(client, uuid="12345678-1234-5678-1234-567812345678")
157
- or
158
- >>> map = await client.get_map(uuid="12345678-1234-5678-1234-567812345678")
159
- """
160
- params = {
161
- 'f': 'json',
162
- 'user_id': user_id,
163
- }
164
- return await super()._get_detail(api, cls.BASE_ENDPOINT, uuid, params, factory_func=lambda api, item: Map(api, item['uuid'], item))
165
-
166
-
167
- @classmethod
168
- async def get_map_by_name(cls, api: 'AsyncGeoboxClient', name: str, user_id: int = None) -> Union['Map', None]:
169
- """
170
- [async] Get a map by name
171
-
172
- Args:
173
- api (AsyncGeoboxClient): The AsyncGeoboxClient instance for making requests.
174
- name (str): the name of the map to get
175
- user_id (int, optional): specific user. privileges required.
176
-
177
- Returns:
178
- Map | None: returns the map if a map matches the given name, else None
179
-
180
- Example:
181
- >>> from geobox.aio import AsyncGeoboxClient
182
- >>> from geobox.aio.map import Map
183
- >>> async with AsyncGeoboxClient() as client:
184
- >>> map = await Map.get_map_by_name(client, name='test')
185
- or
186
- >>> map = await client.get_map_by_name(name='test')
187
- """
188
- maps = await cls.get_maps(api, q=f"name = '{name}'", user_id=user_id)
189
- if maps and maps[0].name == name:
190
- return maps[0]
191
- else:
192
- return None
193
-
194
-
195
- async def update(self, **kwargs) -> Dict:
196
- """
197
- [async] Update the map.
198
-
199
- Keyword Args:
200
- name (str): The name of the map.
201
- display_name (str): The display name of the map.
202
- description (str): The description of the map.
203
- extent (List[float]): The extent of the map.
204
- thumbnail (str): The thumbnail of the map.
205
- style (Dict): The style of the map.
206
-
207
- Returns:
208
- Dict: The updated map data.
209
-
210
- Raises:
211
- ValidationError: If the map data is invalid.
212
-
213
- Example:
214
- >>> from geobox.aio import AsyncGeoboxClient
215
- >>> from geobox.aio.map import Map
216
- >>> async with AsyncGeoboxClient() as client:
217
- >>> map = await Map.get_map(client, uuid="12345678-1234-5678-1234-567812345678")
218
- >>> await map.update(display_name="New Display Name")
219
- """
220
- data = {
221
- "name": kwargs.get('name'),
222
- "display_name": kwargs.get('display_name'),
223
- "description": kwargs.get('description'),
224
- "extent": kwargs.get('extent'),
225
- "thumbnail": kwargs.get('thumbnail'),
226
- "style": kwargs.get('style'),
227
- }
228
- return await super()._update(self.endpoint, data)
229
-
230
-
231
- async def delete(self) -> None:
232
- """
233
- [async] Delete the map.
234
-
235
- Returns:
236
- None
237
-
238
- Example:
239
- >>> from geobox.aio import AsyncGeoboxClient
240
- >>> from geobox.aio.map import Map
241
- >>> async with AsyncGeoboxClient() as client:
242
- >>> map = await Map.get_map(client, uuid="12345678-1234-5678-1234-567812345678")
243
- >>> await map.delete()
244
- """
245
- await super().delete(self.endpoint)
246
-
247
-
248
- @property
249
- async def style(self) -> Dict:
250
- """
251
- [async] Get the style of the map.
252
-
253
- Returns:
254
- Dict: The style of the map.
255
-
256
- Example:
257
- >>> from geobox.aio import AsyncGeoboxClient
258
- >>> from geobox.aio.map import Map
259
- >>> async with AsyncGeoboxClient() as client:
260
- >>> map = await Map.get_map(client, uuid="12345678-1234-5678-1234-567812345678")
261
- >>> await map.style
262
- """
263
- endpoint = urljoin(self.endpoint, 'style/')
264
- response = await self.api.get(endpoint)
265
- return response
266
-
267
-
268
- @property
269
- def thumbnail(self) -> str:
270
- """
271
- Get the thumbnail URL of the map.
272
-
273
- Returns:
274
- str: The thumbnail of the map.
275
-
276
- Example:
277
- >>> from geobox.aio import AsyncGeoboxClient
278
- >>> from geobox.aio.map import Map
279
- >>> async with AsyncGeoboxClient() as client:
280
- >>> map = await Map.get_map(client, uuid="12345678-1234-5678-1234-567812345678")
281
- >>> map.thumbnail
282
- 'https://example.com/thumbnail.png'
283
- """
284
- return super().thumbnail()
285
-
286
-
287
- async def set_readonly(self, readonly: bool) -> None:
288
- """
289
- [async] Set the readonly status of the map.
290
-
291
- Args:
292
- readonly (bool): The readonly status of the map.
293
-
294
- Returns:
295
- None
296
-
297
- Example:
298
- >>> from geobox.aio import AsyncGeoboxClient
299
- >>> from geobox.aio.map import Map
300
- >>> async with AsyncGeoboxClient() as client:
301
- >>> map = await Map.get_map(client, uuid="12345678-1234-5678-1234-567812345678")
302
- >>> await map.set_readonly(True)
303
- """
304
- data = clean_data({
305
- 'readonly': readonly
306
- })
307
- endpoint = urljoin(self.endpoint, 'setReadonly/')
308
- response = await self.api.post(endpoint, data, is_json=False)
309
- self._update_properties(response)
310
-
311
-
312
- async def set_multiuser(self, multiuser: bool) -> None:
313
- """
314
- [async] Set the multiuser status of the map.
315
-
316
- Args:
317
- multiuser (bool): The multiuser status of the map.
318
-
319
- Returns:
320
- None
321
-
322
- Example:
323
- >>> from geobox.aio import AsyncGeoboxClient
324
- >>> from geobox.aio.map import Map
325
- >>> async with AsyncGeoboxClient() as client:
326
- >>> map = await Map.get_map(client, uuid="12345678-1234-5678-1234-567812345678")
327
- >>> await map.set_multiuser(True)
328
- """
329
- data = clean_data({
330
- 'multiuser': multiuser
331
- })
332
- endpoint = urljoin(self.endpoint, 'setMultiuser/')
333
- response = await self.api.post(endpoint, data, is_json=False)
334
- self._update_properties(response)
335
-
336
-
337
-
338
- def wmts(self, scale: int = None) -> str:
339
- """
340
- Get the WMTS URL of the map.
341
-
342
- Args:
343
- scale (int): The scale of the map. value are: 1, 2
344
-
345
- Returns:
346
- str: The WMTS URL of the map.
347
-
348
- Example:
349
- >>> from geobox.aio import AsyncGeoboxClient
350
- >>> from geobox.aio.map import Map
351
- >>> async with AsyncGeoboxClient() as client:
352
- >>> map = await Map.get_map(client, uuid="12345678-1234-5678-1234-567812345678")
353
- >>> map.wmts(scale=1)
354
- """
355
- endpoint = urljoin(self.api.base_url, f'{self.endpoint}wmts/')
356
- if scale:
357
- endpoint = f"{endpoint}?scale={scale}"
358
-
359
- if not self.api.access_token and self.api.apikey:
360
- endpoint = join_url_params(endpoint, {"apikey": self.api.apikey})
361
-
362
- return endpoint
363
-
364
-
365
- async def share(self, users: List['User']) -> None:
366
- """
367
- [async] Shares the map with specified users.
368
-
369
- Args:
370
- users (List[User]): The list of user objects to share the map with.
371
-
372
- Returns:
373
- None
374
-
375
- Example:
376
- >>> from geobox.aio import AsyncGeoboxClient
377
- >>> from geobox.aio.map import Map
378
- >>> async with AsyncGeoboxClient() as client:
379
- >>> map = await Map.get_map(client, uuid="12345678-1234-5678-1234-567812345678")
380
- >>> users = await client.search_users(search='John')
381
- >>> await map.share(users=users)
382
- """
383
- await super()._share(self.endpoint, users)
384
-
385
-
386
- async def unshare(self, users: List['User']) -> None:
387
- """
388
- [async] Unshares the map with specified users.
389
-
390
- Args:
391
- users (List[User]): The list of user objects to unshare the map with.
392
-
393
- Returns:
394
- None
395
-
396
- Example:
397
- >>> from geobox.aio import AsyncGeoboxClient
398
- >>> from geobox.aio.map import Map
399
- >>> async with AsyncGeoboxClient() as client:
400
- >>> map = await Map.get_map(client, uuid="12345678-1234-5678-1234-567812345678")
401
- >>> await users = client.search_users(search='John')
402
- >>> await map.unshare(users=users)
403
- """
404
- await super()._unshare(self.endpoint, users)
405
-
406
-
407
- async def get_shared_users(self, search: str = None, skip: int = 0, limit: int = 10) -> List['User']:
408
- """
409
- [async] Retrieves the list of users the map is shared with.
410
-
411
- Args:
412
- search (str, optional): The search query.
413
- skip (int, optional): The number of users to skip.
414
- limit (int, optional): The maximum number of users to retrieve.
415
-
416
- Returns:
417
- List[User]: The list of shared users.
418
-
419
- Example:
420
- >>> from geobox.aio import AsyncGeoboxClient
421
- >>> from geobox.aio.map import Map
422
- >>> async with AsyncGeoboxClient() as client:
423
- >>> map = await Map.get_map(client, uuid="12345678-1234-5678-1234-567812345678")
424
- >>> await map.get_shared_users(search='John', skip=0, limit=10)
425
- """
426
- params = {
427
- 'search': search,
428
- 'skip': skip,
429
- 'limit': limit
430
- }
431
- return await super()._get_shared_users(self.endpoint, params)
432
-
433
-
434
- async def seed_cache(self,
435
- from_zoom: int = None,
436
- to_zoom: int = None,
437
- extent: List[float] = None,
438
- workers: int = 1,
439
- user_id: int = None,
440
- scale: int = None) -> List['Task']:
441
- """
442
- [async] Seed the cache of the map.
443
-
444
- Args:
445
- from_zoom (int, optional): The zoom level to start caching from.
446
- to_zoom (int, optional): The zoom level to stop caching at.
447
- extent (List[float], optional): The extent of the map.
448
- workers (int, optional): The number of workers to use. default is 1.
449
- user_id (int, optional): Specific user. privileges required.
450
- scale (int, optional): The scale of the map.
451
-
452
- Returns:
453
- List[Task]: The task instance of the cache seeding operation.
454
-
455
- Raises:
456
- ValueError: If the workers is not in [1, 2, 4, 8, 12, 16, 20, 24].
457
- ValueError: If the cache seeding fails.
458
-
459
- Example:
460
- >>> from geobox.aio import AsyncGeoboxClient
461
- >>> from geobox.aio.map import Map
462
- >>> async with AsyncGeoboxClient() as client:
463
- >>> map = await Map.get_map(client, uuid="12345678-1234-5678-1234-567812345678")
464
- >>> task = await map.seed_cache(from_zoom=0, to_zoom=10, extent=[10, 20, 30, 40], workers=1, scale=1)
465
- """
466
- data = {
467
- 'from_zoom': from_zoom,
468
- 'to_zoom': to_zoom,
469
- 'extent': extent,
470
- 'workers': workers,
471
- 'user_id': user_id,
472
- 'scale': scale
473
- }
474
- return await super()._seed_cache(self.endpoint, data)
475
-
476
-
477
- async def update_cache(self,
478
- from_zoom: int = None,
479
- to_zoom: int = None,
480
- extent: List[float] = None,
481
- user_id: int = None,
482
- scale: int = None) -> List['Task']:
483
- """
484
- [async] Update the cache of the map.
485
-
486
- Args:
487
- from_zoom (int, optional): The zoom level to start caching from.
488
- to_zoom (int, optional): The zoom level to stop caching at.
489
- extent (List[float], optional): The extent of the map.
490
- user_id (int, optional): Specific user. privileges required.
491
- scale (int, optional): The scale of the map.
492
-
493
- Returns:
494
- List[Task]: The task instance of the cache updating operation.
495
-
496
- Raises:
497
- ValueError: If the cache updating fails.
498
-
499
- Example:
500
- >>> from geobox.aio import AsyncGeoboxClient
501
- >>> from geobox.aio.map import Map
502
- >>> async with AsyncGeoboxClient() as client:
503
- >>> map = await Map.get_map(client, uuid="12345678-1234-5678-1234-567812345678")
504
- >>> await map.update_cache(from_zoom=0, to_zoom=10, extent=[10, 20, 30, 40], scale=1)
505
- """
506
- data = {
507
- 'from_zoom': from_zoom,
508
- 'to_zoom': to_zoom,
509
- 'extent': extent,
510
- 'user_id': user_id,
511
- 'scale': scale
512
- }
513
- return await super()._update_cache(self.endpoint, data)
514
-
515
-
516
- async def clear_cache(self) -> None:
517
- """
518
- [async] Clear the cache of the map.
519
-
520
- Returns:
521
- None
522
-
523
- Example:
524
- >>> from geobox.aio import AsyncGeoboxClient
525
- >>> from geobox.aio.map import Map
526
- >>> async with AsyncGeoboxClient() as client:
527
- >>> map = await Map.get_map(client, uuid="12345678-1234-5678-1234-567812345678")
528
- >>> await map.clear_cache()
529
- """
530
- return await super()._clear_cache(self.endpoint)
531
-
532
-
533
- @property
534
- async def cache_size(self) -> int:
535
- """
536
- [async] Get the size of the cache of the map.
537
-
538
- Returns:
539
- int: The size of the cache of the map.
540
-
541
- Example:
542
- >>> from geobox.aio import AsyncGeoboxClient
543
- >>> from geobox.aio.map import Map
544
- >>> async with AsyncGeoboxClient() as client:
545
- >>> map = await Map.get_map(client, uuid="12345678-1234-5678-1234-567812345678")
546
- >>> await map.cache_size
547
- """
548
- return await super()._cache_size(self.endpoint)
549
-
550
-
551
- @property
552
- def settings(self) -> Dict:
553
- """
554
- Get the settings of the map
555
-
556
- Returns:
557
- Dict: the settings of the map.
558
-
559
- Example:
560
- >>> from geobox.aio import AsyncGeoboxClient
561
- >>> from geobox.aio.map import Map
562
- >>> async with AsyncGeoboxClient() as client:
563
- >>> map = await Map.get_map(uuid="12345678-1234-5678-1234-567812345678")
564
- >>> map.settings
565
- """
566
- return self.json.get('settings', {
567
- 'general_settings': {},
568
- 'edit_settings': {},
569
- 'snap_settings': {},
570
- 'controls': [],
571
- 'search_settings': {},
572
- 'marker_settings': {},
573
- 'terrain_settings': {},
574
- 'grid_settings': {},
575
- 'view_settings': {},
576
- 'toc_settings': []
577
- })
578
-
579
-
580
- async def update_settings(self, settings: Dict) -> Dict:
581
- """
582
- [async] Update the settings
583
-
584
- settings (Dict): settings dictionary
585
-
586
- Returns:
587
- Dict: updated settings
588
-
589
- Example:
590
- >>> from geobox.aio import AsyncGeoboxClient
591
- >>> async with AsyncGeoboxClient() as client:
592
- >>> map1 = await client.get_map(uuid="12345678-1234-5678-1234-567812345678")
593
- >>> map2 = await client.get_map(uuid="12345678-1234-5678-1234-567812345678")
594
- >>> await map1.update_settings(map2.settings)
595
- """
596
- return await super()._set_settings(self.endpoint, settings)
597
-
598
-
599
- async def set_settings(self, **kwargs) -> Dict:
600
- """
601
- [async] Set the settings of the map using keywords
602
-
603
- Keyword Args:
604
- map_unit (str): 'latlng' | 'utm'.
605
- base_map (str): 'OSM' | 'google' | 'blank'.
606
- flash_color (str): 'rgb(255,0,0)' (rgb color or rgba color or hex color ).
607
- highlight_color (str): 'rgb(255,0,0)' (rgb color or rgba color or hex color ).
608
- selection_color (str): 'rgb(255,0,0)' (rgb color or rgba color or hex color ).
609
- selectable_layers (str): 'ALL' | null | Comma separated list of layers.
610
- calendar_type (str): The type of the calendar.
611
- edit_settings (dict): The settings of the edit.
612
- snap_tolerance (int): number of pixels for snap tolerance.
613
- snap_unit (str): pixels.
614
- snap_mode (str): 'both' | 'edge' | 'vertex'.
615
- snap_cache (int): number of total features for snap cache.
616
- controls (List[str]): The controls of the map.
617
- search_mode (str): 'both' | 'markers' | 'layers'.
618
- search_layers (str): 'ALL' | null | Comma separated list of layers.
619
- geosearch (bool): The geosearch of the map.
620
- remove_unused_tags (bool): The remove unused tags of the map.
621
- terrain_layer (str): The terrain layer of the map.
622
- exaggeration (int): The exaggeration of the terrain.
623
- enable_grid (bool): The enable grid of the map.
624
- grid_unit (str): The unit of the grid.
625
- grid_width (int): The width of the grid.
626
- grid_height (int): The height of the grid.
627
- grid_minzoom (int): The minzoom of the grid.
628
- grid_maxzoom (int): The maxzoom of the grid.
629
- bearing (int): The bearing of the map.
630
- pitch (int): The pitch of the map.
631
- center (List[float]): The center of the map.
632
- zoom (int): The zoom of the map.
633
- toc_settings (List): The settings of the toc.
634
- custom_basemaps (List[str]): The custom basemaps of the map.
635
- show_maptip_on (str): 'ALL' | null | Comma separated list of layers.
636
- snappable_layers (str): 'ALL' | null | Comma separated list of layers.
637
-
638
- Returns:
639
- Dict: The response of the API.
640
-
641
- Example:
642
- >>> from geobox.aio import AsyncGeoboxClient
643
- >>> from geobox.aio.map import Map
644
- >>> async with AsyncGeoboxClient() as client:
645
- >>> map = await Map.get_map(uuid="12345678-1234-5678-1234-567812345678")
646
- >>> await map.set_settings(zoom=10)
647
- """
648
- general_settings = {'map_unit', 'base_map', 'flash_color', 'highlight_color',
649
- 'selection_color', 'selectable_layers', 'calendar_type', 'custom_basemaps', 'show_maptip_on'}
650
- edit_settings = {'editable_layers', 'target_layer'}
651
- snap_settings = {'snap_tolerance', 'snap_unit', 'snap_mode', 'snap_cache', 'snappable_layers'}
652
- search_settings = {'search_mode', 'search_layers', 'geosearch'}
653
- marker_settings = {'remove_unused_tags'}
654
- terrain_settings = {'terrain_layer', 'exaggeration'}
655
- grid_settings = {'enable_grid', 'grid_unit', 'grid_width', 'grid_height', 'grid_minzoom', 'grid_maxzoom'}
656
- view_settings = {'bearing', 'pitch', 'center', 'zoom'}
657
-
658
- settings = self.settings
659
-
660
- for key, value in kwargs.items():
661
- if key in general_settings:
662
- settings['general_settings'][key] = value
663
- elif key in edit_settings:
664
- settings['edit_settings'][key] = value
665
- elif key in snap_settings:
666
- settings['snap_settings'][key] = value
667
- elif key == 'controls':
668
- settings['controls'] = value
669
- elif key in search_settings:
670
- settings['search_settings'][key] = value
671
- elif key in marker_settings:
672
- settings['marker_settings'][key] = value
673
- elif key in terrain_settings:
674
- settings['terrain_settings'][key] = value
675
- elif key in grid_settings:
676
- settings['grid_settings'][key] = value
677
- elif key in view_settings:
678
- settings['view_settings'][key] = value
679
- elif key == 'toc_settings':
680
- settings['toc_settings'] = value
681
-
682
- return await super()._set_settings(self.endpoint, settings)
683
-
684
-
685
- async def get_markers(self) -> Dict:
686
- """
687
- [async] Get the markers of the map.
688
-
689
- Returns:
690
- Dict: The markers of the map.
691
-
692
- Example:
693
- >>> from geobox.aio import AsyncGeoboxClient
694
- >>> from geobox.aio.map import Map
695
- >>> async with AsyncGeoboxClient() as client:
696
- >>> map = await Map.get_map(client, uuid="12345678-1234-5678-1234-567812345678")
697
- >>> await map.get_markers()
698
- """
699
- endpoint = urljoin(self.endpoint, 'markers/')
700
- return await self.api.get(endpoint)
701
-
702
-
703
- async def set_markers(self, data: Dict) -> Dict:
704
- """
705
- [async] Set the markers of the map.
706
-
707
- Args:
708
- data (dict): The data of the markers.
709
-
710
- Returns:
711
- Dict: The response of the API.
712
-
713
- Example:
714
- >>> from geobox.aio import AsyncGeoboxClient
715
- >>> from geobox.aio.map import Map
716
- >>> async with AsyncGeoboxClient() as client:
717
- >>> map = await Map.get_map(client, uuid="12345678-1234-5678-1234-567812345678")
718
- >>> data = {
719
- ... 'tags': {
720
- ... '#general': {
721
- ... 'color': '#ff0000',
722
- ... }
723
- ... },
724
- ... 'locations': [
725
- ... {
726
- ... 'id': 1,
727
- ... 'tag': '#general',
728
- ... 'name': 'test',
729
- ... 'geometry': [
730
- ... 51.13162784422988,
731
- ... 35.766603814763045
732
- ... ],
733
- ... 'description': 'string'
734
- ... }
735
- ... ]
736
- ... }
737
- >>> await map.set_markers(data)
738
- """
739
- endpoint = urljoin(self.endpoint, 'markers/')
740
- response = await self.api.put(endpoint, data)
741
- return response
742
-
743
-
744
- async def get_models(self, json=False) -> Union[List['Model'], Dict]:
745
- """
746
- [async] Get the map models.
747
-
748
- Args:
749
- json (bool, optional): If True, return the response as a dictionary.
750
-
751
- Returns:
752
- List[Model] | Dict: map models objects or the response.
753
-
754
- Example:
755
- >>> from geobox.aio import AsyncGeoboxClient
756
- >>> from geobox.aio.map import Map
757
- >>> async with AsyncGeoboxClient() as client:
758
- >>> map = await Map.get_map(client, uuid="12345678-1234-5678-1234-567812345678")
759
- >>> await map.get_models(json=True)
760
- """
761
- endpoint = urljoin(self.endpoint, 'models/')
762
- response = await self.api.get(endpoint)
763
- if not response or json:
764
- return response
765
- else:
766
- return [Model(self.api, model['obj'], model) for model in response['objects'] if response.get('objects')]
767
-
768
-
769
- async def set_models(self, data: Dict) -> List['Model']:
770
- """
771
- [async] Set multiple models on the map.
772
-
773
- Args:
774
- data (Dict): the data of the models and their location on the map. check the example for the data structure.
775
-
776
- Returns:
777
- List[Model]: the map models objects
778
-
779
- Example:
780
- >>> from geobox.aio import AsyncGeoboxClient
781
- >>> from geobox.aio.map import Map
782
- >>> async with AsyncGeoboxClient() as client:
783
- >>> map = await Map.get_map(uuid="12345678-1234-5678-1234-567812345678")
784
- >>> data = {'objects': [
785
- ... {
786
- ... "name": "transmission_tower",
787
- ... "alias": None,
788
- ... "desc": None,
789
- ... "obj": "12345678-1234-5678-1234-567812345678",
790
- ... "loc": [53.1859045261684, 33.37762747390032, 0.0],
791
- ... "rotation": [0.0, 0.0, 0.0],
792
- ... "scale": 1.0,
793
- ... "min_zoom": 0,
794
- ... "max_zoom": 22
795
- ... }
796
- ... ]}
797
- >>> await map.set_models(data)
798
- """
799
- endpoint = urljoin(self.endpoint, 'models/')
800
- response = await self.api.put(endpoint, data)
801
- return [Model(self.api, model['obj'], model) for model in response['objects'] if response.get('objects')]
802
-
803
-
804
- async def add_model(self,
805
- model: 'Model',
806
- location: List[float],
807
- rotation: List[float] = [0.0, 0.0, 0.0],
808
- scale: float = 1.0,
809
- min_zoom: int = 0,
810
- max_zoom: int = 22,
811
- alias: str = None,
812
- description: str = None) -> List['Model']:
813
- """
814
- [async] Add a model the map.
815
-
816
- Args:
817
- model (Model): The model object.
818
- location (List[float]): location of the model on the map. a list with three float values.
819
- rotation (List[float], optional): rotation of the model on the map. a list with three float vlaues. default is [0.0, 0.0, 0.0].
820
- scale (float, optional): the scale of the model on the map.
821
- min_zoom (int, optional): minimum zoom level.
822
- max_zoom (int, optional): maximum zoom level.
823
- alias (str, optional): alias of the model on the map.
824
- description (str, optional): the description of the model on the map.
825
-
826
- Returns:
827
- List['Model']: The map model objects
828
-
829
- Example:
830
- >>> from geobox.aio import AsyncGeoboxClient
831
- >>> from geobox.aio.map import Map
832
- >>> async with AsyncGeoboxClient() as client:
833
- >>> map = await Map.get_map(client, uuid="12345678-1234-5678-1234-567812345678")
834
- >>> model = await client.get_model(uuid="12345678-1234-5678-1234-567812345678")
835
- >>> await map.add_model(model=model,
836
- ... location=[53.53, 33.33, 0.0],
837
- ... rotation=[0.0, 0.0, 0.0],
838
- ... scale=1.0,
839
- ... min_zoom=0,
840
- ... max_zoom=22,
841
- ... alias=None,
842
- ... description=None)
843
- """
844
- data = await self.get_models(json=True)
845
- if data and data.get('objects') and isinstance(data['objects'], list):
846
- data.get('objects').append({
847
- 'name': model.name,
848
- 'alias': alias,
849
- 'desc': description,
850
- 'obj': model.uuid,
851
- 'loc': location,
852
- 'rotation': rotation,
853
- 'scale': scale,
854
- 'min_zoom': min_zoom,
855
- 'max_zoom': max_zoom
856
- })
857
- else:
858
- data = {'objects':[
859
- {
860
- 'name': model.name,
861
- 'alias': alias,
862
- 'desc': description,
863
- 'obj': model.uuid,
864
- 'loc': location,
865
- 'rotation': rotation,
866
- 'scale': scale,
867
- 'min_zoom': min_zoom,
868
- 'max_zoom': max_zoom
869
- }
870
- ]
871
- }
872
-
873
- endpoint = urljoin(self.endpoint, 'models/')
874
- response = await self.api.put(endpoint, data)
875
- return [Model(self.api, model['obj'], model) for model in response['objects']]
876
-
877
-
878
- def image_tile_url(self, x: str = '{x}', y: str = '{y}', z: str = '{z}', format='.png') -> str:
879
- """
880
- Get map image tile url
881
-
882
- Returns:
883
- str: the image tile url
884
-
885
- Example:
886
- >>> from geobox.aio import AsyncGeoboxClient
887
- >>> from geobox.aio.map import Map
888
- >>> async with AsyncGeoboxClient() as client:
889
- >>> map = await Map.get_map(client, uuid="12345678-1234-5678-1234-567812345678")
890
- >>> map.image_tile_url()
891
- >>> map.image_tile_url(x=1, y=2, z=3, format='.pbf')
892
- """
893
- endpoint = f"{self.api.base_url}{self.endpoint}tiles/{z}/{x}/{y}{format}"
894
-
895
- if not self.api.access_token and self.api.apikey:
896
- endpoint = f'{endpoint}?apikey={self.api.apikey}'
897
-
898
- return endpoint
899
-
900
-
901
- async def export_map_to_image(self, bbox: List, width: int, height: int) -> 'Task':
902
- """
903
- [async] Export the map to image
904
-
905
- Args:
906
- bbox (List): e.g. [50.275, 35.1195, 51.4459, 36.0416]
907
- width (int): minimum: 10, maximum: 10000
908
- height (int): minimum: 10, maximum: 10000
909
-
910
- Returns:
911
- Task: the task object
912
-
913
- Example:
914
- >>> from geobox.aio import AsyncGeoboxClient
915
- >>> from geobox.aio.map import Map
916
- >>> async with AsyncGeoboxClient() as client:
917
- >>> map = await Map.get_map(client, uuid="12345678-1234-5678-1234-567812345678")
918
- >>> task = await map.export_map_to_image(bbox=[50.275, 35.1195, 51.4459, 36.0416],
919
- ... width=1024,
920
- ... height=1024)
921
- """
922
- data = clean_data({
923
- 'uuid': self.uuid,
924
- 'bbox': bbox,
925
- 'width': width,
926
- 'height': height
927
- })
928
- query_string = urlencode(data)
929
- endpoint = urljoin(self.endpoint, 'export/')
930
- endpoint = f"{endpoint}?{query_string}"
931
- response = await self.api.post(endpoint)
932
- return await self.api.get_task(response['task_id'])
933
-
934
-
935
- async def get_attachments(self, **kwargs) -> List['Attachment']:
936
- """
937
- [async] Get the resouces attachments
938
-
939
- Keyword Args:
940
- element_id (str): the id of the element with attachment.
941
- search (str): search term for keyword-based searching among all textual fields.
942
- order_by (str): comma separated list of fields for sorting results [field1 A|D, field2 A|D, …]. e.g. name A, type D. NOTE: "A" denotes ascending order and "D" denotes descending order.
943
- skip (int): Number of items to skip. default is 0.
944
- limit (int): Number of items to return. default is 10.
945
- return_count (bool): Whether to return total count. default is False.
946
-
947
- Returns:
948
- List[Attachment] | int: A list of attachments instances or the total number of attachments.
949
-
950
- Raises:
951
- TypeError: if the resource type is not supported
952
-
953
- Example:
954
- >>> from geobox.aio import AsyncGeoboxClient
955
- >>> from geobox.aio.map import Map
956
- >>> async with AsyncGeoboxClient() as client:
957
- >>> map = await Map.get_map(client, uuid="12345678-1234-5678-1234-567812345678")
958
- >>> await map.get_attachments()
959
- """
960
- from .attachment import Attachment
961
-
962
- return await Attachment.get_attachments(self.api, resource=self, **kwargs)
963
-
964
-
965
- async def create_attachment(self,
966
- name: str,
967
- loc_x: int,
968
- loc_y: int,
969
- file: 'File',
970
- feature: 'Feature' = None,
971
- display_name: str = None,
972
- description: str = None) -> 'Attachment':
973
- """
974
- [async] Create a new Attachment.
975
-
976
- Args:
977
- name (str): The name of the scene.
978
- loc_x (int): x parameter of the attachment location.
979
- loc_y (int): y parameter of the attachment location.
980
- file (File): the file object.
981
- feature (Feature, optional): the feature object.
982
- display_name (str, optional): The display name of the scene.
983
- description (str, optional): The description of the scene.
984
-
985
- Returns:
986
- Attachment: The newly created Attachment instance.
987
-
988
- Raises:
989
- ValidationError: If the Attachment data is invalid.
990
-
991
- Example:
992
- >>> from geobox.aio import AsyncGeoboxClient
993
- >>> from geobox.aio.map import Map
994
- >>> async with AsyncGeoboxClient() as client:
995
- >>> map = await Map.get_map(client, uuid="12345678-1234-5678-1234-567812345678")
996
- >>> files = await client.get_files()
997
- >>> file = files[0]
998
- >>> await map.create_attachment(name='test', loc_x=10, loc_y=10, file=file)
999
- """
1000
- from .attachment import Attachment
1001
-
1002
- return await Attachment.create_attachment(self.api,
1003
- name=name,
1004
- loc_x=loc_x,
1005
- loc_y=loc_y,
1006
- resource=self,
1007
- file=file,
1008
- feature=feature,
1009
- display_name=display_name,
1010
- description=description)
1011
-
1012
-
1013
- def to_sync(self, sync_client: 'SyncGeoboxClient') -> 'SyncMap':
1014
- """
1015
- Switch to sync version of the map instance to have access to the sync methods
1016
-
1017
- Args:
1018
- sync_client (SyncGeoboxClient): The sync version of the GeoboxClient instance for making requests.
1019
-
1020
- Returns:
1021
- geobox.map.Map: the sync instance of the map.
1022
-
1023
- Example:
1024
- >>> from geobox import Geoboxclient
1025
- >>> from geobox.aio import AsyncGeoboxClient
1026
- >>> from geobox.aio.map import Map
1027
- >>> client = GeoboxClient()
1028
- >>> async with AsyncGeoboxClient() as async_client:
1029
- >>> map = await Map.get_map(async_client, uuid="12345678-1234-5678-1234-567812345678")
1030
- >>> sync_map = map.to_sync(client)
1031
- """
1032
- from ..map import Map as SyncMap
1033
-
1034
- return SyncMap(api=sync_client, uuid=self.uuid, data=self.data)
1
+ from typing import Dict, List, Optional, Union, TYPE_CHECKING
2
+ from urllib.parse import urljoin, urlencode
3
+
4
+ from .base import AsyncBase
5
+ from .model3d import AsyncModel
6
+ from .file import AsyncFile
7
+ from .feature import AsyncFeature
8
+ from ..utils import clean_data, join_url_params
9
+
10
+ if TYPE_CHECKING:
11
+ from . import AsyncGeoboxClient
12
+ from .user import AsyncUser
13
+ from .task import AsyncTask
14
+ from .attachment import AsyncAttachment
15
+ from ..api import GeoboxClient
16
+ from ..map import Map
17
+
18
+
19
+ class AsyncMap(AsyncBase):
20
+
21
+ BASE_ENDPOINT = 'maps/'
22
+
23
+ def __init__(self,
24
+ api: 'AsyncGeoboxClient',
25
+ uuid: str,
26
+ data: Optional[Dict] = {}):
27
+ """
28
+ Initialize a Map instance.
29
+
30
+ Args:
31
+ api (AsyncGeoboxClient): The AsyncGeoboxClient instance for making requests.
32
+ name (str): The name of the map.
33
+ uuid (str): The unique identifier for the map.
34
+ data (Dict, optional): The data of the map.
35
+ """
36
+ self.map_layers = {
37
+ 'layers': []
38
+ }
39
+ super().__init__(api, uuid=uuid, data=data)
40
+
41
+
42
+ @classmethod
43
+ async def get_maps(cls, api: 'AsyncGeoboxClient', **kwargs) -> Union[List['AsyncMap'], int]:
44
+ """
45
+ [async] Get list of maps with optional filtering and pagination.
46
+
47
+ Args:
48
+ api (AsyncGeoboxClient): The AsyncGeoboxClient instance for making requests.
49
+
50
+ Keyword Args:
51
+ q (str): query filter based on OGC CQL standard. e.g. "field1 LIKE '%GIS%' AND created_at > '2021-01-01'"
52
+ search (str): search term for keyword-based searching among search_fields or all textual fields if search_fields does not have value. NOTE: if q param is defined this param will be ignored.
53
+ search_fields (str): comma separated list of fields for searching.
54
+ order_by (str): comma separated list of fields for sorting results [field1 A|D, field2 A|D, …]. e.g. name A, type D. NOTE: "A" denotes ascending order and "D" denotes descending order.
55
+ return_count (bool): Whether to return total count. default is False.
56
+ skip (int): Number of items to skip. default is 0.
57
+ limit (int): Number of items to return. default is 10.
58
+ user_id (int): Specific user. privileges required.
59
+ shared (bool): Whether to return shared maps. default is False.
60
+
61
+ Returns:
62
+ List[AsyncMap] | int: A list of Map instances or the total number of maps.
63
+
64
+ Example:
65
+ >>> from geobox.aio import AsyncGeoboxClient
66
+ >>> from geobox.aio.map import AsyncMap
67
+ >>> async with AsyncGeoboxClient() as client:
68
+ >>> maps = await AsyncMap.get_maps(client, q="name LIKE '%My Map%'")
69
+ or
70
+ >>> maps = await client.get_maps(q="name LIKE '%My Map%'")
71
+ """
72
+ params = {
73
+ 'f': 'json',
74
+ 'q': kwargs.get('q'),
75
+ 'search': kwargs.get('search'),
76
+ 'search_fields': kwargs.get('search_fields'),
77
+ 'order_by': kwargs.get('order_by'),
78
+ 'return_count': kwargs.get('return_count', False),
79
+ 'skip': kwargs.get('skip', 0),
80
+ 'limit': kwargs.get('limit', 10),
81
+ 'user_id': kwargs.get('user_id'),
82
+ 'shared': kwargs.get('shared', False)
83
+ }
84
+ return await super()._get_list(api, cls.BASE_ENDPOINT, params, factory_func=lambda api, item: AsyncMap(api, item['uuid'], item))
85
+
86
+
87
+ @classmethod
88
+ async def create_map(cls,
89
+ api: 'AsyncGeoboxClient',
90
+ name: str,
91
+ display_name: str = None,
92
+ description: str = None,
93
+ extent: List[float] = None,
94
+ thumbnail: str = None,
95
+ style: Dict = None,
96
+ user_id: int = None) -> 'AsyncMap':
97
+ """
98
+ [async] Create a new map.
99
+
100
+ Args:
101
+ api (AsyncGeoboxClient): The AsyncGeoboxClient instance for making requests.
102
+ name (str): The name of the map.
103
+ display_name (str, optional): The display name of the map.
104
+ description (str, optional): The description of the map.
105
+ extent (List[float], optional): The extent of the map.
106
+ thumbnail (str, optional): The thumbnail of the map.
107
+ style (Dict, optional): The style of the map.
108
+ user_id (int, optional): Specific user. privileges required.
109
+
110
+ Returns:
111
+ AsyncMap: The newly created map instance.
112
+
113
+ Raises:
114
+ ValidationError: If the map data is invalid.
115
+
116
+ Example:
117
+ >>> from geobox.aio import AsyncGeoboxClient
118
+ >>> from geobox.aio.map import AsyncMap
119
+ >>> async with AsyncGeoboxClient() as client:
120
+ >>> map = await AsyncMap.create_map(client, name="my_map", display_name="My Map", description="This is a description of my map", extent=[10, 20, 30, 40], thumbnail="https://example.com/thumbnail.png", style={"type": "style"})
121
+ or
122
+ >>> map = await client.create_map(name="my_map", display_name="My Map", description="This is a description of my map", extent=[10, 20, 30, 40], thumbnail="https://example.com/thumbnail.png", style={"type": "style"})
123
+ """
124
+ data = {
125
+ "name": name,
126
+ "display_name": display_name,
127
+ "description": description,
128
+ "extent": extent,
129
+ "thumbnail": thumbnail,
130
+ "style": style,
131
+ "user_id": user_id,
132
+ }
133
+ return await super()._create(api, cls.BASE_ENDPOINT, data, factory_func=lambda api, item: AsyncMap(api, item['uuid'], item))
134
+
135
+
136
+ @classmethod
137
+ async def get_map(cls, api: 'AsyncGeoboxClient', uuid: str, user_id: int = None) -> 'AsyncMap':
138
+ """
139
+ [async] Get a map by its UUID.
140
+
141
+ Args:
142
+ api (AsyncGeoboxClient): The AsyncGeoboxClient instance for making requests.
143
+ uuid (str): The UUID of the map to get.
144
+ user_id (int, optional): Specific user. privileges required.
145
+
146
+ Returns:
147
+ AsyncMap: The map object.
148
+
149
+ Raises:
150
+ NotFoundError: If the map with the specified UUID is not found.
151
+
152
+ Example:
153
+ >>> from geobox.aio import AsyncGeoboxClient
154
+ >>> from geobox.aio.map import AsyncMap
155
+ >>> async with AsyncGeoboxClient() as client:
156
+ >>> map = await AsyncMap.get_map(client, uuid="12345678-1234-5678-1234-567812345678")
157
+ or
158
+ >>> map = await client.get_map(uuid="12345678-1234-5678-1234-567812345678")
159
+ """
160
+ params = {
161
+ 'f': 'json',
162
+ 'user_id': user_id,
163
+ }
164
+ return await super()._get_detail(api, cls.BASE_ENDPOINT, uuid, params, factory_func=lambda api, item: AsyncMap(api, item['uuid'], item))
165
+
166
+
167
+ @classmethod
168
+ async def get_map_by_name(cls, api: 'AsyncGeoboxClient', name: str, user_id: int = None) -> Union['AsyncMap', None]:
169
+ """
170
+ [async] Get a map by name
171
+
172
+ Args:
173
+ api (AsyncGeoboxClient): The AsyncGeoboxClient instance for making requests.
174
+ name (str): the name of the map to get
175
+ user_id (int, optional): specific user. privileges required.
176
+
177
+ Returns:
178
+ AsyncMap | None: returns the map if a map matches the given name, else None
179
+
180
+ Example:
181
+ >>> from geobox.aio import AsyncGeoboxClient
182
+ >>> from geobox.aio.map import AsyncMap
183
+ >>> async with AsyncGeoboxClient() as client:
184
+ >>> map = await AsyncMap.get_map_by_name(client, name='test')
185
+ or
186
+ >>> map = await client.get_map_by_name(name='test')
187
+ """
188
+ maps = await cls.get_maps(api, q=f"name = '{name}'", user_id=user_id)
189
+ if maps and maps[0].name == name:
190
+ return maps[0]
191
+ else:
192
+ return None
193
+
194
+
195
+ async def update(self, **kwargs) -> Dict:
196
+ """
197
+ [async] Update the map.
198
+
199
+ Keyword Args:
200
+ name (str): The name of the map.
201
+ display_name (str): The display name of the map.
202
+ description (str): The description of the map.
203
+ extent (List[float]): The extent of the map.
204
+ thumbnail (str): The thumbnail of the map.
205
+ style (Dict): The style of the map.
206
+
207
+ Returns:
208
+ Dict: The updated map data.
209
+
210
+ Raises:
211
+ ValidationError: If the map data is invalid.
212
+
213
+ Example:
214
+ >>> from geobox.aio import AsyncGeoboxClient
215
+ >>> from geobox.aio.map import AsyncMap
216
+ >>> async with AsyncGeoboxClient() as client:
217
+ >>> map = await AsyncMap.get_map(client, uuid="12345678-1234-5678-1234-567812345678")
218
+ >>> await map.update(display_name="New Display Name")
219
+ """
220
+ data = {
221
+ "name": kwargs.get('name'),
222
+ "display_name": kwargs.get('display_name'),
223
+ "description": kwargs.get('description'),
224
+ "extent": kwargs.get('extent'),
225
+ "thumbnail": kwargs.get('thumbnail'),
226
+ "style": kwargs.get('style'),
227
+ }
228
+ return await super()._update(self.endpoint, data)
229
+
230
+
231
+ async def delete(self) -> None:
232
+ """
233
+ [async] Delete the map.
234
+
235
+ Returns:
236
+ None
237
+
238
+ Example:
239
+ >>> from geobox.aio import AsyncGeoboxClient
240
+ >>> from geobox.aio.map import AsyncMap
241
+ >>> async with AsyncGeoboxClient() as client:
242
+ >>> map = await AsyncMap.get_map(client, uuid="12345678-1234-5678-1234-567812345678")
243
+ >>> await map.delete()
244
+ """
245
+ await super()._delete(self.endpoint)
246
+
247
+
248
+ @property
249
+ async def style(self) -> Dict:
250
+ """
251
+ [async] Get the style of the map.
252
+
253
+ Returns:
254
+ Dict: The style of the map.
255
+
256
+ Example:
257
+ >>> from geobox.aio import AsyncGeoboxClient
258
+ >>> from geobox.aio.map import AsyncMap
259
+ >>> async with AsyncGeoboxClient() as client:
260
+ >>> map = await AsyncMap.get_map(client, uuid="12345678-1234-5678-1234-567812345678")
261
+ >>> await map.style
262
+ """
263
+ endpoint = urljoin(self.endpoint, 'style/')
264
+ response = await self.api.get(endpoint)
265
+ return response
266
+
267
+
268
+ @property
269
+ def thumbnail(self) -> str:
270
+ """
271
+ Get the thumbnail URL of the map.
272
+
273
+ Returns:
274
+ str: The thumbnail of the map.
275
+
276
+ Example:
277
+ >>> from geobox.aio import AsyncGeoboxClient
278
+ >>> from geobox.aio.map import AsyncMap
279
+ >>> async with AsyncGeoboxClient() as client:
280
+ >>> map = await AsyncMap.get_map(client, uuid="12345678-1234-5678-1234-567812345678")
281
+ >>> map.thumbnail
282
+ """
283
+ return super()._thumbnail()
284
+
285
+
286
+ async def set_readonly(self, readonly: bool) -> None:
287
+ """
288
+ [async] Set the readonly status of the map.
289
+
290
+ Args:
291
+ readonly (bool): The readonly status of the map.
292
+
293
+ Returns:
294
+ None
295
+
296
+ Example:
297
+ >>> from geobox.aio import AsyncGeoboxClient
298
+ >>> from geobox.aio.map import AsyncMap
299
+ >>> async with AsyncGeoboxClient() as client:
300
+ >>> map = await AsyncMap.get_map(client, uuid="12345678-1234-5678-1234-567812345678")
301
+ >>> await map.set_readonly(True)
302
+ """
303
+ data = clean_data({
304
+ 'readonly': readonly
305
+ })
306
+ endpoint = urljoin(self.endpoint, 'setReadonly/')
307
+ response = await self.api.post(endpoint, data, is_json=False)
308
+ self._update_properties(response)
309
+
310
+
311
+ async def set_multiuser(self, multiuser: bool) -> None:
312
+ """
313
+ [async] Set the multiuser status of the map.
314
+
315
+ Args:
316
+ multiuser (bool): The multiuser status of the map.
317
+
318
+ Returns:
319
+ None
320
+
321
+ Example:
322
+ >>> from geobox.aio import AsyncGeoboxClient
323
+ >>> from geobox.aio.map import AsyncMap
324
+ >>> async with AsyncGeoboxClient() as client:
325
+ >>> map = await AsyncMap.get_map(client, uuid="12345678-1234-5678-1234-567812345678")
326
+ >>> await map.set_multiuser(True)
327
+ """
328
+ data = clean_data({
329
+ 'multiuser': multiuser
330
+ })
331
+ endpoint = urljoin(self.endpoint, 'setMultiuser/')
332
+ response = await self.api.post(endpoint, data, is_json=False)
333
+ self._update_properties(response)
334
+
335
+
336
+
337
+ def wmts(self, scale: int = None) -> str:
338
+ """
339
+ Get the WMTS URL of the map.
340
+
341
+ Args:
342
+ scale (int): The scale of the map. value are: 1, 2
343
+
344
+ Returns:
345
+ str: The WMTS URL of the map.
346
+
347
+ Example:
348
+ >>> from geobox.aio import AsyncGeoboxClient
349
+ >>> from geobox.aio.map import AsyncMap
350
+ >>> async with AsyncGeoboxClient() as client:
351
+ >>> map = await AsyncMap.get_map(client, uuid="12345678-1234-5678-1234-567812345678")
352
+ >>> map.wmts(scale=1)
353
+ """
354
+ endpoint = urljoin(self.api.base_url, f'{self.endpoint}wmts/')
355
+ if scale:
356
+ endpoint = f"{endpoint}?scale={scale}"
357
+
358
+ if not self.api.access_token and self.api.apikey:
359
+ endpoint = join_url_params(endpoint, {"apikey": self.api.apikey})
360
+
361
+ return endpoint
362
+
363
+
364
+ async def share(self, users: List['AsyncUser']) -> None:
365
+ """
366
+ [async] Shares the map with specified users.
367
+
368
+ Args:
369
+ users (List[AsyncUser]): The list of user objects to share the map with.
370
+
371
+ Returns:
372
+ None
373
+
374
+ Example:
375
+ >>> from geobox.aio import AsyncGeoboxClient
376
+ >>> from geobox.aio.map import AsyncMap
377
+ >>> async with AsyncGeoboxClient() as client:
378
+ >>> map = await AsyncMap.get_map(client, uuid="12345678-1234-5678-1234-567812345678")
379
+ >>> users = await client.search_users(search='John')
380
+ >>> await map.share(users=users)
381
+ """
382
+ await super()._share(self.endpoint, users)
383
+
384
+
385
+ async def unshare(self, users: List['AsyncUser']) -> None:
386
+ """
387
+ [async] Unshares the map with specified users.
388
+
389
+ Args:
390
+ users (List[AsyncUser]): The list of user objects to unshare the map with.
391
+
392
+ Returns:
393
+ None
394
+
395
+ Example:
396
+ >>> from geobox.aio import AsyncGeoboxClient
397
+ >>> from geobox.aio.map import AsyncMap
398
+ >>> async with AsyncGeoboxClient() as client:
399
+ >>> map = await AsyncMap.get_map(client, uuid="12345678-1234-5678-1234-567812345678")
400
+ >>> await users = client.search_users(search='John')
401
+ >>> await map.unshare(users=users)
402
+ """
403
+ await super()._unshare(self.endpoint, users)
404
+
405
+
406
+ async def get_shared_users(self, search: str = None, skip: int = 0, limit: int = 10) -> List['AsyncUser']:
407
+ """
408
+ [async] Retrieves the list of users the map is shared with.
409
+
410
+ Args:
411
+ search (str, optional): The search query.
412
+ skip (int, optional): The number of users to skip.
413
+ limit (int, optional): The maximum number of users to retrieve.
414
+
415
+ Returns:
416
+ List[AsyncUser]: The list of shared users.
417
+
418
+ Example:
419
+ >>> from geobox.aio import AsyncGeoboxClient
420
+ >>> from geobox.aio.map import AsyncMap
421
+ >>> async with AsyncGeoboxClient() as client:
422
+ >>> map = await AsyncMap.get_map(client, uuid="12345678-1234-5678-1234-567812345678")
423
+ >>> await map.get_shared_users(search='John', skip=0, limit=10)
424
+ """
425
+ params = {
426
+ 'search': search,
427
+ 'skip': skip,
428
+ 'limit': limit
429
+ }
430
+ return await super()._get_shared_users(self.endpoint, params)
431
+
432
+
433
+ async def seed_cache(self,
434
+ from_zoom: int = None,
435
+ to_zoom: int = None,
436
+ extent: List[float] = None,
437
+ workers: int = 1,
438
+ user_id: int = None,
439
+ scale: int = None) -> List['AsyncTask']:
440
+ """
441
+ [async] Seed the cache of the map.
442
+
443
+ Args:
444
+ from_zoom (int, optional): The zoom level to start caching from.
445
+ to_zoom (int, optional): The zoom level to stop caching at.
446
+ extent (List[float], optional): The extent of the map.
447
+ workers (int, optional): The number of workers to use. default is 1.
448
+ user_id (int, optional): Specific user. privileges required.
449
+ scale (int, optional): The scale of the map.
450
+
451
+ Returns:
452
+ List[AsyncTask]: The task instance of the cache seeding operation.
453
+
454
+ Raises:
455
+ ValueError: If the workers is not in [1, 2, 4, 8, 12, 16, 20, 24].
456
+ ValueError: If the cache seeding fails.
457
+
458
+ Example:
459
+ >>> from geobox.aio import AsyncGeoboxClient
460
+ >>> from geobox.aio.map import AsyncMap
461
+ >>> async with AsyncGeoboxClient() as client:
462
+ >>> map = await AsyncMap.get_map(client, uuid="12345678-1234-5678-1234-567812345678")
463
+ >>> task = await map.seed_cache(from_zoom=0, to_zoom=10, extent=[10, 20, 30, 40], workers=1, scale=1)
464
+ """
465
+ data = {
466
+ 'from_zoom': from_zoom,
467
+ 'to_zoom': to_zoom,
468
+ 'extent': extent,
469
+ 'workers': workers,
470
+ 'user_id': user_id,
471
+ 'scale': scale
472
+ }
473
+ return await super()._seed_cache(self.endpoint, data)
474
+
475
+
476
+ async def update_cache(self,
477
+ from_zoom: int = None,
478
+ to_zoom: int = None,
479
+ extent: List[float] = None,
480
+ user_id: int = None,
481
+ scale: int = None) -> List['AsyncTask']:
482
+ """
483
+ [async] Update the cache of the map.
484
+
485
+ Args:
486
+ from_zoom (int, optional): The zoom level to start caching from.
487
+ to_zoom (int, optional): The zoom level to stop caching at.
488
+ extent (List[float], optional): The extent of the map.
489
+ user_id (int, optional): Specific user. privileges required.
490
+ scale (int, optional): The scale of the map.
491
+
492
+ Returns:
493
+ List[AsyncTask]: The task instance of the cache updating operation.
494
+
495
+ Raises:
496
+ ValueError: If the cache updating fails.
497
+
498
+ Example:
499
+ >>> from geobox.aio import AsyncGeoboxClient
500
+ >>> from geobox.aio.map import AsyncMap
501
+ >>> async with AsyncGeoboxClient() as client:
502
+ >>> map = await AsyncMap.get_map(client, uuid="12345678-1234-5678-1234-567812345678")
503
+ >>> await map.update_cache(from_zoom=0, to_zoom=10, extent=[10, 20, 30, 40], scale=1)
504
+ """
505
+ data = {
506
+ 'from_zoom': from_zoom,
507
+ 'to_zoom': to_zoom,
508
+ 'extent': extent,
509
+ 'user_id': user_id,
510
+ 'scale': scale
511
+ }
512
+ return await super()._update_cache(self.endpoint, data)
513
+
514
+
515
+ async def clear_cache(self) -> None:
516
+ """
517
+ [async] Clear the cache of the map.
518
+
519
+ Returns:
520
+ None
521
+
522
+ Example:
523
+ >>> from geobox.aio import AsyncGeoboxClient
524
+ >>> from geobox.aio.map import AsyncMap
525
+ >>> async with AsyncGeoboxClient() as client:
526
+ >>> map = await AsyncMap.get_map(client, uuid="12345678-1234-5678-1234-567812345678")
527
+ >>> await map.clear_cache()
528
+ """
529
+ return await super()._clear_cache(self.endpoint)
530
+
531
+
532
+ @property
533
+ async def cache_size(self) -> int:
534
+ """
535
+ [async] Get the size of the cache of the map.
536
+
537
+ Returns:
538
+ int: The size of the cache of the map.
539
+
540
+ Example:
541
+ >>> from geobox.aio import AsyncGeoboxClient
542
+ >>> from geobox.aio.map import AsyncMap
543
+ >>> async with AsyncGeoboxClient() as client:
544
+ >>> map = await AsyncMap.get_map(client, uuid="12345678-1234-5678-1234-567812345678")
545
+ >>> await map.cache_size
546
+ """
547
+ return await super()._cache_size(self.endpoint)
548
+
549
+
550
+ @property
551
+ def settings(self) -> Dict:
552
+ """
553
+ Get the settings of the map
554
+
555
+ Returns:
556
+ Dict: the settings of the map.
557
+
558
+ Example:
559
+ >>> from geobox.aio import AsyncGeoboxClient
560
+ >>> from geobox.aio.map import AsyncMap
561
+ >>> async with AsyncGeoboxClient() as client:
562
+ >>> map = await AsyncMap.get_map(uuid="12345678-1234-5678-1234-567812345678")
563
+ >>> map.settings
564
+ """
565
+ return self.json.get('settings', {
566
+ 'general_settings': {},
567
+ 'edit_settings': {},
568
+ 'snap_settings': {},
569
+ 'controls': [],
570
+ 'search_settings': {},
571
+ 'marker_settings': {},
572
+ 'terrain_settings': {},
573
+ 'grid_settings': {},
574
+ 'view_settings': {},
575
+ 'toc_settings': []
576
+ })
577
+
578
+
579
+ async def update_settings(self, settings: Dict) -> Dict:
580
+ """
581
+ [async] Update the settings
582
+
583
+ settings (Dict): settings dictionary
584
+
585
+ Returns:
586
+ Dict: updated settings
587
+
588
+ Example:
589
+ >>> from geobox.aio import AsyncGeoboxClient
590
+ >>> async with AsyncGeoboxClient() as client:
591
+ >>> map1 = await client.get_map(uuid="12345678-1234-5678-1234-567812345678")
592
+ >>> map2 = await client.get_map(uuid="12345678-1234-5678-1234-567812345678")
593
+ >>> await map1.update_settings(map2.settings)
594
+ """
595
+ return await super()._set_settings(self.endpoint, settings)
596
+
597
+
598
+ async def set_settings(self, **kwargs) -> Dict:
599
+ """
600
+ [async] Set the settings of the map using keywords
601
+
602
+ Keyword Args:
603
+ map_unit (str): 'latlng' | 'utm'.
604
+ base_map (str): 'OSM' | 'google' | 'blank'.
605
+ flash_color (str): 'rgb(255,0,0)' (rgb color or rgba color or hex color ).
606
+ highlight_color (str): 'rgb(255,0,0)' (rgb color or rgba color or hex color ).
607
+ selection_color (str): 'rgb(255,0,0)' (rgb color or rgba color or hex color ).
608
+ selectable_layers (str): 'ALL' | null | Comma separated list of layers.
609
+ calendar_type (str): The type of the calendar.
610
+ edit_settings (dict): The settings of the edit.
611
+ snap_tolerance (int): number of pixels for snap tolerance.
612
+ snap_unit (str): pixels.
613
+ snap_mode (str): 'both' | 'edge' | 'vertex'.
614
+ snap_cache (int): number of total features for snap cache.
615
+ controls (List[str]): The controls of the map.
616
+ search_mode (str): 'both' | 'markers' | 'layers'.
617
+ search_layers (str): 'ALL' | null | Comma separated list of layers.
618
+ geosearch (bool): The geosearch of the map.
619
+ remove_unused_tags (bool): The remove unused tags of the map.
620
+ terrain_layer (str): The terrain layer of the map.
621
+ exaggeration (int): The exaggeration of the terrain.
622
+ enable_grid (bool): The enable grid of the map.
623
+ grid_unit (str): The unit of the grid.
624
+ grid_width (int): The width of the grid.
625
+ grid_height (int): The height of the grid.
626
+ grid_minzoom (int): The minzoom of the grid.
627
+ grid_maxzoom (int): The maxzoom of the grid.
628
+ bearing (int): The bearing of the map.
629
+ pitch (int): The pitch of the map.
630
+ center (List[float]): The center of the map.
631
+ zoom (int): The zoom of the map.
632
+ toc_settings (List): The settings of the toc.
633
+ custom_basemaps (List[str]): The custom basemaps of the map.
634
+ show_maptip_on (str): 'ALL' | null | Comma separated list of layers.
635
+ snappable_layers (str): 'ALL' | null | Comma separated list of layers.
636
+
637
+ Returns:
638
+ Dict: The response of the API.
639
+
640
+ Example:
641
+ >>> from geobox.aio import AsyncGeoboxClient
642
+ >>> from geobox.aio.map import AsyncMap
643
+ >>> async with AsyncGeoboxClient() as client:
644
+ >>> map = await AsyncMap.get_map(uuid="12345678-1234-5678-1234-567812345678")
645
+ >>> await map.set_settings(zoom=10)
646
+ """
647
+ general_settings = {'map_unit', 'base_map', 'flash_color', 'highlight_color',
648
+ 'selection_color', 'selectable_layers', 'calendar_type', 'custom_basemaps', 'show_maptip_on'}
649
+ edit_settings = {'editable_layers', 'target_layer'}
650
+ snap_settings = {'snap_tolerance', 'snap_unit', 'snap_mode', 'snap_cache', 'snappable_layers'}
651
+ search_settings = {'search_mode', 'search_layers', 'geosearch'}
652
+ marker_settings = {'remove_unused_tags'}
653
+ terrain_settings = {'terrain_layer', 'exaggeration'}
654
+ grid_settings = {'enable_grid', 'grid_unit', 'grid_width', 'grid_height', 'grid_minzoom', 'grid_maxzoom'}
655
+ view_settings = {'bearing', 'pitch', 'center', 'zoom'}
656
+
657
+ settings = self.settings
658
+
659
+ for key, value in kwargs.items():
660
+ if key in general_settings:
661
+ settings['general_settings'][key] = value
662
+ elif key in edit_settings:
663
+ settings['edit_settings'][key] = value
664
+ elif key in snap_settings:
665
+ settings['snap_settings'][key] = value
666
+ elif key == 'controls':
667
+ settings['controls'] = value
668
+ elif key in search_settings:
669
+ settings['search_settings'][key] = value
670
+ elif key in marker_settings:
671
+ settings['marker_settings'][key] = value
672
+ elif key in terrain_settings:
673
+ settings['terrain_settings'][key] = value
674
+ elif key in grid_settings:
675
+ settings['grid_settings'][key] = value
676
+ elif key in view_settings:
677
+ settings['view_settings'][key] = value
678
+ elif key == 'toc_settings':
679
+ settings['toc_settings'] = value
680
+
681
+ return await super()._set_settings(self.endpoint, settings)
682
+
683
+
684
+ async def get_markers(self) -> Dict:
685
+ """
686
+ [async] Get the markers of the map.
687
+
688
+ Returns:
689
+ Dict: The markers of the map.
690
+
691
+ Example:
692
+ >>> from geobox.aio import AsyncGeoboxClient
693
+ >>> from geobox.aio.map import AsyncMap
694
+ >>> async with AsyncGeoboxClient() as client:
695
+ >>> map = await AsyncMap.get_map(client, uuid="12345678-1234-5678-1234-567812345678")
696
+ >>> await map.get_markers()
697
+ """
698
+ endpoint = urljoin(self.endpoint, 'markers/')
699
+ return await self.api.get(endpoint)
700
+
701
+
702
+ async def set_markers(self, data: Dict) -> Dict:
703
+ """
704
+ [async] Set the markers of the map.
705
+
706
+ Args:
707
+ data (dict): The data of the markers.
708
+
709
+ Returns:
710
+ Dict: The response of the API.
711
+
712
+ Example:
713
+ >>> from geobox.aio import AsyncGeoboxClient
714
+ >>> from geobox.aio.map import AsyncMap
715
+ >>> async with AsyncGeoboxClient() as client:
716
+ >>> map = await AsyncMap.get_map(client, uuid="12345678-1234-5678-1234-567812345678")
717
+ >>> data = {
718
+ ... 'tags': {
719
+ ... '#general': {
720
+ ... 'color': '#ff0000',
721
+ ... }
722
+ ... },
723
+ ... 'locations': [
724
+ ... {
725
+ ... 'id': 1,
726
+ ... 'tag': '#general',
727
+ ... 'name': 'test',
728
+ ... 'geometry': [
729
+ ... 51.13162784422988,
730
+ ... 35.766603814763045
731
+ ... ],
732
+ ... 'description': 'string'
733
+ ... }
734
+ ... ]
735
+ ... }
736
+ >>> await map.set_markers(data)
737
+ """
738
+ endpoint = urljoin(self.endpoint, 'markers/')
739
+ response = await self.api.put(endpoint, data)
740
+ return response
741
+
742
+
743
+ async def get_models(self, json=False) -> Union[List['AsyncModel'], Dict]:
744
+ """
745
+ [async] Get the map models.
746
+
747
+ Args:
748
+ json (bool, optional): If True, return the response as a dictionary.
749
+
750
+ Returns:
751
+ List[AsyncModel] | Dict: map models objects or the response.
752
+
753
+ Example:
754
+ >>> from geobox.aio import AsyncGeoboxClient
755
+ >>> from geobox.aio.map import AsyncMap
756
+ >>> async with AsyncGeoboxClient() as client:
757
+ >>> map = await AsyncMap.get_map(client, uuid="12345678-1234-5678-1234-567812345678")
758
+ >>> await map.get_models(json=True)
759
+ """
760
+ endpoint = urljoin(self.endpoint, 'models/')
761
+ response = await self.api.get(endpoint)
762
+ if not response or json:
763
+ return response
764
+ else:
765
+ return [AsyncModel(self.api, model['obj'], model) for model in response['objects'] if response.get('objects')]
766
+
767
+
768
+ async def set_models(self, data: Dict) -> List['AsyncModel']:
769
+ """
770
+ [async] Set multiple models on the map.
771
+
772
+ Args:
773
+ data (Dict): the data of the models and their location on the map. check the example for the data structure.
774
+
775
+ Returns:
776
+ List[AsyncModel]: the map models objects
777
+
778
+ Example:
779
+ >>> from geobox.aio import AsyncGeoboxClient
780
+ >>> from geobox.aio.map import AsyncMap
781
+ >>> async with AsyncGeoboxClient() as client:
782
+ >>> map = await AsyncMap.get_map(uuid="12345678-1234-5678-1234-567812345678")
783
+ >>> data = {'objects': [
784
+ ... {
785
+ ... "name": "transmission_tower",
786
+ ... "alias": None,
787
+ ... "desc": None,
788
+ ... "obj": "12345678-1234-5678-1234-567812345678",
789
+ ... "loc": [53.1859045261684, 33.37762747390032, 0.0],
790
+ ... "rotation": [0.0, 0.0, 0.0],
791
+ ... "scale": 1.0,
792
+ ... "min_zoom": 0,
793
+ ... "max_zoom": 22
794
+ ... }
795
+ ... ]}
796
+ >>> await map.set_models(data)
797
+ """
798
+ endpoint = urljoin(self.endpoint, 'models/')
799
+ response = await self.api.put(endpoint, data)
800
+ return [AsyncModel(self.api, model['obj'], model) for model in response['objects'] if response.get('objects')]
801
+
802
+
803
+ async def add_model(self,
804
+ model: 'AsyncModel',
805
+ location: List[float],
806
+ rotation: List[float] = [0.0, 0.0, 0.0],
807
+ scale: float = 1.0,
808
+ min_zoom: int = 0,
809
+ max_zoom: int = 22,
810
+ alias: str = None,
811
+ description: str = None) -> List['AsyncModel']:
812
+ """
813
+ [async] Add a model the map.
814
+
815
+ Args:
816
+ model (Model): The model object.
817
+ location (List[float]): location of the model on the map. a list with three float values.
818
+ rotation (List[float], optional): rotation of the model on the map. a list with three float vlaues. default is [0.0, 0.0, 0.0].
819
+ scale (float, optional): the scale of the model on the map.
820
+ min_zoom (int, optional): minimum zoom level.
821
+ max_zoom (int, optional): maximum zoom level.
822
+ alias (str, optional): alias of the model on the map.
823
+ description (str, optional): the description of the model on the map.
824
+
825
+ Returns:
826
+ List['AsyncModel']: The map model objects
827
+
828
+ Example:
829
+ >>> from geobox.aio import AsyncGeoboxClient
830
+ >>> from geobox.aio.map import AsyncMap
831
+ >>> async with AsyncGeoboxClient() as client:
832
+ >>> map = await AsyncMap.get_map(client, uuid="12345678-1234-5678-1234-567812345678")
833
+ >>> model = await client.get_model(uuid="12345678-1234-5678-1234-567812345678")
834
+ >>> await map.add_model(model=model,
835
+ ... location=[53.53, 33.33, 0.0],
836
+ ... rotation=[0.0, 0.0, 0.0],
837
+ ... scale=1.0,
838
+ ... min_zoom=0,
839
+ ... max_zoom=22,
840
+ ... alias=None,
841
+ ... description=None)
842
+ """
843
+ data = await self.get_models(json=True)
844
+ if data and data.get('objects') and isinstance(data['objects'], list):
845
+ data.get('objects').append({
846
+ 'name': model.name,
847
+ 'alias': alias,
848
+ 'desc': description,
849
+ 'obj': model.uuid,
850
+ 'loc': location,
851
+ 'rotation': rotation,
852
+ 'scale': scale,
853
+ 'min_zoom': min_zoom,
854
+ 'max_zoom': max_zoom
855
+ })
856
+ else:
857
+ data = {'objects':[
858
+ {
859
+ 'name': model.name,
860
+ 'alias': alias,
861
+ 'desc': description,
862
+ 'obj': model.uuid,
863
+ 'loc': location,
864
+ 'rotation': rotation,
865
+ 'scale': scale,
866
+ 'min_zoom': min_zoom,
867
+ 'max_zoom': max_zoom
868
+ }
869
+ ]
870
+ }
871
+
872
+ endpoint = urljoin(self.endpoint, 'models/')
873
+ response = await self.api.put(endpoint, data)
874
+ return [AsyncModel(self.api, model['obj'], model) for model in response['objects']]
875
+
876
+
877
+ def image_tile_url(self, x: str = '{x}', y: str = '{y}', z: str = '{z}', format='.png') -> str:
878
+ """
879
+ Get map image tile url
880
+
881
+ Returns:
882
+ str: the image tile url
883
+
884
+ Example:
885
+ >>> from geobox.aio import AsyncGeoboxClient
886
+ >>> from geobox.aio.map import AsyncMap
887
+ >>> async with AsyncGeoboxClient() as client:
888
+ >>> map = await AsyncMap.get_map(client, uuid="12345678-1234-5678-1234-567812345678")
889
+ >>> map.image_tile_url()
890
+ >>> map.image_tile_url(x=1, y=2, z=3, format='.pbf')
891
+ """
892
+ endpoint = f"{self.api.base_url}{self.endpoint}tiles/{z}/{x}/{y}{format}"
893
+
894
+ if not self.api.access_token and self.api.apikey:
895
+ endpoint = f'{endpoint}?apikey={self.api.apikey}'
896
+
897
+ return endpoint
898
+
899
+
900
+ async def export_map_to_image(self, bbox: List, width: int, height: int) -> 'AsyncTask':
901
+ """
902
+ [async] Export the map to image
903
+
904
+ Args:
905
+ bbox (List): e.g. [50.275, 35.1195, 51.4459, 36.0416]
906
+ width (int): minimum: 10, maximum: 10000
907
+ height (int): minimum: 10, maximum: 10000
908
+
909
+ Returns:
910
+ Task: the task object
911
+
912
+ Example:
913
+ >>> from geobox.aio import AsyncGeoboxClient
914
+ >>> from geobox.aio.map import AsyncMap
915
+ >>> async with AsyncGeoboxClient() as client:
916
+ >>> map = await AsyncMap.get_map(client, uuid="12345678-1234-5678-1234-567812345678")
917
+ >>> task = await map.export_map_to_image(bbox=[50.275, 35.1195, 51.4459, 36.0416],
918
+ ... width=1024,
919
+ ... height=1024)
920
+ """
921
+ data = clean_data({
922
+ 'uuid': self.uuid,
923
+ 'bbox': bbox,
924
+ 'width': width,
925
+ 'height': height
926
+ })
927
+ query_string = urlencode(data)
928
+ endpoint = urljoin(self.endpoint, 'export/')
929
+ endpoint = f"{endpoint}?{query_string}"
930
+ response = await self.api.post(endpoint)
931
+ return await self.api.get_task(response['task_id'])
932
+
933
+
934
+ async def get_attachments(self, **kwargs) -> List['AsyncAttachment']:
935
+ """
936
+ [async] Get the resouces attachments
937
+
938
+ Keyword Args:
939
+ element_id (str): the id of the element with attachment.
940
+ search (str): search term for keyword-based searching among all textual fields.
941
+ order_by (str): comma separated list of fields for sorting results [field1 A|D, field2 A|D, …]. e.g. name A, type D. NOTE: "A" denotes ascending order and "D" denotes descending order.
942
+ skip (int): Number of items to skip. default is 0.
943
+ limit (int): Number of items to return. default is 10.
944
+ return_count (bool): Whether to return total count. default is False.
945
+
946
+ Returns:
947
+ List[Attachment] | int: A list of attachments instances or the total number of attachments.
948
+
949
+ Raises:
950
+ TypeError: if the resource type is not supported
951
+
952
+ Example:
953
+ >>> from geobox.aio import AsyncGeoboxClient
954
+ >>> from geobox.aio.map import AsyncMap
955
+ >>> async with AsyncGeoboxClient() as client:
956
+ >>> map = await AsyncMap.get_map(client, uuid="12345678-1234-5678-1234-567812345678")
957
+ >>> await map.get_attachments()
958
+ """
959
+ from .attachment import AsyncAttachment
960
+
961
+ return await AsyncAttachment.get_attachments(self.api, resource=self, **kwargs)
962
+
963
+
964
+ async def create_attachment(self,
965
+ name: str,
966
+ loc_x: int,
967
+ loc_y: int,
968
+ file: 'AsyncFile',
969
+ feature: 'AsyncFeature' = None,
970
+ display_name: str = None,
971
+ description: str = None) -> 'AsyncAttachment':
972
+ """
973
+ [async] Create a new Attachment.
974
+
975
+ Args:
976
+ name (str): The name of the scene.
977
+ loc_x (int): x parameter of the attachment location.
978
+ loc_y (int): y parameter of the attachment location.
979
+ file (File): the file object.
980
+ feature (Feature, optional): the feature object.
981
+ display_name (str, optional): The display name of the scene.
982
+ description (str, optional): The description of the scene.
983
+
984
+ Returns:
985
+ Attachment: The newly created Attachment instance.
986
+
987
+ Raises:
988
+ ValidationError: If the Attachment data is invalid.
989
+
990
+ Example:
991
+ >>> from geobox.aio import AsyncGeoboxClient
992
+ >>> from geobox.aio.map import AsyncMap
993
+ >>> async with AsyncGeoboxClient() as client:
994
+ >>> map = await AsyncMap.get_map(client, uuid="12345678-1234-5678-1234-567812345678")
995
+ >>> files = await client.get_files()
996
+ >>> file = files[0]
997
+ >>> await map.create_attachment(name='test', loc_x=10, loc_y=10, file=file)
998
+ """
999
+ from .attachment import AsyncAttachment
1000
+
1001
+ return await AsyncAttachment.create_attachment(self.api,
1002
+ name=name,
1003
+ loc_x=loc_x,
1004
+ loc_y=loc_y,
1005
+ resource=self,
1006
+ file=file,
1007
+ feature=feature,
1008
+ display_name=display_name,
1009
+ description=description)
1010
+
1011
+
1012
+ def to_sync(self, sync_client: 'GeoboxClient') -> 'Map':
1013
+ """
1014
+ Switch to sync version of the map instance to have access to the sync methods
1015
+
1016
+ Args:
1017
+ sync_client (GeoboxClient): The sync version of the GeoboxClient instance for making requests.
1018
+
1019
+ Returns:
1020
+ Map: the sync instance of the map.
1021
+
1022
+ Example:
1023
+ >>> from geobox import Geoboxclient
1024
+ >>> from geobox.aio import AsyncGeoboxClient
1025
+ >>> from geobox.aio.map import AsyncMap
1026
+ >>> client = GeoboxClient()
1027
+ >>> async with AsyncGeoboxClient() as async_client:
1028
+ >>> map = await AsyncMap.get_map(async_client, uuid="12345678-1234-5678-1234-567812345678")
1029
+ >>> sync_map = map.to_sync(client)
1030
+ """
1031
+ from ..map import Map
1032
+
1033
+ return Map(api=sync_client, uuid=self.uuid, data=self.data)