diff --git a/airbyte_cdk/sources/declarative/resolvers/config_components_resolver.py b/airbyte_cdk/sources/declarative/resolvers/config_components_resolver.py index 949b987db..f4ce80aba 100644 --- a/airbyte_cdk/sources/declarative/resolvers/config_components_resolver.py +++ b/airbyte_cdk/sources/declarative/resolvers/config_components_resolver.py @@ -204,8 +204,10 @@ def _parse_yaml_if_possible(value: Any) -> Any: return yaml.safe_load(value) except ParserError: # "{{ record[0] in ['cohortActiveUsers'] }}" # not valid YAML return value - except ScannerError as e: # "%Y-%m-%d' # not valid yaml + except ScannerError as e: # "%Y-%m-%d" or strings with tabs - not valid YAML if "expected alphabetic or numeric character, but found '%'" in str(e): return value + if "found character '\\t' that cannot start any token" in str(e): + return value raise e return value diff --git a/unit_tests/sources/declarative/resolvers/test_config_components_resolver.py b/unit_tests/sources/declarative/resolvers/test_config_components_resolver.py index 988f27643..2e5f6ceac 100644 --- a/unit_tests/sources/declarative/resolvers/test_config_components_resolver.py +++ b/unit_tests/sources/declarative/resolvers/test_config_components_resolver.py @@ -160,6 +160,20 @@ def to_configured_catalog( } ) +# Manifest with component definition with value containing tab characters +# which would cause YAML ScannerError (tabs cannot start tokens in YAML) +_MANIFEST_WITH_TAB_SCANNER_ERROR = deepcopy(_MANIFEST) +_MANIFEST_WITH_TAB_SCANNER_ERROR["dynamic_streams"][0]["components_resolver"][ + "components_mapping" +].append( + { + "type": "ComponentMappingDefinition", + "create_or_update": True, + "field_path": ["retriever", "requester", "$parameters", "custom_query"], + "value": "SELECT\n\tcampaign.name,\n\tcampaign.id\nFROM campaign", # Contains tab characters + } +) + @pytest.mark.parametrize( "manifest, config, expected_exception, expected_stream_names", @@ -173,8 +187,15 @@ def to_configured_catalog( ), (_MANIFEST_WITH_STREAM_CONFIGS_LIST, _CONFIG, None, ["item_1", "item_2", "default_item"]), (_MANIFEST_WITH_SCANNER_ERROR, _CONFIG, None, ["item_1", "item_2", "default_item"]), + (_MANIFEST_WITH_TAB_SCANNER_ERROR, _CONFIG, None, ["item_1", "item_2", "default_item"]), + ], + ids=[ + "no_duplicates", + "duplicates", + "stream_configs_list", + "scanner_error", + "tab_scanner_error", ], - ids=["no_duplicates", "duplicates", "stream_configs_list", "scanner_error"], ) def test_dynamic_streams_read_with_config_components_resolver( manifest, config, expected_exception, expected_stream_names