logos-sdk 0.0.25.dev26__tar.gz → 0.0.25.dev28__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.dev26 → logos_sdk-0.0.25.dev28}/PKG-INFO +1 -1
- {logos_sdk-0.0.25.dev26 → logos_sdk-0.0.25.dev28}/logos_sdk/big_query/BigQuery.py +51 -1
- {logos_sdk-0.0.25.dev26 → logos_sdk-0.0.25.dev28}/logos_sdk/services/MerchantCenter.py +8 -8
- {logos_sdk-0.0.25.dev26 → logos_sdk-0.0.25.dev28}/logos_sdk.egg-info/PKG-INFO +1 -1
- {logos_sdk-0.0.25.dev26 → logos_sdk-0.0.25.dev28}/LICENSE +0 -0
- {logos_sdk-0.0.25.dev26 → logos_sdk-0.0.25.dev28}/README.md +0 -0
- {logos_sdk-0.0.25.dev26 → logos_sdk-0.0.25.dev28}/logos_sdk/__init__.py +0 -0
- {logos_sdk-0.0.25.dev26 → logos_sdk-0.0.25.dev28}/logos_sdk/big_query/__init__.py +0 -0
- {logos_sdk-0.0.25.dev26 → logos_sdk-0.0.25.dev28}/logos_sdk/logging/LogosLogger.py +0 -0
- {logos_sdk-0.0.25.dev26 → logos_sdk-0.0.25.dev28}/logos_sdk/logging/__init__.py +0 -0
- {logos_sdk-0.0.25.dev26 → logos_sdk-0.0.25.dev28}/logos_sdk/services/CampaignManager.py +0 -0
- {logos_sdk-0.0.25.dev26 → logos_sdk-0.0.25.dev28}/logos_sdk/services/Collabim.py +0 -0
- {logos_sdk-0.0.25.dev26 → logos_sdk-0.0.25.dev28}/logos_sdk/services/DV360.py +0 -0
- {logos_sdk-0.0.25.dev26 → logos_sdk-0.0.25.dev28}/logos_sdk/services/Facebook.py +0 -0
- {logos_sdk-0.0.25.dev26 → logos_sdk-0.0.25.dev28}/logos_sdk/services/GoogleAds.py +0 -0
- {logos_sdk-0.0.25.dev26 → logos_sdk-0.0.25.dev28}/logos_sdk/services/GoogleSheets.py +0 -0
- {logos_sdk-0.0.25.dev26 → logos_sdk-0.0.25.dev28}/logos_sdk/services/MarketMiner.py +0 -0
- {logos_sdk-0.0.25.dev26 → logos_sdk-0.0.25.dev28}/logos_sdk/services/MicrosoftAdvertising.py +0 -0
- {logos_sdk-0.0.25.dev26 → logos_sdk-0.0.25.dev28}/logos_sdk/services/MicrosoftAdvertisingMerchantCenter.py +0 -0
- {logos_sdk-0.0.25.dev26 → logos_sdk-0.0.25.dev28}/logos_sdk/services/Sklik.py +0 -0
- {logos_sdk-0.0.25.dev26 → logos_sdk-0.0.25.dev28}/logos_sdk/services/__init__.py +0 -0
- {logos_sdk-0.0.25.dev26 → logos_sdk-0.0.25.dev28}/logos_sdk.egg-info/SOURCES.txt +0 -0
- {logos_sdk-0.0.25.dev26 → logos_sdk-0.0.25.dev28}/logos_sdk.egg-info/dependency_links.txt +0 -0
- {logos_sdk-0.0.25.dev26 → logos_sdk-0.0.25.dev28}/logos_sdk.egg-info/requires.txt +0 -0
- {logos_sdk-0.0.25.dev26 → logos_sdk-0.0.25.dev28}/logos_sdk.egg-info/top_level.txt +0 -0
- {logos_sdk-0.0.25.dev26 → logos_sdk-0.0.25.dev28}/setup.cfg +0 -0
- {logos_sdk-0.0.25.dev26 → logos_sdk-0.0.25.dev28}/setup.py +0 -0
|
@@ -2,7 +2,7 @@ import os
|
|
|
2
2
|
from datetime import datetime
|
|
3
3
|
|
|
4
4
|
import google.auth.exceptions
|
|
5
|
-
from typing import List, Dict, Union, Optional
|
|
5
|
+
from typing import List, Dict, Union, Optional, Sequence
|
|
6
6
|
|
|
7
7
|
from google.api_core.exceptions import NotFound
|
|
8
8
|
from google.cloud.logging import Client as LoggerClient
|
|
@@ -218,3 +218,53 @@ class BigQuery:
|
|
|
218
218
|
errors = self._service.insert_rows(bq_table, records)
|
|
219
219
|
if errors:
|
|
220
220
|
raise BigQueryException(errors)
|
|
221
|
+
|
|
222
|
+
def upsert_into_table(
|
|
223
|
+
self,
|
|
224
|
+
dataset_id: str,
|
|
225
|
+
target_table: str,
|
|
226
|
+
records: List[Dict],
|
|
227
|
+
schema_columns: List[Dict],
|
|
228
|
+
key_columns: Sequence[str],
|
|
229
|
+
) -> None:
|
|
230
|
+
if not records:
|
|
231
|
+
return
|
|
232
|
+
if not key_columns:
|
|
233
|
+
return
|
|
234
|
+
|
|
235
|
+
bq_table = self.check_table_exists(dataset_id, target_table)
|
|
236
|
+
if bq_table is None:
|
|
237
|
+
self.create_table(dataset_id, target_table, schema_columns)
|
|
238
|
+
table_id = f"{self.project_id}.{dataset_id}.{target_table}"
|
|
239
|
+
cols = [f["name"] for f in schema_columns]
|
|
240
|
+
|
|
241
|
+
staging_table_name = f"_staging_{target_table}"
|
|
242
|
+
staging_table_id = f"{self.project_id}.{dataset_id}.{staging_table_name}"
|
|
243
|
+
self.create_table(dataset_id, staging_table_name, schema_columns)
|
|
244
|
+
|
|
245
|
+
self.insert_into_table(dataset_id, staging_table_name, records)
|
|
246
|
+
|
|
247
|
+
q = lambda c: f"{c}"
|
|
248
|
+
|
|
249
|
+
on_clause = " AND ".join(f"T.{q(k)} = S.{q(k)}" for k in key_columns)
|
|
250
|
+
update_cols = [c for c in cols if c not in set(key_columns)]
|
|
251
|
+
update_set = ",\n ".join(f"{q(c)} = S.{q(c)}" for c in update_cols)
|
|
252
|
+
|
|
253
|
+
insert_cols = ", ".join(q(c) for c in cols)
|
|
254
|
+
insert_vals = ", ".join(f"S.{q(c)}" for c in cols)
|
|
255
|
+
|
|
256
|
+
merge_sql = f"""
|
|
257
|
+
MERGE `{table_id}` T
|
|
258
|
+
USING `{staging_table_id}` S
|
|
259
|
+
ON {on_clause}
|
|
260
|
+
WHEN MATCHED THEN
|
|
261
|
+
UPDATE SET
|
|
262
|
+
{update_set}
|
|
263
|
+
WHEN NOT MATCHED THEN
|
|
264
|
+
INSERT ({insert_cols})
|
|
265
|
+
VALUES ({insert_vals})
|
|
266
|
+
"""
|
|
267
|
+
job = self._service.query(merge_sql)
|
|
268
|
+
job.result()
|
|
269
|
+
|
|
270
|
+
self.delete_table(dataset_id, staging_table_name)
|
|
@@ -21,7 +21,7 @@ class MerchantCenterService:
|
|
|
21
21
|
self._LIST_PRODUCT_STATUSES = self._URL + "/product-service/product-statuses"
|
|
22
22
|
self._REPORTS_SEARCH = self._URL + "/reports-search"
|
|
23
23
|
self._GET_SUPPLEMENTAL_FEEDS = self._URL + "/feed-service/supplemental-feeds"
|
|
24
|
-
self.
|
|
24
|
+
self._PRIMARY_FEEDS = self._URL + "/feed-service/feeds"
|
|
25
25
|
|
|
26
26
|
|
|
27
27
|
def list_accounts(self, merchant_account_id: str, secret_id: str):
|
|
@@ -228,11 +228,11 @@ class MerchantCenterService:
|
|
|
228
228
|
else:
|
|
229
229
|
raise MerchantServiceException(response.content)
|
|
230
230
|
|
|
231
|
-
def
|
|
231
|
+
def get_primary_feeds(self, secret_id: str, merchant_account_id: str):
|
|
232
232
|
body = {"secret_id": secret_id, "merchant_account_id": merchant_account_id}
|
|
233
|
-
header = get_headers(self.
|
|
233
|
+
header = get_headers(self._PRIMARY_FEEDS)
|
|
234
234
|
response = self.session.request(
|
|
235
|
-
"post", url=self.
|
|
235
|
+
"post", url=self._PRIMARY_FEEDS, json=body, headers=header
|
|
236
236
|
)
|
|
237
237
|
|
|
238
238
|
if response.status_code == HTTPStatus.OK:
|
|
@@ -255,9 +255,9 @@ class MerchantCenterService:
|
|
|
255
255
|
"supplemental_feed_id": supplemental_feed_id,
|
|
256
256
|
"action": "attach"
|
|
257
257
|
}
|
|
258
|
-
header = get_headers(self.
|
|
258
|
+
header = get_headers(self._PRIMARY_FEEDS)
|
|
259
259
|
response = self.session.request(
|
|
260
|
-
"patch", url=self.
|
|
260
|
+
"patch", url=self._PRIMARY_FEEDS, json=body, headers=header
|
|
261
261
|
)
|
|
262
262
|
|
|
263
263
|
if response.status_code == HTTPStatus.OK:
|
|
@@ -280,9 +280,9 @@ class MerchantCenterService:
|
|
|
280
280
|
"supplemental_feed_id": supplemental_feed_id,
|
|
281
281
|
"action": "detach"
|
|
282
282
|
}
|
|
283
|
-
header = get_headers(self.
|
|
283
|
+
header = get_headers(self._PRIMARY_FEEDS)
|
|
284
284
|
response = self.session.request(
|
|
285
|
-
"patch", url=self.
|
|
285
|
+
"patch", url=self._PRIMARY_FEEDS, json=body, headers=header
|
|
286
286
|
)
|
|
287
287
|
|
|
288
288
|
if response.status_code == HTTPStatus.OK:
|
|
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
|
{logos_sdk-0.0.25.dev26 → logos_sdk-0.0.25.dev28}/logos_sdk/services/MicrosoftAdvertising.py
RENAMED
|
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
|