logos-sdk 0.0.25.dev28__tar.gz → 0.0.25.dev30__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 (28) hide show
  1. {logos_sdk-0.0.25.dev28 → logos_sdk-0.0.25.dev30}/PKG-INFO +1 -1
  2. {logos_sdk-0.0.25.dev28 → logos_sdk-0.0.25.dev30}/logos_sdk/big_query/BigQuery.py +27 -14
  3. logos_sdk-0.0.25.dev30/logos_sdk/services/GA4.py +98 -0
  4. {logos_sdk-0.0.25.dev28 → logos_sdk-0.0.25.dev30}/logos_sdk.egg-info/PKG-INFO +1 -1
  5. {logos_sdk-0.0.25.dev28 → logos_sdk-0.0.25.dev30}/logos_sdk.egg-info/SOURCES.txt +1 -0
  6. {logos_sdk-0.0.25.dev28 → logos_sdk-0.0.25.dev30}/LICENSE +0 -0
  7. {logos_sdk-0.0.25.dev28 → logos_sdk-0.0.25.dev30}/README.md +0 -0
  8. {logos_sdk-0.0.25.dev28 → logos_sdk-0.0.25.dev30}/logos_sdk/__init__.py +0 -0
  9. {logos_sdk-0.0.25.dev28 → logos_sdk-0.0.25.dev30}/logos_sdk/big_query/__init__.py +0 -0
  10. {logos_sdk-0.0.25.dev28 → logos_sdk-0.0.25.dev30}/logos_sdk/logging/LogosLogger.py +0 -0
  11. {logos_sdk-0.0.25.dev28 → logos_sdk-0.0.25.dev30}/logos_sdk/logging/__init__.py +0 -0
  12. {logos_sdk-0.0.25.dev28 → logos_sdk-0.0.25.dev30}/logos_sdk/services/CampaignManager.py +0 -0
  13. {logos_sdk-0.0.25.dev28 → logos_sdk-0.0.25.dev30}/logos_sdk/services/Collabim.py +0 -0
  14. {logos_sdk-0.0.25.dev28 → logos_sdk-0.0.25.dev30}/logos_sdk/services/DV360.py +0 -0
  15. {logos_sdk-0.0.25.dev28 → logos_sdk-0.0.25.dev30}/logos_sdk/services/Facebook.py +0 -0
  16. {logos_sdk-0.0.25.dev28 → logos_sdk-0.0.25.dev30}/logos_sdk/services/GoogleAds.py +0 -0
  17. {logos_sdk-0.0.25.dev28 → logos_sdk-0.0.25.dev30}/logos_sdk/services/GoogleSheets.py +0 -0
  18. {logos_sdk-0.0.25.dev28 → logos_sdk-0.0.25.dev30}/logos_sdk/services/MarketMiner.py +0 -0
  19. {logos_sdk-0.0.25.dev28 → logos_sdk-0.0.25.dev30}/logos_sdk/services/MerchantCenter.py +0 -0
  20. {logos_sdk-0.0.25.dev28 → logos_sdk-0.0.25.dev30}/logos_sdk/services/MicrosoftAdvertising.py +0 -0
  21. {logos_sdk-0.0.25.dev28 → logos_sdk-0.0.25.dev30}/logos_sdk/services/MicrosoftAdvertisingMerchantCenter.py +0 -0
  22. {logos_sdk-0.0.25.dev28 → logos_sdk-0.0.25.dev30}/logos_sdk/services/Sklik.py +0 -0
  23. {logos_sdk-0.0.25.dev28 → logos_sdk-0.0.25.dev30}/logos_sdk/services/__init__.py +0 -0
  24. {logos_sdk-0.0.25.dev28 → logos_sdk-0.0.25.dev30}/logos_sdk.egg-info/dependency_links.txt +0 -0
  25. {logos_sdk-0.0.25.dev28 → logos_sdk-0.0.25.dev30}/logos_sdk.egg-info/requires.txt +0 -0
  26. {logos_sdk-0.0.25.dev28 → logos_sdk-0.0.25.dev30}/logos_sdk.egg-info/top_level.txt +0 -0
  27. {logos_sdk-0.0.25.dev28 → logos_sdk-0.0.25.dev30}/setup.cfg +0 -0
  28. {logos_sdk-0.0.25.dev28 → logos_sdk-0.0.25.dev30}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: logos-sdk
3
- Version: 0.0.25.dev28
3
+ Version: 0.0.25.dev30
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
@@ -1,4 +1,5 @@
1
1
  import os
2
+ import uuid
2
3
  from datetime import datetime
3
4
 
4
5
  import google.auth.exceptions
@@ -96,6 +97,8 @@ class BigQuery:
96
97
  schema_columns: List[Dict],
97
98
  partitioning_column_name: str,
98
99
  partition_type=bigquery.TimePartitioningType.DAY,
100
+ retention_days: Optional[int] = None,
101
+ cluster_fields: Optional[List[str]] = None,
99
102
  ):
100
103
  bq_table = self.check_table_exists(dataset_id, table_id)
101
104
  if bq_table is None:
@@ -105,6 +108,8 @@ class BigQuery:
105
108
  schema_columns,
106
109
  partitioning_column_name,
107
110
  partition_type,
111
+ retention_days,
112
+ cluster_fields,
108
113
  )
109
114
 
110
115
  self._insert_into_table(bq_table, records)
@@ -127,6 +132,8 @@ class BigQuery:
127
132
  schema_columns: List[Dict],
128
133
  partitioning_column_name: str,
129
134
  partition_type=bigquery.TimePartitioningType.DAY,
135
+ retention_days: Optional[int] = None,
136
+ cluster_fields: Optional[List[str]] = None,
130
137
  ):
131
138
  table_schema = [
132
139
  bigquery.schema.SchemaField(
@@ -140,11 +147,20 @@ class BigQuery:
140
147
  try:
141
148
  sql_format = self._get_table_id_sql_format(dataset_id, table_id)
142
149
  table_object = bigquery.Table(sql_format, schema=table_schema)
143
- # Set partitioning on the "report_date" column
150
+
151
+ time_partitioning_kwargs = {
152
+ "type_": partition_type,
153
+ "field": partitioning_column_name,
154
+ }
155
+ if retention_days is not None and retention_days > 0:
156
+ time_partitioning_kwargs["expiration_ms"] = (
157
+ retention_days * 24 * 60 * 60 * 1000
158
+ )
144
159
  table_object.time_partitioning = bigquery.TimePartitioning(
145
- type_=partition_type,
146
- field=partitioning_column_name, # The column to use for partitioning
160
+ **time_partitioning_kwargs
147
161
  )
162
+ if cluster_fields:
163
+ table_object.clustering_fields = cluster_fields
148
164
  return self._service.create_table(table_object)
149
165
  except google.cloud.exceptions.Conflict:
150
166
  return False
@@ -220,25 +236,22 @@ class BigQuery:
220
236
  raise BigQueryException(errors)
221
237
 
222
238
  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],
239
+ self,
240
+ dataset_id: str,
241
+ target_table: str,
242
+ records: List[Dict],
243
+ schema_columns: List[Dict],
244
+ key_columns: Sequence[str],
229
245
  ) -> None:
230
246
  if not records:
231
247
  return
232
248
  if not key_columns:
233
249
  return
234
250
 
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
251
  table_id = f"{self.project_id}.{dataset_id}.{target_table}"
239
252
  cols = [f["name"] for f in schema_columns]
240
253
 
241
- staging_table_name = f"_staging_{target_table}"
254
+ staging_table_name = f"_staging_{str(uuid.uuid4())}"
242
255
  staging_table_id = f"{self.project_id}.{dataset_id}.{staging_table_name}"
243
256
  self.create_table(dataset_id, staging_table_name, schema_columns)
244
257
 
@@ -248,7 +261,7 @@ class BigQuery:
248
261
 
249
262
  on_clause = " AND ".join(f"T.{q(k)} = S.{q(k)}" for k in key_columns)
250
263
  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)
264
+ update_set = ",\n ".join(f"T.{q(c)} = S.{q(c)}" for c in update_cols)
252
265
 
253
266
  insert_cols = ", ".join(q(c) for c in cols)
254
267
  insert_vals = ", ".join(f"S.{q(c)}" for c in cols)
