Repository: datafold/data-diff
Issue: config key - key_columns throws error when used in TOML

**Describe the bug**
key_columns inside TOML config file doesnt work. It throws an error
 ERROR - [TableSegment] Attribute 'key_columns' expected value of type tuple[str]. Instead got ['XXXX_ID']

If used in the command line it works.


Make sure to include the following (minus sensitive information):

Throws error when using key_columns in config file. It works without errors when using in command line as shown below..

% data-diff --conf ~/config_files/datadiff.toml --run XXXX_bq_csql

[09:53:55] INFO - [PostgreSQL] Starting a threadpool, size=4.
[09:53:57] INFO - Diffing using columns: key=['XXXX_ID'] update=None extra=().
[09:53:57] INFO - Using algorithm 'hashdiff'.
[09:53:57] ERROR - [TableSegment] Attribute 'key_columns' expected value of type tuple[str]. Instead got ['XXXX_ID']

% data-diff --conf ~/config_files/datadiff.toml --run XXXX_bq_csql. -k XXXX_ID

% data-diff --conf ~/config_files/datadiff.toml --run XXXX_bq_csql -k XXXX_ID
[10:00:38] INFO - [PostgreSQL] Starting a threadpool, size=4.
[10:00:41] INFO - Diffing using columns: key=('XXXX_ID',) update=None extra=().
[10:00:41] INFO - Using algorithm 'hashdiff'.
[10:00:41] INFO - Diffing segments at key-range: 0..448966. size: table1 <= 448966, table2 <= 448966
.
.
.

If possible, please paste these as text, and not a screenshot.

**Describe the environment**

% data-diff --version
v0.3.2

Comparing between BigQuery and Postgres.. But this is a generic error , not database specific 


Changed files:
data_diff/config.py, tests/test_config.py

diff --git a/data_diff/config.py b/data_diff/config.py
index 3971f0be..1b091f07 100644
--- a/data_diff/config.py
+++ b/data_diff/config.py
@@ -4,6 +4,12 @@ from typing import Any, Dict
 import toml
 
 
+_ARRAY_FIELDS = (
+    "key_columns",
+    "columns",
+)
+
+
 class ConfigParseError(Exception):
     pass
 
@@ -38,6 +44,11 @@ def _apply_config(config: Dict[str, Any], run_name: str, kw: Dict[str, Any]):
         for index in "12":
             run_args[index] = {attr: kw.pop(f"{attr}{index}") for attr in ("database", "table")}
 
+    # Make sure array fields are decoded as list, since array fields in toml are decoded as list, but TableSegment object requires tuple type.
+    for field in _ARRAY_FIELDS:
+        if isinstance(run_args.get(field), list):
+            run_args[field] = tuple(run_args[field])
+
     # Process databases + tables
     for index in "12":
         try:
diff --git a/tests/test_config.py b/tests/test_config.py
index fb8a6245..960ee15d 100644
--- a/tests/test_config.py
+++ b/tests/test_config.py
@@ -15,6 +15,8 @@ class TestConfig(unittest.TestCase):
 
             [run.default]
             update_column = "timestamp"
+            key_columns = ["id"]
+            columns = ["name", "age"]
             verbose = true
             threads = 2
 
@@ -39,6 +41,8 @@ class TestConfig(unittest.TestCase):
         assert res["table2"] == "rating_del1"
         assert res["threads1"] == 11
         assert res["threads2"] == 22
+        assert res["key_columns"] == ("id",)
+        assert res["columns"] == ("name", "age")
 
         res = apply_config_from_string(config, "pg_pg", {"update_column": "foo", "table2": "bar"})
         assert res["update_column"] == "foo"