Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

🎉 Source Amazon Ads : use optional config report_record_types #18677

Merged
merged 66 commits into from Mar 14, 2023
Merged
Show file tree
Hide file tree
Changes from 62 commits
Commits
Show all changes
66 commits
Select commit Hold shift + click to select a range
4ea218d
use optional config report_record_types
ganpatagarwal Oct 31, 2022
4dc3df5
update spec
ganpatagarwal Oct 31, 2022
5a57c67
update image version
ganpatagarwal Oct 31, 2022
b559c1a
Merge branch 'master' of https://github.com/airbytehq/airbyte into am…
ganpatagarwal Nov 1, 2022
ddfc8d5
Merge branch 'master' of https://github.com/airbytehq/airbyte into am…
ganpatagarwal Nov 3, 2022
b14a827
Merge branch 'master' of https://github.com/airbytehq/airbyte into am…
ganpatagarwal Nov 4, 2022
5b3261f
Merge branch 'master' of https://github.com/airbytehq/airbyte into am…
ganpatagarwal Nov 6, 2022
559447c
Merge branch 'master' into amazon-ads-1
monai Nov 7, 2022
f1c0628
Merge branch 'master' into amazon-ads-1
sajarin Nov 7, 2022
e080398
Merge branch 'master' of https://github.com/airbytehq/airbyte into am…
ganpatagarwal Nov 11, 2022
18b28dc
update
ganpatagarwal Nov 11, 2022
8367e32
correct indentation
ganpatagarwal Nov 11, 2022
8b919dc
remove lint changes
ganpatagarwal Nov 11, 2022
a601922
Merge branch 'master' of https://github.com/airbytehq/airbyte into am…
ganpatagarwal Nov 11, 2022
bf3a425
Merge branch 'master' of https://github.com/airbytehq/airbyte into am…
ganpatagarwal Nov 14, 2022
995c78f
Merge branch 'master' of https://github.com/airbytehq/airbyte into am…
ganpatagarwal Nov 14, 2022
3c5fdb9
add tests for sponsored products report
ganpatagarwal Nov 14, 2022
ab8a412
Merge branch 'master' of https://github.com/airbytehq/airbyte into am…
ganpatagarwal Nov 14, 2022
f1876a0
Merge branch 'master' of https://github.com/airbytehq/airbyte into am…
ganpatagarwal Nov 15, 2022
838de4d
update spec
ganpatagarwal Nov 15, 2022
6b28639
add test for video report
ganpatagarwal Nov 15, 2022
0df73da
Merge branch 'master' of https://github.com/airbytehq/airbyte into am…
ganpatagarwal Nov 16, 2022
ab77c36
Merge branch 'master' of https://github.com/airbytehq/airbyte into am…
ganpatagarwal Nov 16, 2022
a5d0b43
increment amazon-ads connector version
ganpatagarwal Nov 16, 2022
e1815da
Merge branch 'master' into amazon-ads-1
ganpatagarwal Nov 17, 2022
587e4e2
Merge branch 'master' into amazon-ads-1
ganpatagarwal Nov 18, 2022
81155bf
Merge branch 'master' of https://github.com/airbytehq/airbyte into am…
ganpatagarwal Nov 18, 2022
c2551c8
Merge branch 'amazon-ads-1' of https://github.com/ganpatagarwal/airby…
ganpatagarwal Nov 18, 2022
465920c
Merge branch 'master' of https://github.com/airbytehq/airbyte into am…
ganpatagarwal Nov 21, 2022
e73ae2e
add test_strictness_level as high
ganpatagarwal Nov 21, 2022
68cfe5e
Merge branch 'master' into amazon-ads-1
monai Nov 22, 2022
fc00a4c
gradle format update
ganpatagarwal Nov 22, 2022
e6a4720
Merge branch 'master' into amazon-ads-1
monai Nov 23, 2022
f9ec87c
Merge branch 'master' into amazon-ads-1
ganpatagarwal Nov 28, 2022
a9eb708
Merge branch 'master' into amazon-ads-1
ganpatagarwal Nov 30, 2022
141f49b
Merge branch 'master' into amazon-ads-1
ganpatagarwal Dec 5, 2022
15f7864
Merge branch 'master' into amazon-ads-1
ganpatagarwal Dec 10, 2022
549eece
Merge branch 'master' into amazon-ads-1
ganpatagarwal Dec 13, 2022
6d3158a
Merge branch 'master' into amazon-ads-1
ganpatagarwal Dec 20, 2022
bee8928
Merge branch 'master' of https://github.com/airbytehq/airbyte into am…
ganpatagarwal Jan 6, 2023
c87573c
Merge branch 'amazon-ads-1' of https://github.com/ganpatagarwal/airby…
ganpatagarwal Jan 6, 2023
641dca2
Merge branch 'master' of https://github.com/airbytehq/airbyte into am…
ganpatagarwal Jan 8, 2023
64ec3a6
Merge branch 'master' of https://github.com/airbytehq/airbyte into am…
ganpatagarwal Jan 14, 2023
eb13adb
Merge branch 'master' of https://github.com/airbytehq/airbyte into am…
ganpatagarwal Jan 24, 2023
da68abe
Merge branch 'master' of https://github.com/airbytehq/airbyte into am…
ganpatagarwal Jan 30, 2023
e62c6ec
Merge branch 'master' of https://github.com/airbytehq/airbyte into am…
ganpatagarwal Jan 31, 2023
4f95353
Merge branch 'master' of https://github.com/airbytehq/airbyte into am…
ganpatagarwal Jan 31, 2023
45aba9d
Merge branch 'master' of https://github.com/airbytehq/airbyte into am…
ganpatagarwal Feb 1, 2023
976e009
update
ganpatagarwal Feb 1, 2023
e80a2e5
Merge branch 'master' of https://github.com/airbytehq/airbyte into am…
ganpatagarwal Feb 8, 2023
7a5be40
Merge branch 'master' of https://github.com/airbytehq/airbyte into am…
ganpatagarwal Feb 13, 2023
98d7011
Merge branch 'master' of https://github.com/airbytehq/airbyte into am…
ganpatagarwal Feb 22, 2023
d931d57
Merge branch 'master' into amazon-ads-1
natalyjazzviolin Mar 1, 2023
45117c7
Merge branch 'master' of https://github.com/airbytehq/airbyte into am…
ganpatagarwal Mar 2, 2023
ca1a104
Merge branch 'master' into amazon-ads-1
grubberr Mar 2, 2023
3ed9aa0
Merge branch 'master' of https://github.com/airbytehq/airbyte into am…
ganpatagarwal Mar 2, 2023
eb2c393
update tests for new METRIC_RESPONSE
ganpatagarwal Mar 2, 2023
8a0cf6e
Merge branch 'amazon-ads-1' of https://github.com/ganpatagarwal/airby…
ganpatagarwal Mar 2, 2023
88569f6
Merge branch 'master' of https://github.com/airbytehq/airbyte into am…
ganpatagarwal Mar 3, 2023
6ff35e0
Merge branch 'master' of https://github.com/airbytehq/airbyte into am…
ganpatagarwal Mar 4, 2023
a9efcb9
Merge branch 'master' into amazon-ads-1
sh4sh Mar 7, 2023
baeff65
Merge branch 'master' into amazon-ads-1
grubberr Mar 10, 2023
6c190c5
align validation and transformation
ganpatagarwal Mar 10, 2023
fa5ece1
Merge branch 'master' into amazon-ads-1
ganpatagarwal Mar 14, 2023
c83c309
bump connector version
marcosmarxm Mar 14, 2023
8d5ca20
auto-bump connector version
octavia-squidington-iii Mar 14, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -72,6 +72,26 @@
"examples": [3, 10],
"order": 8,
"type": "integer"
},
"report_record_types": {
"title": "Report Record Types",
"description": "Optional configuration which accepts an array of string of record types. Leave blank for default behaviour to pull all report types. Use this config option only if you want to pull specific report type(s). See <a href=\"https://advertising.amazon.com/API/docs/en-us/reporting/v2/report-types\">docs</a> for more details",
"items": {
"type": "string",
"enum": [
"adGroups",
"asins",
"asins_keywords",
"asins_targets",
"campaigns",
"keywords",
"productAds",
"targets"
]
},
"type": "array",
"uniqueItems": true,
"order": 9
}
},
"required": ["client_id", "client_secret", "refresh_token"],
Expand Down
Expand Up @@ -86,6 +86,28 @@ connectionSpecification:
type: "integer"
default: 3
order: 8
report_record_types:
title: Report Record Types
description:
Optional configuration which accepts an array of string of record types.
Leave blank for default behaviour to pull all report types.
Use this config option only if you want to pull specific report type(s).
See <a href="https://advertising.amazon.com/API/docs/en-us/reporting/v2/report-types">docs</a>
for more details
items:
type: string
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Make it enum just like state_filter. Then, it will be easier for the users to pick predefined values from the list and prevent them from entering invalid ones.

NB! There are asins_keywords and asins_targets for Sponsored Products. Make sure that they both work. Add test cases for asins, asins_keywords, and asins_targets.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

since all report types are not supported by each category of reports, making them enum doesn't make sense.

Also, this would be an optional config option, just like profiles

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now, any value can be entered, even nonexistent in any report type. Enum would limit possible values to those that exist at least in one report type. Anyway, your code now ignores invalid values so that nothing would change on the code side.

enum:
- adGroups
- asins
- asins_keywords
- asins_targets
- campaigns
- keywords
- productAds
- targets
type: array
uniqueItems: true
order: 9
required:
- client_id
- client_secret
Expand Down
Expand Up @@ -122,6 +122,8 @@ def __init__(self, config: Mapping[str, Any], profiles: List[Profile], authentic
# Maximum retries Airbyte will attempt for fetching report data. Default is 5.
self.report_generation_maximum_retries: int = get_typed_env("REPORT_GENERATION_MAX_RETRIES", 5)

self._report_record_types = config.get("report_record_types", [])
ganpatagarwal marked this conversation as resolved.
Show resolved Hide resolved

@property
def model(self) -> CatalogModel:
return self._model
Expand Down Expand Up @@ -364,6 +366,9 @@ def _init_reports(self, profile: Profile, report_date: str) -> List[ReportInfo]:
"""
report_infos = []
for record_type, metrics in self.metrics_map.items():
if len(self._report_record_types) > 0 and record_type not in self._report_record_types:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if len(self._report_record_types) > 0 and record_type not in self._report_record_types:
if record_type not in self._report_record_types:

When self._report_record_types is an empty array, which is by default, not in will return True for any value.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's on and condition. If array is empty, the complete condition would always be false

continue

report_init_body = self._get_init_report_body(report_date, record_type, profile)
if not report_init_body:
continue
Expand Down
Expand Up @@ -486,7 +486,6 @@ def test_read_incremental_with_records(config):
stream = SponsoredDisplayReportStream(config, profiles, authenticator=mock.MagicMock())

with freeze_time("2021-01-02 12:00:00") as frozen_datetime:

state = {}
records = list(read_incremental(stream, state))
assert state == {"1": {"reportDate": "20210102"}}
Expand Down Expand Up @@ -531,7 +530,6 @@ def test_read_incremental_without_records_start_date(config):
stream = SponsoredDisplayReportStream(config, profiles, authenticator=mock.MagicMock())

with freeze_time("2021-01-02 12:00:00") as frozen_datetime:

state = {}
reportDates = ["20201231", "20210101", "20210102", "20210103", "20210104"]
for reportDate in reportDates:
Expand All @@ -554,7 +552,6 @@ def test_read_incremental_with_records_start_date(config):
stream = SponsoredDisplayReportStream(config, profiles, authenticator=mock.MagicMock())

with freeze_time("2021-01-02 12:00:00") as frozen_datetime:

state = {}
records = list(read_incremental(stream, state))

Expand Down Expand Up @@ -643,3 +640,148 @@ def test_streams_state_filter(mocker, config, state_filter, stream_class):
assert params["stateFilter"] == ",".join(state_filter)
else:
assert state_filter is None


@responses.activate
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a test for Sponsored Products report and asins_keywords and asins_targets record types. They're treated differently than other types.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have added tests. Please review

@pytest.mark.parametrize(
"custom_record_types, flag_match_error",
[
(
["campaigns"],
True
),
(
["campaigns", "adGroups"],
True
),
(
[],
False
),
(
["invalid_record_type"],
True
)
]
)
def test_display_report_stream_with_custom_record_types(config_gen, custom_record_types, flag_match_error):
setup_responses(
init_response=REPORT_INIT_RESPONSE,
status_response=REPORT_STATUS_RESPONSE,
metric_response=METRIC_RESPONSE,
)

profiles = make_profiles()

stream = SponsoredDisplayReportStream(config_gen(report_record_types=custom_record_types), profiles, authenticator=mock.MagicMock())
stream_slice = {"profile": profiles[0], "reportDate": "20210725"}
records = list(stream.read_records(SyncMode.incremental, stream_slice=stream_slice))
for record in records:
if record['recordType'] not in custom_record_types:
if flag_match_error:
assert False


@responses.activate
@pytest.mark.parametrize(
"custom_record_types, expected_record_types, flag_match_error",
[
(
["campaigns"],
["campaigns"],
True
),
(
["asins_keywords"],
["asins_keywords"],
True
),
(
["asins_targets"],
["asins_targets"],
True
),
(
["campaigns", "adGroups"],
["campaigns", "adGroups"],
True
),
(
[],
[],
False
),
(
["invalid_record_type"],
[],
True
)
]
)
def test_products_report_stream_with_custom_record_types(config_gen, custom_record_types, expected_record_types, flag_match_error):
setup_responses(
init_response_products=REPORT_INIT_RESPONSE,
status_response=REPORT_STATUS_RESPONSE,
metric_response=METRIC_RESPONSE,
)

profiles = make_profiles(profile_type="vendor")

stream = SponsoredProductsReportStream(config_gen(report_record_types=custom_record_types), profiles, authenticator=mock.MagicMock())
stream_slice = {"profile": profiles[0], "reportDate": "20210725", "retry_count": 3}
records = list(stream.read_records(SyncMode.incremental, stream_slice=stream_slice))
for record in records:
print(record)
if record['recordType'] not in expected_record_types:
if flag_match_error:
assert False


@responses.activate
@pytest.mark.parametrize(
"custom_record_types, expected_record_types, flag_match_error",
[
(
["campaigns"],
["campaigns"],
True
),
(
["asins"],
["asins"],
True
),
(
["campaigns", "adGroups"],
["campaigns", "adGroups"],
True
),
(
[],
[],
False
),
(
["invalid_record_type"],
[],
True
)
]
)
def test_brands_video_report_with_custom_record_types(config_gen, custom_record_types, expected_record_types, flag_match_error):
setup_responses(
init_response_brands=REPORT_INIT_RESPONSE,
status_response=REPORT_STATUS_RESPONSE,
metric_response=METRIC_RESPONSE,
)

profiles = make_profiles()

stream = SponsoredBrandsVideoReportStream(config_gen(report_record_types=custom_record_types), profiles, authenticator=mock.MagicMock())
stream_slice = {"profile": profiles[0], "reportDate": "20210725"}
records = list(stream.read_records(SyncMode.incremental, stream_slice=stream_slice))
for record in records:
print(record)
if record['recordType'] not in expected_record_types:
if flag_match_error:
assert False
1 change: 1 addition & 0 deletions docs/integrations/sources/amazon-ads.md
Expand Up @@ -94,6 +94,7 @@ Information about expected report generation waiting time you may find [here](ht

| Version | Date | Pull Request | Subject |
|:--------|:-----------|:---------------------------------------------------------|:----------------------------------------------------------------------------------------------------------------|
| 1.0.1 | 2022-11-01 | [18677](https://github.com/airbytehq/airbyte/pull/18677) | Add optional config report_record_types |
| 1.0.0 | 2023-01-30 | [21677](https://github.com/airbytehq/airbyte/pull/21677) | Fix bug with non-unique primary keys in report streams. Add asins_keywords and asins_targets |
| 0.1.29 | 2023-01-27 | [22038](https://github.com/airbytehq/airbyte/pull/22038) | Set `AvailabilityStrategy` for streams explicitly to `None` |
| 0.1.28 | 2023-01-18 | [19491](https://github.com/airbytehq/airbyte/pull/19491) | Add option to customize look back window value |
Expand Down