forked from microsoft/CameraTraps
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathserver_utils.py
More file actions
92 lines (73 loc) · 3.25 KB
/
server_utils.py
File metadata and controls
92 lines (73 loc) · 3.25 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.
"""
Helper functions for the batch processing API.
"""
import logging
import os
from datetime import datetime
from typing import Tuple, Any, Sequence, Optional
import sas_blob_utils # from ai4eutils
log = logging.getLogger(os.environ['FLASK_APP'])
#%% helper classes and functions
def make_error(error_code: int, error_message: str) -> Tuple[dict, int]:
# TODO log exception when we have more telemetry
log.error(f'Error {error_code} - {error_message}')
return {'error': error_message}, error_code
def check_data_container_sas(input_container_sas: str) -> Optional[Tuple[int, str]]:
"""
Returns a tuple (error_code, msg) if not a usable SAS URL, else returns None
"""
# TODO check that the expiry date of input_container_sas is at least a month
# into the future
permissions = sas_blob_utils.get_permissions_from_uri(input_container_sas)
data = sas_blob_utils.get_all_query_parts(input_container_sas)
msg = ('input_container_sas provided does not have both read and list '
'permissions.')
if 'read' not in permissions or 'list' not in permissions:
if 'si' in data:
# if no permission specified explicitly but has an access policy, assumes okay
# TODO - check based on access policy as well
return None
return 400, msg
return None
def get_utc_time() -> str:
# return current UTC time as a string in the ISO 8601 format (so we can query by
# timestamp in the Cosmos DB job status table.
# example: '2021-02-08T20:02:05.699689Z'
return datetime.utcnow().isoformat(timespec='microseconds') + 'Z'
def get_job_status(request_status: str, message: Any) -> dict:
return {
'request_status': request_status,
'message': message
}
def validate_provided_image_paths(image_paths: Sequence[Any]) -> Tuple[Optional[str], bool]:
"""Given a list of image_paths (list length at least 1), validate them and
determine if metadata is available.
Args:
image_paths: a list of string (image_id) or a list of 2-item lists
([image_id, image_metadata])
Returns:
error: None if checks passed, otherwise a string error message
metadata_available: bool, True if available
"""
# image_paths will have length at least 1, otherwise would have ended before this step
first_item = image_paths[0]
metadata_available = False
if isinstance(first_item, str):
for i in image_paths:
if not isinstance(i, str):
error = 'Not all items in image_paths are of type string.'
return error, metadata_available
return None, metadata_available
elif isinstance(first_item, list):
metadata_available = True
for i in image_paths:
if len(i) != 2: # i should be [image_id, metadata_string]
error = ('Items in image_paths are lists, but not all lists '
'are of length 2 [image locator, metadata].')
return error, metadata_available
return None, metadata_available
else:
error = 'image_paths contain items that are not strings nor lists.'
return error, metadata_available