Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# Changelog

# 2.3.4
[#132](https://github.com/singer-io/tap-bing-ads/pull/132)
* Bump bingads from 13.0.11.1 to 13.0.28
* Fix a bug in complex_type parsing
* Update error handling to raise human readable message if it exists
* Update tests to use env vars for test account info

# 2.3.3
* Bump requests to 2.33.0 for security updates [#127](https://github.com/singer-io/tap-bing-ads/pull/127)

Expand Down
4 changes: 2 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

setup(
name='tap-bing-ads',
version="2.3.3",
version="2.3.4",
description='Singer.io tap for extracting data from the Bing Ads API',
author='Stitch',
url='http://singer.io',
Expand All @@ -14,7 +14,7 @@
'arrow==0.17.0',
# Seems that suds-community is now the reference for 13.0.11.1 so we can install it now with the removal of use_2to3
# https://github.com/BingAds/BingAds-Python-SDK/pull/192
'bingads==13.0.11.1',
'bingads==13.0.28',
'requests==2.33.0',
'singer-python==6.0.1',
'backoff==2.2.1',
Expand Down
34 changes: 28 additions & 6 deletions tap_bing_ads/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,16 @@ def get_user_agent():
class InvalidDateRangeEnd(Exception):
pass

def fault_messages_or_default(errors, default):
"""
Extract the human-readable Message(s) from a SOAP fault's error object(s),
falling back to the raw error object when no Message is present.
"""
if not isinstance(errors, list):
errors = [errors]
messages = [error.Message for error in errors if getattr(error, 'Message', None)]
return ', '.join(messages) if messages else default

def log_service_call(service_method, account_id):
def wrapper(*args, **kwargs): # pylint: disable=inconsistent-return-statements
log_args = list(map(lambda arg: str(arg).replace('\n', '\\n'), args)) + list(map(lambda kv: '{}={}'.format(*kv), kwargs.items()))
Expand All @@ -115,9 +125,17 @@ def wrapper(*args, **kwargs): # pylint: disable=inconsistent-return-statements
if any(invalid_date_range_end_errors):
raise InvalidDateRangeEnd(invalid_date_range_end_errors) from e
LOGGER.info('Caught exception for account: %s', account_id)
raise Exception(operation_errors) from e
raise Exception(fault_messages_or_default(
[oe for (_, oe) in operation_errors], operation_errors)) from e
if hasattr(e.fault.detail, 'AdApiFaultDetail'):
raise Exception(e.fault.detail.AdApiFaultDetail.Errors) from e
errors = e.fault.detail.AdApiFaultDetail.Errors
raise Exception(fault_messages_or_default(
errors.AdApiError, errors)) from e
if hasattr(e.fault.detail, 'ApiFault'):
operation_errors = e.fault.detail.ApiFault.OperationErrors
raise Exception(fault_messages_or_default(
operation_errors.OperationError, operation_errors)) from e
raise

return wrapper

Expand Down Expand Up @@ -277,20 +295,24 @@ def get_array_type(array_type):
return array_obj

def get_complex_type_elements(inherited_types, wsdl_type):
content = wsdl_type.rawchildren[0].rawchildren
## complexType with no child elements (e.g. empty *ReportFilter types)
if not content:
return []
## inherited type
if isinstance(wsdl_type.rawchildren[0].rawchildren[0], suds.xsd.sxbasic.Extension): # pylint: disable=no-else-return
abstract_base = wsdl_type.rawchildren[0].rawchildren[0].ref[0]
if isinstance(content[0], suds.xsd.sxbasic.Extension): # pylint: disable=no-else-return
abstract_base = content[0].ref[0]
if abstract_base not in inherited_types:
inherited_types[abstract_base] = set()
inherited_types[abstract_base].add(wsdl_type.name)

elements = []
for element_group in wsdl_type.rawchildren[0].rawchildren[0].rawchildren:
for element_group in content[0].rawchildren:
for element in element_group:
elements.append(element[0])
return elements
else:
return wsdl_type.rawchildren[0].rawchildren
return content

def wsdl_type_to_schema(inherited_types, wsdl_type):
#Prepare schema from wsdl file
Expand Down
4 changes: 2 additions & 2 deletions tests/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,8 @@ def get_properties(self, original: bool = True):
return_value = {
# 'start_date': '2020-10-01T00:00:00Z', # original start_date
'start_date': self.start_date,
'customer_id': '163875182',
'account_ids': '163078754,140168565,71086605',
'customer_id': os.getenv('TAP_BING_ADS_CUSTOMER_ID'),
'account_ids': os.getenv('TAP_BING_ADS_ACCOUNT_IDS'),
# 'conversion_window': '-15', # advanced option
}
# cid=42183085 aid=71086605 uid=71069166 (RJMetrics)
Expand Down
4 changes: 2 additions & 2 deletions tests/base_new_framework.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ def get_properties(self):
"""Configuration properties required for the tap."""
return_value = {
'start_date': self.start_date,
'customer_id': '163875182',
'account_ids': '163078754,140168565,71086605',
'customer_id': os.getenv('TAP_BING_ADS_CUSTOMER_ID'),
'account_ids': os.getenv('TAP_BING_ADS_ACCOUNT_IDS'),
# 'conversion_window': '-15', # advanced option
}
# cid=42183085 aid=71086605 uid=71069166 (RJMetrics)
Expand Down