logos-sdk 0.0.25.dev11__tar.gz → 0.0.25.dev13__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.
Files changed (26) hide show
  1. {logos_sdk-0.0.25.dev11 → logos_sdk-0.0.25.dev13}/PKG-INFO +1 -1
  2. {logos_sdk-0.0.25.dev11 → logos_sdk-0.0.25.dev13}/logos_sdk/services/CampaignManager.py +13 -13
  3. {logos_sdk-0.0.25.dev11 → logos_sdk-0.0.25.dev13}/logos_sdk/services/DV360.py +17 -17
  4. {logos_sdk-0.0.25.dev11 → logos_sdk-0.0.25.dev13}/logos_sdk/services/Facebook.py +14 -14
  5. {logos_sdk-0.0.25.dev11 → logos_sdk-0.0.25.dev13}/logos_sdk/services/GoogleAds.py +9 -10
  6. {logos_sdk-0.0.25.dev11 → logos_sdk-0.0.25.dev13}/logos_sdk/services/MerchantCenter.py +13 -13
  7. {logos_sdk-0.0.25.dev11 → logos_sdk-0.0.25.dev13}/logos_sdk/services/MicrosoftAdvertising.py +87 -22
  8. {logos_sdk-0.0.25.dev11 → logos_sdk-0.0.25.dev13}/logos_sdk/services/Sklik.py +135 -68
  9. {logos_sdk-0.0.25.dev11 → logos_sdk-0.0.25.dev13}/logos_sdk/services/__init__.py +10 -12
  10. {logos_sdk-0.0.25.dev11 → logos_sdk-0.0.25.dev13}/logos_sdk.egg-info/PKG-INFO +1 -1
  11. {logos_sdk-0.0.25.dev11 → logos_sdk-0.0.25.dev13}/LICENSE +0 -0
  12. {logos_sdk-0.0.25.dev11 → logos_sdk-0.0.25.dev13}/README.md +0 -0
  13. {logos_sdk-0.0.25.dev11 → logos_sdk-0.0.25.dev13}/logos_sdk/__init__.py +0 -0
  14. {logos_sdk-0.0.25.dev11 → logos_sdk-0.0.25.dev13}/logos_sdk/big_query/BigQuery.py +0 -0
  15. {logos_sdk-0.0.25.dev11 → logos_sdk-0.0.25.dev13}/logos_sdk/big_query/__init__.py +0 -0
  16. {logos_sdk-0.0.25.dev11 → logos_sdk-0.0.25.dev13}/logos_sdk/logging/LogosLogger.py +0 -0
  17. {logos_sdk-0.0.25.dev11 → logos_sdk-0.0.25.dev13}/logos_sdk/logging/__init__.py +0 -0
  18. {logos_sdk-0.0.25.dev11 → logos_sdk-0.0.25.dev13}/logos_sdk/services/Collabim.py +0 -0
  19. {logos_sdk-0.0.25.dev11 → logos_sdk-0.0.25.dev13}/logos_sdk/services/GoogleSheets.py +0 -0
  20. {logos_sdk-0.0.25.dev11 → logos_sdk-0.0.25.dev13}/logos_sdk/services/MarketMiner.py +0 -0
  21. {logos_sdk-0.0.25.dev11 → logos_sdk-0.0.25.dev13}/logos_sdk.egg-info/SOURCES.txt +0 -0
  22. {logos_sdk-0.0.25.dev11 → logos_sdk-0.0.25.dev13}/logos_sdk.egg-info/dependency_links.txt +0 -0
  23. {logos_sdk-0.0.25.dev11 → logos_sdk-0.0.25.dev13}/logos_sdk.egg-info/requires.txt +0 -0
  24. {logos_sdk-0.0.25.dev11 → logos_sdk-0.0.25.dev13}/logos_sdk.egg-info/top_level.txt +0 -0
  25. {logos_sdk-0.0.25.dev11 → logos_sdk-0.0.25.dev13}/setup.cfg +0 -0
  26. {logos_sdk-0.0.25.dev11 → logos_sdk-0.0.25.dev13}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: logos-sdk
3
- Version: 0.0.25.dev11
3
+ Version: 0.0.25.dev13
4
4
  Summary: SDK for Logos platform
5
5
  Home-page: https://bitbucket.org/databy/logos-sdk-pip/src/master/
6
6
  Author: Databy.io
@@ -5,8 +5,7 @@ import os
5
5
  import time
6
6
 
7
7
  from random import randint
8
- from logos_sdk.services import get_headers
9
- from requests import request
8
+ from logos_sdk.services import get_headers, get_retry_session
10
9
  from typing import Dict, List
11
10
  from http import HTTPStatus
12
11
  from googleapiclient.http import MediaIoBaseDownload, HttpRequest
@@ -21,6 +20,7 @@ class CampaignManagerServiceException(Exception):
21
20
  class CampaignManagerService:
22
21
  def __init__(self, url: str = None):
23
22
  load_dotenv()
23
+ self.session = get_retry_session()
24
24
  self._URL = url or os.environ.get("CM360_SERVICE_PATH")
25
25
  self._CREATE_REPORT = self._URL + "/create-report"
26
26
  self._GET_REPORT = self._URL + "/get-report"
@@ -67,7 +67,7 @@ class CampaignManagerService:
67
67
  "secret_id": secret_id,
68
68
  }
69
69
  header = get_headers(self._CREATE_REPORT)
70
- response = request(
70
+ response = self.session.request(
71
71
  method="post", url=self._CREATE_REPORT, json=body, headers=header
72
72
  )
73
73
 
@@ -92,7 +92,7 @@ class CampaignManagerService:
92
92
  }
93
93
 
94
94
  header = get_headers(self._GET_REPORT)
95
- response = request("post", url=self._GET_REPORT, json=body, headers=header)
95
+ response = self.session.request("post", url=self._GET_REPORT, json=body, headers=header)
96
96
 
97
97
  if response.status_code == HTTPStatus.OK:
98
98
  service_response = response.json()
@@ -114,7 +114,7 @@ class CampaignManagerService:
114
114
  "secret_id": secret_id,
115
115
  }
116
116
  header = get_headers(self._RUN_REPORT)
117
- response = request("post", url=self._RUN_REPORT, json=body, headers=header)
117
+ response = self.session.request("post", url=self._RUN_REPORT, json=body, headers=header)
118
118
  service_response = response.json()
119
119
 
120
120
  if response.status_code == HTTPStatus.OK:
