Skip to content
Snippets Groups Projects

Filling XLSX: Everything except multiple choice.

Merged Daniel Hornung requested to merge f-json-table into dev
All threads resolved!
Compare and Show latest version
10 files
+ 169
15
Compare changes
  • Side-by-side
  • Inline
Files
10
@@ -23,6 +23,7 @@
from __future__ import annotations
import json
import pathlib
from collections import OrderedDict
from types import SimpleNamespace
from typing import Any, Dict, List, Optional, Union, TextIO
@@ -60,14 +61,6 @@ def _get_column_types(sheet: Worksheet) -> OrderedDict:
return result
def _get_deep_value(data: Dict[str, Any], path: List[str]):
"""Return the value at ``path`` inside the dict ``data``.
"""
if len(path) > 1:
return _get_deep_value(data[path[0]], path[1:])
return data[path[0]]
def _get_foreign_key_columns(sheet: Worksheet) -> Dict[str, SimpleNamespace]:
"""Return the foreign keys of the worksheet.
@@ -269,6 +262,8 @@ out: union[dict, None]
context = TemplateFiller.Context()
context.fill_from_data(data)
explode_later: List[dict] = []
insertables: Dict[str, Any] = {}
for name, content in data.items():
path = current_path + [name]
@@ -282,16 +277,23 @@ out: union[dict, None]
if isinstance(content[0], dict):
# An array of objects: must go into exploded sheet
for entry in content:
self._handle_data(data=entry, current_path=path, context=next_context)
explode_later.append({"data": entry, "current_path": path,
"context": next_context})
continue
elif isinstance(content, dict):
if not current_path: # Special handling for top level
self._handle_data(content, current_path=path, context=next_context)
explode_later.append({"data": content, "current_path": path,
"context": next_context})
continue
insert = self._handle_data(content, current_path=path, context=next_context.copy(),
only_collect_insertables=True)
assert isinstance(insert, dict)
assert not any(key in insertables for key in insert)
# print(insert)
# from IPython import embed
# embed()
insertables.update(insert)
continue
else: # scalars
@@ -308,8 +310,9 @@ out: union[dict, None]
insertables[path_str] = value
if only_collect_insertables:
return insertables
if not current_path:
return None
# if not current_path:
# print("returning early")
# return None
# actual data insertion
insert_row = None
@@ -325,11 +328,21 @@ out: union[dict, None]
sheet.cell(row=insert_row+1, column=col_index+1, value=value)
# continue in exploded sheets
for exploded_content in explode_later:
print(f"Exploding: {exploded_content}")
self._handle_data(**exploded_content)
# Insert foreign keys
if insert_row is not None and sheet is not None and _is_exploded_sheet(sheet):
foreigns = _get_foreign_key_columns(sheet)
for index, path in ((f.index, f.path) for f in foreigns.values()):
value = context[path]
try:
value = context[path]
except KeyError as err:
print(f"\nCurrent context: {context._props}")
from IPython import embed
embed()
sheet.cell(row=insert_row+1, column=index+1, value=value)
return None
@@ -366,4 +379,7 @@ validation_schema: dict, optional
result_wb = load_workbook(template)
template_filler = TemplateFiller(result_wb)
template_filler.fill_data(data=data)
parentpath = pathlib.Path(result).parent
parentpath.mkdir(parents=True, exist_ok=True)
result_wb.save(result)
Loading