geobox 1.4.0__tar.gz → 1.4.1__tar.gz

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 (71) hide show
  1. {geobox-1.4.0 → geobox-1.4.1}/PKG-INFO +1 -1
  2. {geobox-1.4.0 → geobox-1.4.1}/geobox/api.py +11 -7
  3. {geobox-1.4.0 → geobox-1.4.1}/geobox/attachment.py +27 -12
  4. {geobox-1.4.0 → geobox-1.4.1}/geobox/basemap.py +1 -2
  5. {geobox-1.4.0 → geobox-1.4.1}/geobox/enums.py +0 -8
  6. {geobox-1.4.0 → geobox-1.4.1}/geobox/log.py +20 -1
  7. {geobox-1.4.0 → geobox-1.4.1}/geobox/map.py +81 -0
  8. {geobox-1.4.0 → geobox-1.4.1}/geobox/vectorlayer.py +80 -2
  9. {geobox-1.4.0 → geobox-1.4.1}/geobox/view.py +80 -1
  10. {geobox-1.4.0 → geobox-1.4.1}/geobox.egg-info/PKG-INFO +1 -1
  11. {geobox-1.4.0 → geobox-1.4.1}/pyproject.toml +1 -1
  12. {geobox-1.4.0 → geobox-1.4.1}/tests/test_api.py +1 -1
  13. {geobox-1.4.0 → geobox-1.4.1}/tests/test_attachment.py +13 -9
  14. {geobox-1.4.0 → geobox-1.4.1}/tests/test_basemap.py +1 -1
  15. {geobox-1.4.0 → geobox-1.4.1}/tests/test_log.py +7 -0
  16. {geobox-1.4.0 → geobox-1.4.1}/tests/test_map.py +22 -0
  17. {geobox-1.4.0 → geobox-1.4.1}/tests/test_vectorlayer.py +24 -0
  18. {geobox-1.4.0 → geobox-1.4.1}/tests/test_view.py +35 -1
  19. {geobox-1.4.0 → geobox-1.4.1}/LICENSE +0 -0
  20. {geobox-1.4.0 → geobox-1.4.1}/README.md +0 -0
  21. {geobox-1.4.0 → geobox-1.4.1}/geobox/__init__.py +0 -0
  22. {geobox-1.4.0 → geobox-1.4.1}/geobox/apikey.py +0 -0
  23. {geobox-1.4.0 → geobox-1.4.1}/geobox/base.py +0 -0
  24. {geobox-1.4.0 → geobox-1.4.1}/geobox/dashboard.py +0 -0
  25. {geobox-1.4.0 → geobox-1.4.1}/geobox/exception.py +0 -0
  26. {geobox-1.4.0 → geobox-1.4.1}/geobox/feature.py +0 -0
  27. {geobox-1.4.0 → geobox-1.4.1}/geobox/field.py +0 -0
  28. {geobox-1.4.0 → geobox-1.4.1}/geobox/file.py +0 -0
  29. {geobox-1.4.0 → geobox-1.4.1}/geobox/layout.py +0 -0
  30. {geobox-1.4.0 → geobox-1.4.1}/geobox/model3d.py +0 -0
  31. {geobox-1.4.0 → geobox-1.4.1}/geobox/mosaic.py +0 -0
  32. {geobox-1.4.0 → geobox-1.4.1}/geobox/plan.py +0 -0
  33. {geobox-1.4.0 → geobox-1.4.1}/geobox/query.py +0 -0
  34. {geobox-1.4.0 → geobox-1.4.1}/geobox/raster.py +0 -0
  35. {geobox-1.4.0 → geobox-1.4.1}/geobox/route.py +0 -0
  36. {geobox-1.4.0 → geobox-1.4.1}/geobox/scene.py +0 -0
  37. {geobox-1.4.0 → geobox-1.4.1}/geobox/settings.py +0 -0
  38. {geobox-1.4.0 → geobox-1.4.1}/geobox/task.py +0 -0
  39. {geobox-1.4.0 → geobox-1.4.1}/geobox/tile3d.py +0 -0
  40. {geobox-1.4.0 → geobox-1.4.1}/geobox/tileset.py +0 -0
  41. {geobox-1.4.0 → geobox-1.4.1}/geobox/usage.py +0 -0
  42. {geobox-1.4.0 → geobox-1.4.1}/geobox/user.py +0 -0
  43. {geobox-1.4.0 → geobox-1.4.1}/geobox/utils.py +0 -0
  44. {geobox-1.4.0 → geobox-1.4.1}/geobox/version.py +0 -0
  45. {geobox-1.4.0 → geobox-1.4.1}/geobox/workflow.py +0 -0
  46. {geobox-1.4.0 → geobox-1.4.1}/geobox.egg-info/SOURCES.txt +0 -0
  47. {geobox-1.4.0 → geobox-1.4.1}/geobox.egg-info/dependency_links.txt +0 -0
  48. {geobox-1.4.0 → geobox-1.4.1}/geobox.egg-info/requires.txt +0 -0
  49. {geobox-1.4.0 → geobox-1.4.1}/geobox.egg-info/top_level.txt +0 -0
  50. {geobox-1.4.0 → geobox-1.4.1}/setup.cfg +0 -0
  51. {geobox-1.4.0 → geobox-1.4.1}/tests/test_apikey.py +0 -0
  52. {geobox-1.4.0 → geobox-1.4.1}/tests/test_dashboard.py +0 -0
  53. {geobox-1.4.0 → geobox-1.4.1}/tests/test_feature.py +0 -0
  54. {geobox-1.4.0 → geobox-1.4.1}/tests/test_field.py +0 -0
  55. {geobox-1.4.0 → geobox-1.4.1}/tests/test_file.py +0 -0
  56. {geobox-1.4.0 → geobox-1.4.1}/tests/test_layout.py +0 -0
  57. {geobox-1.4.0 → geobox-1.4.1}/tests/test_model3d.py +0 -0
  58. {geobox-1.4.0 → geobox-1.4.1}/tests/test_mosaic.py +0 -0
  59. {geobox-1.4.0 → geobox-1.4.1}/tests/test_plan.py +0 -0
  60. {geobox-1.4.0 → geobox-1.4.1}/tests/test_query.py +0 -0
  61. {geobox-1.4.0 → geobox-1.4.1}/tests/test_raster.py +0 -0
  62. {geobox-1.4.0 → geobox-1.4.1}/tests/test_route.py +0 -0
  63. {geobox-1.4.0 → geobox-1.4.1}/tests/test_scene.py +0 -0
  64. {geobox-1.4.0 → geobox-1.4.1}/tests/test_settings.py +0 -0
  65. {geobox-1.4.0 → geobox-1.4.1}/tests/test_task.py +0 -0
  66. {geobox-1.4.0 → geobox-1.4.1}/tests/test_tile3d.py +0 -0
  67. {geobox-1.4.0 → geobox-1.4.1}/tests/test_tileset.py +0 -0
  68. {geobox-1.4.0 → geobox-1.4.1}/tests/test_usage.py +0 -0
  69. {geobox-1.4.0 → geobox-1.4.1}/tests/test_user.py +0 -0
  70. {geobox-1.4.0 → geobox-1.4.1}/tests/test_version.py +0 -0
  71. {geobox-1.4.0 → geobox-1.4.1}/tests/test_workflow.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: geobox
