From ed03f81556eee57b99493a387d17ea1efbbd2386 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edgar=20Ram=C3=ADrez-Mondrag=C3=B3n?= Date: Fri, 29 Nov 2024 22:39:40 -0600 Subject: [PATCH] fix: Ensure the required global folder tap settings are merged into the concrete implementation settings --- singer_sdk/contrib/filesystem/tap.py | 15 +++++++++++---- singer_sdk/plugin_base.py | 13 ++++++------- singer_sdk/tap_base.py | 4 ++-- 3 files changed, 19 insertions(+), 13 deletions(-) diff --git a/singer_sdk/contrib/filesystem/tap.py b/singer_sdk/contrib/filesystem/tap.py index ff0c98819c..6c9579211b 100644 --- a/singer_sdk/contrib/filesystem/tap.py +++ b/singer_sdk/contrib/filesystem/tap.py @@ -105,6 +105,8 @@ class FolderTap(Tap, t.Generic[_T]): This should be a subclass of `FileStream`. """ + dynamic_catalog: bool = True + config_jsonschema: t.ClassVar[dict] = {"properties": {}} @classmethod @@ -124,11 +126,16 @@ def append_builtin_config(cls: type[FolderTap], config_jsonschema: dict) -> None config_jsonschema: [description] """ - def _merge_missing(source_jsonschema: dict, target_jsonschema: dict) -> None: + def _merge_missing(src: dict, tgt: dict) -> None: # Append any missing properties in the target with those from source. - for k, v in source_jsonschema["properties"].items(): - if k not in target_jsonschema["properties"]: - target_jsonschema["properties"][k] = v + for k, v in src["properties"].items(): + if k not in tgt["properties"]: + tgt["properties"][k] = v + + # Merge the required fields + source_required = src.get("required", []) + target_required = tgt.get("required", []) + tgt["required"] = list(set(source_required + target_required)) _merge_missing(BASE_CONFIG_SCHEMA, config_jsonschema) diff --git a/singer_sdk/plugin_base.py b/singer_sdk/plugin_base.py index f12f152272..dba6accbd4 100644 --- a/singer_sdk/plugin_base.py +++ b/singer_sdk/plugin_base.py @@ -160,14 +160,13 @@ def __init__( validate_config: True to require validation of config settings. Raises: - ValueError: If config is not a dict or path string. + TypeError: If config is not a dict or path string. """ - if not config: - config_dict = {} - elif isinstance(config, (str, PurePath)): + config = config or {} + if isinstance(config, (str, PurePath)): config_dict = read_json_file(config) warnings.warn( - "Passsing a config file path is deprecated. Please pass the config " + "Passing a config file path is deprecated. Please pass the config " "as a dictionary instead.", SingerSDKDeprecationWarning, stacklevel=2, @@ -179,7 +178,7 @@ def __init__( # list will override those of earlier ones. config_dict.update(read_json_file(config_path)) warnings.warn( - "Passsing a list of config file paths is deprecated. Please pass the " + "Passing a list of config file paths is deprecated. Please pass the " "config as a dictionary instead.", SingerSDKDeprecationWarning, stacklevel=2, @@ -188,7 +187,7 @@ def __init__( config_dict = config else: msg = f"Error parsing config of type '{type(config).__name__}'." # type: ignore[unreachable] - raise ValueError(msg) + raise TypeError(msg) if parse_env_config: self.logger.info("Parsing env var for settings config...") config_dict.update(self._env_var_config) diff --git a/singer_sdk/tap_base.py b/singer_sdk/tap_base.py index 82900049c6..64b6b2e01f 100644 --- a/singer_sdk/tap_base.py +++ b/singer_sdk/tap_base.py @@ -105,7 +105,7 @@ def __init__( elif catalog is not None: self._input_catalog = Catalog.from_dict(read_json_file(catalog)) warnings.warn( - "Passsing a catalog file path is deprecated. Please pass the catalog " + "Passing a catalog file path is deprecated. Please pass the catalog " "as a dictionary or Catalog object instead.", SingerSDKDeprecationWarning, stacklevel=2, @@ -123,7 +123,7 @@ def __init__( elif state: state_dict = read_json_file(state) warnings.warn( - "Passsing a state file path is deprecated. Please pass the state " + "Passing a state file path is deprecated. Please pass the state " "as a dictionary instead.", SingerSDKDeprecationWarning, stacklevel=2,