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

Conversation

ganpatagarwal
Copy link
Contributor

What

  • Currently, record types are hard coded in respective reports and doesn't provide user a way to selectively fetch specific record type(s)

How

*Adding an optional configuration option to read a list of selective report types from user. When the optional config is empty, it will fetch for all record types ( default behaviour )

Screenshot 2022-10-31 at 11 19 31 AM

Recommended reading order

  1. source_amazon_ads/spec.yaml
  2. source_amazon_ads/streams/report_streams/report_streams.py

🚨 User Impact 🚨

Not a breaking change

Pre-merge Checklist

Expand the relevant checklist and delete the others.

Updating a connector

Community member or Airbyter

  • Grant edit access to maintainers (instructions)
  • Secrets in the connector's spec are annotated with airbyte_secret
  • Unit & integration tests added and passing. Community members, please provide proof of success locally e.g: screenshot or copy-paste unit, integration, and acceptance test output. To run acceptance tests for a Python connector, follow instructions in the README. For java connectors run ./gradlew :airbyte-integrations:connectors:<name>:integrationTest.
  • Code reviews completed
  • Documentation updated
    • Connector's README.md
    • Connector's bootstrap.md. See description and examples
    • Changelog updated in docs/integrations/<source or destination>/<name>.md including changelog. See changelog example
  • PR name follows PR naming conventions

Airbyter

If this is a community PR, the Airbyte engineer reviewing this PR is responsible for the below items.

  • Create a non-forked branch based on this PR and test the below items on it
  • Build is successful
  • If new credentials are required for use in CI, add them to GSM. Instructions.
  • /test connector=connectors/<name> command is passing
  • New Connector version released on Dockerhub and connector version bumped by running the /publish command described here

Tests

Unit

Results (3.80s):
70 passed
Name Stmts Miss Cover Missing

source_amazon_ads/init.py 2 0 100%
source_amazon_ads/constants.py 1 0 100%
source_amazon_ads/schemas/init.py 7 0 100%
source_amazon_ads/schemas/attribution_report.py 21 0 100%
source_amazon_ads/schemas/common.py 51 1 98% 26
source_amazon_ads/schemas/profile.py 16 0 100%
source_amazon_ads/schemas/sponsored_brands.py 22 0 100%
source_amazon_ads/schemas/sponsored_display.py 31 0 100%
source_amazon_ads/schemas/sponsored_products.py 37 0 100%
source_amazon_ads/source.py 44 1 98% 129
source_amazon_ads/streams/init.py 7 0 100%
source_amazon_ads/streams/attribution_report.py 81 0 100%
source_amazon_ads/streams/common.py 79 1 99% 157
source_amazon_ads/streams/profiles.py 21 0 100%
source_amazon_ads/streams/report_streams/init.py 5 0 100%
source_amazon_ads/streams/report_streams/brands_report.py 10 0 100%
source_amazon_ads/streams/report_streams/brands_video_report.py 10 0 100%
source_amazon_ads/streams/report_streams/display_report.py 16 0 100%
source_amazon_ads/streams/report_streams/products_report.py 18 0 100%
source_amazon_ads/streams/report_streams/report_streams.py 243 19 92% 151, 204-205, 257-258, 380-381, 413-415, 420-421, 430-436
source_amazon_ads/streams/sponsored_brands.py 26 0 100%
source_amazon_ads/streams/sponsored_display.py 31 0 100%
source_amazon_ads/streams/sponsored_products.py 41 0 100%
source_amazon_ads/utils.py 9 0 100%
unit_tests/init.py 0 0 100%
unit_tests/conftest.py 37 0 100%
unit_tests/test_attribution_report.py 66 1 98% 47
unit_tests/test_report_streams.py 315 0 100%
unit_tests/test_source.py 47 0 100%
unit_tests/test_streams.py 126 1 99% 77
unit_tests/utils.py 32 0 100%