3
- Version: 1.4.0
3
+ Version: 1.4.1
4
4
  Summary: SDK for Geobox's APIs
5
5
  Author-email: Hamid Heydari <heydari.h62@gmail.com>
6
6
  License: MIT
@@ -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,
@@ -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))
@@ -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
@@ -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
 
@@ -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)
@@ -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):
@@ -899,3 +903,80 @@ class Map(Base):
899
903
  endpoint = f"{endpoint}?{query_string}"
900
904
  response = self.api.post(endpoint)
901
905
  return self.api.get_task(response['task_id'])
906
+
907
+
908
+ def get_attachments(self, **kwargs) -> List['Attachment']:
909
+ """
910
+ Get the resouces attachments
911
+
912
+ Keyword Args:
913
+ element_id (str): the id of the element with attachment.
914
+ search (str): search term for keyword-based searching among all textual fields.
915
+ 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.
916
+ skip (int): Number of items to skip. default is 0.
917
+ limit (int): Number of items to return. default is 10.
918
+ return_count (bool): Whether to return total count. default is False.
919
+
920
+ Returns:
921
+ List[Attachment] | int: A list of attachments instances or the total number of attachments.
922
+
923
+ Raises:
924
+ TypeError: if the resource type is not supported
925
+
926
+ Example:
927
+ >>> from geobox import GeoboxClient
928
+ >>> from geobox.map import Map
929
+ >>> client = GeoboxClient()
930
+ >>> map = Map.get_map(client, uuid="12345678-1234-5678-1234-567812345678")
931
+ >>> map.get_attachments()
932
+ """
933
+ from .attachment import Attachment
934
+
935
+ return Attachment.get_attachments(self.api, resource=self, **kwargs)
936
+
937
+
938
+ def create_attachment(self,
939
+ name: str,
940
+ loc_x: int,
941
+ loc_y: int,
942
+ file: 'File',
943
+ feature: 'Feature' = None,
944
+ display_name: str = None,
945
+ description: str = None) -> 'Attachment':
946
+ """
947
+ Create a new Attachment.
948
+
949
+ Args:
950
+ name (str): The name of the scene.
951
+ loc_x (int): x parameter of the attachment location.
952
+ loc_y (int): y parameter of the attachment location.
953
+ file (File): the file object.
954
+ feature (Feature, optional): the feature object.
955
+ display_name (str, optional): The display name of the scene.
956
+ description (str, optional): The description of the scene.
957
+
958
+ Returns:
959
+ Attachment: The newly created Attachment instance.
960
+
961
+ Raises:
962
+ ValidationError: If the Attachment data is invalid.
963
+
964
+ Example:
965
+ >>> from geobox import GeoboxClient
966
+ >>> from geobox.map import Map
967
+ >>> client = GeoboxClient()
968
+ >>> map = Map.get_map(client, uuid="12345678-1234-5678-1234-567812345678")
969
+ >>> file = client.get_files()[0]
970
+ >>> map.create_attachment(name='test', loc_x=10, loc_y=10, file=file)
971
+ """
972
+ from .attachment import Attachment
973
+
974
+ return Attachment.create_attachment(self.api,
975
+ name=name,
976
+ loc_x=loc_x,
977
+ loc_y=loc_y,
978
+ resource=self,
979
+ file=file,
980
+ feature=feature,
981
+ display_name=display_name,
982
+ description=description)
@@ -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
  """
@@ -1227,4 +1228,81 @@ class VectorLayer(Base):
1227
1228
  >>> layer.prune_edited_areas()
1228
1229
  """