@@ -173,7 +173,7 @@ class CampaignManagerService:
173
173
  """
174
174
  body = {"report_id": report_id, "file_id": file_id, "secret_id": secret_id}
175
175
  header = get_headers(self._GET_FILE)
176
- response = request("post", url=self._GET_FILE, json=body, headers=header)
176
+ response = self.session.request("post", url=self._GET_FILE, json=body, headers=header)
177
177
 
178
178
  if response.status_code == HTTPStatus.OK:
179
179
  service_response = response.json()
@@ -215,7 +215,7 @@ class CampaignManagerService:
215
215
  header = get_headers(self._GET_FILE_MEDIA_REQUEST)
216
216
 
217
217
  # fetch the authorized request from our service for downloading the report from API
218
- response = request(
218
+ response = self.session.request(
219
219
  "post", url=self._GET_FILE_MEDIA_REQUEST, json=body, headers=header
220
220
  )
221
221
 
@@ -283,7 +283,7 @@ class CampaignManagerService:
283
283
  "secret_id": secret_id,
284
284
  }
285
285
  header = get_headers(self._DELETE_REPORT)
286
- response = request("post", url=self._DELETE_REPORT, json=body, headers=header)
286
+ response = self.session.request("post", url=self._DELETE_REPORT, json=body, headers=header)
287
287
 
288
288
  if response.status_code == HTTPStatus.OK:
289
289
  return True
@@ -325,7 +325,7 @@ class CampaignManagerService:
325
325
  }
326
326
 
327
327
  header = get_headers(self._QUERY_DIMENSION_VALUES)
328
- response = request(
328
+ response = self.session.request(
329
329
  "post", url=self._QUERY_DIMENSION_VALUES, json=body, headers=header
330
330
  )
331
331
 
@@ -338,7 +338,7 @@ class CampaignManagerService:
338
338
  # if there was a last page response is empty string
339
339
  while service_response["data"]["nextPageToken"]:
340
340
  body["page_token"] = service_response["data"]["nextPageToken"]
341
- response = request(
341
+ response = self.session.request(
342
342
  "post", url=self._QUERY_DIMENSION_VALUES, json=body, headers=header
343
343
  )
344
344
 
@@ -411,7 +411,7 @@ class CampaignManagerService:
411
411
  header = get_headers(self._GET_ACCESSIBLE_PARENT_ACCOUNTS)
412
412
  body = {"secret_id": secret_id}
413
413
 
414
- response = request(
414
+ response = self.session.request(
415
415
  "post", url=self._GET_ACCESSIBLE_PARENT_ACCOUNTS, json=body, headers=header
416
416
  )
417
417
 
@@ -436,7 +436,7 @@ class CampaignManagerService:
436
436
  },
437
437
  }
438
438
 
439
- response = request(
439
+ response = self.session.request(
440
440
  "post", url=self._GET_ACCESSIBLE_ADVERTISERS, json=body, headers=header
441
441
  )
442
442
 
@@ -460,7 +460,7 @@ class CampaignManagerService:
460
460
  "advertiser_id": advertiser_id
461
461
  }
462
462
  header = get_headers(self._GET_ACCOUNT_ACCESSIBILITY)
463
- response = request(
463
+ response = self.session.request(
464
464
  "post", url=self._GET_ACCOUNT_ACCESSIBILITY, json=body, headers=header
465
465
  )
466
466
 
@@ -1,5 +1,4 @@
1
- from logos_sdk.services import get_headers
2
- from requests import request
1
+ from logos_sdk.services import get_headers, get_retry_session
3
2
  from http import HTTPStatus
4
3
  from time import sleep
5
4
  from random import randint
@@ -17,6 +16,7 @@ class DV360ServiceException(Exception):
17
16
  class DV360Service:
18
17
  def __init__(self, url=None):
19
18
  load_dotenv()
19
+ self.session = get_retry_session()
20
20
  self._URL = url or os.environ.get("DV360_SERVICE_PATH")
21
21
  self._LIST_LINE_ITEMS = self._URL + "/line-items"
22
22
  self._BULK_LIST_LINE_ITEM_ASSIGNED_TARGETING_OPTIONS = (
@@ -52,7 +52,7 @@ class DV360Service:
52
52
  if filter_string is not None:
53
53
  body["filter"] = filter_string
54
54
 
55
- response = request("post", url=self._LIST_LINE_ITEMS, json=body, headers=header)
55
+ response = self.session.request("post", url=self._LIST_LINE_ITEMS, json=body, headers=header)
56
56
 
57
57
  if response.status_code == HTTPStatus.OK:
58
58
  service_response = response.json()
@@ -75,7 +75,7 @@ class DV360Service:
75
75
  :param filter_string: Allows filtering by line item fields
76
76
  :return List of AssignedTargetingOption objects
77
77
  """
78
- header = get_headers(self._BULK_EDIT_LINE_ITEM_ASSIGNED_TARGETING_OPTIONS)
78
+ header = get_headers(self._BULK_LIST_LINE_ITEM_ASSIGNED_TARGETING_OPTIONS)
79
79
  body = {
80
80
  "advertiser_id": advertiser_id,
81
81
  "secret_id": secret_id,
@@ -83,7 +83,7 @@ class DV360Service:
83
83
  "filter": filter_string,
84
84
  }
85
85
 
