das-cli 1.2.5__py3-none-any.whl → 1.2.6__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.
- das/cli.py +1245 -1234
- das/common/file_utils.py +3 -0
- das/managers/entries_manager.py +21 -15
- das/services/downloads.py +100 -100
- {das_cli-1.2.5.dist-info → das_cli-1.2.6.dist-info}/METADATA +1 -1
- {das_cli-1.2.5.dist-info → das_cli-1.2.6.dist-info}/RECORD +10 -10
- {das_cli-1.2.5.dist-info → das_cli-1.2.6.dist-info}/WHEEL +0 -0
- {das_cli-1.2.5.dist-info → das_cli-1.2.6.dist-info}/entry_points.txt +0 -0
- {das_cli-1.2.5.dist-info → das_cli-1.2.6.dist-info}/licenses/LICENSE +0 -0
- {das_cli-1.2.5.dist-info → das_cli-1.2.6.dist-info}/top_level.txt +0 -0
das/common/file_utils.py
CHANGED
|
@@ -67,6 +67,9 @@ def load_csv_file(file_path: str) -> List[Dict[str, Any]]:
|
|
|
67
67
|
|
|
68
68
|
if not headers:
|
|
69
69
|
raise ValueError("CSV file is empty or has no headers")
|
|
70
|
+
|
|
71
|
+
# Strip leading/trailing whitespace from column headers
|
|
72
|
+
headers = [h.strip() for h in headers]
|
|
70
73
|
|
|
71
74
|
result = []
|
|
72
75
|
for row in reader:
|
das/managers/entries_manager.py
CHANGED
|
@@ -172,7 +172,7 @@ class EntryManager:
|
|
|
172
172
|
|
|
173
173
|
return self.entry_service.create(attribute_id=attribute_id, entry=new_entry)
|
|
174
174
|
|
|
175
|
-
def update(self,
|
|
175
|
+
def update(self, id: str = None, code: str = None, entry: dict = None, entries: list = None) -> list:
|
|
176
176
|
"""
|
|
177
177
|
Update one or more existing entries.
|
|
178
178
|
|
|
@@ -180,7 +180,7 @@ class EntryManager:
|
|
|
180
180
|
If 'entries' is provided, updates multiple entries based on the code in each entry.
|
|
181
181
|
|
|
182
182
|
Args:
|
|
183
|
-
|
|
183
|
+
id (str, optional): The entry ID for single entry update
|
|
184
184
|
code (str, optional): The entry code for single entry update
|
|
185
185
|
entry (dict, optional): The entry data for single entry update
|
|
186
186
|
entries (list, optional): List of entry data for multiple updates
|
|
@@ -206,34 +206,40 @@ class EntryManager:
|
|
|
206
206
|
|
|
207
207
|
# Each entry must have a Code field
|
|
208
208
|
entry_code = next((entry_data.get(key) for key in entry_data if key.lower() == 'code'), None)
|
|
209
|
+
entry_id = next((entry_data.get(key) for key in entry_data if key.lower() == 'id'), None)
|
|
209
210
|
if not entry_code:
|
|
210
|
-
|
|
211
|
+
entry_data['code'] = code
|
|
212
|
+
if not entry_id:
|
|
213
|
+
entry_data['id'] = id
|
|
211
214
|
|
|
212
215
|
try:
|
|
213
|
-
result = self._update_single_entry(
|
|
216
|
+
result = self._update_single_entry(id=id, code=code, entry=entry_data)
|
|
214
217
|
results.append({"code": entry_code, "id": result, "status": "success"})
|
|
215
218
|
except Exception as e:
|
|
216
219
|
results.append({"code": entry_code, "error": str(e), "status": "error"})
|
|
217
220
|
|
|
218
221
|
return results
|
|
219
222
|
|
|
220
|
-
elif code and entry:
|
|
223
|
+
elif (code or id) and entry:
|
|
221
224
|
# Single entry update
|
|
222
|
-
result = self._update_single_entry(
|
|
225
|
+
result = self._update_single_entry(id=id, code=code, entry=entry)
|
|
223
226
|
return [{"code": code, "id": result, "status": "success"}]
|
|
224
227
|
|
|
225
228
|
else:
|
|
226
|
-
raise ValueError("Either 'code' and 'entry' or 'entries' must be provided")
|
|
229
|
+
raise ValueError("Either 'id', 'code' and 'entry' or 'entries' must be provided")
|
|
227
230
|
|
|
228
|
-
def _update_single_entry(self,
|
|
231
|
+
def _update_single_entry(self, id: str = None, code: str = None, entry: dict = None) -> str:
|
|
229
232
|
"""Internal method to update a single entry."""
|
|
230
|
-
if not code:
|
|
231
|
-
raise ValueError("Entry code is required")
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
233
|
+
if not id and not code:
|
|
234
|
+
raise ValueError("Entry ID or code is required")
|
|
235
|
+
if id:
|
|
236
|
+
if not entry:
|
|
237
|
+
raise ValueError("Entry data is required")
|
|
238
|
+
existing_entry_response = self.entry_service.get(id=id)
|
|
239
|
+
elif code:
|
|
240
|
+
existing_entry_response = self.entry_service.get(code=code)
|
|
241
|
+
else:
|
|
242
|
+
raise ValueError("Entry ID or code is required")
|
|
237
243
|
|
|
238
244
|
if not existing_entry_response or not isinstance(existing_entry_response, dict):
|
|
239
245
|
raise ValueError(f"Invalid existing entry response: {existing_entry_response}")
|
das/services/downloads.py
CHANGED
|
@@ -1,101 +1,101 @@
|
|
|
1
|
-
from das.common.api import post_data, get_data, get_binary_response
|
|
2
|
-
from das.common.config import load_token
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
class DownloadRequestService:
|
|
6
|
-
def __init__(self, base_url):
|
|
7
|
-
self.base_url = f"{base_url}/api/services/app/DownloadRequest"
|
|
8
|
-
self.download_files_url = f"{base_url}/File/DownloadRequestSet"
|
|
9
|
-
|
|
10
|
-
def create(self, request_data: list[dict]):
|
|
11
|
-
"""Create a new download request."""
|
|
12
|
-
token = load_token()
|
|
13
|
-
|
|
14
|
-
if (token is None or token == ""):
|
|
15
|
-
raise ValueError("Authorization token is required")
|
|
16
|
-
|
|
17
|
-
headers = {
|
|
18
|
-
"Authorization": f"Bearer {token}",
|
|
19
|
-
"Content-Type": "application/json"
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
url = f"{self.base_url}/Create"
|
|
23
|
-
|
|
24
|
-
response = post_data(url, data=request_data, headers=headers)
|
|
25
|
-
|
|
26
|
-
if response.get('success') == True:
|
|
27
|
-
return response.get('result')
|
|
28
|
-
else:
|
|
29
|
-
raise ValueError(response.get('error'))
|
|
30
|
-
|
|
31
|
-
def delete(self, request_id: str):
|
|
32
|
-
"""Delete a download request by ID."""
|
|
33
|
-
|
|
34
|
-
#check if request_id is valid uuid
|
|
35
|
-
if not isinstance(request_id, str) or len(request_id) != 36:
|
|
36
|
-
raise ValueError("Invalid request ID")
|
|
37
|
-
|
|
38
|
-
token = load_token()
|
|
39
|
-
|
|
40
|
-
if (token is None or token == ""):
|
|
41
|
-
raise ValueError("Authorization token is required")
|
|
42
|
-
|
|
43
|
-
headers = {
|
|
44
|
-
"Authorization": f"Bearer {token}",
|
|
45
|
-
"Content-Type": "application/json"
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
url = f"{self.base_url}/Delete?downloadRequestId={request_id}"
|
|
49
|
-
|
|
50
|
-
response = post_data(url, data={}, headers=headers)
|
|
51
|
-
|
|
52
|
-
if response.get('success') == True:
|
|
53
|
-
return response.get('result')
|
|
54
|
-
else:
|
|
55
|
-
raise ValueError(response.get('error'))
|
|
56
|
-
|
|
57
|
-
def get_my_requests(self):
|
|
58
|
-
"""Get all download requests for the current user."""
|
|
59
|
-
token = load_token()
|
|
60
|
-
|
|
61
|
-
if (token is None or token == ""):
|
|
62
|
-
raise ValueError("Authorization token is required")
|
|
63
|
-
|
|
64
|
-
headers = {
|
|
65
|
-
"Authorization": f"Bearer {token}"
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
url = f"{self.base_url}/GetMyRequests"
|
|
69
|
-
response = get_data(url, headers=headers)
|
|
70
|
-
|
|
71
|
-
# Expected API response shape:
|
|
72
|
-
# { success: true, result: { totalCount: number, items: [...] }, ... }
|
|
73
|
-
if isinstance(response, dict) and response.get('success') is True:
|
|
74
|
-
return response.get('result')
|
|
75
|
-
# Some backends might already return the result without 'success'
|
|
76
|
-
if isinstance(response, dict) and 'result' in response and 'success' not in response:
|
|
77
|
-
return response.get('result')
|
|
78
|
-
# If the API directly returns the payload (result), pass it through
|
|
79
|
-
if isinstance(response, dict) and 'items' in response and 'totalCount' in response:
|
|
80
|
-
return response
|
|
81
|
-
# Otherwise raise a meaningful error
|
|
82
|
-
error_msg = None
|
|
83
|
-
if isinstance(response, dict):
|
|
84
|
-
error_msg = response.get('error') or response.get('message')
|
|
85
|
-
raise ValueError(error_msg or 'Failed to fetch download requests')
|
|
86
|
-
|
|
87
|
-
def download_files(self, request_id: str):
|
|
88
|
-
"""Return a streaming HTTP response for the download bundle of a request."""
|
|
89
|
-
token = load_token()
|
|
90
|
-
|
|
91
|
-
if (token is None or token == ""):
|
|
92
|
-
raise ValueError("Authorization token is required")
|
|
93
|
-
|
|
94
|
-
headers = {
|
|
95
|
-
"Authorization": f"Bearer {token}"
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
url = f"{self.download_files_url}?requestId={request_id}"
|
|
99
|
-
|
|
100
|
-
response = get_binary_response(url, headers=headers, params=None, stream=True)
|
|
1
|
+
from das.common.api import post_data, get_data, get_binary_response
|
|
2
|
+
from das.common.config import load_token
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class DownloadRequestService:
|
|
6
|
+
def __init__(self, base_url):
|
|
7
|
+
self.base_url = f"{base_url}/api/services/app/DownloadRequest"
|
|
8
|
+
self.download_files_url = f"{base_url}/File/DownloadRequestSet"
|
|
9
|
+
|
|
10
|
+
def create(self, request_data: list[dict]):
|
|
11
|
+
"""Create a new download request."""
|
|
12
|
+
token = load_token()
|
|
13
|
+
|
|
14
|
+
if (token is None or token == ""):
|
|
15
|
+
raise ValueError("Authorization token is required")
|
|
16
|
+
|
|
17
|
+
headers = {
|
|
18
|
+
"Authorization": f"Bearer {token}",
|
|
19
|
+
"Content-Type": "application/json"
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
url = f"{self.base_url}/Create"
|
|
23
|
+
|
|
24
|
+
response = post_data(url, data=request_data, headers=headers)
|
|
25
|
+
|
|
26
|
+
if response.get('success') == True:
|
|
27
|
+
return response.get('result')
|
|
28
|
+
else:
|
|
29
|
+
raise ValueError(response.get('error'))
|
|
30
|
+
|
|
31
|
+
def delete(self, request_id: str):
|
|
32
|
+
"""Delete a download request by ID."""
|
|
33
|
+
|
|
34
|
+
#check if request_id is valid uuid
|
|
35
|
+
if not isinstance(request_id, str) or len(request_id) != 36:
|
|
36
|
+
raise ValueError("Invalid request ID")
|
|
37
|
+
|
|
38
|
+
token = load_token()
|
|
39
|
+
|
|
40
|
+
if (token is None or token == ""):
|
|
41
|
+
raise ValueError("Authorization token is required")
|
|
42
|
+
|
|
43
|
+
headers = {
|
|
44
|
+
"Authorization": f"Bearer {token}",
|
|
45
|
+
"Content-Type": "application/json"
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
url = f"{self.base_url}/Delete?downloadRequestId={request_id}"
|
|
49
|
+
|
|
50
|
+
response = post_data(url, data={}, headers=headers)
|
|
51
|
+
|
|
52
|
+
if response.get('success') == True:
|
|
53
|
+
return response.get('result')
|
|
54
|
+
else:
|
|
55
|
+
raise ValueError(response.get('error'))
|
|
56
|
+
|
|
57
|
+
def get_my_requests(self):
|
|
58
|
+
"""Get all download requests for the current user."""
|
|
59
|
+
token = load_token()
|
|
60
|
+
|
|
61
|
+
if (token is None or token == ""):
|
|
62
|
+
raise ValueError("Authorization token is required")
|
|
63
|
+
|
|
64
|
+
headers = {
|
|
65
|
+
"Authorization": f"Bearer {token}"
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
url = f"{self.base_url}/GetMyRequests"
|
|
69
|
+
response = get_data(url, headers=headers)
|
|
70
|
+
|
|
71
|
+
# Expected API response shape:
|
|
72
|
+
# { success: true, result: { totalCount: number, items: [...] }, ... }
|
|
73
|
+
if isinstance(response, dict) and response.get('success') is True:
|
|
74
|
+
return response.get('result')
|
|
75
|
+
# Some backends might already return the result without 'success'
|
|
76
|
+
if isinstance(response, dict) and 'result' in response and 'success' not in response:
|
|
77
|
+
return response.get('result')
|
|
78
|
+
# If the API directly returns the payload (result), pass it through
|
|
79
|
+
if isinstance(response, dict) and 'items' in response and 'totalCount' in response:
|
|
80
|
+
return response
|
|
81
|
+
# Otherwise raise a meaningful error
|
|
82
|
+
error_msg = None
|
|
83
|
+
if isinstance(response, dict):
|
|
84
|
+
error_msg = response.get('error') or response.get('message')
|
|
85
|
+
raise ValueError(error_msg or 'Failed to fetch download requests')
|
|
86
|
+
|
|
87
|
+
def download_files(self, request_id: str):
|
|
88
|
+
"""Return a streaming HTTP response for the download bundle of a request."""
|
|
89
|
+
token = load_token()
|
|
90
|
+
|
|
91
|
+
if (token is None or token == ""):
|
|
92
|
+
raise ValueError("Authorization token is required")
|
|
93
|
+
|
|
94
|
+
headers = {
|
|
95
|
+
"Authorization": f"Bearer {token}"
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
url = f"{self.download_files_url}?requestId={request_id}"
|
|
99
|
+
|
|
100
|
+
response = get_binary_response(url, headers=headers, params=None, stream=True)
|
|
101
101
|
return response
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
das/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
2
|
das/app.py,sha256=kKxN4Vn84SA5Ph3zY13avMG2vrUp-ffpdDkhwYR9Bho,1475
|
|
3
|
-
das/cli.py,sha256=
|
|
3
|
+
das/cli.py,sha256=lh6RGqxACR4OOS7wrkhfD2yXli-Z7dsrch1_HNF05LM,51264
|
|
4
4
|
das/ai/plugins/dasai.py,sha256=1P-0q4ReAnmJxliGAPMxR1aij9RWKxyTIHJzWTwLZLo,2459
|
|
5
5
|
das/ai/plugins/entries/entries_plugin.py,sha256=Dhv6PrguQj5mzxBW6DlCzkmwucszazLQfzwlp9EhIGk,608
|
|
6
6
|
das/authentication/auth.py,sha256=DTtH66Ft6nuuMe7EYvrr3GqGVEGGxE7GmD2fO7vRv4s,1501
|
|
@@ -9,24 +9,24 @@ das/common/api.py,sha256=GNY1nF5B8JgFDAGifC2jR2ZTtKt4GLd7W20ARky4wcY,4501
|
|
|
9
9
|
das/common/config.py,sha256=VQi_tJ7hvIa--gvx9VCBkfVI9p0ptOvifIu08tc8kEs,6127
|
|
10
10
|
das/common/entry_fields_constants.py,sha256=5Yh4Ujt70HEF-FsnwVBPBm3DB3HHzQWSWR-9Upt7C5I,93
|
|
11
11
|
das/common/enums.py,sha256=jS0frv6717duG_wZNockXMTZ-VfsGu_f8_-lgYGnrcY,1745
|
|
12
|
-
das/common/file_utils.py,sha256
|
|
12
|
+
das/common/file_utils.py,sha256=Mb1uV9OAHle4zPSQFrythsU_8fzYV5grjgc1p9cmeA4,7129
|
|
13
13
|
das/managers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
14
14
|
das/managers/digital_objects_manager.py,sha256=v7VAYfKoDpmWJGVgpVoSyk6hqGMiQJeOX5rgm65xE5U,3677
|
|
15
15
|
das/managers/download_manager.py,sha256=bZuRX5yoKC_n00Tbjn_aRHgHLeq6SjI0TqDqgjttOQU,5431
|
|
16
|
-
das/managers/entries_manager.py,sha256=
|
|
16
|
+
das/managers/entries_manager.py,sha256=UEl4iI-W4OuIxYTIKVCckXOTe1pvPVoKluMrT-EcLxY,20873
|
|
17
17
|
das/managers/search_manager.py,sha256=vXf0JmK5oW-xEGUdDnppfc1-6HdH1hfiZR7L2bCz9u0,4263
|
|
18
18
|
das/services/attributes.py,sha256=78E9f1wNZYxG9Hg5HfX_h1CFmACaMjwD2Y6Ilb7PJGY,2616
|
|
19
19
|
das/services/cache.py,sha256=g-vY51gqGV_1Vpza476PkMqGpuDNo1NbTwQWIIsvO0s,1932
|
|
20
20
|
das/services/digital_objects.py,sha256=ww1KHVLNmm_ffzgqP4Jt4wCbHMVfhD2FJWahlSPFaes,4935
|
|
21
|
-
das/services/downloads.py,sha256=
|
|
21
|
+
das/services/downloads.py,sha256=cn2eoiKEDRcINlzoLgw6mpN3VVLBBiccdFyuCO7TB2I,3709
|
|
22
22
|
das/services/entries.py,sha256=Dzvzx4wOljfumjBBg4sboXmgDTQf3FNbTQp-sl9hAn0,5755
|
|
23
23
|
das/services/entry_fields.py,sha256=x2wUDkKNduj9pf4s56hRo0UW-eBhipkU9gFMEjFw5DA,1290
|
|
24
24
|
das/services/hangfire.py,sha256=hidmVP9yb4znzBaJJRyKawYx7oYaBv5OVL-t0BhvN_A,818
|
|
25
25
|
das/services/search.py,sha256=3X_KPb9fs024FhxoTr4j-xY5ymm5rvvzlekxuh8tLdg,1374
|
|
26
26
|
das/services/users.py,sha256=iNijO2UPIEtcpPy8Tkemdxxym9rYLCUyckQHIQj68W0,795
|
|
27
|
-
das_cli-1.2.
|
|
28
|
-
das_cli-1.2.
|
|
29
|
-
das_cli-1.2.
|
|
30
|
-
das_cli-1.2.
|
|
31
|
-
das_cli-1.2.
|
|
32
|
-
das_cli-1.2.
|
|
27
|
+
das_cli-1.2.6.dist-info/licenses/LICENSE,sha256=4EDhysVgQWBlzo0rdUl_k89s-iVfgCcSa1gUx1TM1vA,1124
|
|
28
|
+
das_cli-1.2.6.dist-info/METADATA,sha256=u4cqs0vje7GcJSFi9OX-9c_PIkSCVU0z-Ez2beawnOA,26209
|
|
29
|
+
das_cli-1.2.6.dist-info/WHEEL,sha256=qELbo2s1Yzl39ZmrAibXA2jjPLUYfnVhUNTlyF1rq0Y,92
|
|
30
|
+
das_cli-1.2.6.dist-info/entry_points.txt,sha256=ZrdMae7NcvogQhzM1zun8E8n_QwYq-LpZvoJCr2_I4g,36
|
|
31
|
+
das_cli-1.2.6.dist-info/top_level.txt,sha256=OJsPEeJyJ2rJlpEn2DTPgbMSvYG-6FeD13_m5qLpw3E,4
|
|
32
|
+
das_cli-1.2.6.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|