1229
1230
  endpoint = urljoin(self.endpoint, 'prune/')
1230
- return self.api.post(endpoint)
1231
+ return self.api.post(endpoint)
1232
+
1233
+
1234
+ def get_attachments(self, **kwargs) -> List['Attachment']:
1235
+ """
1236
+ Get the resouces attachments
1237
+
1238
+ Keyword Args:
1239
+ element_id (str): the id of the element with attachment.
1240
+ search (str): search term for keyword-based searching among all textual fields.
1241
+ 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.
1242
+ skip (int): Number of items to skip. default is 0.
1243
+ limit (int): Number of items to return. default is 10.
1244
+ return_count (bool): Whether to return total count. default is False.
1245
+
1246
+ Returns:
1247
+ List[Attachment] | int: A list of attachments instances or the total number of attachments.
1248
+
1249
+ Raises:
1250
+ TypeError: if the resource type is not supported
1251
+
1252
+ Example:
1253
+ >>> from geobox import GeoboxClient
1254
+ >>> from geobox.vectorlayer import VectorLayer
1255
+ >>> client = GeoboxClient()
1256
+ >>> layer = VectorLayer.get_vector(api=client, uuid="12345678-1234-5678-1234-567812345678")
1257
+ >>> layer.get_attachments()
1258
+ """
1259
+ from .attachment import Attachment
1260
+
1261
+ return Attachment.get_attachments(self.api, resource=self, **kwargs)
1262
+
1263
+
1264
+ def create_attachment(self,
1265
+ name: str,
1266
+ loc_x: int,
1267
+ loc_y: int,
1268
+ file: 'File',
1269
+ feature: 'Feature' = None,
1270
+ display_name: str = None,
1271
+ description: str = None) -> 'Attachment':
1272
+ """
1273
+ Create a new Attachment.
1274
+
1275
+ Args:
1276
+ name (str): The name of the scene.
1277
+ loc_x (int): x parameter of the attachment location.
1278
+ loc_y (int): y parameter of the attachment location.
1279
+ file (File): the file object.
1280
+ feature (Feature, optional): the feature object.
1281
+ display_name (str, optional): The display name of the scene.
1282
+ description (str, optional): The description of the scene.
1283
+
1284
+ Returns:
1285
+ Attachment: The newly created Attachment instance.
1286
+
1287
+ Raises:
1288
+ ValidationError: If the Attachment data is invalid.
1289
+
1290
+ Example:
1291
+ >>> from geobox import GeoboxClient
1292
+ >>> from geobox.vectorlayer import VectorLayer
1293
+ >>> client = GeoboxClient()
1294
+ >>> layer = VectorLayer.get_vector(api=client, uuid="12345678-1234-5678-1234-567812345678")
1295
+ >>> file = client.get_files()[0]
1296
+ >>> layer.create_attachment(name='test', loc_x=10, loc_y=10, file=file)
1297
+ """
1298
+ from .attachment import Attachment
1299
+
1300
+ return Attachment.create_attachment(self.api,
1301
+ name=name,
1302
+ loc_x=loc_x,
1303
+ loc_y=loc_y,
1304
+ resource=self,
1305
+ file=file,
1306
+ feature=feature,
1307
+ display_name=display_name,
1308
+ description=description)
@@ -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):
@@ -862,3 +864,80 @@ class VectorLayerView(VectorLayer):
862
864
  >>> view.prune_edited_areas()
863
865
  """
864
866
  return super().prune_edited_areas()
867
+
868
+
869
+ def get_attachments(self, **kwargs) -> List['Attachment']:
870
+ """
871
+ Get the resouces attachments
872
+
873
+ Keyword Args:
874
+ element_id (str): the id of the element with attachment.
875
+ search (str): search term for keyword-based searching among all textual fields.
876
+ 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.
877
+ skip (int): Number of items to skip. default is 0.
878
+ limit (int): Number of items to return. default is 10.
879
+ return_count (bool): Whether to return total count. default is False.
880
+
881
+ Returns:
882
+ List[Attachment] | int: A list of attachments instances or the total number of attachments.
883
+
884
+ Raises:
885
+ TypeError: if the resource type is not supported
886
+
887
+ Example:
888
+ >>> from geobox import GeoboxClient
889
+ >>> from geobox.view import VectorLayerView
890
+ >>> client = GeoboxClient()
891
+ >>> view = VectorLayerView.get_view(client, uuid="12345678-1234-5678-1234-567812345678")
892
+ >>> view.get_attachments()
893
+ """
894
+ from .attachment import Attachment
895
+
896
+ return Attachment.get_attachments(self.api, resource=self, **kwargs)
897
+
898
+
899
+ def create_attachment(self,
900
+ name: str,
901
+ loc_x: int,
902
+ loc_y: int,
903
+ file: 'File',
904
+ feature: 'Feature' = None,
905
+ display_name: str = None,
906
+ description: str = None) -> 'Attachment':
907
+ """
908
+ Create a new Attachment.
909
+
910
+ Args:
911
+ name (str): The name of the scene.
912
+ loc_x (int): x parameter of the attachment location.
913
+ loc_y (int): y parameter of the attachment location.
914
+ file (File): the file object.
915
+ feature (Feature, optional): the feature object.
916
+ display_name (str, optional): The display name of the scene.
917
+ description (str, optional): The description of the scene.
918
+
919
+ Returns:
920
+ Attachment: The newly created Attachment instance.
921
+
922
+ Raises:
923
+ ValidationError: If the Attachment data is invalid.
924
+
925
+ Example:
926
+ >>> from geobox import GeoboxClient
927
+ >>> from geobox.view import VectorLayerView
928
+ >>> client = GeoboxClient()
929
+ >>> view = VectorLayerView.get_view(client, uuid="12345678-1234-5678-1234-567812345678")
930
+ >>> file = client.get_files()[0]
931
+ >>> view.create_attachment(name='test', loc_x=10, loc_y=10, file=file)
932
+ """
933
+ from .attachment import Attachment
934
+
935
+ return Attachment.create_attachment(self.api,
936
+ name=name,
937
+ loc_x=loc_x,
938
+ loc_y=loc_y,
939
+ resource=self,
940
+ file=file,
941
+ feature=feature,
942
+ display_name=display_name,
943
+ 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.1
4
4
  Summary: SDK for Geobox's APIs
5
5
  Author-email: Hamid Heydari <heydari.h62@gmail.com>
6
6
  License: MIT
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "geobox"
7
- version = "1.4.0"
7
+ version = "1.4.1"
8
8
  description = "SDK for Geobox's APIs"
9
9
  authors = [
10
10
  {name = "Hamid Heydari", email = "heydari.h62@gmail.com"}
@@ -1812,7 +1812,7 @@ def test_get_attachments(mock_attachment_data, mock_vector_data):
1812
1812
 
1813
1813
  client = GeoboxClient(username='testuser', password='testpassword')
1814
1814
  layer = VectorLayer(client, mock_vector_data['uuid'], LayerType.Polygon, mock_vector_data)
1815
- attachments = client.get_attachments(resource_type=AttachmentResourceType.Vector, resource_uuid=layer.uuid)
1815
+ attachments = client.get_attachments(resource=layer)
1816
1816
 
1817
1817
  assert len(attachments) == 2
1818
1818
  assert isinstance(attachments[0], Attachment)
@@ -1,6 +1,6 @@
1
1
  import pytest
2
2
 
3
- from geobox.attachment import Attachment, AttachmentResourceType
3
+ from geobox.attachment import Attachment
4
4
  from geobox.file import File
5
5
  from geobox.vectorlayer import VectorLayer, LayerType
6
6
  from geobox.feature import Feature
@@ -31,12 +31,16 @@ def test_file(api, mock_attachment_data):
31
31
  def test_get_attachments(api, mock_attachment_data, mock_vector_data):
32
32
  api.get.return_value = [mock_attachment_data, mock_attachment_data]
33
33
  layer = VectorLayer(api, mock_vector_data['uuid'], LayerType.Polygon, mock_vector_data)
34
- attachments = Attachment.get_attachments(api, resource_type=AttachmentResourceType.Vector, resource_uuid=layer.uuid)
34
+ attachments = Attachment.get_attachments(api, resource=layer)
35
35
  api.get.assert_called_once_with(f'{Attachment.BASE_ENDPOINT}?resource_type=vector&resource_uuid=297fa7ca-877a-400c-8003-d65de9e791c2&skip=0&limit=10')
36
36
  assert len(attachments) == 2
37
37
  assert type(attachments[0]) == Attachment
38
38
  assert attachments[0].data == mock_attachment_data
39
39
 
40
+ # error
41
+ with pytest.raises(TypeError):
42
+ Attachment.get_attachments(api, resource='')
43
+
40
44
 
41
45
  def test_create_attachment(api, mock_attachment_data, mock_vector_data, mock_feature_data, mock_view_data, mock_map_data):
42
46
  api.post.return_value = mock_attachment_data
@@ -104,7 +108,7 @@ def test_update_attachment(api, mock_attachment_data):
104
108
  def test_update(api, mock_attachment_data, mock_vector_data):
105
109
  api.get.return_value = [mock_attachment_data, mock_attachment_data]
106
110
  layer = VectorLayer(api, mock_attachment_data['key'].split(':')[1], LayerType.Polygon, mock_vector_data)
107
- attachment = Attachment.get_attachments(api, resource_type=AttachmentResourceType.Vector, resource_uuid=layer.uuid)[0]
111
+ attachment = Attachment.get_attachments(api, resource=layer)[0]
108
112
  expected_data = {'name': 'updated_name',
109
113
  'display_name': 'updated display name',
110
114
  'description': 'updated description',
@@ -122,10 +126,10 @@ def test_update(api, mock_attachment_data, mock_vector_data):
122
126
  assert attachment.data == updated_data
123
127
 
124
128
 
125
- def test_delete(api, mock_attachment_data, mock_vector_data):
129
+ def test_delete(api, mock_attachment_data, mock_map_data):
126
130
  api.get.return_value = [mock_attachment_data, mock_attachment_data]
127
- layer = VectorLayer(api, mock_attachment_data['key'].split(':')[1], LayerType.Polygon, mock_vector_data)
128
- attachment = Attachment.get_attachments(api, resource_type=AttachmentResourceType.Vector, resource_uuid=layer.uuid)[0]
131
+ map = Map(api, mock_attachment_data['key'].split(':')[1], mock_map_data)
132
+ attachment = Attachment.get_attachments(api, resource=map)[0]
129
133
  endpoint = attachment.endpoint
130
134
  attachment.delete()
131
135
  api.delete.assert_called_once_with(endpoint)
@@ -133,10 +137,10 @@ def test_delete(api, mock_attachment_data, mock_vector_data):
133
137
  assert attachment.endpoint is None
134
138
 
135
139
 
136
- def test_thumbnail(api, mock_attachment_data, mock_vector_data):
140
+ def test_thumbnail(api, mock_attachment_data, mock_view_data):
137
141
  api.get.return_value = [mock_attachment_data, mock_attachment_data]
138
- layer = VectorLayer(api, mock_attachment_data['key'].split(':')[1], LayerType.Polygon, mock_vector_data)
139
- attachment = Attachment.get_attachments(api, resource_type=AttachmentResourceType.Vector, resource_uuid=layer.uuid)[0]
142
+ view = VectorLayerView(api, mock_attachment_data['key'].split(':')[1], LayerType.Polygon, mock_view_data)
143
+ attachment = Attachment.get_attachments(api, resource=view)[0]
140
144
  thumbnail_url = attachment.thumbnail
141
145
  assert thumbnail_url == f"{api.base_url}{attachment.endpoint}thumbnail"
142
146
 
@@ -42,7 +42,7 @@ def test_get_basemap(api, mock_basemap_data, mock_basemap_list_data):
42
42
  def test_thumbnail(api, mock_basemap_data):
43
43
  basemap = Basemap(api, mock_basemap_data)
44
44
  thumbnail_url = basemap.thumbnail
45
- assert thumbnail_url == f"{api.base_url}{basemap.endpoint}/thumbnail.png"
45
+ assert thumbnail_url == f"{api.base_url}{basemap.endpoint}thumbnail.png"
46
46
 
47
47
 
48
48
  def test_wmts(api, mock_basemap_data):
@@ -2,6 +2,7 @@ import pytest
2
2
  from unittest.mock import patch
3
3
 
4
4
  from geobox.log import Log
5
+ from geobox.user import User
5
6
 
6
7
  def test_init(api, mock_log_data):
7
8
  log = Log(api, mock_log_data['id'], mock_log_data)
@@ -32,3 +33,9 @@ def test_delete(api, mock_log_data):
32
33
  assert log.log_id is None
33
34
  assert log.endpoint is None
34
35
 
36
+
37
+ def test_user_property(api, mock_log_data, mock_user_data):
38
+ log = Log(api, mock_log_data['id'], mock_log_data)
39
+ api.get_user.return_value = User(api, mock_user_data['1']['id'], mock_user_data['1'])
40
+ user = log.user
41
+ assert user.data == mock_user_data['1']
@@ -7,6 +7,8 @@ from geobox.map import Map
7
7
  from geobox.model3d import Model
8
8
  from geobox.user import User
9
9
  from geobox.task import Task
10
+ from geobox.attachment import Attachment
11
+ from geobox.file import File
10
12
 
11
13
 
12
14
  def test_init(api, mock_map_data):
@@ -574,3 +576,23 @@ def test_export_map_to_image(api, mock_map_data, mock_success_task_data):
574
576
 
575
577
  api.post.assert_called_once_with('maps/da9a505b-7b51-4042-a3ba-c821e4f2cd34/export/?uuid=da9a505b-7b51-4042-a3ba-c821e4f2cd34&bbox=%5B50.275%2C+35.1195%2C+51.4459%2C+36.0416%5D&width=100&height=100')
576
578
  assert type(task) == Task
579
+
580
+
581
+ def test_get_attachments(api, mock_map_data, mock_attachment_data):
582
+ map = Map(api, uuid=mock_map_data['uuid'], data=mock_map_data)
583
+
584
+ api.get.return_value = [mock_attachment_data, mock_attachment_data, mock_attachment_data]
585
+
586
+ attachments = map.get_attachments()
587
+ assert len(attachments) == 3
588
+ assert type(attachments[0]) == Attachment
589
+
590
+
591
+ def test_create_attachment(api, mock_map_data, mock_attachment_data, mock_file_data):
592
+ map = Map(api, uuid=mock_map_data['uuid'], data=mock_map_data)
593
+ file = File(api, uuid=mock_file_data['uuid'], data=mock_file_data)
594
+
595
+ api.post.return_value = mock_attachment_data
596
+ attachment = map.create_attachment(name='test', loc_x=10, loc_y=10, file=file)
597
+ assert type(attachment) == Attachment
598
+ assert attachment.data == mock_attachment_data
@@ -11,6 +11,7 @@ from geobox.view import VectorLayerView
11
11
  from geobox.user import User
12
12
  from geobox.task import Task
13
13
  from geobox.file import File
14
+ from geobox.attachment import Attachment
14
15
  from geobox.exception import NotFoundError
15
16
  from geobox.utils import clean_data
16
17
 
@@ -750,3 +751,26 @@ def test_prune_edited_areas(api, mock_vector_data, layer_type):
750
751
  layer = VectorLayer(api, uuid=mock_vector_data['uuid'], data=mock_vector_data, layer_type=layer_type)
751
752
  layer.prune_edited_areas()
752
753
  api.post.assert_called_once_with(f'{layer.endpoint}prune/')
754
+
755
+
756
+ @pytest.mark.parametrize("layer_type", [type for type in LayerType])
757
+ def test_get_attachments(api, mock_vector_data, mock_attachment_data, layer_type):
758
+ layer = VectorLayer(api, uuid=mock_vector_data['uuid'], data=mock_vector_data, layer_type=layer_type)
759
+
760
+ api.get.return_value = [mock_attachment_data, mock_attachment_data, mock_attachment_data]
761
+
762
+ attachments = layer.get_attachments()
763
+ assert len(attachments) == 3
764
+ assert type(attachments[0]) == Attachment
765
+
766
+
767
+ @pytest.mark.parametrize("layer_type", [type for type in LayerType])
768
+ def test_create_attachment(api, mock_vector_data, mock_attachment_data, mock_file_data, layer_type):
769
+ layer = VectorLayer(api, uuid=mock_vector_data['uuid'], data=mock_vector_data, layer_type=layer_type)
770
+
771
+ file = File(api, uuid=mock_file_data['uuid'], data=mock_file_data)
772
+
773
+ api.post.return_value = mock_attachment_data
774
+ attachment = layer.create_attachment(name='test', loc_x=10, loc_y=10, file=file)
775
+ assert type(attachment) == Attachment
776
+ assert attachment.data == mock_attachment_data
@@ -9,6 +9,7 @@ from geobox.field import Field, FieldType
9
9
  from geobox.exception import NotFoundError
10
10
  from geobox.task import Task
11
11
  from geobox.file import File
12
+ from geobox.attachment import Attachment
12
13
  from geobox.utils import clean_data
13
14
 
14
15
 
@@ -711,4 +712,37 @@ def test_prune_edited_areas(api, mock_view_data, layer_type):
711
712
  data=mock_view_data
712
713
  )
713
714
  view.prune_edited_areas()
714
- api.post.assert_called_once_with(f'{view.endpoint}prune/')
715
+ api.post.assert_called_once_with(f'{view.endpoint}prune/')
716
+
717
+
718
+ @pytest.mark.parametrize("layer_type", [type for type in LayerType])
719
+ def test_get_attachments(api, mock_view_data, mock_attachment_data, layer_type):
720
+ view = VectorLayerView(
721
+ api=api,
722
+ uuid=mock_view_data['uuid'],
723
+ layer_type=layer_type,
724
+ data=mock_view_data
725
+ )
726
+
727
+ api.get.return_value = [mock_attachment_data, mock_attachment_data, mock_attachment_data]
728
+
729
+ attachments = view.get_attachments()
730
+ assert len(attachments) == 3
731
+ assert type(attachments[0]) == Attachment
732
+
733
+
734
+ @pytest.mark.parametrize("layer_type", [type for type in LayerType])
735
+ def test_create_attachment(api, mock_view_data, mock_attachment_data, mock_file_data, layer_type):
736
+ view = VectorLayerView(
737
+ api=api,
738
+ uuid=mock_view_data['uuid'],
739
+ layer_type=layer_type,
740
+ data=mock_view_data
741
+ )
742
+
743
+ file = File(api, uuid=mock_file_data['uuid'], data=mock_file_data)
744
+
745
+ api.post.return_value = mock_attachment_data
746
+ attachment = view.create_attachment(name='test', loc_x=10, loc_y=10, file=file)
747
+ assert type(attachment) == Attachment
748
+ assert attachment.data == mock_attachment_data
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes