airbyte-source-google-ads 4.1.4__py3-none-any.whl → 4.1.4.dev202511261224__py3-none-any.whl

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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: airbyte-source-google-ads
3
- Version: 4.1.4
3
+ Version: 4.1.4.dev202511261224
4
4
  Summary: Source implementation for Google Ads.
5
5
  Home-page: https://airbyte.com
6
6
  License: Elv2
@@ -11,7 +11,7 @@ Classifier: License :: Other/Proprietary License
11
11
  Classifier: Programming Language :: Python :: 3
12
12
  Classifier: Programming Language :: Python :: 3.10
13
13
  Classifier: Programming Language :: Python :: 3.11
14
- Requires-Dist: airbyte-cdk (>=7.5.1.post3.dev19705070276,<8.0.0)
14
+ Requires-Dist: airbyte-cdk (>=7.4.1,<8.0.0)
15
15
  Requires-Dist: google-ads (==27.0.0)
16
16
  Requires-Dist: pendulum (<3.0.0)
17
17
  Requires-Dist: protobuf (==4.25.2)
@@ -1,17 +1,17 @@
1
1
  source_google_ads/__init__.py,sha256=Nlo5H6LlaSgg7tx_LyqMIy3MXiAagfk3izZ9o44VvSE,1201
2
- source_google_ads/components.py,sha256=hzd6hgBuE0HvHVO71r3gdHsbM5sApQKpzW_QWKEAv8g,41479
2
+ source_google_ads/components.py,sha256=_Jku4_NHRg4OzYSmtk23H0LfYo0bbqfx1navUoUztug,40970
3
3
  source_google_ads/config_migrations.py,sha256=oBi_qNqBpLS8GNCaIOBo0stNdYuyqVl6lkrhdXRwMX8,4405
4
4
  source_google_ads/google_ads.py,sha256=cxS18tz0fFJjmIhlhFQ3Zvu2K8bhDtmsl1kFeO7nNhk,11595
5
- source_google_ads/manifest.yaml,sha256=4LzKMj23yS8Vo8M6tfxv77vIp58pIIEN26x3lz3rm1M,223987
5
+ source_google_ads/manifest.yaml,sha256=ICDxfH8-pT78PfQwU2h_mgCVkv-sSzuQBR4BdnVZEpU,219342
6
6
  source_google_ads/models.py,sha256=ZmdS3z_2roaEQgV2Mx1CDm33MztpQ66SfHDzP8XwZog,1658
7
7
  source_google_ads/run.py,sha256=ydIyq_vSNV5Z4mJYnsO5GyNDsLDd0qibBsq6wnvuFAo,2002
8
8
  source_google_ads/schemas/customer_client.json,sha256=oThcyUDO1yWpxtWPWdoAFqTXEIweF8N4q6mRI73Q6yU,984
9
9
  source_google_ads/schemas/service_accounts.json,sha256=HVSyzbEoxzB4rntRHOjAh0ZYgbR584ew0W0CdJH7ECU,3485
10
- source_google_ads/source.py,sha256=hz5ep6stMWHNvD73PIF_7bjnee49sY9YHHjaYNAPnOQ,1425
10
+ source_google_ads/source.py,sha256=xmfWTrefFYNDm8Nl5FUqnTByjgQTcJI6VVBD_khY6No,1791
11
11
  source_google_ads/spec.json,sha256=8hbc7smbaffIkYCkX2BYJLB9kgaH8vYKCg-H0y1FvUs,7810
12
12
  source_google_ads/streams.py,sha256=FB-DNJlXhjQADptT-wrv3iGWoliyRuvDuHGeqiN9HsY,13349
13
13
  source_google_ads/utils.py,sha256=-KpgGv2W8WueXvGRC3xbVreDl5-5-vU9OwzC5SZDKVc,21409