@@ -0,0 +1,98 @@
1
+ from requests.exceptions import Timeout
2
+ from typing import List, Union, Dict
3
+ from logos_sdk.services import get_headers, get_retry_session
4
+ from http import HTTPStatus
5
+ from dotenv import load_dotenv
6
+ import os
7
+ import time
8
+ import random
9
+
10
+
11
+ class GA4ServiceException(Exception):
12
+ pass
13
+
14
+
15
+ class GA4Service:
16
+ def __init__(self, url=None):
17
+ load_dotenv()
18
+ self.session = get_retry_session()
19
+ self._URL = url or os.environ.get("GA4_SERVICE_PATH")
20
+ self._RUN_REPORT = self._URL + "/run-report"
21
+ self._GET_ACCESSIBLE_ACCOUNTS = self._URL + "/accessible-accounts"
22
+ self._GET_ACCOUNT_ACCESSIBILITY = self._URL + "/get-account-accessibility"
23
+
24
+ def get_accessible_accounts(
25
+ self,
26
+ secret_id: str,
27
+ ) -> List[Dict]:
28
+ body = {
29
+ "secret_id": secret_id,
30
+ }
31
+
32
+ header = get_headers(self._GET_ACCESSIBLE_ACCOUNTS)
33
+ response = self.session.request(
34
+ "post", url=self._GET_ACCESSIBLE_ACCOUNTS, json=body, headers=header
35
+ )
36
+
37
+ if response.status_code == HTTPStatus.OK:
38
+ service_response = response.json()
39
+ return service_response["data"]
40
+ else:
41
+ raise GA4ServiceException(response.content)
42
+
43
+ def get_account_accessibility(self, secret_id: str, account_id: str) -> bool:
44
+ """
45
+ Gets account accessibility
46
+ :param secret_id: The ID of the secret in secret manager
47
+ :param account_id: The ID of the account.
48
+ :return: True if account has access
49
+ """
50
+ body = {"secret_id": secret_id, "account_id": account_id}
51
+ header = get_headers(self._GET_ACCOUNT_ACCESSIBILITY)
52
+ response = self.session.request(
53
+ "post", url=self._GET_ACCOUNT_ACCESSIBILITY, json=body, headers=header
54
+ )
55
+
56
+ if response.status_code == HTTPStatus.OK:
57
+ service_response = response.json()
58
+ return service_response["data"]
59
+ else:
60
+ raise GA4ServiceException(response.content)
61
+
62
+ def run_report(self, account_id, secret_id, start_date, end_date, dimensions, metrics, filters=None,
63
+ order_by_metric=None):
64
+ """
65
+ Runs report
66
+ :param account_id: The ID of the account,
67
+ :param secret_id: The ID of the secret in secret manager
68
+ :param start_date: report start date in format "YYYY-MM-DD"
69
+ :param end_date: report end date in format "YYYY-MM-DD"
70
+ :param dimensions: The dimesions for the query
71
+ :param metrics: The metrics for the query
72
+ :param filters: The filters for the query
73
+ :param order_by_metric: The metric to order by
74
+ :return: report result
75
+ """
76
+ header = get_headers(self._RUN_REPORT)
77
+ body = {
78
+ "property_id": account_id,
79
+ "secret_id": secret_id,
80
+ "start_date": start_date,
81
+ "end_date": end_date,
82
+ "dimensions": dimensions,
83
+ "metrics": metrics,
84
+ }
85
+ if filters is not None:
86
+ body["filters"] = filters
87
+ if order_by_metric is not None:
88
+ body['order_by_metric'] = order_by_metric
89
+
90
+ response = self.session.request(
91
+ "post", url=self._RUN_REPORT, json=body, headers=header
92
+ )
93
+
94
+ if response.status_code == HTTPStatus.OK:
95
+ service_response = response.json()
96
+ return service_response["data"]
97
+ else:
98
+ raise GA4ServiceException(response.content)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: logos-sdk
3
- Version: 0.0.25.dev28
3
+ Version: 0.0.25.dev30
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
@@ -16,6 +16,7 @@ logos_sdk/services/CampaignManager.py
16
16
  logos_sdk/services/Collabim.py
17
17
  logos_sdk/services/DV360.py
18
18
  logos_sdk/services/Facebook.py
19
+ logos_sdk/services/GA4.py
19
20
  logos_sdk/services/GoogleAds.py
20
21
  logos_sdk/services/GoogleSheets.py
21
22
  logos_sdk/services/MarketMiner.py