diff --git a/src/caosadvancedtools/table_json_conversion/table_generator.py b/src/caosadvancedtools/table_json_conversion/table_generator.py index 1f4fb813d48c57eecf6da3279d1f5a9fbd0b8832..b8c50e7d8d40775f86c1a01d0934effe570cf20d 100644 --- a/src/caosadvancedtools/table_json_conversion/table_generator.py +++ b/src/caosadvancedtools/table_json_conversion/table_generator.py @@ -125,25 +125,38 @@ class TableTemplateGenerator(ABC): path=[rt_name], foreign_keys=foreign_keys) return sheets - def _get_foreign_keys(self, keys: dict, path: list) -> list: + def _get_foreign_keys(self, keys: dict, path: list) -> list[list[str]]: """Return the foreign keys that are needed at the location to which path points. Returns ------- -foreign_keys: list - Contains strings or lists of strings. +foreign_keys: list[list[str]] + Contains lists of strings, each element is the path to one foreign key. """ - msg = f"A foreign key definition is missing for path:\n{path}\nKeys are:\n{keys}" + msg_missing = f"A foreign key definition is missing for path:\n{path}\nKeys are:\n{keys}" + orig_path = path.copy() while path: if keys is None or path[0] not in keys: - raise ValueError(msg) + raise ValueError(msg_missing) keys = keys[path[0]] path = path[1:] if isinstance(keys, dict) and "__this__" in keys: - return keys["__this__"] - if isinstance(keys, list): - return keys - raise ValueError(msg) + keys = keys["__this__"] + if isinstance(keys, str): + raise ValueError("Foreign keys must be a list of strings, but a single " + "string was given:\n" + f"{orig_path} -> {keys}") + if not isinstance(keys, list): + raise ValueError(msg_missing) + + # Keys must be either all lists or all strings + types = {type(key) for key in keys} + if len(types) > 1: + raise ValueError("The keys of this path must bei either all lists or all strings:" + f" {orig_path}") + if types.pop() is str: + keys = [[key] for key in keys] + return keys def _treat_schema_element(self, schema: dict, sheets: dict, path: list[str], foreign_keys: Optional[dict] = None, level_in_sheet_name: int = 1, @@ -204,13 +217,7 @@ foreign_keys: list # and add the foreign keys that are necessary up to this point for array_path in array_paths: foreigns = self._get_foreign_keys(foreign_keys, array_path) - if isinstance(foreigns, str): - raise ValueError("Foreign keys must be a list of strings, but a single " - "string was given:\n" - f"{array_path} -> {foreigns}") for foreign in foreigns: - if isinstance(foreign, str): - foreign = [foreign] internal_key = p2s(array_path + foreign) if internal_key in sheets[sheetname]: raise ValueError("The schema would lead to two columns with the " diff --git a/unittests/table_json_conversion/test_table_template_generator.py b/unittests/table_json_conversion/test_table_template_generator.py index 179f121db5c5c49fbda3a38da5d7c72b93eda89a..d9a84dcf53ec991eec709aab406a7652881e6ea8 100644 --- a/unittests/table_json_conversion/test_table_template_generator.py +++ b/unittests/table_json_conversion/test_table_template_generator.py @@ -172,10 +172,10 @@ def test_generate_sheets_from_schema(): def test_get_foreign_keys(): generator = XLSXTemplateGenerator() fkd = {"Training": ['a']} - assert ['a'] == generator._get_foreign_keys(fkd, ['Training']) + assert [['a']] == generator._get_foreign_keys(fkd, ['Training']) fkd = {"Training": {"__this__": ['a']}} - assert ['a'] == generator._get_foreign_keys(fkd, ['Training']) + assert [['a']] == generator._get_foreign_keys(fkd, ['Training']) fkd = {"Training": {'hallo'}} with pytest.raises(ValueError, match=r"A foreign key definition is missing for path:\n\[" @@ -183,7 +183,7 @@ def test_get_foreign_keys(): generator._get_foreign_keys(fkd, ['Training']) fkd = {"Training": {"__this__": ['a'], 'b': ['c']}} - assert ['c'] == generator._get_foreign_keys(fkd, ['Training', 'b']) + assert [['c']] == generator._get_foreign_keys(fkd, ['Training', 'b']) with pytest.raises(ValueError, match=r"A foreign key definition is missing for .*"): generator._get_foreign_keys({}, ['Training'])