findly.unified-reporting-sdk 0.7.10__tar.gz → 0.7.12__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.
- {findly_unified_reporting_sdk-0.7.10 → findly_unified_reporting_sdk-0.7.12}/PKG-INFO +1 -1
- {findly_unified_reporting_sdk-0.7.10 → findly_unified_reporting_sdk-0.7.12}/findly/unified_reporting_sdk/data_sources/ga4/ga4_client.py +55 -16
- {findly_unified_reporting_sdk-0.7.10 → findly_unified_reporting_sdk-0.7.12}/findly/unified_reporting_sdk/data_sources/ga4/ga4_query_args_parser.py +13 -9
- {findly_unified_reporting_sdk-0.7.10 → findly_unified_reporting_sdk-0.7.12}/pyproject.toml +1 -1
- {findly_unified_reporting_sdk-0.7.10 → findly_unified_reporting_sdk-0.7.12}/LICENSE +0 -0
- {findly_unified_reporting_sdk-0.7.10 → findly_unified_reporting_sdk-0.7.12}/README.md +0 -0
- {findly_unified_reporting_sdk-0.7.10 → findly_unified_reporting_sdk-0.7.12}/findly/__init__.py +0 -0
- {findly_unified_reporting_sdk-0.7.10 → findly_unified_reporting_sdk-0.7.12}/findly/unified_reporting_sdk/__init__.py +0 -0
- {findly_unified_reporting_sdk-0.7.10 → findly_unified_reporting_sdk-0.7.12}/findly/unified_reporting_sdk/data_sources/__init__.py +0 -0
- {findly_unified_reporting_sdk-0.7.10 → findly_unified_reporting_sdk-0.7.12}/findly/unified_reporting_sdk/data_sources/common/__init__.py +0 -0
- {findly_unified_reporting_sdk-0.7.10 → findly_unified_reporting_sdk-0.7.12}/findly/unified_reporting_sdk/data_sources/common/common_parser.py +0 -0
- {findly_unified_reporting_sdk-0.7.10 → findly_unified_reporting_sdk-0.7.12}/findly/unified_reporting_sdk/data_sources/common/date_range_helper.py +0 -0
- {findly_unified_reporting_sdk-0.7.10 → findly_unified_reporting_sdk-0.7.12}/findly/unified_reporting_sdk/data_sources/common/entities.py +0 -0
- {findly_unified_reporting_sdk-0.7.10 → findly_unified_reporting_sdk-0.7.12}/findly/unified_reporting_sdk/data_sources/common/reports_client.py +0 -0
- {findly_unified_reporting_sdk-0.7.10 → findly_unified_reporting_sdk-0.7.12}/findly/unified_reporting_sdk/data_sources/common/where_string_comparison.py +0 -0
- {findly_unified_reporting_sdk-0.7.10 → findly_unified_reporting_sdk-0.7.12}/findly/unified_reporting_sdk/data_sources/fb_ads/__init__.py +0 -0
- {findly_unified_reporting_sdk-0.7.10 → findly_unified_reporting_sdk-0.7.12}/findly/unified_reporting_sdk/data_sources/fb_ads/fb_ads_client.py +0 -0
- {findly_unified_reporting_sdk-0.7.10 → findly_unified_reporting_sdk-0.7.12}/findly/unified_reporting_sdk/data_sources/fb_ads/fb_ads_query_args_parser.py +0 -0
- {findly_unified_reporting_sdk-0.7.10 → findly_unified_reporting_sdk-0.7.12}/findly/unified_reporting_sdk/data_sources/fb_ads/metadata/action_breakdowns.csv +0 -0
- {findly_unified_reporting_sdk-0.7.10 → findly_unified_reporting_sdk-0.7.12}/findly/unified_reporting_sdk/data_sources/fb_ads/metadata/breakdowns.csv +0 -0
- {findly_unified_reporting_sdk-0.7.10 → findly_unified_reporting_sdk-0.7.12}/findly/unified_reporting_sdk/data_sources/fb_ads/metadata/dimensions.jsonl +0 -0
- {findly_unified_reporting_sdk-0.7.10 → findly_unified_reporting_sdk-0.7.12}/findly/unified_reporting_sdk/data_sources/fb_ads/metadata/fields.csv +0 -0
- {findly_unified_reporting_sdk-0.7.10 → findly_unified_reporting_sdk-0.7.12}/findly/unified_reporting_sdk/data_sources/fb_ads/metadata/metrics.jsonl +0 -0
- {findly_unified_reporting_sdk-0.7.10 → findly_unified_reporting_sdk-0.7.12}/findly/unified_reporting_sdk/data_sources/ga4/__init__.py +0 -0
- {findly_unified_reporting_sdk-0.7.10 → findly_unified_reporting_sdk-0.7.12}/findly/unified_reporting_sdk/data_sources/ga4/metadata/dimensions.jsonl +0 -0
- {findly_unified_reporting_sdk-0.7.10 → findly_unified_reporting_sdk-0.7.12}/findly/unified_reporting_sdk/data_sources/gsc/__init__.py +0 -0
- {findly_unified_reporting_sdk-0.7.10 → findly_unified_reporting_sdk-0.7.12}/findly/unified_reporting_sdk/data_sources/gsc/gsc_client.py +0 -0
- {findly_unified_reporting_sdk-0.7.10 → findly_unified_reporting_sdk-0.7.12}/findly/unified_reporting_sdk/data_sources/gsc/gsc_service.py +0 -0
- {findly_unified_reporting_sdk-0.7.10 → findly_unified_reporting_sdk-0.7.12}/findly/unified_reporting_sdk/protos/.gitignore +0 -0
- {findly_unified_reporting_sdk-0.7.10 → findly_unified_reporting_sdk-0.7.12}/findly/unified_reporting_sdk/protos/__init__.py +0 -0
- {findly_unified_reporting_sdk-0.7.10 → findly_unified_reporting_sdk-0.7.12}/findly/unified_reporting_sdk/protos/findly_semantic_layer_pb2.py +0 -0
- {findly_unified_reporting_sdk-0.7.10 → findly_unified_reporting_sdk-0.7.12}/findly/unified_reporting_sdk/protos/findly_semantic_layer_pb2.pyi +0 -0
- {findly_unified_reporting_sdk-0.7.10 → findly_unified_reporting_sdk-0.7.12}/findly/unified_reporting_sdk/urs.py +0 -0
- {findly_unified_reporting_sdk-0.7.10 → findly_unified_reporting_sdk-0.7.12}/findly/unified_reporting_sdk/util/__init__.py +0 -0
- {findly_unified_reporting_sdk-0.7.10 → findly_unified_reporting_sdk-0.7.12}/findly/unified_reporting_sdk/util/create_numeric_string_series.py +0 -0
|
@@ -240,6 +240,18 @@ class GA4Client(ReportsClient):
|
|
|
240
240
|
)
|
|
241
241
|
return None
|
|
242
242
|
|
|
243
|
+
def _deduplicate_dimensions(self, dimensions: List[Dimension]) -> List[Dimension]:
|
|
244
|
+
"""
|
|
245
|
+
Deduplicate a list of Dimension objects using their name as a unique key.
|
|
246
|
+
"""
|
|
247
|
+
seen = set()
|
|
248
|
+
deduped = []
|
|
249
|
+
for d in dimensions:
|
|
250
|
+
if d.name not in seen:
|
|
251
|
+
seen.add(d.name)
|
|
252
|
+
deduped.append(d)
|
|
253
|
+
return deduped
|
|
254
|
+
|
|
243
255
|
@backoff.on_exception(
|
|
244
256
|
backoff.expo, Exception, max_time=60, max_tries=3, giveup=give_up
|
|
245
257
|
)
|
|
@@ -260,10 +272,11 @@ class GA4Client(ReportsClient):
|
|
|
260
272
|
) -> Optional[RunReportResponse]:
|
|
261
273
|
report_response = None
|
|
262
274
|
try:
|
|
275
|
+
deduplicated_dimensions = self._deduplicate_dimensions(dimensions)
|
|
263
276
|
request = RunReportRequest(
|
|
264
277
|
property=f"properties/{property_id}",
|
|
265
278
|
date_ranges=date_ranges,
|
|
266
|
-
dimensions=
|
|
279
|
+
dimensions=deduplicated_dimensions,
|
|
267
280
|
metrics=metrics,
|
|
268
281
|
metric_filter=metric_filter,
|
|
269
282
|
dimension_filter=dimension_filter,
|
|
@@ -313,22 +326,48 @@ class GA4Client(ReportsClient):
|
|
|
313
326
|
include_totals: bool = True,
|
|
314
327
|
**kwargs: str,
|
|
315
328
|
) -> Optional[RunReportResponse]:
|
|
316
|
-
#
|
|
317
|
-
deduplicated_dimensions =
|
|
329
|
+
# Use the new deduplication method instead of set() to avoid the unhashable error.
|
|
330
|
+
deduplicated_dimensions = self._deduplicate_dimensions(dimensions)
|
|
318
331
|
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
+
try:
|
|
333
|
+
request = RunReportRequest(
|
|
334
|
+
property=f"properties/{property_id}",
|
|
335
|
+
date_ranges=date_ranges,
|
|
336
|
+
dimensions=deduplicated_dimensions,
|
|
337
|
+
metrics=metrics,
|
|
338
|
+
metric_filter=metric_filter,
|
|
339
|
+
dimension_filter=dimension_filter,
|
|
340
|
+
order_bys=order_bys,
|
|
341
|
+
limit=limit,
|
|
342
|
+
offset=offset,
|
|
343
|
+
keep_empty_rows=True,
|
|
344
|
+
metric_aggregations=(
|
|
345
|
+
[MetricAggregation.TOTAL] if include_totals else None
|
|
346
|
+
),
|
|
347
|
+
)
|
|
348
|
+
report_response = await asyncio.wait_for(
|
|
349
|
+
self._client.run_report(request), timeout=REQUEST_TIMEOUT
|
|
350
|
+
)
|
|
351
|
+
except (TimeoutError, asyncio.exceptions.TimeoutError) as timeout_error:
|
|
352
|
+
LOGGER.warning(
|
|
353
|
+
{
|
|
354
|
+
"error": str(timeout_error),
|
|
355
|
+
"msg": "timeout_error_from_ga4_client",
|
|
356
|
+
"property_id": property_id,
|
|
357
|
+
}
|
|
358
|
+
)
|
|
359
|
+
raise timeout_error
|
|
360
|
+
except Exception as e:
|
|
361
|
+
LOGGER.warning(
|
|
362
|
+
{
|
|
363
|
+
"msg": "failed_to_run_report",
|
|
364
|
+
"property_id": property_id,
|
|
365
|
+
"error": str(e),
|
|
366
|
+
}
|
|
367
|
+
)
|
|
368
|
+
raise e
|
|
369
|
+
|
|
370
|
+
return report_response
|
|
332
371
|
|
|
333
372
|
@cached(ttl=300, cache=Cache.MEMORY) # Cache results for 5 minutes
|
|
334
373
|
async def _decorated_query(
|
|
@@ -225,16 +225,20 @@ class GA4QueryArgsParser(CommonParser):
|
|
|
225
225
|
query_args: QueryArgs,
|
|
226
226
|
property_id: str,
|
|
227
227
|
) -> Dict[str, Any]:
|
|
228
|
+
# Remove duplicates from metrics and dimensions to avoid redundant processing.
|
|
229
|
+
unique_metrics = list(dict.fromkeys(query_args.metrics))
|
|
230
|
+
unique_dimensions = list(dict.fromkeys(query_args.group_by_columns))
|
|
231
|
+
|
|
228
232
|
ga4_metrics_list = await self.get_metrics(
|
|
229
|
-
metrics_name_list=
|
|
233
|
+
metrics_name_list=unique_metrics,
|
|
230
234
|
)
|
|
231
235
|
LOGGER.info("sucessfully got metrics")
|
|
232
|
-
|
|
236
|
+
|
|
233
237
|
ga4_dimensions_list = await self.get_dimensions(
|
|
234
|
-
dimensions_name_list=
|
|
238
|
+
dimensions_name_list=unique_dimensions,
|
|
235
239
|
)
|
|
236
240
|
LOGGER.info("sucessfully got dimensions")
|
|
237
|
-
|
|
241
|
+
|
|
238
242
|
ga4_date_ranges = self.get_date_ranges(
|
|
239
243
|
date_str_range_list=(
|
|
240
244
|
list(query_args.date_ranges)
|
|
@@ -244,7 +248,7 @@ class GA4QueryArgsParser(CommonParser):
|
|
|
244
248
|
format_function=format_ga4_date_ranges_default,
|
|
245
249
|
)
|
|
246
250
|
LOGGER.info("sucessfully got date ranges")
|
|
247
|
-
|
|
251
|
+
|
|
248
252
|
ga4_order_by_list = await self.get_order_by(
|
|
249
253
|
order_by_list=(
|
|
250
254
|
list(query_args.order_by) if query_args.order_by is not None else None
|
|
@@ -253,17 +257,17 @@ class GA4QueryArgsParser(CommonParser):
|
|
|
253
257
|
order_by_dimensions_candidates=list(query_args.group_by_columns),
|
|
254
258
|
)
|
|
255
259
|
LOGGER.info("sucessfully got order by")
|
|
256
|
-
|
|
260
|
+
|
|
257
261
|
ga4_dimension_filter_list = await self.get_filter_clause(
|
|
258
262
|
filter_clause=query_args.where_clause
|
|
259
263
|
)
|
|
260
264
|
LOGGER.info("sucessfully got dimension filter")
|
|
261
|
-
|
|
265
|
+
|
|
262
266
|
ga4_metrics_filter_list = await self.get_filter_clause(
|
|
263
267
|
filter_clause=query_args.having_clause
|
|
264
268
|
)
|
|
265
269
|
LOGGER.info("sucessfully got metrics filter")
|
|
266
|
-
|
|
270
|
+
|
|
267
271
|
LOGGER.info(
|
|
268
272
|
{
|
|
269
273
|
"msg": "query_parts",
|
|
@@ -279,7 +283,7 @@ class GA4QueryArgsParser(CommonParser):
|
|
|
279
283
|
"limit": query_args.limit,
|
|
280
284
|
}
|
|
281
285
|
)
|
|
282
|
-
|
|
286
|
+
|
|
283
287
|
ga4_request = {
|
|
284
288
|
"metrics": ga4_metrics_list,
|
|
285
289
|
"dimensions": ga4_dimensions_list,
|
|
File without changes
|
|
File without changes
|
{findly_unified_reporting_sdk-0.7.10 → findly_unified_reporting_sdk-0.7.12}/findly/__init__.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
|
|
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
|