logos-sdk 0.0.25.dev7__tar.gz → 0.0.25.dev9__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.
- {logos_sdk-0.0.25.dev7 → logos_sdk-0.0.25.dev9}/PKG-INFO +1 -1
- {logos_sdk-0.0.25.dev7 → logos_sdk-0.0.25.dev9}/logos_sdk/big_query/BigQuery.py +28 -10
- {logos_sdk-0.0.25.dev7 → logos_sdk-0.0.25.dev9}/logos_sdk/services/Collabim.py +2 -1
- {logos_sdk-0.0.25.dev7 → logos_sdk-0.0.25.dev9}/logos_sdk/services/MarketMiner.py +4 -2
- {logos_sdk-0.0.25.dev7 → logos_sdk-0.0.25.dev9}/logos_sdk/services/MerchantCenter.py +19 -6
- {logos_sdk-0.0.25.dev7 → logos_sdk-0.0.25.dev9}/logos_sdk/services/Sklik.py +45 -1
- {logos_sdk-0.0.25.dev7 → logos_sdk-0.0.25.dev9}/logos_sdk.egg-info/PKG-INFO +1 -1
- {logos_sdk-0.0.25.dev7 → logos_sdk-0.0.25.dev9}/LICENSE +0 -0
- {logos_sdk-0.0.25.dev7 → logos_sdk-0.0.25.dev9}/README.md +0 -0
- {logos_sdk-0.0.25.dev7 → logos_sdk-0.0.25.dev9}/logos_sdk/__init__.py +0 -0
- {logos_sdk-0.0.25.dev7 → logos_sdk-0.0.25.dev9}/logos_sdk/big_query/__init__.py +0 -0
- {logos_sdk-0.0.25.dev7 → logos_sdk-0.0.25.dev9}/logos_sdk/logging/LogosLogger.py +0 -0
- {logos_sdk-0.0.25.dev7 → logos_sdk-0.0.25.dev9}/logos_sdk/logging/__init__.py +0 -0
- {logos_sdk-0.0.25.dev7 → logos_sdk-0.0.25.dev9}/logos_sdk/services/CampaignManager.py +0 -0
- {logos_sdk-0.0.25.dev7 → logos_sdk-0.0.25.dev9}/logos_sdk/services/DV360.py +0 -0
- {logos_sdk-0.0.25.dev7 → logos_sdk-0.0.25.dev9}/logos_sdk/services/Facebook.py +0 -0
- {logos_sdk-0.0.25.dev7 → logos_sdk-0.0.25.dev9}/logos_sdk/services/GoogleAds.py +0 -0
- {logos_sdk-0.0.25.dev7 → logos_sdk-0.0.25.dev9}/logos_sdk/services/GoogleSheets.py +0 -0
- {logos_sdk-0.0.25.dev7 → logos_sdk-0.0.25.dev9}/logos_sdk/services/MicrosoftAdvertising.py +0 -0
- {logos_sdk-0.0.25.dev7 → logos_sdk-0.0.25.dev9}/logos_sdk/services/__init__.py +0 -0
- {logos_sdk-0.0.25.dev7 → logos_sdk-0.0.25.dev9}/logos_sdk.egg-info/SOURCES.txt +0 -0
- {logos_sdk-0.0.25.dev7 → logos_sdk-0.0.25.dev9}/logos_sdk.egg-info/dependency_links.txt +0 -0
- {logos_sdk-0.0.25.dev7 → logos_sdk-0.0.25.dev9}/logos_sdk.egg-info/requires.txt +0 -0
- {logos_sdk-0.0.25.dev7 → logos_sdk-0.0.25.dev9}/logos_sdk.egg-info/top_level.txt +0 -0
- {logos_sdk-0.0.25.dev7 → logos_sdk-0.0.25.dev9}/setup.cfg +0 -0
- {logos_sdk-0.0.25.dev7 → logos_sdk-0.0.25.dev9}/setup.py +0 -0
|
@@ -36,6 +36,19 @@ class BigQuery:
|
|
|
36
36
|
except DefaultCredentialsError:
|
|
37
37
|
self.logger = None
|
|
38
38
|
|
|
39
|
+
def parse_fields(self, fields):
|
|
40
|
+
result = []
|
|
41
|
+
for row in fields:
|
|
42
|
+
result.append(
|
|
43
|
+
bigquery.schema.SchemaField(
|
|
44
|
+
row["name"],
|
|
45
|
+
row["col_type"],
|
|
46
|
+
mode=row["mode"],
|
|
47
|
+
fields=self.parse_fields(row["fields"]) if "fields" in row else [],
|
|
48
|
+
)
|
|
49
|
+
)
|
|
50
|
+
return result
|
|
51
|
+
|
|
39
52
|
def get_dataset(self, dataset_id: str):
|
|
40
53
|
return self._service.get_dataset(dataset_id)
|
|
41
54
|
|
|
@@ -57,17 +70,17 @@ class BigQuery:
|
|
|
57
70
|
return self._service.get_table(sql_format)
|
|
58
71
|
|
|
59
72
|
def insert_into_table(
|
|
60
|
-
|
|
73
|
+
self, dataset_id: str, table_id: str, records: List[Dict]
|
|
61
74
|
) -> None:
|
|
62
75
|
bq_table = self.get_table(dataset_id, table_id)
|
|
63
76
|
self._insert_into_table(bq_table, records)
|
|
64
77
|
|
|
65
78
|
def insert_create_table(
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
79
|
+
self,
|
|
80
|
+
dataset_id: str,
|
|
81
|
+
table_id: str,
|
|
82
|
+
records: List[Dict],
|
|
83
|
+
schema_columns: List[Dict],
|
|
71
84
|
) -> None:
|
|
72
85
|
bq_table = self.check_table_exists(dataset_id, table_id)
|
|
73
86
|
if bq_table is None:
|
|
@@ -87,10 +100,15 @@ class BigQuery:
|
|
|
87
100
|
return None
|
|
88
101
|
|
|
89
102
|
def create_table(
|
|
90
|
-
|
|
103
|
+
self, dataset_id: str, table_id: str, schema_columns: List[Dict]
|
|
91
104
|
) -> Union[bool, Table]:
|
|
92
105
|
table_schema = [
|
|
93
|
-
bigquery.schema.SchemaField(
|
|
106
|
+
bigquery.schema.SchemaField(
|
|
107
|
+
row["name"],
|
|
108
|
+
row["col_type"],
|
|
109
|
+
mode=row["mode"],
|
|
110
|
+
fields=self.parse_fields(row["fields"]) if "fields" in row else [],
|
|
111
|
+
)
|
|
94
112
|
for row in schema_columns
|
|
95
113
|
]
|
|
96
114
|
try:
|
|
@@ -132,13 +150,13 @@ class BigQuery:
|
|
|
132
150
|
|
|
133
151
|
@retry_on_not_found
|
|
134
152
|
def _insert_into_table(
|
|
135
|
-
|
|
153
|
+
self, bq_table: Table, records: List[Dict], attempts: int
|
|
136
154
|
) -> None:
|
|
137
155
|
if len(records) > self.BQ_ROWS_LIMIT:
|
|
138
156
|
for index in range(0, len(records), self.BQ_ROWS_LIMIT):
|
|
139
157
|
errors = self._service.insert_rows(
|
|
140
158
|
bq_table,
|
|
141
|
-
records[index: (index + self.BQ_ROWS_LIMIT)],
|
|
159
|
+
records[index : (index + self.BQ_ROWS_LIMIT)],
|
|
142
160
|
retry=Retry(
|
|
143
161
|
total=2, connect=4, backoff_factor=2, allowed_methods=None
|
|
144
162
|
),
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from requests import request
|
|
1
|
+
"""from requests import request
|
|
2
2
|
from typing import List, Dict
|
|
3
3
|
from logos_sdk.services import get_headers
|
|
4
4
|
from http import HTTPStatus
|
|
@@ -208,3 +208,4 @@ class CollabimService:
|
|
|
208
208
|
return service_response["data"]
|
|
209
209
|
|
|
210
210
|
raise CollabimServiceException(service_response)
|
|
211
|
+
"""
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
"""
|
|
1
2
|
from requests import request
|
|
2
3
|
from typing import List
|
|
3
4
|
from logos_sdk.services import get_headers
|
|
@@ -18,12 +19,12 @@ class MarketMiner:
|
|
|
18
19
|
self._SEARCH_VOLUME = self._URL + "/search-volume-data"
|
|
19
20
|
|
|
20
21
|
def search_volume_data(self, lang: str, keywords: List[str]) -> List:
|
|
21
|
-
|
|
22
|
+
|
|
22
23
|
Function to call mm api point
|
|
23
24
|
:param lang: Language can be "cs", "sk", "us", "pl", "gb"
|
|
24
25
|
:param keywords: List of keywords you want search volume
|
|
25
26
|
:return:
|
|
26
|
-
|
|
27
|
+
|
|
27
28
|
body = {
|
|
28
29
|
"lang": lang,
|
|
29
30
|
"keywords": keywords
|
|
@@ -37,3 +38,4 @@ class MarketMiner:
|
|
|
37
38
|
return service_response["data"]
|
|
38
39
|
|
|
39
40
|
raise MarketMinerServiceException(service_response)
|
|
41
|
+
"""
|
|
@@ -92,26 +92,39 @@ class MerchantCenterService:
|
|
|
92
92
|
service_response = response.json()
|
|
93
93
|
yield service_response["data"]["results"]
|
|
94
94
|
|
|
95
|
-
def list_products_statuses(self, merchant_account_id: str, secret_id: str):
|
|
95
|
+
def list_products_statuses(self, merchant_account_id: str, secret_id: str, page_size: int = 250):
|
|
96
96
|
"""
|
|
97
97
|
Lists the statuses of the products in your Merchant Center account
|
|
98
98
|
:param merchant_account_id: The ID of the
|
|
99
99
|
account that contains the products. This account cannot be a multi-client account
|
|
100
100
|
:param secret_id: The ID of the secret in secret manager
|
|
101
|
+
:param page_size: size of the page
|
|
101
102
|
:return: List[Dict]
|
|
102
103
|
"""
|
|
103
|
-
body = {"merchant_account_id": merchant_account_id, "secret_id": secret_id}
|
|
104
|
+
body = {"merchant_account_id": merchant_account_id, "secret_id": secret_id, "page_size": page_size}
|
|
104
105
|
header = get_headers(self._LIST_PRODUCT_STATUSES)
|
|
105
106
|
response = request(
|
|
106
107
|
"post", url=self._LIST_PRODUCT_STATUSES, json=body, headers=header
|
|
107
108
|
)
|
|
108
109
|
|
|
109
|
-
if response.status_code
|
|
110
|
-
service_response = response.json()
|
|
111
|
-
return service_response["data"]
|
|
112
|
-
else:
|
|
110
|
+
if response.status_code != HTTPStatus.OK:
|
|
113
111
|
raise MerchantServiceException(response.content)
|
|
114
112
|
|
|
113
|
+
service_response = response.json()
|
|
114
|
+
yield service_response["data"]["results"]
|
|
115
|
+
|
|
116
|
+
while service_response["data"]["nextPageToken"] is not None:
|
|
117
|
+
body["page_token"] = service_response["data"]["nextPageToken"]
|
|
118
|
+
response = request(
|
|
119
|
+
"post", url=self._LIST_PRODUCT_STATUSES, json=body, headers=header
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
if response.status_code != HTTPStatus.OK:
|
|
123
|
+
raise MerchantServiceException(response.content)
|
|
124
|
+
|
|
125
|
+
service_response = response.json()
|
|
126
|
+
yield service_response["data"]["results"]
|
|
127
|
+
|
|
115
128
|
def reports_search(
|
|
116
129
|
self,
|
|
117
130
|
merchant_account_id: str,
|
|
@@ -46,6 +46,21 @@ def get_session_if_malformed(wrapped_function):
|
|
|
46
46
|
|
|
47
47
|
return inner
|
|
48
48
|
|
|
49
|
+
def get_report_results_if_expired(wrapped_function):
|
|
50
|
+
@wraps(wrapped_function)
|
|
51
|
+
def inner(*args, **kwargs):
|
|
52
|
+
try:
|
|
53
|
+
return wrapped_function(*args, **kwargs)
|
|
54
|
+
except SklikServiceException as err:
|
|
55
|
+
if json.loads(err.args[0].decode("utf8")).get("detail") == "Requested report has expired. Please create a new report by calling createReport endpoint.":
|
|
56
|
+
print("Report expired, creating new report")
|
|
57
|
+
args[0].get_session(args[0]._secret_id, args[0]._account_email)
|
|
58
|
+
return wrapped_function(*args, **kwargs)
|
|
59
|
+
else:
|
|
60
|
+
raise err
|
|
61
|
+
|
|
62
|
+
return inner
|
|
63
|
+
|
|
49
64
|
|
|
50
65
|
class SklikService:
|
|
51
66
|
def __init__(self, url=None):
|
|
@@ -54,6 +69,7 @@ class SklikService:
|
|
|
54
69
|
self._CREATE_REPORT = self._URL + "/create-report"
|
|
55
70
|
self._READ_REPORT = self._URL + "/read-report"
|
|
56
71
|
self._API = self._URL + "/call-api"
|
|
72
|
+
self._GET_CLIENT = self._URL + "/get-client"
|
|
57
73
|
self._CHECK_DATA_READY = self._URL + "/check-data-ready"
|
|
58
74
|
self._LOGOUT = self._URL + "/logout"
|
|
59
75
|
self._API_LIMITS = self._URL + "/api-limits"
|
|
@@ -95,6 +111,7 @@ class SklikService:
|
|
|
95
111
|
pass
|
|
96
112
|
|
|
97
113
|
@get_session_if_malformed
|
|
114
|
+
@get_report_results_if_expired
|
|
98
115
|
def get_report_results(
|
|
99
116
|
self,
|
|
100
117
|
secret_id: str,
|
|
@@ -267,6 +284,33 @@ class SklikService:
|
|
|
267
284
|
raise SklikServiceException(response.content)
|
|
268
285
|
|
|
269
286
|
@get_session_if_malformed
|
|
287
|
+
def get_client(
|
|
288
|
+
self,
|
|
289
|
+
secret_id: str,
|
|
290
|
+
account_email: str,
|
|
291
|
+
) -> Union[List, Dict]:
|
|
292
|
+
"""
|
|
293
|
+
Function to call SklikService get-client route
|
|
294
|
+
:param secret_id: The ID of the secret in secret manager
|
|
295
|
+
:param account_email: Account email to refers to Sklik accountId
|
|
296
|
+
:return:
|
|
297
|
+
"""
|
|
298
|
+
|
|
299
|
+
if self.session is None:
|
|
300
|
+
self.get_session(secret_id, account_email)
|
|
301
|
+
|
|
302
|
+
response = execute_request(
|
|
303
|
+
"post",
|
|
304
|
+
url=self._GET_CLIENT,
|
|
305
|
+
json={"sklik_session": self.session["sklik_session"]},
|
|
306
|
+
)
|
|
307
|
+
|
|
308
|
+
if response.status_code == HTTPStatus.OK:
|
|
309
|
+
service_response = response.json()
|
|
310
|
+
return service_response["data"]
|
|
311
|
+
else:
|
|
312
|
+
raise SklikServiceException(response.content)
|
|
313
|
+
@get_session_if_malformed
|
|
270
314
|
def check_data_ready(
|
|
271
315
|
self,
|
|
272
316
|
secret_id: str,
|
|
@@ -327,4 +371,4 @@ class SklikService:
|
|
|
327
371
|
service_response = response.json()
|
|
328
372
|
return service_response["data"]
|
|
329
373
|
else:
|
|
330
|
-
raise SklikServiceException(response.content)
|
|
374
|
+
raise SklikServiceException(response.content)
|
|
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
|
|
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
|
|
File without changes
|