hito_tools 26.1rc2__tar.gz → 26.1rc3__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.
Potentially problematic release.
This version of hito_tools might be problematic. Click here for more details.
- {hito_tools-26.1rc2 → hito_tools-26.1rc3}/PKG-INFO +1 -1
- {hito_tools-26.1rc2 → hito_tools-26.1rc3}/hito_tools/nsip.py +82 -21
- {hito_tools-26.1rc2 → hito_tools-26.1rc3}/pyproject.toml +1 -1
- {hito_tools-26.1rc2 → hito_tools-26.1rc3}/LICENSE +0 -0
- {hito_tools-26.1rc2 → hito_tools-26.1rc3}/README.md +0 -0
- {hito_tools-26.1rc2 → hito_tools-26.1rc3}/hito_tools/ad.py +0 -0
- {hito_tools-26.1rc2 → hito_tools-26.1rc3}/hito_tools/agents.py +0 -0
- {hito_tools-26.1rc2 → hito_tools-26.1rc3}/hito_tools/core.py +0 -0
- {hito_tools-26.1rc2 → hito_tools-26.1rc3}/hito_tools/exceptions.py +0 -0
- {hito_tools-26.1rc2 → hito_tools-26.1rc3}/hito_tools/projects.py +0 -0
- {hito_tools-26.1rc2 → hito_tools-26.1rc3}/hito_tools/teams.py +0 -0
- {hito_tools-26.1rc2 → hito_tools-26.1rc3}/hito_tools/utils.py +0 -0
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import datetime
|
|
3
3
|
import re
|
|
4
4
|
from io import StringIO
|
|
5
|
-
from typing import Dict, List
|
|
5
|
+
from typing import Dict, List, Optional
|
|
6
6
|
|
|
7
7
|
import pandas as pd
|
|
8
8
|
|
|
@@ -30,6 +30,12 @@ HTTP_STATUS_FORBIDDEN = 403
|
|
|
30
30
|
HTTP_STATUS_NOT_FOUND = 404
|
|
31
31
|
HTTP_STATUS_CONFLICT = 409
|
|
32
32
|
|
|
33
|
+
AGENT_HAS_MULTIPLE_CONTRACTS_PATTERN = re.compile(
|
|
34
|
+
(
|
|
35
|
+
r'"Agent has active multi-contracts in same laboratory - manual action needed\s+'
|
|
36
|
+
r"\|\s+idAgentContract\s+:\s+(?P<id1>\d+)\s+\|\s+idAgentContract\s+:\s+(?P<id2>\d+)"
|
|
37
|
+
)
|
|
38
|
+
)
|
|
33
39
|
AGENT_NOT_IN_PROJECT_PATTERN = re.compile(
|
|
34
40
|
r'"Error : This project has not been affected to this agent, declaration forbidden"$'
|
|
35
41
|
)
|
|
@@ -84,6 +90,26 @@ class NSIPConnection:
|
|
|
84
90
|
f"{self.api_params[api_category][api_name]}"
|
|
85
91
|
)
|
|
86
92
|
|
|
93
|
+
def _check_multiple_contracts(self, reason: str) -> Optional[str]:
|
|
94
|
+
"""
|
|
95
|
+
One of the possible error during agent-related updates is that the user has
|
|
96
|
+
multiple contracts attached to the lab for the current period. In this case
|
|
97
|
+
the reason contains the different contract IDs: used the last one
|
|
98
|
+
the update is retried with the second contract (generally the current one)
|
|
99
|
+
mentioned in the error message.
|
|
100
|
+
|
|
101
|
+
:param reason: error message returned by API
|
|
102
|
+
:return: contract ID if it is the multiple contract error or None
|
|
103
|
+
"""
|
|
104
|
+
|
|
105
|
+
m = AGENT_HAS_MULTIPLE_CONTRACTS_PATTERN.match(http_reason)
|
|
106
|
+
if m:
|
|
107
|
+
contract = m.group("id2")
|
|
108
|
+
else:
|
|
109
|
+
contract = None
|
|
110
|
+
|
|
111
|
+
return contract
|
|
112
|
+
|
|
87
113
|
def get_agent_list(self, context: str = "NSIP"):
|
|
88
114
|
"""
|
|
89
115
|
Retrieve NSIP agents from NSIP API and return a dict built from the retrieved JSON
|
|
@@ -117,27 +143,52 @@ class NSIPConnection:
|
|
|
117
143
|
http_status, http_reason
|
|
118
144
|
"""
|
|
119
145
|
|
|
146
|
+
contract = None
|
|
120
147
|
url = self._get_api_url("agent_api", "project_assign")
|
|
121
148
|
params = {
|
|
122
149
|
"projectId": project_id,
|
|
123
|
-
"emailReseda": email,
|
|
124
150
|
"startDate": start_date.date().isoformat(),
|
|
125
151
|
"context": "NSIP",
|
|
126
152
|
}
|
|
127
153
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
154
|
+
retry = True
|
|
155
|
+
retry_attempts = 0
|
|
156
|
+
while retry:
|
|
157
|
+
# adding agent is retried only for some specific errors
|
|
158
|
+
retry = False
|
|
159
|
+
|
|
160
|
+
if contract:
|
|
161
|
+
print(f"INFO: adding agent {email} to project {project_id} using contract {contract}")
|
|
162
|
+
params["idAgentContract"] = contract
|
|
163
|
+
else:
|
|
164
|
+
params["emailReseda"] = email
|
|
165
|
+
|
|
166
|
+
r = requests.post(url, headers={"Authorization": f"Bearer {self.token}"}, params=params)
|
|
167
|
+
if r.content:
|
|
168
|
+
reason = r.content.decode("utf-8")
|
|
169
|
+
else:
|
|
170
|
+
reason = ""
|
|
171
|
+
|
|
172
|
+
if r.status_code == HTTP_STATUS_OK:
|
|
173
|
+
status = 0
|
|
174
|
+
elif r.status_code == HTTP_STATUS_CREATED:
|
|
175
|
+
status = 0
|
|
176
|
+
print(f"INFO: agent {email} successfully added to project {project_id}")
|
|
177
|
+
elif r.status_code == HTTP_STATUS_NOT_FOUND:
|
|
178
|
+
contract = self._check_multiple_contracts(r.reason)
|
|
179
|
+
if retry_attempts == 0 and contract is not None:
|
|
180
|
+
retry = True
|
|
181
|
+
print(
|
|
182
|
+
(
|
|
183
|
+
f"Agent {row.email_reseda} has several contracts for the"
|
|
184
|
+
f" current period: retrying update with contract {contract}"
|
|
185
|
+
)
|
|
186
|
+
)
|
|
187
|
+
else:
|
|
188
|
+
status = 1
|
|
189
|
+
else:
|
|
190
|
+
status = 1
|
|
133
191
|
|
|
134
|
-
if r.status_code == HTTP_STATUS_OK:
|
|
135
|
-
status = 0
|
|
136
|
-
elif r.status_code == HTTP_STATUS_CREATED:
|
|
137
|
-
status = 0
|
|
138
|
-
print(f"INFO: agent {email} successfully added to project {project_id}")
|
|
139
|
-
else:
|
|
140
|
-
status = 1
|
|
141
192
|
return status, r.status_code, reason
|
|
142
193
|
|
|
143
194
|
def update_agent(
|
|
@@ -199,7 +250,6 @@ class NSIPConnection:
|
|
|
199
250
|
time: int,
|
|
200
251
|
period_start: str,
|
|
201
252
|
validation_date: datetime.date = None,
|
|
202
|
-
contract: int = None,
|
|
203
253
|
) -> int:
|
|
204
254
|
"""
|
|
205
255
|
Add or update a project declaration for a user specified by its RESEDA email
|
|
@@ -211,22 +261,17 @@ class NSIPConnection:
|
|
|
211
261
|
week)
|
|
212
262
|
:param period_start: start date of the validation period
|
|
213
263
|
:param validation_date: validation date
|
|
214
|
-
:param contract: contract ID in case the agent has multiple contracts for the period
|
|
215
264
|
:return: status (0 for successful add, -1 for successful update, positive value if errors),
|
|
216
265
|
http_status if errors else declaration ID added/modified, http_reason
|
|
217
266
|
"""
|
|
218
267
|
|
|
268
|
+
contract = None
|
|
219
269
|
url = self._get_api_url("agent_api", "declaration_add")
|
|
220
270
|
if project_type:
|
|
221
271
|
params = {"projectId": int(project_id), "referenceId": ""}
|
|
222
272
|
else:
|
|
223
273
|
params = {"projectId": "", "referenceId": int(project_id)}
|
|
224
274
|
params["context"] = "NSIP"
|
|
225
|
-
if contract:
|
|
226
|
-
print(f"INFO: updating {email} declaration using contract {contract}")
|
|
227
|
-
params["idAgentContract"] = contract
|
|
228
|
-
else:
|
|
229
|
-
params["emailReseda"] = email
|
|
230
275
|
params["time"] = time
|
|
231
276
|
if validation_date:
|
|
232
277
|
validation_date_str = validation_date.date().isoformat()
|
|
@@ -238,6 +283,12 @@ class NSIPConnection:
|
|
|
238
283
|
# declaration update is retried only for some specific errors
|
|
239
284
|
retry = False
|
|
240
285
|
|
|
286
|
+
if contract:
|
|
287
|
+
print(f"INFO: updating {email} declaration using contract {contract}")
|
|
288
|
+
params["idAgentContract"] = contract
|
|
289
|
+
else:
|
|
290
|
+
params["emailReseda"] = email
|
|
291
|
+
|
|
241
292
|
r = requests.post(url, headers={"Authorization": f"Bearer {self.token}"}, params=params)
|
|
242
293
|
reason = r.text
|
|
243
294
|
|
|
@@ -289,6 +340,16 @@ class NSIPConnection:
|
|
|
289
340
|
f" (error={http_status}, reason={http_reason})"
|
|
290
341
|
)
|
|
291
342
|
status = -2
|
|
343
|
+
else:
|
|
344
|
+
contract = self._check_multiple_contracts(r.reason)
|
|
345
|
+
if contract:
|
|
346
|
+
retry = True
|
|
347
|
+
print(
|
|
348
|
+
(
|
|
349
|
+
f"Agent {row.email_reseda} has several contracts for the"
|
|
350
|
+
f" current period: retrying update with contract {contract}"
|
|
351
|
+
)
|
|
352
|
+
)
|
|
292
353
|
|
|
293
354
|
if r.status_code == HTTP_STATUS_OK:
|
|
294
355
|
return status, declaration_id, reason
|
|
@@ -4,7 +4,7 @@ build-backend = "poetry.core.masonry.api"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "hito_tools"
|
|
7
|
-
version = "26.1.
|
|
7
|
+
version = "26.1.rc3"
|
|
8
8
|
description = "Modules for interacting with Hito and NSIP"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
authors = [ { name = "Michel Jouvin", email = "michel.jouvin@ijclab.in2p3.fr" } ]
|
|
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
|