dotstat_io 1.0.3__tar.gz → 1.0.4__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 dotstat_io might be problematic. Click here for more details.
- {dotstat_io-1.0.3 → dotstat_io-1.0.4}/PKG-INFO +2 -2
- {dotstat_io-1.0.3 → dotstat_io-1.0.4}/dotstat_io/client.py +60 -53
- {dotstat_io-1.0.3 → dotstat_io-1.0.4}/pyproject.toml +1 -1
- {dotstat_io-1.0.3 → dotstat_io-1.0.4}/README.md +0 -0
- {dotstat_io-1.0.3 → dotstat_io-1.0.4}/dotstat_io/__init__.py +0 -0
- {dotstat_io-1.0.3 → dotstat_io-1.0.4}/dotstat_io/authentication.py +0 -0
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
from enum import IntEnum
|
|
1
2
|
import os
|
|
2
3
|
import requests
|
|
3
4
|
import chardet
|
|
@@ -8,6 +9,12 @@ import xml.etree.ElementTree as ET
|
|
|
8
9
|
from pathlib import Path
|
|
9
10
|
from time import sleep
|
|
10
11
|
|
|
12
|
+
from dotstat_io.authentication import Authentication
|
|
13
|
+
|
|
14
|
+
class ValidationType(IntEnum):
|
|
15
|
+
BASIC = 0
|
|
16
|
+
ADVANCED = 1
|
|
17
|
+
|
|
11
18
|
|
|
12
19
|
# class to download or upload data from/to .Stat Suite
|
|
13
20
|
class Client():
|
|
@@ -35,10 +42,10 @@ class Client():
|
|
|
35
42
|
|
|
36
43
|
# Initialise Client
|
|
37
44
|
def __init__(self,
|
|
38
|
-
access_token: str = None,
|
|
39
|
-
authentication_obj:
|
|
40
|
-
|
|
41
|
-
|
|
45
|
+
access_token: None | str = None,
|
|
46
|
+
authentication_obj: None | Authentication = None):
|
|
47
|
+
Client.__access_token = access_token
|
|
48
|
+
Client.__authentication_obj = authentication_obj
|
|
42
49
|
|
|
43
50
|
|
|
44
51
|
#
|
|
@@ -65,7 +72,7 @@ class Client():
|
|
|
65
72
|
@classmethod
|
|
66
73
|
def init_with_authentication_obj(
|
|
67
74
|
cls,
|
|
68
|
-
authentication_obj:
|
|
75
|
+
authentication_obj: Authentication
|
|
69
76
|
):
|
|
70
77
|
return cls(
|
|
71
78
|
authentication_obj=authentication_obj
|
|
@@ -78,18 +85,18 @@ class Client():
|
|
|
78
85
|
returned_result = ""
|
|
79
86
|
|
|
80
87
|
#
|
|
81
|
-
if
|
|
82
|
-
|
|
88
|
+
if Client.__authentication_obj is not None:
|
|
89
|
+
Client.__access_token = Client.__authentication_obj.get_token()
|
|
83
90
|
|
|
84
91
|
headers = {
|
|
85
92
|
'accept': content_format,
|
|
86
|
-
'authorization': 'Bearer '+
|
|
93
|
+
'authorization': 'Bearer '+Client.__access_token
|
|
87
94
|
}
|
|
88
95
|
|
|
89
96
|
#
|
|
90
97
|
response = requests.get(dotstat_url, verify=True, headers=headers)
|
|
91
98
|
except Exception as err:
|
|
92
|
-
returned_result =
|
|
99
|
+
returned_result = Client.__ERROR_OCCURRED + str(err) + os.linesep
|
|
93
100
|
|
|
94
101
|
# Write the result to the log
|
|
95
102
|
for line in returned_result.split(os.linesep):
|
|
@@ -97,7 +104,7 @@ class Client():
|
|
|
97
104
|
self.__log.info(' ' + line)
|
|
98
105
|
else:
|
|
99
106
|
if response.status_code != 200:
|
|
100
|
-
returned_result =
|
|
107
|
+
returned_result = Client.__ERROR_OCCURRED
|
|
101
108
|
if len(str(response.status_code)) > 0:
|
|
102
109
|
returned_result += 'Error code: ' + str(response.status_code) + os.linesep
|
|
103
110
|
if len(str(response.reason)) > 0:
|
|
@@ -111,7 +118,7 @@ class Client():
|
|
|
111
118
|
os.remove(file_path)
|
|
112
119
|
with open(file_path, "wb") as file:
|
|
113
120
|
file.write(response.content)
|
|
114
|
-
returned_result =
|
|
121
|
+
returned_result = Client.__DOWNLOAD_SUCCESS
|
|
115
122
|
|
|
116
123
|
# Write the result to the log
|
|
117
124
|
for line in returned_result.split(os.linesep):
|
|
@@ -127,19 +134,19 @@ class Client():
|
|
|
127
134
|
returned_result = ""
|
|
128
135
|
|
|
129
136
|
#
|
|
130
|
-
if
|
|
131
|
-
__access_token =
|
|
137
|
+
if Client.__authentication_obj is not None:
|
|
138
|
+
Client.__access_token = Client.__authentication_obj.get_token()
|
|
132
139
|
|
|
133
140
|
headers = {
|
|
134
141
|
'accept': content_format,
|
|
135
142
|
'Transfer-Encoding': 'chunked',
|
|
136
|
-
'authorization': 'Bearer '+
|
|
143
|
+
'authorization': 'Bearer '+Client.__access_token
|
|
137
144
|
}
|
|
138
145
|
|
|
139
146
|
#
|
|
140
147
|
return requests.get(dotstat_url, verify=True, headers=headers, stream=True)
|
|
141
148
|
except Exception as err:
|
|
142
|
-
returned_result =
|
|
149
|
+
returned_result = Client.__ERROR_OCCURRED + str(err) + os.linesep
|
|
143
150
|
return returned_result
|
|
144
151
|
|
|
145
152
|
|
|
@@ -154,8 +161,8 @@ class Client():
|
|
|
154
161
|
returned_result = ""
|
|
155
162
|
|
|
156
163
|
#
|
|
157
|
-
if
|
|
158
|
-
|
|
164
|
+
if Client.__authentication_obj is not None:
|
|
165
|
+
Client.__access_token = Client.__authentication_obj.get_token()
|
|
159
166
|
|
|
160
167
|
payload = {
|
|
161
168
|
'dataspace': space,
|
|
@@ -164,7 +171,7 @@ class Client():
|
|
|
164
171
|
|
|
165
172
|
headers = {
|
|
166
173
|
'accept': 'application/json',
|
|
167
|
-
'authorization': "Bearer "+
|
|
174
|
+
'authorization': "Bearer "+Client.__access_token
|
|
168
175
|
}
|
|
169
176
|
|
|
170
177
|
if use_filepath:
|
|
@@ -183,7 +190,7 @@ class Client():
|
|
|
183
190
|
#
|
|
184
191
|
response = requests.post(transfer_url, verify=True, headers=headers, files=files)
|
|
185
192
|
except Exception as err:
|
|
186
|
-
returned_result =
|
|
193
|
+
returned_result = Client.__ERROR_OCCURRED + str(err) + os.linesep
|
|
187
194
|
|
|
188
195
|
# Write the result to the log
|
|
189
196
|
for line in returned_result.split(os.linesep):
|
|
@@ -204,7 +211,7 @@ class Client():
|
|
|
204
211
|
returned_result = result + os.linesep
|
|
205
212
|
|
|
206
213
|
# Check the request status
|
|
207
|
-
if (result != "" and result.find(
|
|
214
|
+
if (result != "" and result.find(Client.__ERROR_OCCURRED ) == -1):
|
|
208
215
|
# Extract the request ID the returned message
|
|
209
216
|
start = 'with ID'
|
|
210
217
|
end = 'was successfully'
|
|
@@ -225,8 +232,8 @@ class Client():
|
|
|
225
232
|
sleep(3)
|
|
226
233
|
|
|
227
234
|
previous_result = result
|
|
228
|
-
while (result in [
|
|
229
|
-
or
|
|
235
|
+
while (result in [Client.__EXECUTION_IN_PROGRESS, Client.__EXECUTION_IN_QUEUED]
|
|
236
|
+
or Client.__CONNECTION_ABORTED in result):
|
|
230
237
|
result = self.__check_request_status(transfer_url, requestId, space)
|
|
231
238
|
|
|
232
239
|
# Prevent loging again the same information such as "Queued" or "InProgress"
|
|
@@ -235,14 +242,14 @@ class Client():
|
|
|
235
242
|
|
|
236
243
|
# Write the result to the log
|
|
237
244
|
for line in previous_result.split(os.linesep):
|
|
238
|
-
if (len(line) > 0 and line not in [
|
|
239
|
-
and
|
|
245
|
+
if (len(line) > 0 and line not in [Client.__EXECUTION_IN_PROGRESS, Client.__EXECUTION_IN_QUEUED]
|
|
246
|
+
and Client.__CONNECTION_ABORTED not in line):
|
|
240
247
|
self.__log.info(' ' + line)
|
|
241
248
|
sleep(3)
|
|
242
249
|
|
|
243
250
|
returned_result = returned_result + result + os.linesep
|
|
244
251
|
else:
|
|
245
|
-
returned_result =
|
|
252
|
+
returned_result = Client.__ERROR_OCCURRED
|
|
246
253
|
if len(str(response.status_code)) > 0:
|
|
247
254
|
returned_result += 'Error code: ' + str(response.status_code) + os.linesep
|
|
248
255
|
if len(str(response.reason)) > 0:
|
|
@@ -256,7 +263,7 @@ class Client():
|
|
|
256
263
|
if len(line) > 0:
|
|
257
264
|
self.__log.info(' ' + line)
|
|
258
265
|
except ValueError as err:
|
|
259
|
-
returned_result =
|
|
266
|
+
returned_result = Client.__ERROR_OCCURRED
|
|
260
267
|
if len(str(response.status_code)) > 0:
|
|
261
268
|
returned_result += 'Error code: ' + str(response.status_code) + os.linesep
|
|
262
269
|
if len(str(response.reason)) > 0:
|
|
@@ -282,8 +289,8 @@ class Client():
|
|
|
282
289
|
returned_result = ""
|
|
283
290
|
|
|
284
291
|
#
|
|
285
|
-
if
|
|
286
|
-
|
|
292
|
+
if Client.__authentication_obj is not None:
|
|
293
|
+
Client.__access_token = Client.__authentication_obj.get_token()
|
|
287
294
|
|
|
288
295
|
payload = {
|
|
289
296
|
'dataspace': space,
|
|
@@ -292,7 +299,7 @@ class Client():
|
|
|
292
299
|
|
|
293
300
|
headers = {
|
|
294
301
|
'accept': 'application/json',
|
|
295
|
-
'authorization': "Bearer "+
|
|
302
|
+
'authorization': "Bearer "+Client.__access_token
|
|
296
303
|
}
|
|
297
304
|
|
|
298
305
|
excel_file = open(os.path.realpath(excelfile_path), 'rb')
|
|
@@ -307,7 +314,7 @@ class Client():
|
|
|
307
314
|
#
|
|
308
315
|
response = requests.post(transfer_url, verify=True, headers=headers, files=files)
|
|
309
316
|
except Exception as err:
|
|
310
|
-
returned_result =
|
|
317
|
+
returned_result = Client.__ERROR_OCCURRED + str(err) + os.linesep
|
|
311
318
|
|
|
312
319
|
# Write the result to the log
|
|
313
320
|
for line in returned_result.split(os.linesep):
|
|
@@ -328,7 +335,7 @@ class Client():
|
|
|
328
335
|
returned_result = result + os.linesep
|
|
329
336
|
|
|
330
337
|
# Check the request status
|
|
331
|
-
if (result != "" and result.find(
|
|
338
|
+
if (result != "" and result.find(Client.__ERROR_OCCURRED ) == -1):
|
|
332
339
|
# Extract the request ID the returned message
|
|
333
340
|
start = 'with ID'
|
|
334
341
|
end = 'was successfully'
|
|
@@ -349,8 +356,8 @@ class Client():
|
|
|
349
356
|
sleep(3)
|
|
350
357
|
|
|
351
358
|
previous_result = result
|
|
352
|
-
while (result in [
|
|
353
|
-
or
|
|
359
|
+
while (result in [Client.__EXECUTION_IN_PROGRESS, Client.__EXECUTION_IN_QUEUED]
|
|
360
|
+
or Client.__CONNECTION_ABORTED in result):
|
|
354
361
|
result = self.__check_request_status(transfer_url, requestId, space)
|
|
355
362
|
|
|
356
363
|
# Prevent loging again the same information such as "Queued" or "InProgress"
|
|
@@ -359,14 +366,14 @@ class Client():
|
|
|
359
366
|
|
|
360
367
|
# Write the result to the log
|
|
361
368
|
for line in previous_result.split(os.linesep):
|
|
362
|
-
if (len(line) > 0 and line not in [
|
|
363
|
-
and
|
|
369
|
+
if (len(line) > 0 and line not in [Client.__EXECUTION_IN_PROGRESS, Client.__EXECUTION_IN_QUEUED]
|
|
370
|
+
and Client.__CONNECTION_ABORTED not in line):
|
|
364
371
|
self.__log.info(' ' + line)
|
|
365
372
|
sleep(3)
|
|
366
373
|
|
|
367
374
|
returned_result = returned_result + result + os.linesep
|
|
368
375
|
else:
|
|
369
|
-
returned_result =
|
|
376
|
+
returned_result = Client.__ERROR_OCCURRED
|
|
370
377
|
if len(str(response.status_code)) > 0:
|
|
371
378
|
returned_result += 'Error code: ' + str(response.status_code) + os.linesep
|
|
372
379
|
if len(str(response.reason)) > 0:
|
|
@@ -380,7 +387,7 @@ class Client():
|
|
|
380
387
|
if len(line) > 0:
|
|
381
388
|
self.__log.info(' ' + line)
|
|
382
389
|
except ValueError as err:
|
|
383
|
-
returned_result =
|
|
390
|
+
returned_result = Client.__ERROR_OCCURRED
|
|
384
391
|
if len(str(response.status_code)) > 0:
|
|
385
392
|
returned_result += 'Error code: ' + str(response.status_code) + os.linesep
|
|
386
393
|
if len(str(response.reason)) > 0:
|
|
@@ -401,8 +408,8 @@ class Client():
|
|
|
401
408
|
returned_result = ""
|
|
402
409
|
|
|
403
410
|
#
|
|
404
|
-
if
|
|
405
|
-
|
|
411
|
+
if Client.__authentication_obj is not None:
|
|
412
|
+
Client.__access_token = Client.__authentication_obj.get_token()
|
|
406
413
|
|
|
407
414
|
# Detect the encoding used in file
|
|
408
415
|
detected_encoding = self.__detect_encode(file_path)
|
|
@@ -417,13 +424,13 @@ class Client():
|
|
|
417
424
|
|
|
418
425
|
headers = {
|
|
419
426
|
'Content-Type': 'application/xml',
|
|
420
|
-
'authorization': "Bearer "+
|
|
427
|
+
'authorization': "Bearer "+Client.__access_token
|
|
421
428
|
}
|
|
422
429
|
|
|
423
430
|
#
|
|
424
431
|
response = requests.post(transfer_url, verify=True, headers=headers, data=xml_data)
|
|
425
432
|
except Exception as err:
|
|
426
|
-
returned_result =
|
|
433
|
+
returned_result = Client.__ERROR_OCCURRED + str(err) + os.linesep
|
|
427
434
|
|
|
428
435
|
# Write the result to the log
|
|
429
436
|
for line in returned_result.split(os.linesep):
|
|
@@ -433,7 +440,7 @@ class Client():
|
|
|
433
440
|
try:
|
|
434
441
|
response.raise_for_status()
|
|
435
442
|
except requests.exceptions.HTTPError as e:
|
|
436
|
-
returned_result = f'{
|
|
443
|
+
returned_result = f'{Client.__UPLOAD_FAILED}{response.status_code}: {e}'
|
|
437
444
|
|
|
438
445
|
# Write the result to the log
|
|
439
446
|
for line in returned_result.split(os.linesep):
|
|
@@ -441,11 +448,11 @@ class Client():
|
|
|
441
448
|
self.__log.info(' ' + line)
|
|
442
449
|
else:
|
|
443
450
|
response_tree = ET.XML(response.content)
|
|
444
|
-
for
|
|
445
|
-
text_element =
|
|
451
|
+
for element in response_tree.findall("./{0}ErrorMessage".format(Client.__NAMESPACE_MESSAGE)):
|
|
452
|
+
text_element = element.find("./{0}Text".format(Client.__NAMESPACE_COMMON))
|
|
446
453
|
if (text_element is not None):
|
|
447
454
|
if returned_result == "":
|
|
448
|
-
returned_result = f'{
|
|
455
|
+
returned_result = f'{Client.__UPLOAD_SUCCESS}with status code: {response.status_code}' + os.linesep
|
|
449
456
|
returned_result = returned_result + text_element.text + os.linesep
|
|
450
457
|
|
|
451
458
|
# Write the result to the log
|
|
@@ -479,12 +486,12 @@ class Client():
|
|
|
479
486
|
returned_result = ""
|
|
480
487
|
|
|
481
488
|
#
|
|
482
|
-
if
|
|
483
|
-
|
|
489
|
+
if Client.__authentication_obj is not None:
|
|
490
|
+
Client.__access_token = Client.__authentication_obj.get_token()
|
|
484
491
|
|
|
485
492
|
headers = {
|
|
486
493
|
'accept': 'application/json',
|
|
487
|
-
'authorization': "Bearer "+
|
|
494
|
+
'authorization': "Bearer "+Client.__access_token
|
|
488
495
|
}
|
|
489
496
|
|
|
490
497
|
payload = {
|
|
@@ -501,7 +508,7 @@ class Client():
|
|
|
501
508
|
#
|
|
502
509
|
response = requests.post(transfer_url, verify=True, headers=headers, data=payload)
|
|
503
510
|
except Exception as err:
|
|
504
|
-
returned_result =
|
|
511
|
+
returned_result = Client.__ERROR_OCCURRED + str(err)
|
|
505
512
|
else:
|
|
506
513
|
# If the response object cannot be converted to json, return an error
|
|
507
514
|
results_json = None
|
|
@@ -509,8 +516,8 @@ class Client():
|
|
|
509
516
|
results_json = json.loads(response.text)
|
|
510
517
|
if response.status_code == 200:
|
|
511
518
|
executionStatus = 'Execution status: ' + results_json['executionStatus']
|
|
512
|
-
if (results_json['executionStatus'] in [
|
|
513
|
-
or
|
|
519
|
+
if (results_json['executionStatus'] in [Client.__EXECUTION_IN_PROGRESS, Client.__EXECUTION_IN_QUEUED]
|
|
520
|
+
or Client.__CONNECTION_ABORTED in results_json['executionStatus']):
|
|
514
521
|
returned_result = results_json['executionStatus']
|
|
515
522
|
else:
|
|
516
523
|
returned_result = executionStatus + os.linesep + 'Outcome: ' + results_json['outcome'] + os.linesep
|
|
@@ -519,7 +526,7 @@ class Client():
|
|
|
519
526
|
returned_result = returned_result + 'Log' + str(index) + ': ' + results_json['logs'][index]['message'] + os.linesep
|
|
520
527
|
index += 1
|
|
521
528
|
else:
|
|
522
|
-
returned_result =
|
|
529
|
+
returned_result = Client.__ERROR_OCCURRED
|
|
523
530
|
if len(str(response.status_code)) > 0:
|
|
524
531
|
returned_result += 'Error code: ' + str(response.status_code) + os.linesep
|
|
525
532
|
if len(str(response.reason)) > 0:
|
|
@@ -529,7 +536,7 @@ class Client():
|
|
|
529
536
|
|
|
530
537
|
returned_result += os.linesep
|
|
531
538
|
except ValueError as err:
|
|
532
|
-
returned_result =
|
|
539
|
+
returned_result = Client.__ERROR_OCCURRED
|
|
533
540
|
if len(str(response.status_code)) > 0:
|
|
534
541
|
returned_result += 'Error code: ' + str(response.status_code) + os.linesep
|
|
535
542
|
if len(str(response.reason)) > 0:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "dotstat_io"
|
|
3
|
-
version = "1.0.
|
|
3
|
+
version = "1.0.4"
|
|
4
4
|
description = "Utility to download or upload data from/to .Stat Suite using ADFS authentication to connect to it"
|
|
5
5
|
license = "MIT"
|
|
6
6
|
authors = ["Gyorgy Gyomai <gyorgy.gyomai@oecd.org>", "Abdel Aliaoui <abdel.aliaoui@oecd.org>"]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|