14
- airbyte_source_google_ads-4.1.4.dist-info/METADATA,sha256=K-SPkHaTXmmXpZa6kWRHhMwrK8wqBQG4LNvm3ldwLsI,5381
15
- airbyte_source_google_ads-4.1.4.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
16
- airbyte_source_google_ads-4.1.4.dist-info/entry_points.txt,sha256=pP4Llir93XGkHFDZfXXxK7qOWo9_U1ssCJToyxEUB4w,63
17
- airbyte_source_google_ads-4.1.4.dist-info/RECORD,,
14
+ airbyte_source_google_ads-4.1.4.dev202511261224.dist-info/METADATA,sha256=hF_jEn4xE6E4jWFnE9O0bCHOBI4rFJPegmqUH9JdhPc,5376
15
+ airbyte_source_google_ads-4.1.4.dev202511261224.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
16
+ airbyte_source_google_ads-4.1.4.dev202511261224.dist-info/entry_points.txt,sha256=pP4Llir93XGkHFDZfXXxK7qOWo9_U1ssCJToyxEUB4w,63
17
+ airbyte_source_google_ads-4.1.4.dev202511261224.dist-info/RECORD,,
@@ -697,7 +697,6 @@ class CustomGAQueryHttpRequester(HttpRequester):
697
697
  def __post_init__(self, parameters: Mapping[str, Any]):
698
698
  super().__post_init__(parameters=parameters)
699
699
  self.query = GAQL.parse(parameters.get("query"))
700
- self.stream_response = True
701
700
 
702
701
  @staticmethod
703
702
  def is_metrics_in_custom_query(query: GAQL) -> bool:
@@ -762,17 +761,6 @@ class CustomGAQueryHttpRequester(HttpRequester):
762
761
  return self.query[from_index + 4 :].strip()
763
762
 
764
763
 
765
- class CustomGAQueryClickViewHttpRequester(CustomGAQueryHttpRequester):
766
- @staticmethod
767
- def _insert_segments_date_expr(query: GAQL, start_date: str, end_date: str) -> GAQL:
768
- if "segments.date" not in query.fields:
769
- query = query.append_field("segments.date")
770
- condition = f"segments.date ='{start_date}'"
771
- if query.where:
772
- return query.set_where(query.where + " AND " + condition)
773
- return query.set_where(condition)
774
-
775
-
776
764
  @dataclass()
777
765
  class CustomGAQuerySchemaLoader(SchemaLoader):
778
766
  """
@@ -65,15 +65,27 @@ definitions:
65
65
  field_path:
66
66
  - results
67
67
 
68
+ cursor_paginator:
69
+ type: DefaultPaginator
70
+ pagination_strategy:
71
+ type: CursorPagination
72
+ cursor_value: "{{ response.get('nextPageToken', '') }}"
73
+ stop_condition: "{{ response.get('nextPageToken', '') is none }}"
74
+ page_token_option:
75
+ type: RequestOption
76
+ inject_into: body_json
77
+ field_path: ["page_token"]
78
+
68
79
  base_retriever:
69
80
  type: SimpleRetriever
70
81
  requester:
71
82
  $ref: "#/definitions/stream_requester"
72
83
  record_selector:
73
84
  $ref: "#/definitions/base_selector"
85
+ paginator:
86
+ $ref: "#/definitions/cursor_paginator"
74
87
  decoder:
75
- type: CustomDecoder
76
- class_name: "source_google_ads.components.GoogleAdsStreamingDecoder"
88
+ type: JsonDecoder
77
89
 
78
90
  stream_base:
79
91
  type: DeclarativeStream
@@ -187,7 +199,7 @@ definitions:
187
199
  $ref: "#/schemas"
188
200
  authenticator:
189
201
  $ref: "#/definitions/authenticator"
190
- url_base: "https://googleads.googleapis.com/v20/{{ stream_partition['customer_id'] }}/googleAds:searchStream"
202
+ url_base: "https://googleads.googleapis.com/v20/{{ stream_partition['customer_id'] }}/googleAds:search"
191
203
  http_method: POST
192
204
  error_handler:
193
205
  $ref: "#/definitions/base_error_handler"
@@ -212,7 +224,7 @@ definitions:
212
224
  incremental_stream:
213
225
  $ref: "#/definitions/incremental_stream_base"
214
226
  $parameters:
215
- url_base: "https://googleads.googleapis.com/v20/{{ stream_partition['parent_slice']['customer_id'] }}/googleAds:searchStream"
227
+ url_base: "https://googleads.googleapis.com/v20/{{ stream_partition['parent_slice']['customer_id'] }}/googleAds:search"
216
228
  retriever:
217
229
  type: CustomRetriever
218
230
  class_name: "source_google_ads.components.CriterionRetriever"
@@ -228,6 +240,8 @@ definitions:
228
240
  http_method: POST
229
241
  error_handler:
230
242
  $ref: "#/definitions/base_error_handler"
243
+ paginator:
244
+ $ref: "#/definitions/cursor_paginator"
231
245
  record_selector:
232
246
  type: RecordSelector
233
247
  extractor:
@@ -283,6 +297,8 @@ definitions:
283
297
  $ref: "#/definitions/base_requester"
284
298
  url_base: "https://googleads.googleapis.com/v20/customers:listAccessibleCustomers"
285
299
  http_method: GET
300
+ paginator:
301
+ type: NoPagination
286
302
  record_selector:
287
303
  extractor:
288
304
  type: CustomRecordExtractor
@@ -406,6 +422,11 @@ definitions:
406
422
  parent_key: "clientCustomer"
407
423
  partition_field: "customer_id"
408
424
  stream: "#/definitions/customer_client"
425
+ decoder:
426
+ type: CustomDecoder
427
+ class_name: "source_google_ads.components.GoogleAdsStreamingDecoder"
428
+ paginator:
429
+ type: NoPagination
409
430
  transformations:
410
431
  - type: CustomTransformation
411
432
  class_name: "source_google_ads.components.KeysToSnakeCaseGoogleAdsTransformation"
@@ -466,6 +487,13 @@ definitions:
466
487
 
467
488
  ad_group_ad_stream:
468
489
  $ref: "#/definitions/incremental_stream_base"
490
+ retriever:
491
+ $ref: "#/definitions/incremental_stream_base/retriever"
492
+ paginator:
493
+ type: NoPagination
494
+ decoder:
495
+ type: CustomDecoder
496
+ class_name: "source_google_ads.components.GoogleAdsStreamingDecoder"
469
497
  name: ad_group_ad
470
498
  primary_key:
471
499
  - ad_group.id
@@ -637,10 +665,12 @@ definitions:
637
665
  $ref: "#/schemas/click_view"
638
666
  authenticator:
639
667
  $ref: "#/definitions/authenticator"
640
- url_base: "https://googleads.googleapis.com/v20/{{ stream_partition['customer_id'] }}/googleAds:searchStream"
668
+ url_base: "https://googleads.googleapis.com/v20/{{ stream_partition['customer_id'] }}/googleAds:search"
641
669
  http_method: POST
642
670
  error_handler:
643
671
  $ref: "#/definitions/base_error_handler"
672
+ paginator:
673
+ $ref: "#/definitions/cursor_paginator"
644
674
  incremental_sync:
645
675
  type: DatetimeBasedCursor
646
676
  cursor_field: segments.date
@@ -829,6 +859,8 @@ definitions:
829
859
  error_handler:
830
860
  $ref: "#/definitions/base_error_handler"
831
861
  name: change_status
862
+ paginator:
863
+ $ref: "#/definitions/cursor_paginator"
832
864
  pagination_reset:
833
865
  type: PaginationReset
834
866
  action: SPLIT_USING_CURSOR
@@ -998,6 +1030,14 @@ definitions:
998
1030
  )
999
1031
  }}
1000
1032
  create_or_update: true
1033
+ - type: ComponentMappingDefinition
1034
+ field_path:
1035
+ - retriever
1036
+ - requester
1037
+ - $parameters
1038
+ - query
1039
+ value: "{{ components_values.get('query', None) }}"
1040
+ create_or_update: true
1001
1041
  - type: ComponentMappingDefinition
1002
1042
  field_path:
1003
1043
  - retriever
@@ -1045,130 +1085,6 @@ definitions:
1045
1085
  )
1046
1086
  }}
1047
1087
  create_or_update: true
1048
- - type: ComponentMappingDefinition
1049
- field_path:
1050
- - incremental_sync
1051
- - step
1052
- value: "P1D"
1053
- condition: >-
1054
- {{
1055
- (
1056
- (
1057
- components_values.get('query', '').count('segments.date') == 1
1058
- and (components_values.get('query') | regex_search('(?i)(\\bSELECT\\b[\\s\\S]*?segments\\.date[\\s\\S]*?\\bFROM\\b)'))
1059
- )
1060
- or
1061
- (
1062
- components_values.get('query', '').count('segments.date') == 2
1063
- and (components_values.get('query') | regex_search('(?i)(\\bSELECT\\b[\\s\\S]*?segments\\.date[\\s\\S]*?\\bFROM\\b)'))
1064
- and (components_values.get('query') | regex_search('(?i)(\\bORDER\\s+BY\\b[\\s\\S]*?segments\\.date)'))
1065
- )
1066
- ) and components_values.get('query', '') | regex_search('(?i)(\\bFROM\\s+click_view\\b)')
1067
- }}
1068
- create_or_update: true
1069
- - type: ComponentMappingDefinition
1070
- field_path:
1071
- - incremental_sync
1072
- - start_datetime
1073
- value: >-
1074
- {
1075
- "type": "MinMaxDatetime",
1076
- "datetime": "{{ max(config.get('start_date', day_delta(-90, format='%Y-%m-%d')), day_delta(-90, format='%Y-%m-%d')) }}",
1077
- "datetime_format": "%Y-%m-%d"
1078
- }
1079
- condition: >-
1080
- {{
1081
- (
1082
- (
1083
- components_values.get('query', '').count('segments.date') == 1
1084
- and (components_values.get('query') | regex_search('(?i)(\\bSELECT\\b[\\s\\S]*?segments\\.date[\\s\\S]*?\\bFROM\\b)'))
1085
- )
1086
- or
1087
- (
1088
- components_values.get('query', '').count('segments.date') == 2
1089
- and (components_values.get('query') | regex_search('(?i)(\\bSELECT\\b[\\s\\S]*?segments\\.date[\\s\\S]*?\\bFROM\\b)'))
1090
- and (components_values.get('query') | regex_search('(?i)(\\bORDER\\s+BY\\b[\\s\\S]*?segments\\.date)'))
1091
- )
1092
- ) and components_values.get('query', '') | regex_search('(?i)(\\bFROM\\s+click_view\\b)')
1093
- }}
1094
- create_or_update: true
1095
- - type: ComponentMappingDefinition
1096
- field_path:
1097
- - incremental_sync
1098
- - end_datetime
1099
- value: >-
1100
- {
1101
- "type": "MinMaxDatetime",
1102
- "datetime": "{{ format_datetime((str_to_datetime(config.get('end_date')) if config.get('end_date') else now_utc()) + duration('P1D'), '%Y-%m-%d') }}",
1103
- "datetime_format": "%Y-%m-%d"
1104
- }
1105
- condition: >-
1106
- {{
1107
- (
1108
- (
1109
- components_values.get('query', '').count('segments.date') == 1
1110
- and (components_values.get('query') | regex_search('(?i)(\\bSELECT\\b[\\s\\S]*?segments\\.date[\\s\\S]*?\\bFROM\\b)'))
1111
- )
1112
- or
1113
- (
1114
- components_values.get('query', '').count('segments.date') == 2
1115
- and (components_values.get('query') | regex_search('(?i)(\\bSELECT\\b[\\s\\S]*?segments\\.date[\\s\\S]*?\\bFROM\\b)'))
1116
- and (components_values.get('query') | regex_search('(?i)(\\bORDER\\s+BY\\b[\\s\\S]*?segments\\.date)'))
1117
- )
1118
- ) and components_values.get('query', '') | regex_search('(?i)(\\bFROM\\s+click_view\\b)')
1119
- }}
1120
- create_or_update: true
1121
- - type: ComponentMappingDefinition
1122
- field_path:
1123
- - incremental_sync
1124
- - cursor_granularity
1125
- value: P1D
1126
- condition: >-
1127
- {{
1128
- (
1129
- (
1130
- components_values.get('query', '').count('segments.date') == 1
1131
- and (components_values.get('query') | regex_search('(?i)(\\bSELECT\\b[\\s\\S]*?segments\\.date[\\s\\S]*?\\bFROM\\b)'))
1132
- )
1133
- or
1134
- (
1135
- components_values.get('query', '').count('segments.date') == 2
1136
- and (components_values.get('query') | regex_search('(?i)(\\bSELECT\\b[\\s\\S]*?segments\\.date[\\s\\S]*?\\bFROM\\b)'))
1137
- and (components_values.get('query') | regex_search('(?i)(\\bORDER\\s+BY\\b[\\s\\S]*?segments\\.date)'))
1138
- )
1139
- ) and components_values.get('query', '') | regex_search('(?i)(\\bFROM\\s+click_view\\b)')
1140
- }}
1141
- create_or_update: true
1142
- - type: ComponentMappingDefinition
1143
- field_path:
1144
- - retriever
1145
- - requester
1146
- - class_name
1147
- value: "source_google_ads.components.CustomGAQueryClickViewHttpRequester"
1148
- condition: >-
1149
- {{
1150
- (
1151
- (
1152
- components_values.get('query', '').count('segments.date') == 1
1153
- and (components_values.get('query') | regex_search('(?i)(\\bSELECT\\b[\\s\\S]*?segments\\.date[\\s\\S]*?\\bFROM\\b)'))
1154
- )
1155
- or
1156
- (
1157
- components_values.get('query', '').count('segments.date') == 2
1158
- and (components_values.get('query') | regex_search('(?i)(\\bSELECT\\b[\\s\\S]*?segments\\.date[\\s\\S]*?\\bFROM\\b)'))
1159
- and (components_values.get('query') | regex_search('(?i)(\\bORDER\\s+BY\\b[\\s\\S]*?segments\\.date)'))
1160
- )
1161
- ) and components_values.get('query', '') | regex_search('(?i)(\\bFROM\\s+click_view\\b)')
1162
- }}
1163
- create_or_update: true
1164
- - type: ComponentMappingDefinition
1165
- field_path:
1166
- - retriever
1167
- - requester
1168
- - $parameters
1169
- - query
1170
- value: "{{ components_values.get('query', None) }}"
1171
- create_or_update: true
1172
1088
  - type: ComponentMappingDefinition
1173
1089
  field_path:
1174
1090
  - retriever
@@ -34,6 +34,12 @@ class SourceGoogleAds(YamlDeclarativeSource):
34
34
  config["customer_ids"] = config["customer_id"].split(",")
35
35
  config.pop("customer_id")
36
36
 
37
+ # Replace tabs with spaces in custom queries to prevent YAML parsing errors
38
+ if "custom_queries_array" in config:
39
+ for query_config in config["custom_queries_array"]:
40
+ if "query" in query_config and isinstance(query_config["query"], str):
41
+ query_config["query"] = query_config["query"].replace("\t", " ")
42
+
37
43
  return config
38
44
 
39
45
  def streams(self, config: Mapping[str, Any]) -> List[Stream]: