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.
Files changed (35) hide show
  1. {findly_unified_reporting_sdk-0.7.10 → findly_unified_reporting_sdk-0.7.12}/PKG-INFO +1 -1
  2. {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
  3. {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
  4. {findly_unified_reporting_sdk-0.7.10 → findly_unified_reporting_sdk-0.7.12}/pyproject.toml +1 -1
  5. {findly_unified_reporting_sdk-0.7.10 → findly_unified_reporting_sdk-0.7.12}/LICENSE +0 -0
  6. {findly_unified_reporting_sdk-0.7.10 → findly_unified_reporting_sdk-0.7.12}/README.md +0 -0
  7. {findly_unified_reporting_sdk-0.7.10 → findly_unified_reporting_sdk-0.7.12}/findly/__init__.py +0 -0
  8. {findly_unified_reporting_sdk-0.7.10 → findly_unified_reporting_sdk-0.7.12}/findly/unified_reporting_sdk/__init__.py +0 -0
  9. {findly_unified_reporting_sdk-0.7.10 → findly_unified_reporting_sdk-0.7.12}/findly/unified_reporting_sdk/data_sources/__init__.py +0 -0
  10. {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
  11. {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
  12. {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
  13. {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
  14. {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
  15. {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
  16. {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
  17. {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
  18. {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
  19. {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
  20. {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
  21. {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
  22. {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
  23. {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
  24. {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
  25. {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
  26. {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
  27. {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
  28. {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
  29. {findly_unified_reporting_sdk-0.7.10 → findly_unified_reporting_sdk-0.7.12}/findly/unified_reporting_sdk/protos/.gitignore +0 -0
  30. {findly_unified_reporting_sdk-0.7.10 → findly_unified_reporting_sdk-0.7.12}/findly/unified_reporting_sdk/protos/__init__.py +0 -0
  31. {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
  32. {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
  33. {findly_unified_reporting_sdk-0.7.10 → findly_unified_reporting_sdk-0.7.12}/findly/unified_reporting_sdk/urs.py +0 -0
  34. {findly_unified_reporting_sdk-0.7.10 → findly_unified_reporting_sdk-0.7.12}/findly/unified_reporting_sdk/util/__init__.py +0 -0
  35. {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
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: findly.unified-reporting-sdk
3
- Version: 0.7.10
3
+ Version: 0.7.12
4
4
  Summary:
5
5
  License: GPL-3.0-only
6
6
  Requires-Python: >=3.9,<4.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=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
- # deduplicate dimensions, otherwise we get an error
317
- deduplicated_dimensions = list(set(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
- return await self._decorated_query_from_parts(
320
- metrics=metrics,
321
- dimensions=deduplicated_dimensions,
322
- date_ranges=date_ranges,
323
- dimension_filter=dimension_filter,
324
- metric_filter=metric_filter,
325
- order_bys=order_bys,
326
- limit=limit,
327
- offset=offset,
328
- property_id=property_id,
329
- include_totals=include_totals,
330
- **kwargs,
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=list(query_args.metrics),
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=list(query_args.group_by_columns),
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,
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "findly.unified-reporting-sdk"
3
- version = "0.7.10"
3
+ version = "0.7.12"
4
4
  license = "GPL-3.0-only"
5
5
  description = ""
6
6
  authors = []