Skip to content
Snippets Groups Projects
Commit 29a0bdf3 authored by Henrik tom Wörden's avatar Henrik tom Wörden
Browse files

FIX: foreign keys

parent 5ae24891
No related branches found
No related tags found
4 merge requests!100WIP: Filling XLSX: Seems to be working.,!94ENH: add framework for converting json schema into table templates,!93Filling XLSX: Everything except multiple choice.,!92ENH: xlsx template generator
Pipeline #48097 failed
......@@ -103,7 +103,7 @@ class TableTemplateGenerator(ABC):
if foreign_keys is None:
foreign_keys = {}
# here, we treat the top level
# sheets[sheetname][colname]= (COL_TYPE, [path])
# sheets[sheetname][colname]= (COL_TYPE, description, [path])
sheets: dict[str, dict[str, tuple[str, list]]] = {}
if "properties" not in schema:
raise ValueError("Inappropriate JSON schema: The following part should contain "
......@@ -139,24 +139,42 @@ class TableTemplateGenerator(ABC):
return selected_keys
def _treat_schema_element(self, schema: dict, sheets: dict = None, path: list = None,
foreign_keys: dict = None, level_in_sheet_name: int = 1
) -> dict[str, tuple[str, list]]:
""" recursively transforms elements from the schema into column definitions """
foreign_keys: dict = None, level_in_sheet_name: int = 1,
array_paths: list = None
) -> dict[str, tuple[str, str, list]]:
""" recursively transforms elements from the schema into column definitions
sheets is modified in place.
Returns
-------
dict
describing the columns; see doc string of _generate_sheets_from_schema
"""
if not ("type" in schema or "enum" in schema or "oneOf" in schema or "anyOf" in schema):
raise ValueError("Inappropriate JSON schema: The following part should contain the "
f"'type' key:\n{schema}\n")
if array_paths is None:
array_paths = [path]
ctype = ColumnType.SCALAR
# if it is an array, value defs are in 'items'
if 'type' in schema and schema['type'] == 'array':
if 'type' in schema['items'] and schema['items']['type'] == 'object' and len(path) > 1: # list of references; special treatment
if ('type' in schema['items'] and schema['items']['type'] == 'object'
and len(path) > 1): # list of references; special treatment
# we add a new sheet
sheets[path[-1]] = self._treat_schema_element(schema['items'], sheets, path,
foreign_keys,
len(path))
for c in self._get_foreign_keys(foreign_keys, path[:-1]):
sheets[path[-1]].update({c: (ColumnType.FOREIGN, f"see sheet '{path[0]}'", path[:-1]+[c])})
sheetname = ".".join(path)
sheets[sheetname] = self._treat_schema_element(
schema['items'], sheets, path, foreign_keys, len(path),
array_paths=array_paths+[path])
print("Sel", path)
for p in array_paths:
keys = self._get_foreign_keys(foreign_keys, p)
for k in keys:
print(k, p)
sheets[sheetname].update({k: (ColumnType.FOREIGN, f"see sheet '{path[0]}'", p+[k])})
# columns are added to the new sheet, thus we do not return columns
return {}
else:
......@@ -175,7 +193,7 @@ class TableTemplateGenerator(ABC):
for pname in schema["properties"].keys():
cols.update(self._treat_schema_element(
schema["properties"][pname], sheets, path+[pname], foreign_keys,
level_in_sheet_name))
level_in_sheet_name, array_paths=array_paths))
return cols
else:
description = schema['description'] if 'description' in schema else None
......
......@@ -69,7 +69,7 @@ def test_generate_sheets_from_schema():
with pytest.raises(ValueError,
match="Inappropriate JSON schema: The following part "
"should define an object.*"):
generator._generate_sheets_from_schema(schema)
generator._generate_sheets_from_schema(schema, {'Training': ['a']})
# bad schema
schema = {
......@@ -83,7 +83,7 @@ def test_generate_sheets_from_schema():
with pytest.raises(ValueError,
match="Inappropriate JSON schema: The following part "
"should define an object.*"):
generator._generate_sheets_from_schema(schema)
generator._generate_sheets_from_schema(schema, {'Training': ['a']})
# minimal case: one RT with one P
schema = {
......@@ -100,7 +100,7 @@ def test_generate_sheets_from_schema():
}
}
}
sdef = generator._generate_sheets_from_schema(schema)
sdef = generator._generate_sheets_from_schema(schema, {'Training': ['a']})
assert "Training" in sdef
tdef = sdef['Training']
assert 'name' in tdef
......@@ -111,8 +111,9 @@ def test_generate_sheets_from_schema():
schema = json.load(sfi)
with pytest.raises(ValueError, match="A foreign key definition is missing.*"):
generator._generate_sheets_from_schema(schema)
sdef = generator._generate_sheets_from_schema(schema,
foreign_keys={'Training': {"__this__": ['date', 'url']}})
sdef = generator._generate_sheets_from_schema(
schema,
foreign_keys={'Training': {"__this__": ['date', 'url']}})
assert "Training" in sdef
tdef = sdef['Training']
assert tdef['date'] == (ColumnType.SCALAR, 'date', ["Training", 'date'])
......@@ -127,7 +128,7 @@ def test_generate_sheets_from_schema():
assert tdef['participants'] == (ColumnType.SCALAR, None, ["Training", 'participants'])
assert tdef['subjects'] == (ColumnType.LIST, None, ["Training", 'subjects'])
assert tdef['remote'] == (ColumnType.SCALAR, None, ["Training", 'remote'])
cdef = sdef['coach']
cdef = sdef['Training.coach']
assert cdef['family_name'] == (ColumnType.SCALAR, None, ["Training", 'coach', 'family_name'])
assert cdef['given_name'] == (ColumnType.SCALAR, None, ["Training", 'coach', 'given_name'])
assert cdef['Organisation'] == (ColumnType.SCALAR, None, ["Training", 'coach',
......@@ -166,7 +167,9 @@ def test_template_generator():
schema = json.load(sfi)
path = os.path.join(tempfile.mkdtemp(), 'test.xlsx')
assert not os.path.exists(path)
generator.generate(schema=schema, foreign_keys={'Training': {"__this__": ['date', 'url']}}, filepath=path)
generator.generate(schema=schema,
foreign_keys={'Training': {"__this__": ['date', 'url']}},
filepath=path)
assert os.path.exists(path)
generated = load_workbook(path) # workbook can be read
example = load_workbook(rfp("example_template.xlsx"))
......@@ -195,9 +198,7 @@ def test_template_generator():
continue
with open(fk_path) as sfi:
fk = json.load(sfi)
generator.generate(schema=schema,
foreign_keys=fk,
filepath=path)
generator.generate(schema=schema, foreign_keys=fk, filepath=path)
os.system(f'libreoffice {path}')
# TODO test collisions of sheet or colnames
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment