airbyte-source-google-ads 4.1.4__tar.gz → 4.1.4.dev202511261224__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.
- {airbyte_source_google_ads-4.1.4 → airbyte_source_google_ads-4.1.4.dev202511261224}/PKG-INFO +2 -2
- {airbyte_source_google_ads-4.1.4 → airbyte_source_google_ads-4.1.4.dev202511261224}/pyproject.toml +2 -2
- {airbyte_source_google_ads-4.1.4 → airbyte_source_google_ads-4.1.4.dev202511261224}/source_google_ads/components.py +0 -12
- {airbyte_source_google_ads-4.1.4 → airbyte_source_google_ads-4.1.4.dev202511261224}/source_google_ads/manifest.yaml +45 -129
- {airbyte_source_google_ads-4.1.4 → airbyte_source_google_ads-4.1.4.dev202511261224}/source_google_ads/source.py +6 -0
- {airbyte_source_google_ads-4.1.4 → airbyte_source_google_ads-4.1.4.dev202511261224}/README.md +0 -0
- {airbyte_source_google_ads-4.1.4 → airbyte_source_google_ads-4.1.4.dev202511261224}/source_google_ads/__init__.py +0 -0
- {airbyte_source_google_ads-4.1.4 → airbyte_source_google_ads-4.1.4.dev202511261224}/source_google_ads/config_migrations.py +0 -0
- {airbyte_source_google_ads-4.1.4 → airbyte_source_google_ads-4.1.4.dev202511261224}/source_google_ads/google_ads.py +0 -0
- {airbyte_source_google_ads-4.1.4 → airbyte_source_google_ads-4.1.4.dev202511261224}/source_google_ads/models.py +0 -0
- {airbyte_source_google_ads-4.1.4 → airbyte_source_google_ads-4.1.4.dev202511261224}/source_google_ads/run.py +0 -0
- {airbyte_source_google_ads-4.1.4 → airbyte_source_google_ads-4.1.4.dev202511261224}/source_google_ads/schemas/customer_client.json +0 -0
- {airbyte_source_google_ads-4.1.4 → airbyte_source_google_ads-4.1.4.dev202511261224}/source_google_ads/schemas/service_accounts.json +0 -0
- {airbyte_source_google_ads-4.1.4 → airbyte_source_google_ads-4.1.4.dev202511261224}/source_google_ads/spec.json +0 -0
- {airbyte_source_google_ads-4.1.4 → airbyte_source_google_ads-4.1.4.dev202511261224}/source_google_ads/streams.py +0 -0
- {airbyte_source_google_ads-4.1.4 → airbyte_source_google_ads-4.1.4.dev202511261224}/source_google_ads/utils.py +0 -0
{airbyte_source_google_ads-4.1.4 → airbyte_source_google_ads-4.1.4.dev202511261224}/PKG-INFO
RENAMED
|
@@ -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.
|
|
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)
|
{airbyte_source_google_ads-4.1.4 → airbyte_source_google_ads-4.1.4.dev202511261224}/pyproject.toml
RENAMED
|
@@ -3,7 +3,7 @@ requires = [ "poetry-core>=1.0.0",]
|
|
|
3
3
|
build-backend = "poetry.core.masonry.api"
|
|
4
4
|
|
|
5
5
|
[tool.poetry]
|
|
6
|
-
version = "4.1.4"
|
|
6
|
+
version = "4.1.4.dev.202511261224"
|
|
7
7
|
name = "airbyte-source-google-ads"
|
|
8
8
|
description = "Source implementation for Google Ads."
|
|
9
9
|
authors = [ "Airbyte <contact@airbyte.io>",]
|
|
@@ -20,7 +20,7 @@ python = "^3.10,<3.12"
|
|
|
20
20
|
google-ads = "==27.0.0"
|
|
21
21
|
protobuf = "==4.25.2"
|
|
22
22
|
pendulum = "<3.0.0"
|
|
23
|
-
airbyte-cdk = "^7.
|
|
23
|
+
airbyte-cdk = "^7.4.1"
|
|
24
24
|
|
|
25
25
|
[tool.poetry.scripts]
|
|
26
26
|
source-google-ads = "source_google_ads.run:run"
|
|
@@ -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:
|
|
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:
|
|
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:
|
|
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:
|
|
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]:
|
{airbyte_source_google_ads-4.1.4 → airbyte_source_google_ads-4.1.4.dev202511261224}/README.md
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
|