TOTAL 1452 24 98%

@monai monai self-assigned this Nov 7, 2022
@sajarin sajarin requested a review from monai November 7, 2022 15:12
@sajarin sajarin added the bounty-S Maintainer program: claimable small bounty PR label Nov 7, 2022
Copy link
Contributor

@monai monai left a comment

Choose a reason for hiding this comment

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

Thank you contribution. Overall the PR looks great, but I would like you to make a few improvements.

@@ -355,6 +356,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



@responses.activate
def test_display_report_stream_single_record_type(config_gen):
Copy link
Contributor

Choose a reason for hiding this comment

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

  1. Both tests are the same except for the custom_record_types parameter. Deduplicate code by using @pytest.mark.parametrize. See test_streams_state_filter for an example.

  2. Add two more test cases: custom_record_types = None and custom_record_types = ["invalid_record_type"] to make the test more exhaustive.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

sure, will do

stream = SponsoredDisplayReportStream(config_gen(report_record_types=custom_record_types), profiles, authenticator=mock.MagicMock())
stream_slice = {"profile": profiles[0], "reportDate": "20210725"}
metrics = [m for m in stream.read_records(SyncMode.incremental, stream_slice=stream_slice)]
assert len(metrics) == len(custom_record_types) * len(stream.metrics_map)
Copy link
Contributor

Choose a reason for hiding this comment

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

Assertion for the length doesn't ensure that the retrieved record types are the same as requested. Instead, assert whether the set of retrieved record["recordType"] is equal to the set of custom_record_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.

makes sense


stream = SponsoredDisplayReportStream(config_gen(report_record_types=custom_record_types), profiles, authenticator=mock.MagicMock())
stream_slice = {"profile": profiles[0], "reportDate": "20210725"}
metrics = [m for m in stream.read_records(SyncMode.incremental, stream_slice=stream_slice)]
Copy link
Contributor

Choose a reason for hiding this comment

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

a_list = list(generator) is a cleaner way to materialize a generator into a list.

Suggested change
metrics = [m for m in stream.read_records(SyncMode.incremental, stream_slice=stream_slice)]
metrics = list(stream.read_records(SyncMode.incremental, stream_slice=stream_slice))

order: 10
type: array
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.

@@ -612,3 +609,43 @@ 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

Copy link
Contributor Author

@ganpatagarwal ganpatagarwal left a comment

Choose a reason for hiding this comment

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

@monai PTAL

@@ -612,3 +609,43 @@ 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 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

@monai
Copy link
Contributor

monai commented Nov 15, 2022

Could you please refactor the spec input type to enum? See #18677 (comment)

@grubberr
Copy link
Contributor

grubberr commented Mar 2, 2023

/test connector=connectors/source-amazon-ads

🕑 connectors/source-amazon-ads https://github.com/airbytehq/airbyte/actions/runs/4312854605
❌ connectors/source-amazon-ads https://github.com/airbytehq/airbyte/actions/runs/4312854605
🐛 https://gradle.com/s/o35vdud5tvkek

Build Failed

Test summary info:

	 =========================== short test summary info ============================
	 FAILED unit_tests/test_report_streams.py::test_products_report_stream_with_custom_record_types[custom_record_types1-expected_record_types1-True]
	 FAILED unit_tests/test_report_streams.py::test_products_report_stream_with_custom_record_types[custom_record_types2-expected_record_types2-True]
	 �[31m================= �[31m�[1m2 failed�[0m, �[32m82 passed�[0m, �[33m1368 warnings�[0m�[31m in 6.57s�[0m�[31m ==================�[0m

@ganpatagarwal
Copy link
Contributor Author

@grubberr I have updated the tests as per new METRIC_RESPONSE value.

Please review again

@sh4sh
Copy link
Contributor

sh4sh commented Mar 7, 2023

/test connector=connectors/source-amazon-ads

🕑 connectors/source-amazon-ads https://github.com/airbytehq/airbyte/actions/runs/4358004236
✅ connectors/source-amazon-ads https://github.com/airbytehq/airbyte/actions/runs/4358004236
Python tests coverage:

Name                                                              Stmts   Miss  Cover
-------------------------------------------------------------------------------------
source_amazon_ads/utils.py                                           22      0   100%
source_amazon_ads/streams/sponsored_products.py                      41      0   100%
source_amazon_ads/streams/sponsored_display.py                       31      0   100%
source_amazon_ads/streams/sponsored_brands.py                        26      0   100%
source_amazon_ads/streams/report_streams/products_report.py          20      0   100%
source_amazon_ads/streams/report_streams/display_report.py           18      0   100%
source_amazon_ads/streams/report_streams/brands_video_report.py      12      0   100%
source_amazon_ads/streams/report_streams/brands_report.py            12      0   100%
source_amazon_ads/streams/report_streams/__init__.py                  5      0   100%
source_amazon_ads/streams/profiles.py                                21      0   100%
source_amazon_ads/streams/attribution_report.py                      81      0   100%
source_amazon_ads/streams/__init__.py                                 7      0   100%
source_amazon_ads/schemas/sponsored_products.py                      37      0   100%
source_amazon_ads/schemas/sponsored_display.py                       31      0   100%
source_amazon_ads/schemas/sponsored_brands.py                        22      0   100%
source_amazon_ads/schemas/profile.py                                 16      0   100%
source_amazon_ads/schemas/attribution_report.py                      21      0   100%
source_amazon_ads/schemas/__init__.py                                 7      0   100%
source_amazon_ads/constants.py                                        1      0   100%
source_amazon_ads/__init__.py                                         2      0   100%
source_amazon_ads/schemas/common.py                                  50      1    98%
source_amazon_ads/source.py                                          47      1    98%
source_amazon_ads/streams/common.py                                  83      2    98%
source_amazon_ads/streams/report_streams/report_streams.py          246     19    92%
-------------------------------------------------------------------------------------
TOTAL                                                               859     23    97%

Build Passed

Test summary info:

=========================== short test summary info ============================
SKIPPED [1] ../usr/local/lib/python3.9/site-packages/connector_acceptance_test/tests/test_core.py:509: The previous and actual discovered catalogs are identical.
================== 37 passed, 1 skipped in 484.93s (0:08:04) ===================

@grubberr
Copy link
Contributor

grubberr commented Mar 10, 2023

/test connector=connectors/source-amazon-ads

🕑 connectors/source-amazon-ads https://github.com/airbytehq/airbyte/actions/runs/4384003202
✅ connectors/source-amazon-ads https://github.com/airbytehq/airbyte/actions/runs/4384003202
Python tests coverage:

Name                                                              Stmts   Miss  Cover
-------------------------------------------------------------------------------------
source_amazon_ads/utils.py                                           22      0   100%
source_amazon_ads/streams/sponsored_products.py                      41      0   100%
source_amazon_ads/streams/sponsored_display.py                       31      0   100%
source_amazon_ads/streams/sponsored_brands.py                        26      0   100%
source_amazon_ads/streams/report_streams/products_report.py          20      0   100%
source_amazon_ads/streams/report_streams/display_report.py           18      0   100%
source_amazon_ads/streams/report_streams/brands_video_report.py      12      0   100%
source_amazon_ads/streams/report_streams/brands_report.py            12      0   100%
source_amazon_ads/streams/report_streams/__init__.py                  5      0   100%
source_amazon_ads/streams/profiles.py                                21      0   100%
source_amazon_ads/streams/attribution_report.py                      81      0   100%
source_amazon_ads/streams/__init__.py                                 7      0   100%
source_amazon_ads/schemas/sponsored_products.py                      37      0   100%
source_amazon_ads/schemas/sponsored_display.py                       31      0   100%
source_amazon_ads/schemas/sponsored_brands.py                        22      0   100%
source_amazon_ads/schemas/profile.py                                 16      0   100%
source_amazon_ads/schemas/attribution_report.py                      21      0   100%
source_amazon_ads/schemas/__init__.py                                 7      0   100%
source_amazon_ads/constants.py                                        1      0   100%
source_amazon_ads/__init__.py                                         2      0   100%
source_amazon_ads/schemas/common.py                                  50      1    98%
source_amazon_ads/source.py                                          47      1    98%
source_amazon_ads/streams/common.py                                  83      2    98%
source_amazon_ads/streams/report_streams/report_streams.py          246     19    92%
-------------------------------------------------------------------------------------
TOTAL                                                               859     23    97%

Build Passed

Test summary info:

=========================== short test summary info ============================
SKIPPED [1] ../usr/local/lib/python3.9/site-packages/connector_acceptance_test/tests/test_core.py:509: The previous and actual discovered catalogs are identical.
================== 37 passed, 1 skipped in 473.59s (0:07:53) ===================

@grubberr
Copy link
Contributor

grubberr commented Mar 10, 2023

/test connector=connectors/source-amazon-ads

🕑 connectors/source-amazon-ads https://github.com/airbytehq/airbyte/actions/runs/4384742923
✅ connectors/source-amazon-ads https://github.com/airbytehq/airbyte/actions/runs/4384742923
Python tests coverage:

Name                                                              Stmts   Miss  Cover
-------------------------------------------------------------------------------------
source_amazon_ads/utils.py                                           22      0   100%
source_amazon_ads/streams/sponsored_products.py                      41      0   100%
source_amazon_ads/streams/sponsored_display.py                       31      0   100%
source_amazon_ads/streams/sponsored_brands.py                        26      0   100%
source_amazon_ads/streams/report_streams/products_report.py          20      0   100%
source_amazon_ads/streams/report_streams/display_report.py           18      0   100%
source_amazon_ads/streams/report_streams/brands_video_report.py      12      0   100%
source_amazon_ads/streams/report_streams/brands_report.py            12      0   100%
source_amazon_ads/streams/report_streams/__init__.py                  5      0   100%
source_amazon_ads/streams/profiles.py                                21      0   100%
source_amazon_ads/streams/attribution_report.py                      81      0   100%
source_amazon_ads/streams/__init__.py                                 7      0   100%
source_amazon_ads/schemas/sponsored_products.py                      37      0   100%
source_amazon_ads/schemas/sponsored_display.py                       31      0   100%
source_amazon_ads/schemas/sponsored_brands.py                        22      0   100%
source_amazon_ads/schemas/profile.py                                 16      0   100%
source_amazon_ads/schemas/attribution_report.py                      21      0   100%
source_amazon_ads/schemas/__init__.py                                 7      0   100%
source_amazon_ads/constants.py                                        1      0   100%
source_amazon_ads/__init__.py                                         2      0   100%
source_amazon_ads/schemas/common.py                                  50      1    98%
source_amazon_ads/source.py                                          48      1    98%
source_amazon_ads/streams/common.py                                  83      2    98%
source_amazon_ads/streams/report_streams/report_streams.py          246     19    92%
-------------------------------------------------------------------------------------
TOTAL                                                               860     23    97%

Build Passed

Test summary info:

=========================== short test summary info ============================
SKIPPED [1] ../usr/local/lib/python3.9/site-packages/connector_acceptance_test/tests/test_core.py:509: The previous and actual discovered catalogs are identical.
================== 37 passed, 1 skipped in 486.33s (0:08:06) ===================

@ganpatagarwal
Copy link
Contributor Author

@marcosmarxm @natalyjazzviolin

Please help in merging this PR.

Thanks !!

@marcosmarxm
Copy link
Member

marcosmarxm commented Mar 14, 2023

/publish connector=connectors/source-amazon-ads

🕑 Publishing the following connectors:
connectors/source-amazon-ads
https://github.com/airbytehq/airbyte/actions/runs/4418720211


Connector Did it publish? Were definitions generated?
connectors/source-amazon-ads

if you have connectors that successfully published but failed definition generation, follow step 4 here ▶️

@marcosmarxm marcosmarxm merged commit 2b81405 into airbytehq:master Mar 14, 2023
32 of 39 checks passed
@ganpatagarwal ganpatagarwal deleted the amazon-ads-1 branch March 15, 2023 09:22
adriennevermorel pushed a commit to adriennevermorel/airbyte that referenced this pull request Mar 17, 2023
…ehq#18677)

* use optional config report_record_types

* update spec

* update image version

* update

* correct indentation

* remove lint changes

* add tests for sponsored products report

* update spec

* add test for video report

* increment amazon-ads connector version

* add test_strictness_level as high

* gradle format update

* update

* update tests for new METRIC_RESPONSE

* align validation and transformation

* bump connector version

* auto-bump connector version

---------

Co-authored-by: Juozas V <monai@cure.lt>
Co-authored-by: Sajarin <sajarindider@gmail.com>
Co-authored-by: Nataly Merezhuk <65251165+natalyjazzviolin@users.noreply.github.com>
Co-authored-by: Serhii Chvaliuk <grubberr@gmail.com>
Co-authored-by: sh4sh <6833405+sh4sh@users.noreply.github.com>
Co-authored-by: marcosmarxm <marcosmarxm@gmail.com>
Co-authored-by: Octavia Squidington III <octavia-squidington-iii@users.noreply.github.com>
erohmensing pushed a commit that referenced this pull request Mar 22, 2023
* use optional config report_record_types

* update spec

* update image version

* update

* correct indentation

* remove lint changes

* add tests for sponsored products report

* update spec

* add test for video report

* increment amazon-ads connector version

* add test_strictness_level as high

* gradle format update

* update

* update tests for new METRIC_RESPONSE

* align validation and transformation

* bump connector version

* auto-bump connector version

---------

Co-authored-by: Juozas V <monai@cure.lt>
Co-authored-by: Sajarin <sajarindider@gmail.com>
Co-authored-by: Nataly Merezhuk <65251165+natalyjazzviolin@users.noreply.github.com>
Co-authored-by: Serhii Chvaliuk <grubberr@gmail.com>
Co-authored-by: sh4sh <6833405+sh4sh@users.noreply.github.com>
Co-authored-by: marcosmarxm <marcosmarxm@gmail.com>
Co-authored-by: Octavia Squidington III <octavia-squidington-iii@users.noreply.github.com>
erohmensing pushed a commit that referenced this pull request Mar 22, 2023
* use optional config report_record_types

* update spec

* update image version

* update

* correct indentation

* remove lint changes

* add tests for sponsored products report

* update spec

* add test for video report

* increment amazon-ads connector version

* add test_strictness_level as high

* gradle format update

* update

* update tests for new METRIC_RESPONSE

* align validation and transformation

* bump connector version

* auto-bump connector version

---------

Co-authored-by: Juozas V <monai@cure.lt>
Co-authored-by: Sajarin <sajarindider@gmail.com>
Co-authored-by: Nataly Merezhuk <65251165+natalyjazzviolin@users.noreply.github.com>
Co-authored-by: Serhii Chvaliuk <grubberr@gmail.com>
Co-authored-by: sh4sh <6833405+sh4sh@users.noreply.github.com>
Co-authored-by: marcosmarxm <marcosmarxm@gmail.com>
Co-authored-by: Octavia Squidington III <octavia-squidington-iii@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/connectors Connector related issues area/documentation Improvements or additions to documentation bounty bounty-S Maintainer program: claimable small bounty PR community connectors/source/amazon-ads team/connectors-python
Projects
Development

Successfully merging this pull request may close these issues.

None yet

10 participants