pygeobox 1.0.0__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.
- pygeobox/__init__.py +63 -0
- pygeobox/api.py +2518 -0
- pygeobox/apikey.py +233 -0
- pygeobox/attachment.py +298 -0
- pygeobox/base.py +364 -0
- pygeobox/basemap.py +163 -0
- pygeobox/dashboard.py +316 -0
- pygeobox/enums.py +355 -0
- pygeobox/exception.py +47 -0
- pygeobox/feature.py +508 -0
- pygeobox/field.py +309 -0
- pygeobox/file.py +494 -0
- pygeobox/log.py +101 -0
- pygeobox/map.py +858 -0
- pygeobox/model3d.py +334 -0
- pygeobox/mosaic.py +647 -0
- pygeobox/plan.py +261 -0
- pygeobox/query.py +668 -0
- pygeobox/raster.py +756 -0
- pygeobox/route.py +63 -0
- pygeobox/scene.py +317 -0
- pygeobox/settings.py +166 -0
- pygeobox/task.py +354 -0
- pygeobox/tile3d.py +295 -0
- pygeobox/tileset.py +585 -0
- pygeobox/usage.py +211 -0
- pygeobox/user.py +424 -0
- pygeobox/utils.py +44 -0
- pygeobox/vectorlayer.py +1150 -0
- pygeobox/version.py +249 -0
- pygeobox/view.py +859 -0
- pygeobox/workflow.py +315 -0
- pygeobox-1.0.0.dist-info/METADATA +106 -0
- pygeobox-1.0.0.dist-info/RECORD +37 -0
- pygeobox-1.0.0.dist-info/WHEEL +5 -0
- pygeobox-1.0.0.dist-info/licenses/LICENSE +21 -0
- pygeobox-1.0.0.dist-info/top_level.txt +1 -0
pygeobox/file.py
ADDED
@@ -0,0 +1,494 @@
|
|
1
|
+
from urllib.parse import urljoin
|
2
|
+
from typing import Optional, Dict, List, Union, TYPE_CHECKING
|
3
|
+
import os
|
4
|
+
import mimetypes
|
5
|
+
import requests
|
6
|
+
import sys
|
7
|
+
|
8
|
+
from .base import Base
|
9
|
+
from .enums import FileType, PublishFileType, InputGeomType
|
10
|
+
from .utils import clean_data
|
11
|
+
from .task import Task
|
12
|
+
|
13
|
+
if TYPE_CHECKING:
|
14
|
+
from . import GeoboxClient
|
15
|
+
from .user import User
|
16
|
+
|
17
|
+
class File(Base):
|
18
|
+
"""
|
19
|
+
A class to interact with files in Geobox.
|
20
|
+
|
21
|
+
This class provides functionality to interact with files in Geobox.
|
22
|
+
It supports various operations including CRUD operations on files, as well as advanced operations like publishing, and sharing files.
|
23
|
+
It also provides properties to access the file data, and a method to download the file.
|
24
|
+
"""
|
25
|
+
BASE_ENDPOINT: str = 'files/'
|
26
|
+
|
27
|
+
def __init__(self,
|
28
|
+
api: 'GeoboxClient',
|
29
|
+
uuid: str,
|
30
|
+
data: Optional[Dict] = {}):
|
31
|
+
"""
|
32
|
+
Constructs all the necessary attributes for the File object.
|
33
|
+
|
34
|
+
Args:
|
35
|
+
api (Api): The API instance.
|
36
|
+
uuid (str): The UUID of the file.
|
37
|
+
data (Dict, optional): The data of the file.
|
38
|
+
"""
|
39
|
+
super().__init__(api, uuid=uuid, data=data)
|
40
|
+
|
41
|
+
|
42
|
+
def __repr__(self) -> str:
|
43
|
+
"""
|
44
|
+
Return a string representation of the File object.
|
45
|
+
|
46
|
+
Returns:
|
47
|
+
str: A string representation of the File object.
|
48
|
+
"""
|
49
|
+
return f"File(file_name={self.name}, file_type={self.file_type})"
|
50
|
+
|
51
|
+
|
52
|
+
@property
|
53
|
+
def layers(self) -> List[Dict]:
|
54
|
+
"""
|
55
|
+
Get the layers of the file.
|
56
|
+
|
57
|
+
Returns:
|
58
|
+
List[Dict]: The layers of the file.
|
59
|
+
|
60
|
+
Example:
|
61
|
+
>>> from geobox import GeoboxClient
|
62
|
+
>>> client = GeoboxClient()
|
63
|
+
>>> file = File.get_file(client, uuid="12345678-1234-5678-1234-567812345678")
|
64
|
+
>>> file.layers
|
65
|
+
"""
|
66
|
+
return self.data.get('layers', {}).get('layers', [])
|
67
|
+
|
68
|
+
|
69
|
+
@classmethod
|
70
|
+
def upload_file(cls, api: 'GeoboxClient', path: str, user_id: int = None, scan_archive: bool = True) -> 'File':
|
71
|
+
"""
|
72
|
+
Upload a file to the GeoBox API.
|
73
|
+
|
74
|
+
Args:
|
75
|
+
api (GeoboxClient): The API instance.
|
76
|
+
path (str): The path to the file to upload.
|
77
|
+
user_id (int, optional): specific user. privileges required.
|
78
|
+
scan_archive (bool, optional): Whether to scan the archive for layers. default: True
|
79
|
+
|
80
|
+
Returns:
|
81
|
+
File: The uploaded file instance.
|
82
|
+
|
83
|
+
Raises:
|
84
|
+
ValueError: If the file type is invalid.
|
85
|
+
FileNotFoundError: If the file does not exist.
|
86
|
+
|
87
|
+
Example:
|
88
|
+
>>> from geobox import GeoboxClient
|
89
|
+
>>> from geobox.file import File
|
90
|
+
>>> client = GeoboxClient()
|
91
|
+
>>> file = File.upload_file(client, path='path/to/file.shp')
|
92
|
+
or
|
93
|
+
>>> file = client.upload_file(path='path/to/file.shp')
|
94
|
+
"""
|
95
|
+
# Check if the file exists
|
96
|
+
if not os.path.exists(path):
|
97
|
+
raise FileNotFoundError(f"File not found: {path}")
|
98
|
+
|
99
|
+
# Check if the file type is valid
|
100
|
+
FileType(os.path.splitext(path)[1])
|
101
|
+
|
102
|
+
data = clean_data({
|
103
|
+
"user_id": user_id,
|
104
|
+
"scan_archive": scan_archive
|
105
|
+
})
|
106
|
+
|
107
|
+
endpoint = cls.BASE_ENDPOINT
|
108
|
+
with open(path, 'rb') as f:
|
109
|
+
files = {'file': f}
|
110
|
+
file_data = api.post(endpoint, data, is_json=False, files=files)
|
111
|
+
return cls(api, file_data['uuid'], file_data)
|
112
|
+
|
113
|
+
|
114
|
+
@classmethod
|
115
|
+
def get_files(cls, api:'GeoboxClient', **kwargs) -> Union[List['File'], int]:
|
116
|
+
"""
|
117
|
+
Retrieves a list of files.
|
118
|
+
|
119
|
+
Args:
|
120
|
+
api (GeoboxClient): The GeoboxClient instance for making requests.
|
121
|
+
|
122
|
+
Keyword Args:
|
123
|
+
q (str): query filter based on OGC CQL standard. e.g. "field1 LIKE '%GIS%' AND created_at > '2021-01-01'"
|
124
|
+
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.
|
125
|
+
search_fields (str): comma separated list of fields for searching
|
126
|
+
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.
|
127
|
+
return_count (bool): if true, the total number of results will be returned. default is False.
|
128
|
+
skip (int): number of results to skip. default is 0.
|
129
|
+
limit (int): number of results to return. default is 10.
|
130
|
+
user_id (int): filter by user id.
|
131
|
+
shared (bool): Whether to return shared files. default is False.
|
132
|
+
|
133
|
+
Returns:
|
134
|
+
List[File] | int: A list of File objects or the total number of results.
|
135
|
+
|
136
|
+
Example:
|
137
|
+
>>> from geobox import GeoboxClient
|
138
|
+
>>> from geobox.file import File
|
139
|
+
>>> client = GeoboxClient()
|
140
|
+
>>> files = File.get_files(client, search_fields='name', search='GIS', order_by='name', skip=10, limit=10)
|
141
|
+
or
|
142
|
+
>>> files = client.get_files(search_fields='name', search='GIS', order_by='name', skip=10, limit=10)
|
143
|
+
"""
|
144
|
+
params = {
|
145
|
+
'f': 'json',
|
146
|
+
'q': kwargs.get('q', None),
|
147
|
+
'search': kwargs.get('search', None),
|
148
|
+
'search_fields': kwargs.get('search_fields', None),
|
149
|
+
'order_by': kwargs.get('order_by', None),
|
150
|
+
'return_count': kwargs.get('return_count', False),
|
151
|
+
'skip': kwargs.get('skip', 0),
|
152
|
+
'limit': kwargs.get('limit', 10),
|
153
|
+
'user_id': kwargs.get('user_id', None),
|
154
|
+
'shared': kwargs.get('shared', False)
|
155
|
+
}
|
156
|
+
return super()._get_list(api, cls.BASE_ENDPOINT, params, factory_func=lambda api, item: cls(api, item['uuid'], item))
|
157
|
+
|
158
|
+
|
159
|
+
@classmethod
|
160
|
+
def get_file(cls, api: 'GeoboxClient', uuid: str, user_id: int = None) -> 'File':
|
161
|
+
"""
|
162
|
+
Retrieves a file by its UUID.
|
163
|
+
|
164
|
+
Args:
|
165
|
+
api (Api): The API instance.
|
166
|
+
uuid (str): The UUID of the file.
|
167
|
+
user_id (int, optional): specific user. privileges required.
|
168
|
+
|
169
|
+
Returns:
|
170
|
+
File: The retrieved file instance.
|
171
|
+
|
172
|
+
Raises:
|
173
|
+
NotFoundError: If the file with the specified UUID is not found.
|
174
|
+
|
175
|
+
Example:
|
176
|
+
>>> from geobox import GeoboxClient
|
177
|
+
>>> from geobox.file import File
|
178
|
+
>>> client = GeoboxClient()
|
179
|
+
>>> file = File.get_file(client, uuid="12345678-1234-5678-1234-567812345678")
|
180
|
+
or
|
181
|
+
>>> file = client.get_file(uuid="12345678-1234-5678-1234-567812345678")
|
182
|
+
"""
|
183
|
+
params = {
|
184
|
+
'f': 'json',
|
185
|
+
'user_id': user_id
|
186
|
+
}
|
187
|
+
return super()._get_detail(api, cls.BASE_ENDPOINT, f'{uuid}/info', params, factory_func=lambda api, item: File(api, item['uuid'], item))
|
188
|
+
|
189
|
+
|
190
|
+
@classmethod
|
191
|
+
def get_file_by_name(cls, api: 'GeoboxClient', name: str, user_id: int = None) -> Union['File', None]:
|
192
|
+
"""
|
193
|
+
Get a file by name
|
194
|
+
|
195
|
+
Args:
|
196
|
+
api (GeoboxClient): The GeoboxClient instance for making requests.
|
197
|
+
name (str): the name of the file to get
|
198
|
+
user_id (int, optional): specific user. privileges required.
|
199
|
+
|
200
|
+
Returns:
|
201
|
+
File | None: returns the file if a file matches the given name, else None
|
202
|
+
|
203
|
+
Example:
|
204
|
+
>>> from geobox import GeoboxClient
|
205
|
+
>>> from geobox.file import File
|
206
|
+
>>> client = GeoboxClient()
|
207
|
+
>>> file = File.get_file_by_name(client, name='test')
|
208
|
+
or
|
209
|
+
>>> file = client.get_file_by_name(name='test')
|
210
|
+
"""
|
211
|
+
files = cls.get_files(api, q=f"name = '{name}'", user_id=user_id)
|
212
|
+
if files and files[0].name == name:
|
213
|
+
return files[0]
|
214
|
+
else:
|
215
|
+
return None
|
216
|
+
|
217
|
+
|
218
|
+
def _get_save_path(self, save_path: str = None) -> str:
|
219
|
+
"""
|
220
|
+
Get the path where the file should be saved.
|
221
|
+
|
222
|
+
Args:
|
223
|
+
save_path (str, optional): The path to save the file.
|
224
|
+
|
225
|
+
Returns:
|
226
|
+
str: The path where the file is saved.
|
227
|
+
|
228
|
+
Raises:
|
229
|
+
ValueError: If save_path does not end with a '/'.
|
230
|
+
|
231
|
+
Example:
|
232
|
+
>>> from geobox import GeoboxClient
|
233
|
+
>>> from geobox.file import File
|
234
|
+
>>> from geobox import GeoboxClient
|
235
|
+
>>> client = GeoboxClient()
|
236
|
+
>>> file_path = File.get_file(client, uuid="12345678-1234-5678-1234-567812345678")
|
237
|
+
"""
|
238
|
+
# Get the original filename from data or use uuid
|
239
|
+
if self.name:
|
240
|
+
filename = f"{self.name.split('.')[0]}" if len(self.name.split('.')) > 1 else f'{self.name}'
|
241
|
+
else:
|
242
|
+
filename = f'{self.uuid}'
|
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}{filename}'
|
247
|
+
|
248
|
+
if save_path and not save_path.endswith('/'):
|
249
|
+
raise ValueError("save_path must end with a '/'")
|
250
|
+
|
251
|
+
return os.path.join(os.getcwd(), filename)
|
252
|
+
|
253
|
+
|
254
|
+
def _get_file_ext(self, response: requests.Response) -> str:
|
255
|
+
"""
|
256
|
+
Get the file extension of the response.
|
257
|
+
|
258
|
+
Args:
|
259
|
+
response (requests.Response): The response of the request.
|
260
|
+
|
261
|
+
Returns:
|
262
|
+
str: The file extension of the response.
|
263
|
+
"""
|
264
|
+
ext = ""
|
265
|
+
if 'Content-Disposition' in response.headers:
|
266
|
+
content_disposition = response.headers['Content-Disposition']
|
267
|
+
if 'filename=' in content_disposition:
|
268
|
+
filename = content_disposition.split('filename=')[-1].strip().strip('"')
|
269
|
+
ext = f".{filename.split('.')[-1]}"
|
270
|
+
|
271
|
+
else:
|
272
|
+
content_type = response.headers.get("Content-Type", "")
|
273
|
+
ext = mimetypes.guess_extension(content_type.split(";")[0])
|
274
|
+
|
275
|
+
return ext
|
276
|
+
|
277
|
+
|
278
|
+
def _create_progress_bar(self) -> 'tqdm':
|
279
|
+
"""Creates a progress bar for the task."""
|
280
|
+
try:
|
281
|
+
from tqdm.auto import tqdm
|
282
|
+
except ImportError:
|
283
|
+
from .api import logger
|
284
|
+
logger.warning("[tqdm] extra is required to show the progress bar. install with: pip insatll pygeobox[tqdm]")
|
285
|
+
return None
|
286
|
+
|
287
|
+
return tqdm(unit="B",
|
288
|
+
total=int(self.size),
|
289
|
+
file=sys.stdout,
|
290
|
+
dynamic_ncols=True,
|
291
|
+
desc="Downloading",
|
292
|
+
unit_scale=True,
|
293
|
+
unit_divisor=1024,
|
294
|
+
ascii=True
|
295
|
+
)
|
296
|
+
|
297
|
+
|
298
|
+
def download(self, save_path: str = None, progress_bar: bool = True) -> str:
|
299
|
+
"""
|
300
|
+
Download a file and save it to the specified path.
|
301
|
+
|
302
|
+
Args:
|
303
|
+
save_path (str, optional): Path where the file should be saved.
|
304
|
+
If not provided, it saves to the current working directory
|
305
|
+
using the original filename and appropriate extension.
|
306
|
+
progress_bar (bool, optional): Whether to show a progress bar. default: True
|
307
|
+
|
308
|
+
Returns:
|
309
|
+
str: Path where the file was saved
|
310
|
+
|
311
|
+
Raises:
|
312
|
+
ValueError: If uuid is not set
|
313
|
+
OSError: If there are issues with file operations
|
314
|
+
|
315
|
+
Example:
|
316
|
+
>>> from geobox import GeoboxClient
|
317
|
+
>>> from geobox.file import File
|
318
|
+
>>> client = GeoboxClient()
|
319
|
+
>>> file = File.get_file(client, uuid="12345678-1234-5678-1234-567812345678")
|
320
|
+
>>> file.download(save_path='path/to/save/')
|
321
|
+
"""
|
322
|
+
if not self.uuid:
|
323
|
+
raise ValueError("File UUID is required to download the file")
|
324
|
+
|
325
|
+
save_path = self._get_save_path(save_path)
|
326
|
+
os.makedirs(os.path.dirname(save_path), exist_ok=True)
|
327
|
+
|
328
|
+
with self.api.get(f"{self.endpoint}download/", stream=True) as response, \
|
329
|
+
open(save_path, 'wb') as f:
|
330
|
+
pbar = self._create_progress_bar() if progress_bar else None
|
331
|
+
for chunk in response.iter_content(chunk_size=8192):
|
332
|
+
f.write(chunk)
|
333
|
+
if pbar:
|
334
|
+
pbar.update(len(chunk))
|
335
|
+
pbar.refresh()
|
336
|
+
if pbar:
|
337
|
+
pbar.close()
|
338
|
+
|
339
|
+
final_path = os.path.abspath(save_path) + self._get_file_ext(response)
|
340
|
+
os.rename(os.path.abspath(save_path), os.path.abspath(final_path))
|
341
|
+
return os.path.abspath(final_path)
|
342
|
+
|
343
|
+
|
344
|
+
def delete(self) -> None:
|
345
|
+
"""
|
346
|
+
Deletes the file.
|
347
|
+
|
348
|
+
Returns:
|
349
|
+
None
|
350
|
+
|
351
|
+
Example:
|
352
|
+
>>> from geobox import GeoboxClient
|
353
|
+
>>> from geobox.file import File
|
354
|
+
>>> client = GeoboxClient()
|
355
|
+
>>> file = File.get_file(client, uuid="12345678-1234-5678-1234-567812345678")
|
356
|
+
>>> file.delete()
|
357
|
+
"""
|
358
|
+
return super().delete(self.endpoint)
|
359
|
+
|
360
|
+
|
361
|
+
def publish(self,
|
362
|
+
publish_as: 'PublishFileType',
|
363
|
+
name: str,
|
364
|
+
input_geom_type: 'InputGeomType' = None,
|
365
|
+
input_layer: str = None,
|
366
|
+
input_dataset: str = None,
|
367
|
+
user_id: int = None,
|
368
|
+
input_srid: int = None,
|
369
|
+
file_encoding: str = "utf-8",
|
370
|
+
replace_domain_codes_by_values: bool = False,
|
371
|
+
report_errors: bool = True,
|
372
|
+
as_terrain: bool = False) -> 'Task':
|
373
|
+
"""
|
374
|
+
Publishes a file as a layer.
|
375
|
+
|
376
|
+
Args:
|
377
|
+
publish_as (PublishFileType): The type of layer to publish as.
|
378
|
+
name (str): The name of the layer.
|
379
|
+
input_geom_type (InputGeomType, optional): The geometry type of the layer.
|
380
|
+
input_layer (str, optional): The name of the input layer.
|
381
|
+
input_dataset (str, optional): The name of the input dataset.
|
382
|
+
user_id (int, optional): Specific user. privileges required.
|
383
|
+
input_srid (int, optional): The SRID of the layer.
|
384
|
+
file_encoding (str, optional): The encoding of the file. default is "utf-8".
|
385
|
+
replace_domain_codes_by_values (bool, optional): Whether to replace domain codes by values. default is False.
|
386
|
+
report_errors (bool, optional): Whether to report errors. default is True.
|
387
|
+
as_terrain (bool, optional): Whether to publish as terrain. default is False.
|
388
|
+
|
389
|
+
Returns:
|
390
|
+
Task: The task object.
|
391
|
+
|
392
|
+
Raises:
|
393
|
+
ValueError: If the publish_as is not a valid PublishFileType.
|
394
|
+
|
395
|
+
Example:
|
396
|
+
>>> from geobox import GeoboxClient
|
397
|
+
>>> from geobox.file import File
|
398
|
+
>>> client = GeoboxClient()
|
399
|
+
>>> file = File.get_file(client, uuid="12345678-1234-5678-1234-567812345678")
|
400
|
+
>>> file.publish(publish_as=PublishFileType.VECTOR,
|
401
|
+
... layer_name='my_layer',
|
402
|
+
... input_geom_type=InputGeomType.POINT,
|
403
|
+
... input_layer='layer1',
|
404
|
+
... input_dataset='dataset1',
|
405
|
+
... input_srid=4326,
|
406
|
+
... file_encoding='utf-8')
|
407
|
+
"""
|
408
|
+
data = clean_data({
|
409
|
+
"publish_as": publish_as.value if isinstance(publish_as, PublishFileType) else publish_as,
|
410
|
+
"layer_name": name,
|
411
|
+
"input_layer": input_layer,
|
412
|
+
"input_geom_type": input_geom_type.value if isinstance(input_geom_type, InputGeomType) else input_geom_type,
|
413
|
+
"replace_domain_codes_by_values": replace_domain_codes_by_values,
|
414
|
+
"input_dataset": self.name if not input_dataset else input_dataset,
|
415
|
+
"user_id": user_id,
|
416
|
+
"input_srid": input_srid,
|
417
|
+
"file_encoding": file_encoding,
|
418
|
+
"report_errors": report_errors,
|
419
|
+
"as_terrain": as_terrain
|
420
|
+
})
|
421
|
+
|
422
|
+
endpoint = urljoin(self.endpoint, 'publish/')
|
423
|
+
response = self.api.post(endpoint, data, is_json=False)
|
424
|
+
task = Task.get_task(self.api, response.get('task_id'))
|
425
|
+
return task
|
426
|
+
|
427
|
+
|
428
|
+
def share(self, users: List['User']) -> None:
|
429
|
+
"""
|
430
|
+
Shares the file with specified users.
|
431
|
+
|
432
|
+
Args:
|
433
|
+
users (List[User]): The list of users objects to share the file with.
|
434
|
+
|
435
|
+
Returns:
|
436
|
+
None
|
437
|
+
|
438
|
+
Example:
|
439
|
+
>>> from geobox import GeoboxClient
|
440
|
+
>>> from geobox.file import File
|
441
|
+
>>> client = GeoboxClient()
|
442
|
+
>>> file = File.get_file(client, uuid="12345678-1234-5678-1234-567812345678")
|
443
|
+
>>> users = client.search_users(search='John')
|
444
|
+
>>> file.share(users=users)
|
445
|
+
"""
|
446
|
+
super()._share(self.endpoint, users)
|
447
|
+
|
448
|
+
|
449
|
+
def unshare(self, users: List['User']) -> None:
|
450
|
+
"""
|
451
|
+
Unshares the file with specified users.
|
452
|
+
|
453
|
+
Args:
|
454
|
+
users (List[User]): The list of users objects to unshare the file with.
|
455
|
+
|
456
|
+
Returns:
|
457
|
+
None
|
458
|
+
|
459
|
+
Example:
|
460
|
+
>>> from geobox import GeoboxClient
|
461
|
+
>>> from geobox.file import File
|
462
|
+
>>> client = GeoboxClient()
|
463
|
+
>>> file = File.get_file(client, uuid="12345678-1234-5678-1234-567812345678")
|
464
|
+
>>> users = client.search_users(search='John')
|
465
|
+
>>> file.unshare(users=users)
|
466
|
+
"""
|
467
|
+
super()._unshare(self.endpoint, users)
|
468
|
+
|
469
|
+
|
470
|
+
def get_shared_users(self, search: str = None, skip: int = 0, limit: int = 10) -> List['User']:
|
471
|
+
"""
|
472
|
+
Retrieves the list of users the file is shared with.
|
473
|
+
|
474
|
+
Args:
|
475
|
+
search (str, optional): The search query.
|
476
|
+
skip (int, optional): The number of users to skip.
|
477
|
+
limit (int, optional): The maximum number of users to retrieve.
|
478
|
+
|
479
|
+
Returns:
|
480
|
+
List[User]: The list of shared users.
|
481
|
+
|
482
|
+
Example:
|
483
|
+
>>> from geobox import GeoboxClient
|
484
|
+
>>> from geobox.file import File
|
485
|
+
>>> client = GeoboxClient()
|
486
|
+
>>> file = File.get_file(client, uuid="12345678-1234-5678-1234-567812345678")
|
487
|
+
>>> file.get_shared_users(search='John', skip=0, limit=10)
|
488
|
+
"""
|
489
|
+
params = {
|
490
|
+
'search': search,
|
491
|
+
'skip': skip,
|
492
|
+
'limit': limit
|
493
|
+
}
|
494
|
+
return super()._get_shared_users(self.endpoint, params)
|
pygeobox/log.py
ADDED
@@ -0,0 +1,101 @@
|
|
1
|
+
from urllib.parse import urljoin
|
2
|
+
from typing import Optional, Dict, List, Union, TYPE_CHECKING
|
3
|
+
from datetime import datetime
|
4
|
+
|
5
|
+
from .base import Base
|
6
|
+
|
7
|
+
if TYPE_CHECKING:
|
8
|
+
from . import GeoboxClient
|
9
|
+
|
10
|
+
|
11
|
+
class Log(Base):
|
12
|
+
|
13
|
+
BASE_ENDPOINT = 'logs/'
|
14
|
+
|
15
|
+
def __init__(self,
|
16
|
+
api: 'GeoboxClient',
|
17
|
+
log_id: int,
|
18
|
+
data: Optional[Dict] = {}):
|
19
|
+
"""
|
20
|
+
Constructs all the necessary attributes for the Log object.
|
21
|
+
|
22
|
+
Args:
|
23
|
+
api (Api): The GeoboxClient instance for making requests.
|
24
|
+
log_id (int): The id of the log.
|
25
|
+
data (Dict, optional): The data of the log.
|
26
|
+
"""
|
27
|
+
super().__init__(api, data=data)
|
28
|
+
self.log_id = log_id
|
29
|
+
self.endpoint = f"{self.BASE_ENDPOINT}{self.log_id}"
|
30
|
+
|
31
|
+
|
32
|
+
def __repr__(self) -> str:
|
33
|
+
"""
|
34
|
+
Return a string representation of the Log object.
|
35
|
+
|
36
|
+
Returns:
|
37
|
+
str: A string representation of the Log object.
|
38
|
+
"""
|
39
|
+
return f"Log(id={self.log_id}, activity_type={self.activity_type})"
|
40
|
+
|
41
|
+
|
42
|
+
@classmethod
|
43
|
+
def get_logs(cls, api: 'GeoboxClient', **kwargs) -> List['Log']:
|
44
|
+
"""
|
45
|
+
Get a list of Logs
|
46
|
+
|
47
|
+
Args:
|
48
|
+
api (GeoboxClient): The GeoboxClient instance for making requests.
|
49
|
+
|
50
|
+
Keyword Args:
|
51
|
+
search (str): search term for keyword-based searching among all textual fields
|
52
|
+
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.
|
53
|
+
skip (int): Number of items to skip. default is 0.
|
54
|
+
limit (int): Number of items to return. default is 10.
|
55
|
+
user_id (int): Specific user. Privileges required.
|
56
|
+
from_date (datetime): datetime object in this format: "%Y-%m-%dT%H:%M:%S.%f".
|
57
|
+
to_date (datetime): datetime object in this format: "%Y-%m-%dT%H:%M:%S.%f".
|
58
|
+
user_identity (str): the user identity in this format: username - firstname lastname - email .
|
59
|
+
activity_type (str): the user activity type.
|
60
|
+
|
61
|
+
Returns:
|
62
|
+
List[Log]: a list of logs
|
63
|
+
|
64
|
+
Example:
|
65
|
+
>>> from geobox import Geobox
|
66
|
+
>>> from geopox.log import Log
|
67
|
+
>>> client = GeoboxClient()
|
68
|
+
>>> logs = Log.get_logs(client)
|
69
|
+
or
|
70
|
+
>>> logs = client.get_logs()
|
71
|
+
"""
|
72
|
+
params = {
|
73
|
+
'search': kwargs.get('search'),
|
74
|
+
'order_by': kwargs.get('order_by'),
|
75
|
+
'skip': kwargs.get('skip'),
|
76
|
+
'limit': kwargs.get('limit'),
|
77
|
+
'user_id': kwargs.get('user_id'),
|
78
|
+
'from_date': kwargs.get('from_date').strftime("%Y-%m-%dT%H:%M:%S.%f") if kwargs.get('from_date') else None,
|
79
|
+
'to_date': kwargs.get('to_date').strftime("%Y-%m-%dT%H:%M:%S.%f") if kwargs.get('to_date') else None,
|
80
|
+
'user_identity': kwargs.get('user_identity'),
|
81
|
+
'activity_type': kwargs.get('activity_type')
|
82
|
+
}
|
83
|
+
return super()._get_list(api, cls.BASE_ENDPOINT, params, factory_func=lambda api, item: Log(api, item['id'], item))
|
84
|
+
|
85
|
+
|
86
|
+
def delete(self) -> None:
|
87
|
+
"""
|
88
|
+
Delete a log (privileges required)
|
89
|
+
|
90
|
+
Returns:
|
91
|
+
None
|
92
|
+
|
93
|
+
Example:
|
94
|
+
>>> from geobox import Geobox
|
95
|
+
>>> from geopox.log import Log
|
96
|
+
>>> client = GeoboxClient()
|
97
|
+
>>> log = Log.get_logs(client)[0]
|
98
|
+
>>> log.delete()
|
99
|
+
"""
|
100
|
+
super().delete(self.endpoint)
|
101
|
+
self.log_id = None
|