86
- response = request(
86
+ response = self.session.request(
87
87
  "post",
88
88
  url=self._BULK_LIST_LINE_ITEM_ASSIGNED_TARGETING_OPTIONS,
89
89
  json=body,
@@ -128,7 +128,7 @@ class DV360Service:
128
128
  if create_requests is not None:
129
129
  body["create_requests"] = create_requests
130
130
 
131
- response = request(
131
+ response = self.session.request(
132
132
  "post",
133
133
  url=self._BULK_EDIT_LINE_ITEM_ASSIGNED_TARGETING_OPTIONS,
134
134
  json=body,
@@ -152,7 +152,7 @@ class DV360Service:
152
152
  header = get_headers(self._CREATE_CHANNEL)
153
153
  body = {"advertiser_id": advertiser_id, "secret_id": secret_id, "name": name}
154
154
 
155
- response = request("post", url=self._CREATE_CHANNEL, json=body, headers=header)
155
+ response = self.session.request("post", url=self._CREATE_CHANNEL, json=body, headers=header)
156
156
 
157
157
  if response.status_code == HTTPStatus.OK:
158
158
  service_response = response.json()
@@ -174,7 +174,7 @@ class DV360Service:
174
174
  if filter_string is not None:
175
175
  body["filter"] = filter_string
176
176
 
177
- response = request("post", url=self._LIST_CHANNELS, json=body, headers=header)
177
+ response = self.session.request("post", url=self._LIST_CHANNELS, json=body, headers=header)
178
178
 
179
179
  if response.status_code == HTTPStatus.OK:
180
180
  service_response = response.json()
@@ -203,7 +203,7 @@ class DV360Service:
203
203
  if filter_string is not None:
204
204
  body["filter"] = filter_string
205
205
 
206
- response = request(
206
+ response = self.session.request(
207
207
  "post", url=self._LIST_CHANNEL_SITES, json=body, headers=header
208
208
  )
209
209
 
@@ -243,7 +243,7 @@ class DV360Service:
243
243
  if created_sites is not None:
244
244
  body["created_sites"] = created_sites
245
245
 
246
- response = request(
246
+ response = self.session.request(
247
247
  "post",
248
248
  url=self._BULK_EDIT_CHANNEL_SITES,
249
249
  json=body,
@@ -277,7 +277,7 @@ class DV360Service:
277
277
  "metrics_names": metrics_names,
278
278
  }
279
279
 
280
- response = request("post", url=self._CREATE_QUERY, json=body, headers=header)
280
+ response = self.session.request("post", url=self._CREATE_QUERY, json=body, headers=header)
281
281
 
282
282
  if response.status_code == HTTPStatus.OK:
283
283
  service_response = response.json()
@@ -296,7 +296,7 @@ class DV360Service:
296
296
  header = get_headers(self._RUN_QUERY)
297
297
  body = {"secret_id": secret_id, "query_id": query_id}
298
298
 
299
- response = request("post", url=self._RUN_QUERY, json=body, headers=header)
299
+ response = self.session.request("post", url=self._RUN_QUERY, json=body, headers=header)
300
300
 
301
301
  if response.status_code == HTTPStatus.OK:
302
302
  service_response = response.json()
@@ -319,7 +319,7 @@ class DV360Service:
319
319
  },
320
320
  }
321
321
 
322
- response = request(
322
+ response = self.session.request(
323
323
  "post", url=self._GET_ACCESSIBLE_PARTNERS, json=body, headers=header
324
324
  )
325
325
 
@@ -344,7 +344,7 @@ class DV360Service:
344
344
  },
345
345
  }
346
346
 
347
- response = request(
347
+ response = self.session.request(
348
348
  "post", url=self._GET_ACCESSIBLE_ADVERTISERS, json=body, headers=header
349
349
  )
350
350
 
@@ -366,7 +366,7 @@ class DV360Service:
366
366
  "advertiser_id": advertiser_id
367
367
  }
368
368
  header = get_headers(self._GET_ACCOUNT_ACCESSIBILITY)
369
- response = request(
369
+ response = self.session.request(
370
370
  "post", url=self._GET_ACCOUNT_ACCESSIBILITY, json=body, headers=header
371
371
  )
372
372
 
@@ -408,7 +408,7 @@ class DV360Service:
408
408
  header = get_headers(self._GET_QUERY_METADATA)
409
409
  body = {"secret_id": secret_id, "query_id": query_id, "report_id": report_id}
410
410
 
411
- response = request(
411
+ response = self.session.request(
412
412
  "post", url=self._GET_QUERY_METADATA, json=body, headers=header
413
413
  )
414
414
 
@@ -464,7 +464,7 @@ class DV360Service:
464
464
  header = get_headers(self._DELETE_QUERY)
465
465
  body = {"secret_id": secret_id, "query_id": query_id}
466
466
 
467
- response = request("post", url=self._DELETE_QUERY, json=body, headers=header)
467
+ response = self.session.request("post", url=self._DELETE_QUERY, json=body, headers=header)
468
468
 
469
469
  if response.status_code == HTTPStatus.OK:
470
470
  return True
@@ -1,6 +1,5 @@
1
- from requests import request
2
1
  from typing import List, Dict, Optional
3
- from logos_sdk.services import get_headers
2
+ from logos_sdk.services import get_headers, get_retry_session
4
3
  from http import HTTPStatus
5
4
  from random import randint
6
5
  from dotenv import load_dotenv
@@ -15,6 +14,7 @@ class FacebookServiceException(Exception):
15
14
  class FacebookService:
16
15
  def __init__(self, url=None):
17
16
  load_dotenv()
17
+ self.session = get_retry_session()
18
18
  self._URL = url or os.environ.get("FACEBOOK_SERVICE_PATH")
19
19
  self._ACCESSIBLE_ACCOUNTS = self._URL + "/accessible-accounts"
20
20
  self._INSIGHTS = self._URL + "/insights"
@@ -48,7 +48,7 @@ class FacebookService:
48
48
 
49
49
  header = get_headers(self._ACCESSIBLE_ACCOUNTS)
50
50
 
51
- response = request(
51
+ response = self.session.request(
52
52
  "post",
53
53
  url=self._ACCESSIBLE_ACCOUNTS,
54
54
  json=body,
@@ -74,7 +74,7 @@ class FacebookService:
74
74
  "account_id": account_id
75
75
  }
76
76
  header = get_headers(self._GET_ACCOUNT_ACCESSIBILITY)
77
- response = request(
77
+ response = self.session.request(
78
78
  "post", url=self._GET_ACCOUNT_ACCESSIBILITY, json=body, headers=header
79
79
  )
80
80
 
@@ -121,7 +121,7 @@ class FacebookService:
121
121
  body["level"] = level
122
122
  header = get_headers(self._INSIGHTS)
123
123
 
124
- response = request(
124
+ response = self.session.request(
125
125
  "post", url=self._INSIGHTS, json=body, headers=header, timeout=timeout
126
126
  )
127
127
  if response.status_code == HTTPStatus.OK:
@@ -162,7 +162,7 @@ class FacebookService:
162
162
 
163
163
  header = get_headers(self._LINK_URLS)
164
164
 
165
- response = request(
165
+ response = self.session.request(
166
166
  "post", url=self._LINK_URLS, json=body, headers=header, timeout=timeout
167
167
  )
168
168
 
@@ -187,7 +187,7 @@ class FacebookService:
187
187
 
188
188
  header = get_headers(self._ACCESSIBLE_BUSINESSES)
189
189
 
190
- response = request(
190
+ response = self.session.request(
191
191
  "post",
192
192
  url=self._ACCESSIBLE_BUSINESSES,
193
193
  json=body,
@@ -226,7 +226,7 @@ class FacebookService:
226
226
 
227
227
  header = get_headers(self._PRODUCT_CATALOGS)
228
228
 
229
- response = request(
229
+ response = self.session.request(
230
230
  "post",
231
231
  url=self._PRODUCT_CATALOGS,
232
232
  json=body,
@@ -262,7 +262,7 @@ class FacebookService:
262
262
 
263
263
  header = get_headers(self._PRODUCT_CATALOG)
264
264
 
265
- response = request(
265
+ response = self.session.request(
266
266
  "post",
267
267
  url=self._PRODUCT_CATALOG,
268
268
  json=body,
@@ -304,7 +304,7 @@ class FacebookService:
304
304
 
305
305
  header = get_headers(self._PRODUCTS)
306
306
 
307
- response = request(
307
+ response = self.session.request(
308
308
  "post", url=self._PRODUCTS, json=body, headers=header, timeout=timeout
309
309
  )
310
310
  if response.status_code == HTTPStatus.OK:
@@ -325,7 +325,7 @@ class FacebookService:
325
325
  body = {"secret_id": secret_id, "catalog_id": catalog_id}
326
326
 
327
327
  header = get_headers(self._FEEDS)
328
- response = request(
328
+ response = self.session.request(
329
329
  "post", url=self._FEEDS, json=body, headers=header, timeout=timeout
330
330
  )
331
331
 
@@ -348,7 +348,7 @@ class FacebookService:
348
348
  body = {"secret_id": secret_id, "feed_id": feed_id}
349
349
 
350
350
  header = get_headers(self._FEED_ERRORS)
351
- response = request(
351
+ response = self.session.request(
352
352
  "post", url=self._FEED_ERRORS, json=body, headers=header, timeout=timeout
353
353
  )
354
354
 
@@ -370,7 +370,7 @@ class FacebookService:
370
370
  body = {"secret_id": secret_id, "feed_id": feed_id}
371
371
 
372
372
  header = get_headers(self._FEED_ERRORS_REPORT_STATUS)
373
- response = request(
373
+ response = self.session.request(
374
374
  "post",
375
375
  url=self._FEED_ERRORS_REPORT_STATUS,
376
376
  json=body,
@@ -398,7 +398,7 @@ class FacebookService:
398
398
  body = {"secret_id": secret_id, "feed_id": feed_id}
399
399
 
400
400
  header = get_headers(self._FEED_ERRORS_REPORT)
401
- response = request(
401
+ response = self.session.request(
402
402
  "post",
403
403
  url=self._FEED_ERRORS_REPORT,
404
404
  json=body,
@@ -1,7 +1,6 @@
1
- from requests import request
2
1
  from requests.exceptions import Timeout
3
2
  from typing import List, Union, Dict
4
- from logos_sdk.services import get_headers
3
+ from logos_sdk.services import get_headers, get_retry_session
5
4
  from http import HTTPStatus
6
5
  from dotenv import load_dotenv
7
6
  import os
@@ -16,6 +15,7 @@ class GoogleAdsServiceException(Exception):
16
15
  class GoogleAdsService:
17
16
  def __init__(self, url=None):
18
17
  load_dotenv()
18
+ self.session = get_retry_session()
19
19
  self._URL = url or os.environ.get("GOOGLE_ADS_SERVICE_PATH")
20
20
  self._SEARCH_STREAM = self._URL + "/search-stream"
21
21
  self._SEARCH = self._URL + "/search"
@@ -24,11 +24,10 @@ class GoogleAdsService:
24
24
  self._GET_ACCESSIBLE_ACCOUNTS = self._URL + "/list-accessible-accounts"
25
25
  self._GET_ACCOUNT_ACCESSIBILITY = self._URL + "/get-account-accessibility"
26
26
 
27
- @staticmethod
28
- def fetch_with_retry_on_timeout(url, json, headers):
27
+ def fetch_with_retry_on_timeout(self,url, json, headers):
29
28
  for attempt in range(5):
30
29
  try:
31
- return request("post", url, json=json, headers=headers, timeout=25)
30
+ return self.session.request("post", url, json=json, headers=headers, timeout=25)
32
31
  except Timeout:
33
32
  delay = 2 * (2 ** attempt) + random.randint(0, 9)
34
33
  print(
@@ -103,7 +102,7 @@ class GoogleAdsService:
103
102
  # if there was a last page response is empty string
104
103
  while service_response["data"]["next_page_token"]:
105
104
  body["page_token"] = service_response["data"]["next_page_token"]
106
- response = request("post", url=self._SEARCH, json=body, headers=header)
105
+ response = self.session.request("post", url=self._SEARCH, json=body, headers=header)
107
106
 
108
107
  if response.status_code != HTTPStatus.OK:
109
108
  raise GoogleAdsServiceException(response.content)
@@ -130,7 +129,7 @@ class GoogleAdsService:
130
129
  }
131
130
 
132
131
  header = get_headers(self._EXCLUDE_FOR_ACCOUNT)
133
- response = request(
132
+ response = self.session.request(
134
133
  "post", url=self._EXCLUDE_FOR_ACCOUNT, json=body, headers=header
135
134
  )
136
135
 
@@ -163,7 +162,7 @@ class GoogleAdsService:
163
162
  }
164
163
 
165
164
  header = get_headers(self._EXCLUDE_FOR_AD_GROUP)
166
- response = request(
165
+ response = self.session.request(
167
166
  "post", url=self._EXCLUDE_FOR_AD_GROUP, json=body, headers=header
168
167
  )
169
168
 
@@ -199,7 +198,7 @@ class GoogleAdsService:
199
198
 
200
199
  while service_response["data"]["next_page_token"]:
201
200
  body["page_token"] = service_response["data"]["next_page_token"]
202
- response = request(
201
+ response = self.session.request(
203
202
  "post", url=self._GET_ACCESSIBLE_ACCOUNTS, json=body, headers=header
204
203
  )
205
204
 
@@ -223,7 +222,7 @@ class GoogleAdsService:
223
222
  "account_id": account_id
224
223
  }
225
224
  header = get_headers(self._GET_ACCOUNT_ACCESSIBILITY)
226
- response = request(
225
+ response = self.session.request(
227
226
  "post", url=self._GET_ACCOUNT_ACCESSIBILITY, json=body, headers=header
228
227
  )
229
228
 
@@ -1,6 +1,5 @@
1
1
  from http import HTTPStatus
2
- from requests import request
3
- from logos_sdk.services import get_headers
2
+ from logos_sdk.services import get_headers, get_retry_session
4
3
  from dotenv import load_dotenv
5
4
  import os
6
5
 
@@ -12,6 +11,7 @@ class MerchantServiceException(Exception):
12
11
  class MerchantCenterService:
13
12
  def __init__(self, url=None):
14
13
  load_dotenv()
14
+ self.session = get_retry_session()
15
15
  self._URL = url or os.environ.get("MERCHANT_CENTER_SERVICE_PATH")
16
16
  self._LIST_ACCOUNTS = self._URL + "/account-service/accounts"
17
17
  self._LIST_ACCESSIBLE_ACCOUNTS = self._URL + "/account-service/list-accessible-accounts"
@@ -30,7 +30,7 @@ class MerchantCenterService:
30
30
  """
31
31
  body = {"merchant_account_id": merchant_account_id, "secret_id": secret_id}
32
32
  header = get_headers(self._LIST_ACCOUNTS)
33
- response = request("post", url=self._LIST_ACCOUNTS, json=body, headers=header)
33
+ response = self.session.request("post", url=self._LIST_ACCOUNTS, json=body, headers=header)
34
34
 
35
35
  if response.status_code == HTTPStatus.OK:
36
36
  service_response = response.json()
@@ -46,7 +46,7 @@ class MerchantCenterService:
46
46
  """
47
47
  body = {"secret_id": secret_id}
48
48
  header = get_headers(self._LIST_ACCESSIBLE_ACCOUNTS)
49
- response = request("post", url=self._LIST_ACCESSIBLE_ACCOUNTS, json=body, headers=header)
49
+ response = self.session.request("post", url=self._LIST_ACCESSIBLE_ACCOUNTS, json=body, headers=header)
50
50
 
51
51
  if response.status_code == HTTPStatus.OK:
52
52
  service_response = response.json()
@@ -70,7 +70,7 @@ class MerchantCenterService:
70
70
  "secret_id": secret_id,
71
71
  }
72
72
  header = get_headers(self._LIST_ACCOUNT_STATUSES)
73
- response = request(
73
+ response = self.session.request(
74
74
  "post", url=self._LIST_ACCOUNT_STATUSES, json=body, headers=header
75
75
  )
76
76
 
@@ -90,7 +90,7 @@ class MerchantCenterService:
90
90
  """
91
91
  body = {"merchant_account_id": merchant_account_id, "secret_id": secret_id, "page_size": page_size}
92
92
  header = get_headers(self._LIST_PRODUCTS)
93
- response = request("post", url=self._LIST_PRODUCTS, json=body, headers=header)
93
+ response = self.session.request("post", url=self._LIST_PRODUCTS, json=body, headers=header)
94
94
 
95
95
  if response.status_code != HTTPStatus.OK:
96
96
  raise MerchantServiceException(response.content)
@@ -100,7 +100,7 @@ class MerchantCenterService:
100
100
 
101
101
  while service_response["data"]["nextPageToken"] is not None:
102
102
  body["page_token"] = service_response["data"]["nextPageToken"]
103
- response = request(
103
+ response = self.session.request(
104
104
  "post", url=self._LIST_PRODUCTS, json=body, headers=header
105
105
  )
106
106
 
@@ -121,7 +121,7 @@ class MerchantCenterService:
121
121
  """
122
122
  body = {"merchant_account_id": merchant_account_id, "secret_id": secret_id, "page_size": page_size}
123
123
  header = get_headers(self._LIST_PRODUCT_STATUSES)
124
- response = request(
124
+ response = self.session.request(
125
125
  "post", url=self._LIST_PRODUCT_STATUSES, json=body, headers=header
126
126
  )
127
127
 
@@ -133,7 +133,7 @@ class MerchantCenterService:
133
133
 
134
134
  while service_response["data"]["nextPageToken"] is not None:
135
135
  body["page_token"] = service_response["data"]["nextPageToken"]
136
- response = request(
136
+ response = self.session.request(
137
137
  "post", url=self._LIST_PRODUCT_STATUSES, json=body, headers=header
138
138
  )
139
139
 
@@ -159,7 +159,7 @@ class MerchantCenterService:
159
159
  "page_size": page_size,
160
160
  }
161
161
  header = get_headers(self._REPORTS_SEARCH)
162
- response = request("post", url=self._REPORTS_SEARCH, json=body, headers=header)
162
+ response = self.session.request("post", url=self._REPORTS_SEARCH, json=body, headers=header)
163
163
 
164
164
  if response.status_code == HTTPStatus.OK:
165
165
  service_response = response.json()
@@ -181,7 +181,7 @@ class MerchantCenterService:
181
181
  "page_size": page_size,
182
182
  }
183
183
  header = get_headers(self._REPORTS_SEARCH)
184
- response = request("post", url=self._REPORTS_SEARCH, json=body, headers=header)
184
+ response = self.session.request("post", url=self._REPORTS_SEARCH, json=body, headers=header)
185
185
 
186
186
  if response.status_code != HTTPStatus.OK:
187
187
  raise MerchantServiceException(response.content)
@@ -191,7 +191,7 @@ class MerchantCenterService:
191
191
 
192
192
  while service_response["data"]["nextPageToken"] is not None:
193
193
  body["page_token"] = service_response["data"]["nextPageToken"]
194
- response = request(
194
+ response = self.session.request(
195
195
  "post", url=self._REPORTS_SEARCH, json=body, headers=header
196
196
  )
197
197
 
@@ -215,7 +215,7 @@ class MerchantCenterService:
215
215
  "account_id": account_id
216
216
  }
217
217
  header = get_headers(self._GET_ACCOUNT_ACCESSIBILITY)
218
- response = request(
218
+ response = self.session.request(
219
219
  "post", url=self._GET_ACCOUNT_ACCESSIBILITY, json=body, headers=header
220
220
  )
221
221
 
@@ -1,6 +1,5 @@
1
1
  from http import HTTPStatus
2
- from requests import request
3
- from logos_sdk.services import get_headers
2
+ from logos_sdk.services import get_headers, get_retry_session
4
3
  from typing import List
5
4
  from dotenv import load_dotenv
6
5
  import os
@@ -18,16 +17,28 @@ class EntityStatus:
18
17
  PAUSED = "Paused"
19
18
 
20
19
 
20
+ class BidMatchType:
21
+ EXACT = "Exact"
22
+ PHRASE = "Phrase"
23
+ BROAD = "Broad"
24
+
25
+
21
26
  class MicrosoftAdvertising:
22
27
  def __init__(self, url=None):
23
28
  load_dotenv()
29
+ self.session = get_retry_session()
24
30
  self._URL = url or os.environ.get("MICROSOFT_ADVERTISING_PATH")
25
31
  self._GET_ACCESSIBLE_ACCOUNTS = self._URL + "/accessible-accounts"
26
32
  self._GET_ACCOUNT_ACCESSIBILITY = self._URL + "/get-account-accessibility"
27
33
  self._GET_DESTINATION_URL_REPORT = self._URL + "/destination-url-report"
28
- self._GET_CAMPAIGN_PERFORMANCE_REPORT = self._URL + "/campaign-performance-report"
29
- self._GET_GEOGRAPHIC_PERFORMANCE_REPORT = self._URL + "/geographic-performance-report"
34
+ self._GET_CAMPAIGN_PERFORMANCE_REPORT = (
35
+ self._URL + "/campaign-performance-report"
36
+ )
37
+ self._GET_GEOGRAPHIC_PERFORMANCE_REPORT = (
38
+ self._URL + "/geographic-performance-report"
39
+ )
30
40
  self._GET_BUDGET_SUMMARY_REPORT = self._URL + "/budget-summary-report"
41
+ self._GET_SHARE_OF_VOICE_REPORT = self._URL + "/share-of-voice-report"
31
42
 
32
43
  def get_destination_url_report(
33
44
  self,
@@ -66,7 +77,7 @@ class MicrosoftAdvertising:
66
77
  } | entity_statuses
67
78
 
68
79
  header = get_headers(self._GET_DESTINATION_URL_REPORT)
69
- response = request(
80
+ response = self.session.request(
70
81
  "post", url=self._GET_DESTINATION_URL_REPORT, json=body, headers=header
71
82
  )
72
83
 
@@ -112,8 +123,70 @@ class MicrosoftAdvertising:
112
123
  } | entity_statuses
113
124
 
114
125
  header = get_headers(self._GET_GEOGRAPHIC_PERFORMANCE_REPORT)
115
- response = request(
116
- "post", url=self._GET_GEOGRAPHIC_PERFORMANCE_REPORT, json=body, headers=header
126
+ response = self.session.request(
127
+ "post",
128
+ url=self._GET_GEOGRAPHIC_PERFORMANCE_REPORT,
129
+ json=body,
130
+ headers=header,
131
+ )
132
+
133
+ if response.status_code == HTTPStatus.OK:
134
+ service_response = response.json()
135
+ return service_response["data"]
136
+ else:
137
+ raise MicrosoftAdvertisingException(response.content)
138
+
139
+ def get_share_of_voice_report(
140
+ self,
141
+ account_id: str,
142
+ secret_id: str,
143
+ date_from: str,
144
+ date_to: str,
145
+ report_columns: List[str],
146
+ bid_match_type: str = None,
147
+ filter_keywords: List[str] = None,
148
+ entity_statuses: dict = None,
149
+ ) -> List:
150
+ """
151
+ Calls endpoint for getting share of voice stats
152
+ https://learn.microsoft.com/en-us/advertising/reporting-service/geographicperformancereportrequest?view=bingads-13&tabs=xml
153
+ :param account_id: The ID of the account in Microsoft Advertising
154
+ :param secret_id: The ID of the secret in secret manager
155
+ :param date_from: The date we want the report to start from. Must be before date to
156
+ :param date_to: The date we want the report to end at
157
+ :param report_columns: stats we want included in the report
158
+ :param bid_match_type: keywords with this bid match type will be returned
159
+ :param filter_keywords: just keywords from this list will be returned
160
+ :param entity_statuses: dict containing status ad_group_status, campaign_status, keyword_status and account_status
161
+ :return: List of share of voice stats
162
+ """
163
+ if entity_statuses is None:
164
+ entity_statuses = {
165
+ "ad_group_status": EntityStatus.ACTIVE,
166
+ "campaign_status": EntityStatus.ACTIVE,
167
+ "account_status": EntityStatus.ACTIVE,
168
+ "keyword_status": EntityStatus.ACTIVE,
169
+ }
170
+
171
+ body = {
172
+ "account_id": account_id,
173
+ "secret_id": secret_id,
174
+ "date_from": date_from,
175
+ "date_to": date_to,
176
+ "report_columns": report_columns,
177
+ } | entity_statuses
178
+
179
+ if bid_match_type:
180
+ body["bid_match_type"] = bid_match_type
181
+ if filter_keywords:
182
+ body["filter_keywords"] = filter_keywords
183
+
184
+ header = get_headers(self._GET_SHARE_OF_VOICE_REPORT)
185
+ response = self.session.request(
186
+ "post",
187
+ url=self._GET_SHARE_OF_VOICE_REPORT,
188
+ json=body,
189
+ headers=header,
117
190
  )
118
191
 
119
192
  if response.status_code == HTTPStatus.OK:
@@ -157,7 +230,7 @@ class MicrosoftAdvertising:
157
230
  } | entity_statuses
158
231
 
159
232
  header = get_headers(self._GET_CAMPAIGN_PERFORMANCE_REPORT)
160
- response = request(
233
+ response = self.session.request(
161
234
  "post", url=self._GET_CAMPAIGN_PERFORMANCE_REPORT, json=body, headers=header
162
235
  )
163
236
 
@@ -173,7 +246,7 @@ class MicrosoftAdvertising:
173
246
  secret_id: str,
174
247
  date_from: str,
175
248
  date_to: str,
176
- report_columns: List[str]
249
+ report_columns: List[str],
177
250
  ):
178
251
  """
179
252
  Calls endpoint for getting budget summary
@@ -195,7 +268,7 @@ class MicrosoftAdvertising:
195
268
  }
196
269
 
197
270
  header = get_headers(self._GET_BUDGET_SUMMARY_REPORT)
198
- response = request(
271
+ response = self.session.request(
199
272
  "post", url=self._GET_BUDGET_SUMMARY_REPORT, json=body, headers=header
200
273
  )
201
274
 
@@ -211,14 +284,9 @@ class MicrosoftAdvertising:
211
284
  :param secret_id: The ID of the secret in secret manager
212
285
  :return: List of dicts with account_id and name keys
213
286
  """
214
- body = {
215
- "secret_id": secret_id,
216
- "filters": {
217
- "hide_inactive": True
218
- }
219
- }
287
+ body = {"secret_id": secret_id, "filters": {"hide_inactive": True}}
220
288
  header = get_headers(self._GET_ACCESSIBLE_ACCOUNTS)
221
- response = request(
289
+ response = self.session.request(
222
290
  "post", url=self._GET_ACCESSIBLE_ACCOUNTS, json=body, headers=header
223
291
  )
224
292
 
@@ -235,12 +303,9 @@ class MicrosoftAdvertising:
235
303
  :param account_id: The ID of the account in Microsoft Advertising
236
304
  :return: True if account has access
237
305
  """
238
- body = {
239
- "secret_id": secret_id,
240
- "account_id": account_id
241
- }
306
+ body = {"secret_id": secret_id, "account_id": account_id}
242
307
  header = get_headers(self._GET_ACCOUNT_ACCESSIBILITY)
243
- response = request(
308
+ response = self.session.request(
244
309
  "post", url=self._GET_ACCOUNT_ACCESSIBILITY, json=body, headers=header
245
310
  )
246
311
 
@@ -1,5 +1,5 @@
1
1
  from typing import List, Dict, Union
2
- from logos_sdk.services import execute_request
2
+ from logos_sdk.services import get_retry_session, get_headers
3
3
  from http import HTTPStatus
4
4
 
5
5
  import logging
@@ -38,7 +38,10 @@ def get_session_if_malformed(wrapped_function):
38
38
  try:
39
39
  return wrapped_function(*args, **kwargs)
40
40
  except SklikServiceException as err:
41
- if json.loads(err.args[0].decode("utf8")).get("detail") == "Session has expired or is malformed.":
41
+ if (
42
+ json.loads(err.args[0].decode("utf8")).get("detail")
43
+ == "Session has expired or is malformed."
44
+ ):
42
45
  args[0].get_session(args[0]._secret_id, args[0]._account_email)
43
46
  return wrapped_function(*args, **kwargs)
44
47
  else:
@@ -53,8 +56,10 @@ def get_report_results_if_expired(wrapped_function):
53
56
  try:
54
57
  return wrapped_function(*args, **kwargs)
55
58
  except SklikServiceException as err:
56
- if json.loads(err.args[0].decode("utf8")).get(
57
- "detail") == "Requested report has expired. Please create a new report by calling createReport endpoint.":
59
+ if (
60
+ json.loads(err.args[0].decode("utf8")).get("detail")
61
+ == "Requested report has expired. Please create a new report by calling createReport endpoint."
62
+ ):
58
63
  print("Report expired, creating new report")
59
64
  args[0].get_session(args[0]._secret_id, args[0]._account_email)
60
65
  return wrapped_function(*args, **kwargs)
@@ -67,6 +72,7 @@ def get_report_results_if_expired(wrapped_function):
67
72
  class SklikService:
68
73
  def __init__(self, url=None):
69
74
  load_dotenv()
75
+ self.request_session = get_retry_session()
70
76
  self._URL = url or os.environ.get("SKLIK_SERVICE_PATH")
71
77
  self._CREATE_REPORT = self._URL + "/create-report"
72
78
  self._READ_REPORT = self._URL + "/read-report"
@@ -89,7 +95,10 @@ class SklikService:
89
95
  :return: Dict
90
96
  """
91
97
  body = {"account_email": account_email, "secret_id": secret_id}
92
- response = execute_request("post", url=self._GET_SESSION, json=body)
98
+ header = get_headers(self._GET_SESSION)
99
+ response = self.request_session.request(
100
+ "post", url=self._GET_SESSION, json=body, timeout=70, headers=header
101
+ )
93
102
 
94
103
  if response.status_code == HTTPStatus.OK:
95
104
  service_response = response.json()
@@ -109,7 +118,14 @@ class SklikService:
109
118
  :return: Dict
110
119
  """
111
120
  body = {"secret_id": secret_id}
112
- response = execute_request("post", url=self._GET_SESSION_WITHOUT_ACCOUNT, json=body)
121
+ header = get_headers(self._GET_SESSION_WITHOUT_ACCOUNT)
122
+ response = self.request_session.request(
123
+ "post",
124
+ url=self._GET_SESSION_WITHOUT_ACCOUNT,
125
+ json=body,
126
+ timeout=70,
127
+ headers=header,
128
+ )
113
129
 
114
130
  if response.status_code == HTTPStatus.OK:
115
131
  service_response = response.json()
@@ -128,22 +144,30 @@ class SklikService:
128
144
  """
129
145
  try:
130
146
  if self.session is not None:
131
- execute_request("post", url=self._LOGOUT, json=self.session)
147
+ header = get_headers(self._LOGOUT)
148
+ self.request_session.request(
149
+ "post",
150
+ url=self._LOGOUT,
151
+ json=self.session,
152
+ timeout=70,
153
+ headers=header,
154
+ )
155
+
132
156
  except:
133
157
  pass
134
158
 
135
159
  @get_session_if_malformed
136
160
  @get_report_results_if_expired
137
161
  def get_report_results(
138
- self,
139
- secret_id: str,
140
- account_email: str,
141
- report_type: str,
142
- date_from: str,
143
- date_to: str,
144
- columns: List[str],
145
- create_params: Dict[str, Union[int, str]] = None,
146
- read_params: Dict[str, Union[int, str]] = None,
162
+ self,
163
+ secret_id: str,
164
+ account_email: str,
165
+ report_type: str,
166
+ date_from: str,
167
+ date_to: str,
168
+ columns: List[str],
169
+ create_params: Dict[str, Union[int, str]] = None,
170
+ read_params: Dict[str, Union[int, str]] = None,
147
171
  ) -> List[Dict]:
148
172
  """
149
173
  It creates sklik report with /create-report call in sklik service and reads sklik report with pagination
@@ -174,10 +198,14 @@ class SklikService:
174
198
  if read_params:
175
199
  body.update({"params": read_params})
176
200
 
177
- response = execute_request(
178
- "post", url=self._READ_REPORT, json=body | self.session
201
+ header = get_headers(self._READ_REPORT)
202
+ response = self.request_session.request(
203
+ "post", url=self._READ_REPORT, json=body | self.session,
204
+ timeout=70,
205
+ headers=header,
179
206
  )
180
207
 
208
+
181
209
  if response.status_code == HTTPStatus.OK:
182
210
  service_response = response.json()
183
211
  result.extend(service_response["data"])
@@ -188,14 +216,14 @@ class SklikService:
188
216
 
189
217
  @get_session_if_malformed
190
218
  def get_streamed_report_results(
191
- self,
192
- secret_id: str,
193
- account_email: str,
194
- report_type: str,
195
- date_from: str,
196
- date_to: str,
197
- columns: List[str],
198
- create_params: Dict[str, Union[int, str]] = None,
219
+ self,
220
+ secret_id: str,
221
+ account_email: str,
222
+ report_type: str,
223
+ date_from: str,
224
+ date_to: str,
225
+ columns: List[str],
226
+ create_params: Dict[str, Union[int, str]] = None,
199
227
  ) -> List[Dict]:
200
228
  """
201
229
  It creates sklik report with /create-report call in sklik service and reads sklik report with pagination
@@ -224,8 +252,11 @@ class SklikService:
224
252
  "columns": columns,
225
253
  }
226
254
 
227
- response = execute_request(
228
- "post", url=self._READ_REPORT, json=body | self.session
255
+ header = get_headers(self._READ_REPORT)
256
+ response = self.request_session.request(
257
+ "post", url=self._READ_REPORT, json=body | self.session,
258
+ timeout=70,
259
+ headers=header,
229
260
  )
230
261
 
231
262
  if response.status_code == HTTPStatus.OK:
@@ -235,13 +266,13 @@ class SklikService:
235
266
  raise SklikServiceException(response.content)
236
267
 
237
268
  def _create_report(
238
- self,
239
- secret_id: str,
240
- account_email: str,
241
- report_type: str,
242
- date_from: str,
243
- date_to: str,
244
- params: Dict[str, Union[int, str]] = None,
269
+ self,
270
+ secret_id: str,
271
+ account_email: str,
272
+ report_type: str,
273
+ date_from: str,
274
+ date_to: str,
275
+ params: Dict[str, Union[int, str]] = None,
245
276
  ) -> Dict:
246
277
  """
247
278
  Function creates sklik report with /create-report call
@@ -266,8 +297,11 @@ class SklikService:
266
297
  }
267
298
  body = self.params_
268
299
 
269
- response = execute_request(
270
- "post", url=self._CREATE_REPORT, json=body | self.session
300
+ header = get_headers(self._CREATE_REPORT)
301
+ response = self.request_session.request(
302
+ "post", url=self._CREATE_REPORT, json=body | self.session,
303
+ timeout=70,
304
+ headers=header,
271
305
  )
272
306
 
273
307
  if response.status_code == HTTPStatus.OK:
@@ -278,7 +312,7 @@ class SklikService:
278
312
 
279
313
  @get_session_if_malformed
280
314
  def call_api(
281
- self, secret_id: str, account_email: str, method: str, params: List[Dict]
315
+ self, secret_id: str, account_email: str, method: str, params: List[Dict]
282
316
  ) -> Union[List, Dict]:
283
317
  """
284
318
  Function to call SklikService get-api route
@@ -297,7 +331,13 @@ class SklikService:
297
331
  "params": params,
298
332
  }
299
333
 
300
- response = execute_request("post", url=self._API, json=body | self.session)
334
+ header = get_headers(self._API)
335
+ response = self.request_session.request(
336
+ "post", url=self._API, json=body | self.session,
337
+ timeout=70,
338
+ headers=header,
339
+ )
340
+
301
341
 
302
342
  if response.status_code == HTTPStatus.OK:
303
343
  service_response = response.json()
@@ -307,9 +347,9 @@ class SklikService:
307
347
 
308
348
  @get_session_if_malformed
309
349
  def get_client(
310
- self,
311
- secret_id: str,
312
- account_email: str,
350
+ self,
351
+ secret_id: str,
352
+ account_email: str,
313
353
  ) -> Union[List, Dict]:
314
354
  """
315
355
  Function to call SklikService get-client route
@@ -321,12 +361,16 @@ class SklikService:
321
361
  if self.session is None:
322
362
  self.get_session(secret_id, account_email)
323
363
 
324
- response = execute_request(
364
+ header = get_headers(self._GET_CLIENT)
365
+ response = self.request_session.request(
325
366
  "post",
326
367
  url=self._GET_CLIENT,
327
368
  json={"sklik_session": self.session["sklik_session"]},
369
+ timeout=70,
370
+ headers=header,
328
371
  )
329
372
 
373
+
330
374
  if response.status_code == HTTPStatus.OK:
331
375
  service_response = response.json()
332
376
  return service_response["data"]
@@ -335,8 +379,8 @@ class SklikService:
335
379
 
336
380
  @get_session_if_malformed
337
381
  def get_accessible_accounts(
338
- self,
339
- secret_id: str,
382
+ self,
383
+ secret_id: str,
340
384
  ) -> Union[List, Dict]:
341
385
  """
342
386
  Function to retrieve accessible accounts
@@ -347,37 +391,41 @@ class SklikService:
347
391
  if self.session is None:
348
392
  self.get_session_without_account(secret_id)
349
393
 
350
- response = execute_request(
394
+ header = get_headers(self._GET_CLIENT)
395
+ response = self.request_session.request(
351
396
  "post",
352
397
  url=self._GET_CLIENT,
353
398
  json={
354
399
  "sklik_session": self.session["sklik_session"],
355
- "filters": {
356
- "hide_inactive": True
357
- }
400
+ "filters": {"hide_inactive": True},
358
401
  },
402
+ timeout=70,
403
+ headers=header,
359
404
  )
360
405
 
406
+
361
407
  if response.status_code == HTTPStatus.OK:
362
408
  accounts = []
363
409
  service_response = response.json()
364
410
  data = service_response["data"]
365
411
  for account in data["foreignAccounts"]:
366
- accounts.append({
367
- "id": account['userId'],
368
- "name": account['username'],
369
- "active": account["relationStatus"] == "live"
370
- })
412
+ accounts.append(
413
+ {
414
+ "id": account["userId"],
415
+ "name": account["username"],
416
+ "active": account["relationStatus"] == "live",
417
+ }
418
+ )
371
419
  return accounts
372
420
  else:
373
421
  raise SklikServiceException(response.content)
374
422
 
375
423
  @get_session_if_malformed
376
424
  def check_data_ready(
377
- self,
378
- secret_id: str,
379
- account_email: str,
380
- date: str = None,
425
+ self,
426
+ secret_id: str,
427
+ account_email: str,
428
+ date: str = None,
381
429
  ) -> int:
382
430
  """
383
431
  Checks if data on server are ready
@@ -391,15 +439,19 @@ class SklikService:
391
439
  self.get_session(secret_id, account_email)
392
440
 
393
441
  date = date or (
394
- datetime.now(timezone("UTC")).astimezone(timezone("Europe/Prague"))
395
- - timedelta(days=1)
442
+ datetime.now(timezone("UTC")).astimezone(timezone("Europe/Prague"))
443
+ - timedelta(days=1)
396
444
  ).strftime("%Y-%m-%d")
397
445
 
398
446
  body = {"date": date}
399
447
 
400
- response = execute_request(
401
- "post", url=self._CHECK_DATA_READY, json=body | self.session
448
+ header = get_headers(self._CHECK_DATA_READY)
449
+ response = self.request_session.request(
450
+ "post", url=self._CHECK_DATA_READY, json=body | self.session,
451
+ timeout=70,
452
+ headers=header,
402
453
  )
454
+
403
455
  if response.status_code == HTTPStatus.OK:
404
456
  service_response = response.json()
405
457
  if service_response["data"] == DataStatus.PENDING:
@@ -413,9 +465,9 @@ class SklikService:
413
465
 
414
466
  @get_session_if_malformed
415
467
  def fetch_api_limits(
416
- self,
417
- secret_id: str,
418
- account_email: str,
468
+ self,
469
+ secret_id: str,
470
+ account_email: str,
419
471
  ) -> Union[List, Dict]:
420
472
  """
421
473
  Function to call SklikService api/limits route
@@ -427,7 +479,12 @@ class SklikService:
427
479
  if self.session is None:
428
480
  self.get_session(secret_id, account_email)
429
481
 
430
- response = execute_request("post", url=self._API_LIMITS, json=self.session)
482
+ header = get_headers(self._API_LIMITS)
483
+ response = self.request_session.request(
484
+ "post", url=self._API_LIMITS, json=self.session,
485
+ timeout=70,
486
+ headers=header,
487
+ )
431
488
 
432
489
  if response.status_code == HTTPStatus.OK:
433
490
  service_response = response.json()
@@ -443,9 +500,19 @@ class SklikService:
443
500
  :return: True if account has access
444
501
  """
445
502
  body = {"account_email": account_email, "secret_id": secret_id}
446
- response = execute_request("post", url=self._GET_SESSION, json=body)
503
+ header = get_headers(self._GET_SESSION)
504
+ response = self.request_session.request(
505
+ "post", url=self._GET_SESSION, json=body,
506
+ timeout=70,
507
+ headers=header,
508
+ )
509
+
447
510
  if response.status_code == 200:
448
511
  return True
449
- if response.status_code == 401 or response.status_code == 403 or response.status_code == 404:
512
+ if (
513
+ response.status_code == 401
514
+ or response.status_code == 403
515
+ or response.status_code == 404
516
+ ):
450
517
  return False
451
518
  raise SklikServiceException(response.content)
@@ -15,21 +15,19 @@ def get_headers(route):
15
15
  }
16
16
 
17
17
 
18
- def execute_request(method, url, json):
18
+ def get_retry_session():
19
+ session = requests.Session()
20
+
19
21
  retry_strategy = Retry(
20
22
  total=3,
21
23
  raise_on_status=False,
22
- status_forcelist=[429, 500, 502, 503, 504],
23
- backoff_factor=1,
24
- allowed_methods=None
24
+ status_forcelist=[104,400,429, 500, 502, 503, 504],
25
+ allowed_methods=None,
26
+ backoff_factor=1
25
27
  )
28
+
26
29
  adapter = HTTPAdapter(max_retries=retry_strategy)
27
- http = requests.Session()
28
- http.mount("https://", adapter)
29
- http.mount("http://", adapter)
30
- header = get_headers(url)
31
- # 70 is magic number, we tolerate the API to tell us to wait 60 seconds max,
32
- # otherwise we kill it
33
- response = http.request(method, url=url, json=json, timeout=70, headers=header)
30
+ session.mount("http://", adapter)
31
+ session.mount("https://", adapter)
34
32
 
35
- return response
33
+ return session
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: logos-sdk
3
- Version: 0.0.25.dev11
3
+ Version: 0.0.25.dev13
4
4
  Summary: SDK for Logos platform
5
5
  Home-page: https://bitbucket.org/databy/logos-sdk-pip/src/master/
6
6
  Author: Databy.io