geobox 1.4.0__py3-none-any.whl → 1.4.2__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.
geobox/api.py CHANGED
@@ -29,7 +29,7 @@ from .route import Routing
29
29
  from .plan import Plan
30
30
  from .dashboard import Dashboard
31
31
  from .basemap import Basemap
32
- from .attachment import Attachment, AttachmentResourceType
32
+ from .attachment import Attachment
33
33
  from .apikey import ApiKey
34
34
  from .log import Log
35
35
  from .usage import Usage, UsageScale, UsageParam
@@ -2294,13 +2294,12 @@ class GeoboxClient:
2294
2294
  return Basemap.proxy_basemap(self, url)
2295
2295
 
2296
2296
 
2297
- def get_attachments(self, resource_type: AttachmentResourceType, resource_uuid: str, **kwargs) -> Union[List['Attachment'], int]:
2297
+ def get_attachments(self, resource: Union['Map', 'VectorLayer', 'VectorLayerView'], **kwargs) -> List['Attachment']:
2298
2298
  """
2299
- Get list of attachments with optional filtering and pagination.
2299
+ Get the resouces attachments
2300
2300
 
2301
2301
  Args:
2302
- resource_type (AttachmentResourceType): The resource type of the attachment. options are: Map, Vector, View
2303
- resource_uuid (str): The Resoource uuid of the attachment.
2302
+ resource (Map | VectorLayer | VectorLayerView): options are: Map, Vector, View objects
2304
2303
 
2305
2304
  Keyword Args:
2306
2305
  element_id (str): the id of the element with attachment.
@@ -2313,12 +2312,17 @@ class GeoboxClient:
2313
2312
  Returns:
2314
2313
  List[Attachment] | int: A list of attachments instances or the total number of attachments.
2315
2314
 
2315
+ Raises:
2316
+ TypeError: if the resource type is not supported
2317
+
2316
2318
  Example:
2317
2319
  >>> from geobox import GeoboxClient
2320
+ >>> from geobox.attachment import Attachment
2318
2321
  >>> client = GeoboxClient()
2319
- >>> attachments = client.get_attachments(q="name LIKE '%My attachment%'")
2322
+ >>> map = client.get_maps()[0]
2323
+ >>> attachments = client.get_attachments(resource=map)
2320
2324
  """
2321
- return Attachment.get_attachments(self, resource_type, resource_uuid, **kwargs)
2325
+ return Attachment.get_attachments(self, resource=resource, **kwargs)
2322
2326
 
2323
2327
 
2324
2328
  def create_attachment(self,
geobox/attachment.py CHANGED
@@ -3,7 +3,6 @@ from urllib.parse import urljoin
3
3
 
4
4
  from .base import Base
5
5
  from .utils import clean_data
6
- from .enums import AttachmentResourceType
7
6
  from .map import Map
8
7
  from .vectorlayer import VectorLayer
9
8
  from .view import VectorLayerView
@@ -56,14 +55,13 @@ class Attachment(Base):
56
55
 
57
56
 
58
57
  @classmethod
59
- def get_attachments(cls, api: 'GeoboxClient', resource_type: AttachmentResourceType, resource_uuid: str, **kwargs) -> Union[List['Attachment'], int]:
58
+ def get_attachments(cls, api: 'GeoboxClient', resource: Union['Map', 'VectorLayer', 'VectorLayerView'], **kwargs) -> Union[List['Attachment'], int]:
60
59
  """
61
60
  Get list of attachments with optional filtering and pagination.
62
61
 
63
62
  Args:
64
63
  api (GeoboxClient): The GeoboxClient instance for making requests.
65
- resource_type (AttachmentResourceType): The resource type of the attachment. options are: Map, Vector, View
66
- resource_uuid (str): The Resoource uuid of the attachment.
64
+ resource (Map | VectorLayer | VectorLayerView): options are: Map, Vector, View objects
67
65
 
68
66
  Keyword Args:
69
67
  element_id (str): the id of the element with attachment.
@@ -76,17 +74,34 @@ class Attachment(Base):
76
74
  Returns:
77
75
  List[Attachment] | int: A list of attachments instances or the total number of attachments.
78
76
 
77
+ Raises:
78
+ TypeError: if the resource type is not supported
79
+
79
80
  Example:
80
81
  >>> from geobox import GeoboxClient
81
82
  >>> from geobox.attachment import Attachment
82
83
  >>> client = GeoboxClient()
83
- >>> attachments = Attachment.get_attachments(client, q="name LIKE '%My attachment%'")
84
+ >>> map = client.get_maps()[0]
85
+ >>> attachments = Attachment.get_attachments(client, resource=map, q="name LIKE '%My attachment%'")
84
86
  or
85
- >>> attachments = client.get_attachments(q="name LIKE '%My attachment%'")
87
+ >>> attachments = client.get_attachments(resource=map, q="name LIKE '%My attachment%'")
86
88
  """
89
+ if type(resource) == VectorLayer:
90
+ resource_type = 'vector'
91
+
92
+ elif type(resource) == VectorLayerView:
93
+ resource_type = 'view'
94
+
95
+ elif type(resource) == Map:
96
+ resource_type = 'map'
97
+
98
+ else:
99
+ raise TypeError('resource must be a vectorlayer or view or map object')
100
+
101
+
87
102
  params = {
88
- 'resource_type': resource_type.value,
89
- 'resource_uuid': resource_uuid,
103
+ 'resource_type': resource_type,
104
+ 'resource_uuid': resource.uuid,
90
105
  'element_id': kwargs.get('element_id'),
91
106
  'search': kwargs.get('search'),
92
107
  'order_by': kwargs.get('order_by'),
@@ -155,13 +170,13 @@ class Attachment(Base):
155
170
  ... description="Attachment Description")
156
171
  """
157
172
  if isinstance(resource, VectorLayer):
158
- resource_type = AttachmentResourceType.Vector.value
173
+ resource_type = 'vector'
159
174
 
160
175
  if isinstance(resource, VectorLayerView):
161
- resource_type = AttachmentResourceType.View.value
176
+ resource_type = 'view'
162
177
 
163
178
  if isinstance(resource, Map):
164
- resource_type = AttachmentResourceType.Map.value
179
+ resource_type = 'map'
165
180
 
166
181
  data = {
167
182
  "name": name,
@@ -171,7 +186,7 @@ class Attachment(Base):
171
186
  "loc_y": loc_y,
172
187
  "resource_type": resource_type,
173
188
  "resource_uuid": resource.uuid,
174
- "element_id": feature.id,
189
+ "element_id": feature.id if feature else None,
175
190
  "file_id": file.id
176
191
  }
177
192
  return super()._create(api, cls.BASE_ENDPOINT, data, factory_func=lambda api, item: Attachment(api, item['id'], item))
geobox/basemap.py CHANGED
@@ -95,8 +95,7 @@ class Basemap(Base):
95
95
  Returns:
96
96
  str: the thumbnail url
97
97
  """
98
- endpoint = f"{self.api.base_url}{self.endpoint}/thumbnail.png"
99
- return endpoint
98
+ return super().thumbnail()
100
99
 
101
100
 
102
101
  @property
geobox/enums.py CHANGED
@@ -272,14 +272,6 @@ class UserStatus(Enum):
272
272
  DISABLED = "Disabled"
273
273
 
274
274
 
275
- class AttachmentResourceType(Enum):
276
- Map = "map"
277
-
278
- Vector = "vector"
279
-
280
- View = "view"
281
-
282
-
283
275
  class MaxLogPolicy(Enum):
284
276
  OverwriteFirstLog = "OverwriteFirstLog"
285
277
 
geobox/log.py CHANGED
@@ -6,6 +6,7 @@ from .base import Base
6
6
 
7
7
  if TYPE_CHECKING:
8
8
  from . import GeoboxClient
9
+ from .user import User
9
10
 
10
11
 
11
12
  class Log(Base):
@@ -98,4 +99,22 @@ class Log(Base):
98
99
  >>> log.delete()
99
100
  """
100
101
  super().delete(self.endpoint)
101
- self.log_id = None
102
+ self.log_id = None
103
+
104
+
105
+ @property
106
+ def user(self) -> Union['User', None]:
107
+ """
108
+ Get the owner user for the log
109
+
110
+ Returns:
111
+ User | None: if the log has owner user
112
+
113
+ Example:
114
+ >>> from geobox import Geobox
115
+ >>> from geopox.log import Log
116
+ >>> client = GeoboxClient()
117
+ >>> log = Log.get_logs(client)[0]
118
+ >>> log.user
119
+ """
120
+ return self.api.get_user(self.owner_id)
geobox/map.py CHANGED
@@ -4,11 +4,15 @@ from urllib.parse import urljoin, urlencode
4
4
  from .base import Base
5
5
  from .utils import clean_data, join_url_params
6
6
  from .model3d import Model
7
+ from .file import File
8
+ from .feature import Feature
7
9
 
8
10
  if TYPE_CHECKING:
9
11
  from . import GeoboxClient
10
12
  from .user import User
11
13
  from .task import Task
14
+ from .attachment import Attachment
15
+
12
16
 
13
17
 
14
18
  class Map(Base):
@@ -570,11 +574,30 @@ class Map(Base):
570
574
  'view_settings': {},
571
575
  'toc_settings': []
572
576
  })
577
+
578
+
579
+ def update_settings(self, settings: Dict) -> Dict:
580
+ """
581
+ Update the settings
582
+
583
+ settings (Dict): settings dictionary
584
+
585
+ Returns:
586
+ Dict: updated settings
587
+
588
+ Example:
589
+ >>> from geobox import GeoboxClient
590
+ >>> client = GeoboxClient()
591
+ >>> map1 = client.get_map(uuid="12345678-1234-5678-1234-567812345678")
592
+ >>> map2 = client.get_map(uuid="12345678-1234-5678-1234-567812345678")
593
+ >>> map1.update_settings(map2.settings)
594
+ """
595
+ return super()._set_settings(self.endpoint, settings)
573
596
 
574
597
 
575
598
  def set_settings(self, **kwargs) -> Dict:
576
599
  """
577
- Set the settings of the map.
600
+ Set the settings of the map using keywords
578
601
 
579
602
  Keyword Args:
580
603
  map_unit (str): 'latlng' | 'utm'.
@@ -732,7 +755,7 @@ class Map(Base):
732
755
  if not response or json:
733
756
  return response
734
757
  else:
735
- return [Model(self.api, model['obj'], model) for model in response['objects']]
758
+ return [Model(self.api, model['obj'], model) for model in response['objects'] if response.get('objects')]
736
759
 
737
760
 
738
761
  def set_models(self, data: Dict) -> List['Model']:
@@ -767,7 +790,7 @@ class Map(Base):
767
790
  """
768
791
  endpoint = urljoin(self.endpoint, 'models/')
769
792
  response = self.api.put(endpoint, data)
770
- return [Model(self.api, model['obj'], model) for model in response['objects']]
793
+ return [Model(self.api, model['obj'], model) for model in response['objects'] if response.get('objects')]
771
794
 
772
795
 
773
796
  def add_model(self,
@@ -899,3 +922,80 @@ class Map(Base):
899
922
  endpoint = f"{endpoint}?{query_string}"
900
923
  response = self.api.post(endpoint)
901
924
  return self.api.get_task(response['task_id'])
925
+
926
+
927
+ def get_attachments(self, **kwargs) -> List['Attachment']:
928
+ """
929
+ Get the resouces attachments
930
+
931
+ Keyword Args:
932
+ element_id (str): the id of the element with attachment.
933
+ search (str): search term for keyword-based searching among all textual fields.
934
+ 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.
935
+ skip (int): Number of items to skip. default is 0.
936
+ limit (int): Number of items to return. default is 10.
937
+ return_count (bool): Whether to return total count. default is False.
938
+
939
+ Returns:
940
+ List[Attachment] | int: A list of attachments instances or the total number of attachments.
941
+
942
+ Raises:
943
+ TypeError: if the resource type is not supported
944
+
945
+ Example:
946
+ >>> from geobox import GeoboxClient
947
+ >>> from geobox.map import Map
948
+ >>> client = GeoboxClient()
949
+ >>> map = Map.get_map(client, uuid="12345678-1234-5678-1234-567812345678")
950
+ >>> map.get_attachments()
951
+ """
952
+ from .attachment import Attachment
953
+
954
+ return Attachment.get_attachments(self.api, resource=self, **kwargs)
955
+
956
+
957
+ def create_attachment(self,
958
+ name: str,
959
+ loc_x: int,
960
+ loc_y: int,
961
+ file: 'File',
962
+ feature: 'Feature' = None,
963
+ display_name: str = None,
964
+ description: str = None) -> 'Attachment':
965
+ """
966
+ Create a new Attachment.
967
+
968
+ Args:
969
+ name (str): The name of the scene.
970
+ loc_x (int): x parameter of the attachment location.
971
+ loc_y (int): y parameter of the attachment location.
972
+ file (File): the file object.
973
+ feature (Feature, optional): the feature object.
974
+ display_name (str, optional): The display name of the scene.
975
+ description (str, optional): The description of the scene.
976
+
977
+ Returns:
978
+ Attachment: The newly created Attachment instance.
979
+
980
+ Raises:
981
+ ValidationError: If the Attachment data is invalid.
982
+
983
+ Example:
984
+ >>> from geobox import GeoboxClient
985
+ >>> from geobox.map import Map
986
+ >>> client = GeoboxClient()
987
+ >>> map = Map.get_map(client, uuid="12345678-1234-5678-1234-567812345678")
988
+ >>> file = client.get_files()[0]
989
+ >>> map.create_attachment(name='test', loc_x=10, loc_y=10, file=file)
990
+ """
991
+ from .attachment import Attachment
992
+
993
+ return Attachment.create_attachment(self.api,
994
+ name=name,
995
+ loc_x=loc_x,
996
+ loc_y=loc_y,
997
+ resource=self,
998
+ file=file,
999
+ feature=feature,
1000
+ display_name=display_name,
1001
+ description=description)
geobox/model3d.py CHANGED
@@ -1,5 +1,10 @@
1
1
  from typing import Dict, List, Optional, Optional, Union, TYPE_CHECKING
2
2
  from urllib.parse import urljoin, urlencode
3
+ import os
4
+ import zipfile
5
+ import sys
6
+ import requests
7
+ import mimetypes
3
8
 
4
9
  from .base import Base
5
10
  from .exception import ApiRequestError
@@ -216,33 +221,113 @@ class Model(Base):
216
221
  super().delete(self.endpoint)
217
222
 
218
223
 
219
- def get_content(self) -> bytes:
224
+ def _get_save_path(self, save_path: str = None) -> str:
220
225
  """
221
- Get the raw content of the 3D model.
226
+ Get the path where the file should be saved.
227
+
228
+ Args:
229
+ save_path (str, optional): The path to save the file.
222
230
 
223
231
  Returns:
224
- bytes: The raw content of the 3D model in glTF format.
232
+ str: The path where the file is saved.
233
+
234
+ Raises:
235
+ ValueError: If save_path does not end with a '/'.
236
+
237
+ Example:
238
+ >>> from geobox import GeoboxClient
239
+ >>> from geobox.file import File
240
+ >>> from geobox import GeoboxClient
241
+ >>> client = GeoboxClient()
242
+ >>> file_path = File.get_file(client, uuid="12345678-1234-5678-1234-567812345678")
243
+ """
244
+ # If save_path is provided, check if it ends with a '/'
245
+ if save_path and save_path.endswith('/'):
246
+ return f'{save_path}'
247
+
248
+ if save_path and not save_path.endswith('/'):
249
+ raise ValueError("save_path must end with a '/'")
250
+
251
+ return os.getcwd()
252
+
253
+
254
+ def _create_progress_bar(self) -> 'tqdm':
255
+ """Creates a progress bar for the task."""
256
+ try:
257
+ from tqdm.auto import tqdm
258
+ except ImportError:
259
+ from .api import logger
260
+ logger.warning("[tqdm] extra is required to show the progress bar. install with: pip insatll geobox[tqdm]")
261
+ return None
262
+
263
+ return tqdm(unit="B",
264
+ total=int(self.size),
265
+ file=sys.stdout,
266
+ dynamic_ncols=True,
267
+ desc="Downloading",
268
+ unit_scale=True,
269
+ unit_divisor=1024,
270
+ ascii=True
271
+ )
272
+
273
+
274
+ def download(self, save_path: str = None, progress_bar: bool = True) -> str:
275
+ """
276
+ Download the 3D model, save it as a .glb file, zip it, and return the zip file path.
277
+
278
+ Args:
279
+ save_path (str, optional): Directory where the file should be saved.
280
+ progress_bar (bool, optional): Whether to show a progress bar. Default: True
281
+
282
+ Returns:
283
+ str: Path to the .zip file containing the .glb model.
225
284
 
226
285
  Raises:
227
286
  ApiRequestError: If the API request fails.
228
287
 
229
288
  Example:
230
289
  >>> from geobox import GeoboxClient
231
- >>> from geobox.model3d import Model
232
290
  >>> client = GeoboxClient()
233
- >>> model = Model.get_model(api=client, uuid="12345678-1234-5678-1234-567812345678")
234
- >>> content = model.get_content()
235
- >>> # Save the content to a file
236
- >>> with open('model.gltf', 'wb') as f:
237
- ... f.write(content)
291
+ >>> model = client.get_models()[0]
292
+ >>> model.get_content()
238
293
  """
239
- endpoint = urljoin(self.api.base_url, f'{self.endpoint}/content/')
240
- response = self.api.session.get(endpoint)
241
-
242
- if response.status_code != 200:
243
- raise ApiRequestError(f"Failed to get model content: {response.status_code}")
244
-
245
- return response.content
294
+ if not self.uuid:
295
+ raise ValueError("Model UUID is required to download content")
296
+
297
+ if self.data.get('obj'):
298
+ model = self.api.get_model(self.obj)
299
+ else:
300
+ model = self
301
+
302
+ save_path = model._get_save_path(save_path)
303
+ os.makedirs(save_path, exist_ok=True)
304
+
305
+ endpoint = urljoin(model.api.base_url, f"{model.endpoint}/content/")
306
+ with model.api.session.get(endpoint, stream=True) as response:
307
+ if response.status_code != 200:
308
+ raise ApiRequestError(f"Failed to get model content: {response.status_code}")
309
+
310
+ glb_filename = f"{model.name}.glb"
311
+ glb_path = os.path.join(save_path, glb_filename)
312
+
313
+ with open(glb_path, "wb") as f:
314
+ pbar = model._create_progress_bar() if progress_bar else None
315
+ for chunk in response.iter_content(chunk_size=8192):
316
+ f.write(chunk)
317
+ if pbar:
318
+ pbar.update(len(chunk))
319
+ pbar.refresh()
320
+ if pbar:
321
+ pbar.close()
322
+
323
+ zip_filename = f"{model.name}.zip"
324
+ zip_path = os.path.join(save_path, zip_filename)
325
+ with zipfile.ZipFile(zip_path, "w", zipfile.ZIP_DEFLATED) as zipf:
326
+ zipf.write(glb_path, arcname=os.path.basename(glb_path))
327
+
328
+ os.remove(glb_path)
329
+
330
+ return os.path.abspath(zip_path)
246
331
 
247
332
 
248
333
  @property
geobox/mosaic.py CHANGED
@@ -401,6 +401,25 @@ class Mosaic(Raster):
401
401
  """
402
402
  return super().settings
403
403
 
404
+
405
+ def update_settings(self, settings: Dict) -> Dict:
406
+ """
407
+ Update the settings
408
+
409
+ settings (Dict): settings dictionary
410
+
411
+ Returns:
412
+ Dict: updated settings
413
+
414
+ Example:
415
+ >>> from geobox import GeoboxClient
416
+ >>> client = GeoboxClient()
417
+ >>> mosaic1 = client.get_mosaic(uuid="12345678-1234-5678-1234-567812345678")
418
+ >>> mosaic2 = client.get_mosaic(uuid="12345678-1234-5678-1234-567812345678")
419
+ >>> mosaic1.update_settings(mosaic2.settings)
420
+ """
421
+ return super().update_settings(settings)
422
+
404
423
 
405
424
  def set_settings(self, **kwargs) -> None:
406
425
  """
geobox/query.py CHANGED
@@ -179,7 +179,7 @@ class Query(Base):
179
179
 
180
180
 
181
181
  @classmethod
182
- def create_query(cls, api: 'GeoboxClient', name: str, display_name: str = None, sql: str = None, params: List = None) -> 'Query':
182
+ def create_query(cls, api: 'GeoboxClient', name: str, display_name: str = None, description:str = None, sql: str = None, params: List = None) -> 'Query':
183
183
  """
184
184
  Creates a new query.
185
185
 
@@ -187,6 +187,7 @@ class Query(Base):
187
187
  api (Api): The GeoboxClient instance for making requests.
188
188
  name (str): The name of the query.
189
189
  display_name (str, optional): The display name of the query.
190
+ description (str, optional): The description of the query.
190
191
  sql (str, optional): The SQL statement for the query.
191
192
  params (list, optional): The parameters for the SQL statement.
192
193
 
@@ -204,6 +205,7 @@ class Query(Base):
204
205
  data = {
205
206
  "name": name,
206
207
  "display_name": display_name,
208
+ "description": description,
207
209
  "sql": sql,
208
210
  "params": params
209
211
  }
geobox/raster.py CHANGED
@@ -641,6 +641,25 @@ class Raster(Base):
641
641
  >>> raster.settings
642
642
  """
643
643
  return super()._get_settings(self.endpoint)
644
+
645
+
646
+ def update_settings(self, settings: Dict) -> Dict:
647
+ """
648
+ Update the settings
649
+
650
+ settings (Dict): settings dictionary
651
+
652
+ Returns:
653
+ Dict: updated settings
654
+
655
+ Example:
656
+ >>> from geobox import GeoboxClient
657
+ >>> client = GeoboxClient()
658
+ >>> raster1 = client.get_raster(uuid="12345678-1234-5678-1234-567812345678")
659
+ >>> raster2 = client.get_raster(uuid="12345678-1234-5678-1234-567812345678")
660
+ >>> raster1.update_settings(raster2.settings)
661
+ """
662
+ return super()._set_settings(self.endpoint, settings)
644
663
 
645
664
 
646
665
  def set_settings(self, **kwargs) -> None:
geobox/vectorlayer.py CHANGED
@@ -11,12 +11,13 @@ from .task import Task
11
11
  from .enums import InputGeomType, FileOutputFormat
12
12
  from .version import VectorLayerVersion
13
13
 
14
-
15
14
  if TYPE_CHECKING:
16
15
  from .api import GeoboxClient
17
16
  from .view import VectorLayerView
18
17
  from .user import User
19
18
  from .file import File
19
+ from .attachment import Attachment
20
+
20
21
 
21
22
  class VectorLayer(Base):
22
23
  """
@@ -1061,6 +1062,25 @@ class VectorLayer(Base):
1061
1062
  >>> setting = layer.setting
1062
1063
  """
1063
1064
  return super()._get_settings(endpoint=self.endpoint)
1065
+
1066
+
1067
+ def update_settings(self, settings: Dict) -> Dict:
1068
+ """
1069
+ Update the settings
1070
+
1071
+ settings (Dict): settings dictionary
1072
+
1073
+ Returns:
1074
+ Dict: updated settings
1075
+
1076
+ Example:
1077
+ >>> from geobox import GeoboxClient
1078
+ >>> client = GeoboxClient()
1079
+ >>> layer1 = client.get_vector(uuid="12345678-1234-5678-1234-567812345678")
1080
+ >>> layer2 = client.get_vector(uuid="12345678-1234-5678-1234-567812345678")
1081
+ >>> layer1.update_settings(layer2.settings)
1082
+ """
1083
+ return super()._set_settings(self.endpoint, settings)
1064
1084
 
1065
1085
 
1066
1086
  def set_settings(self, **kwargs) -> Dict:
@@ -1227,4 +1247,81 @@ class VectorLayer(Base):
1227
1247
  >>> layer.prune_edited_areas()
1228
1248
  """
1229
1249
  endpoint = urljoin(self.endpoint, 'prune/')
1230
- return self.api.post(endpoint)
1250
+ return self.api.post(endpoint)
1251
+
1252
+
1253
+ def get_attachments(self, **kwargs) -> List['Attachment']:
1254
+ """
1255
+ Get the resouces attachments
1256
+
1257
+ Keyword Args:
1258
+ element_id (str): the id of the element with attachment.
1259
+ search (str): search term for keyword-based searching among all textual fields.
1260
+ 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.
1261
+ skip (int): Number of items to skip. default is 0.
1262
+ limit (int): Number of items to return. default is 10.
1263
+ return_count (bool): Whether to return total count. default is False.
1264
+
1265
+ Returns:
1266
+ List[Attachment] | int: A list of attachments instances or the total number of attachments.
1267
+
1268
+ Raises:
1269
+ TypeError: if the resource type is not supported
1270
+
1271
+ Example:
1272
+ >>> from geobox import GeoboxClient
1273
+ >>> from geobox.vectorlayer import VectorLayer
1274
+ >>> client = GeoboxClient()
1275
+ >>> layer = VectorLayer.get_vector(api=client, uuid="12345678-1234-5678-1234-567812345678")
1276
+ >>> layer.get_attachments()
1277
+ """
1278
+ from .attachment import Attachment
1279
+
1280
+ return Attachment.get_attachments(self.api, resource=self, **kwargs)
1281
+
1282
+
1283
+ def create_attachment(self,
1284
+ name: str,
1285
+ loc_x: int,
1286
+ loc_y: int,
1287
+ file: 'File',
1288
+ feature: 'Feature' = None,
1289
+ display_name: str = None,
1290
+ description: str = None) -> 'Attachment':
1291
+ """
1292
+ Create a new Attachment.
1293
+
1294
+ Args:
1295
+ name (str): The name of the scene.
1296
+ loc_x (int): x parameter of the attachment location.
1297
+ loc_y (int): y parameter of the attachment location.
1298
+ file (File): the file object.
1299
+ feature (Feature, optional): the feature object.
1300
+ display_name (str, optional): The display name of the scene.
1301
+ description (str, optional): The description of the scene.
1302
+
1303
+ Returns:
1304
+ Attachment: The newly created Attachment instance.
1305
+
1306
+ Raises:
1307
+ ValidationError: If the Attachment data is invalid.
1308
+
1309
+ Example:
1310
+ >>> from geobox import GeoboxClient
1311
+ >>> from geobox.vectorlayer import VectorLayer
1312
+ >>> client = GeoboxClient()
1313
+ >>> layer = VectorLayer.get_vector(api=client, uuid="12345678-1234-5678-1234-567812345678")
1314
+ >>> file = client.get_files()[0]
1315
+ >>> layer.create_attachment(name='test', loc_x=10, loc_y=10, file=file)
1316
+ """
1317
+ from .attachment import Attachment
1318
+
1319
+ return Attachment.create_attachment(self.api,
1320
+ name=name,
1321
+ loc_x=loc_x,
1322
+ loc_y=loc_y,
1323
+ resource=self,
1324
+ file=file,
1325
+ feature=feature,
1326
+ display_name=display_name,
1327
+ description=description)
geobox/view.py CHANGED
@@ -7,9 +7,11 @@ if TYPE_CHECKING:
7
7
  from . import GeoboxClient
8
8
  from .field import Field
9
9
  from .user import User
10
- from .enums import InputGeomType, FieldType
10
+ from .enums import InputGeomType
11
11
  from .task import Task
12
12
  from .file import File
13
+ from .attachment import Attachment
14
+
13
15
 
14
16
 
15
17
  class VectorLayerView(VectorLayer):
@@ -720,6 +722,25 @@ class VectorLayerView(VectorLayer):
720
722
  return super().settings
721
723
 
722
724
 
725
+ def update_settings(self, settings: Dict) -> Dict:
726
+ """
727
+ Update the settings
728
+
729
+ settings (Dict): settings dictionary
730
+
731
+ Returns:
732
+ Dict: updated settings
733
+
734
+ Example:
735
+ >>> from geobox import GeoboxClient
736
+ >>> client = GeoboxClient()
737
+ >>> view1 = client.get_view(uuid="12345678-1234-5678-1234-567812345678")
738
+ >>> view2 = client.get_view(uuid="12345678-1234-5678-1234-567812345678")
739
+ >>> view1.update_settings(view2.settings)
740
+ """
741
+ return super().update_settings(settings)
742
+
743
+
723
744
  def set_settings(self, **kwargs) -> Dict:
724
745
  """
725
746
  Set the settings of the Vector Layer.
@@ -862,3 +883,80 @@ class VectorLayerView(VectorLayer):
862
883
  >>> view.prune_edited_areas()
863
884
  """
864
885
  return super().prune_edited_areas()
886
+
887
+
888
+ def get_attachments(self, **kwargs) -> List['Attachment']:
889
+ """
890
+ Get the resouces attachments
891
+
892
+ Keyword Args:
893
+ element_id (str): the id of the element with attachment.
894
+ search (str): search term for keyword-based searching among all textual fields.
895
+ 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.
896
+ skip (int): Number of items to skip. default is 0.
897
+ limit (int): Number of items to return. default is 10.
898
+ return_count (bool): Whether to return total count. default is False.
899
+
900
+ Returns:
901
+ List[Attachment] | int: A list of attachments instances or the total number of attachments.
902
+
903
+ Raises:
904
+ TypeError: if the resource type is not supported
905
+
906
+ Example:
907
+ >>> from geobox import GeoboxClient
908
+ >>> from geobox.view import VectorLayerView
909
+ >>> client = GeoboxClient()
910
+ >>> view = VectorLayerView.get_view(client, uuid="12345678-1234-5678-1234-567812345678")
911
+ >>> view.get_attachments()
912
+ """
913
+ from .attachment import Attachment
914
+
915
+ return Attachment.get_attachments(self.api, resource=self, **kwargs)
916
+
917
+
918
+ def create_attachment(self,
919
+ name: str,
920
+ loc_x: int,
921
+ loc_y: int,
922
+ file: 'File',
923
+ feature: 'Feature' = None,
924
+ display_name: str = None,
925
+ description: str = None) -> 'Attachment':
926
+ """
927
+ Create a new Attachment.
928
+
929
+ Args:
930
+ name (str): The name of the scene.
931
+ loc_x (int): x parameter of the attachment location.
932
+ loc_y (int): y parameter of the attachment location.
933
+ file (File): the file object.
934
+ feature (Feature, optional): the feature object.
935
+ display_name (str, optional): The display name of the scene.
936
+ description (str, optional): The description of the scene.
937
+
938
+ Returns:
939
+ Attachment: The newly created Attachment instance.
940
+
941
+ Raises:
942
+ ValidationError: If the Attachment data is invalid.
943
+
944
+ Example:
945
+ >>> from geobox import GeoboxClient
946
+ >>> from geobox.view import VectorLayerView
947
+ >>> client = GeoboxClient()
948
+ >>> view = VectorLayerView.get_view(client, uuid="12345678-1234-5678-1234-567812345678")
949
+ >>> file = client.get_files()[0]
950
+ >>> view.create_attachment(name='test', loc_x=10, loc_y=10, file=file)
951
+ """
952
+ from .attachment import Attachment
953
+
954
+ return Attachment.create_attachment(self.api,
955
+ name=name,
956
+ loc_x=loc_x,
957
+ loc_y=loc_y,
958
+ resource=self,
959
+ file=file,
960
+ feature=feature,
961
+ display_name=display_name,
962
+ description=description)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: geobox
3
- Version: 1.4.0
3
+ Version: 1.4.2
4
4
  Summary: SDK for Geobox's APIs
5
5
  Author-email: Hamid Heydari <heydari.h62@gmail.com>
6
6
  License: MIT
@@ -1,23 +1,23 @@
1
1
  geobox/__init__.py,sha256=iRkJAFIjMXiAaLTVXvZcW5HM7ttyipGdxFZ15NCM8qU,1895
2
- geobox/api.py,sha256=lqVpQ_NLyPpDnySxYlSBLiZelkbL7IFd5uX3K-9QRho,105246
2
+ geobox/api.py,sha256=8wO1AvyIWf0n2gi-Jv22IM6gyjtbX4KGBYXJTKTh01A,105230
3
3
  geobox/apikey.py,sha256=OXsf1ltXcN1jIQJHECdnIE5R_Qksb897xVJOkORRsxw,7522
4
- geobox/attachment.py,sha256=qplcYfHkoV9aHaXQ7xFnkrsYxwmUs0PNPbjoSerET34,11582
4
+ geobox/attachment.py,sha256=Q5LVn2j8gm-CptDVhpqtfzyQTDDd1FjW_9MEJBRQb6M,11865
5
5
  geobox/base.py,sha256=OdabLbBflglLkNWM7TGCWtPh73M_-42_Ph963K26JQg,12931
6
- geobox/basemap.py,sha256=7Jo2MeEN8U8Av54kPPaFzQFjajcNYgMRMOTZXPUcXyk,4529
6
+ geobox/basemap.py,sha256=fQhCj6ERYCEaY4RLINrftEt4RDakddKZ-wG9Av4Rv_8,4468
7
7
  geobox/dashboard.py,sha256=x99jUGzUJra4cdcffSYC0_FvrihZh6sPI4o79f-Aptc,11694
8
- geobox/enums.py,sha256=C7PQf8pisiRwHE7-wsgSQ_rZcpvP6-7EDpx8iXijkMs,6300
8
+ geobox/enums.py,sha256=Ur8zbUjfx09oxXb-uzwFfDT_Nt8I4AP5pFQKJ9bxVxI,6204
9
9
  geobox/exception.py,sha256=jvpnv0M2Ck1FpxHTL_aKYWxGvLnCQ3d9vOrMIktjw1U,1507
10
10
  geobox/feature.py,sha256=3Kbc1LjIkBt1YqRAry84BrR7qxx9BexvBB3YQ8D9mGk,18504
11
11
  geobox/field.py,sha256=p9eitUpnsiGj6GUhjSomk6HWlsNJSbE-Oh_4VcjaqVo,10562
12
12
  geobox/file.py,sha256=cMm-SwTzRKALiIj-gkY4UJzUsOuN5SGz50eU1ylNAxk,20079
13
13
  geobox/layout.py,sha256=TdE5FJ7fzbhkexojY8h-r68hXb5UYM6MIfNkxfs_RKA,11285
14
- geobox/log.py,sha256=ZTmVErhyAszf7M5YFxT5mqXNNDGPnRwXPeGLDS1G6PE,3582
15
- geobox/map.py,sha256=oMhpbmeRtamI1iVYZIWXgGQa3NOcKh6O57mgrDBQkno,32723
16
- geobox/model3d.py,sha256=GUpZdRcy6Fs83PdqdfX70F_uxIAqkyTbsMWYSI7rV5k,12011
17
- geobox/mosaic.py,sha256=6wSK9xkjtBUEtIsZANWVYwsJbDx112mO1SQOXcPTVo8,23780
14
+ geobox/log.py,sha256=Xuq4oKPwaypZ4nYEOIXu13dH4AkQcf0pkTw85gDQqS4,4063
15
+ geobox/map.py,sha256=kksFBS79TOKN9KBByXzj2atSvZhIAuMA85hSjo_szeA,36788
16
+ geobox/model3d.py,sha256=acT5dXwq3Lmhfq5-cPOnYJMZR1gzj3cfF6kyxMleHag,14924
17
+ geobox/mosaic.py,sha256=zKo6cEtaqz7fFcWIzhURxZIkICUQlpEhpFBjGJ5GJ1M,24385
18
18
  geobox/plan.py,sha256=jUzl6CQBY6IsdieEppJOmE0sSjwvu6eHO89pC_JFs6I,12066
19
- geobox/query.py,sha256=FqeiZf2E4tJ2FG-mIfRKov6H1QWUrMSErVpNWcb3Wx0,24038
20
- geobox/raster.py,sha256=gBWZUm88uJwjgSlp7auS0nEB9KjkTv1F9hvdPaJqCic,30084
19
+ geobox/query.py,sha256=ubS1Og3rC_6-zW-cbR30o7bZw2MZNZY652VLCvVvmWE,24173
20
+ geobox/raster.py,sha256=fTIM9HKVddaFfO9o-mEbZSM31qpCr6KAszguInZjd2A,30702
21
21
  geobox/route.py,sha256=cKZTTHBHM8woWbhHIpCvrRX_doJcTkGktouee0z7oG0,2723
22
22
  geobox/scene.py,sha256=GEzvWB-l-xO-8IodwFAPt4T7lZxuzEKJ1H0cqfx78W4,11301
23
23
  geobox/settings.py,sha256=rGRdM18Vo7xnjfZXPLRMbKeoVC_lZmzkNRPS0SQv05o,5660
@@ -27,12 +27,12 @@ geobox/tileset.py,sha256=bQOckE04F31vb-NYmNsQzXndZSTDZyskWspRikjZuBs,24241
27
27
  geobox/usage.py,sha256=_54xL-n-2Bg9wGpoOBKnh85WqdpMWEtqxRJVaFlVWe0,7908
28
28
  geobox/user.py,sha256=YY72uRvjKUUWUZbxhrft37FVBlqDeosPMf3EpMVBhc0,15069
29
29
  geobox/utils.py,sha256=qLtchKIdw-az3KCiiFv0-Cpmx9RfBxORjlATvVyDIaQ,1314
30
- geobox/vectorlayer.py,sha256=5IglRp7uoMm3yggYpHurDRAGQo9x7KdjJGicSLpxrSs,53035
30
+ geobox/vectorlayer.py,sha256=s8zH68ALeBvep5bW5wuHkDm9x07Z52GhPaeDbznJ3wY,57066
31
31
  geobox/version.py,sha256=0GLPhxCeEb2bAkdpPJWtXPXc1KP6kQ_TOMwLAL0ldo0,9374
32
- geobox/view.py,sha256=ZNJNBQclM6fc0cxXmU_L_XEBwd4lbsEncs6ynxWU9lc,37531
32
+ geobox/view.py,sha256=xAxBhxwoWAoiG8YJBEF93UJ4e4VeJx17rZpfdl2Q8DU,41507
33
33
  geobox/workflow.py,sha256=_WEIy1zLpBFx5yeuZ4ClnwPdU90jQbdy5bWYYIRa4JY,11549
34
- geobox-1.4.0.dist-info/licenses/LICENSE,sha256=AvFB7W94sJYKLDhBxLRshL3upexCOG8HQY_1JibB96w,1063
35
- geobox-1.4.0.dist-info/METADATA,sha256=GGoWFZt8cAf-9N_3YIEz4ZLyv77uMT0IO-kZyAj6-rQ,2658
36
- geobox-1.4.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
37
- geobox-1.4.0.dist-info/top_level.txt,sha256=ppXH8Bu2mlB-pLQ6lsoWEm2Gr6wZx1uzkhetsYA5ins,7
38
- geobox-1.4.0.dist-info/RECORD,,
34
+ geobox-1.4.2.dist-info/licenses/LICENSE,sha256=AvFB7W94sJYKLDhBxLRshL3upexCOG8HQY_1JibB96w,1063
35
+ geobox-1.4.2.dist-info/METADATA,sha256=5-4FR_CCE6LGfz96_urdMuEjN1s0xikKEn8vG2Q5WPI,2658
36
+ geobox-1.4.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
37
+ geobox-1.4.2.dist-info/top_level.txt,sha256=ppXH8Bu2mlB-pLQ6lsoWEm2Gr6wZx1uzkhetsYA5ins,7
38
+ geobox-1.4.2.dist-info/RECORD,,
File without changes