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

STY: fixing linting warnings

parent 3912400d
Branches
Tags
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 #48129 passed
...@@ -23,16 +23,16 @@ ...@@ -23,16 +23,16 @@
This module allows to generate template tables from JSON schemas. This module allows to generate template tables from JSON schemas.
""" """
import re import re
import sys
from abc import ABC, abstractmethod from abc import ABC, abstractmethod
from enum import Enum from enum import Enum
from typing import Dict, List, Optional, Tuple, Union from typing import Dict, Optional, Tuple
from openpyxl import Workbook from openpyxl import Workbook
from openpyxl.workbook.child import INVALID_TITLE_REGEX from openpyxl.workbook.child import INVALID_TITLE_REGEX
class ColumnType(Enum): class ColumnType(Enum):
""" column types enum """
SCALAR = 1 SCALAR = 1
LIST = 2 LIST = 2
FOREIGN = 3 FOREIGN = 3
...@@ -40,12 +40,15 @@ class ColumnType(Enum): ...@@ -40,12 +40,15 @@ class ColumnType(Enum):
class RowType(Enum): class RowType(Enum):
""" row types enum """
COL_TYPE = 1 COL_TYPE = 1
PATH = 2 PATH = 2
IGNORE = 3 IGNORE = 3
class TableTemplateGenerator(ABC): class TableTemplateGenerator(ABC):
""" base class for generating tables from json schema """
def __init__(self): def __init__(self):
pass pass
...@@ -69,10 +72,10 @@ class TableTemplateGenerator(ABC): ...@@ -69,10 +72,10 @@ class TableTemplateGenerator(ABC):
Example: {"Training": {"__this__": ["date"], "Person": [key1, key2]}} Example: {"Training": {"__this__": ["date"], "Person": [key1, key2]}}
Here, "date" is the sole key for Training. Here, "date" is the sole key for Training.
""" """
pass
def _generate_sheets_from_schema(self, schema: dict, foreign_keys: Optional[dict] = None def _generate_sheets_from_schema(self, schema: dict, foreign_keys: Optional[dict] = None
) -> Dict[str, Dict[str, Tuple[ColumnType, Optional[str], list]]]: ) -> Dict[str, Dict[str,
Tuple[ColumnType, Optional[str], list]]]:
""" generates a sheet definition from a given JSON schema """ generates a sheet definition from a given JSON schema
Parameters Parameters
...@@ -106,14 +109,14 @@ class TableTemplateGenerator(ABC): ...@@ -106,14 +109,14 @@ class TableTemplateGenerator(ABC):
if "properties" not in schema: if "properties" not in schema:
raise ValueError("Inappropriate JSON schema: The following part should contain " raise ValueError("Inappropriate JSON schema: The following part should contain "
f"the 'properties' key:\n{schema}\n") f"the 'properties' key:\n{schema}\n")
for RTname in schema["properties"].keys(): for rt_name in schema["properties"].keys():
sheets[RTname] = self._treat_schema_element(schema["properties"][RTname], sheets[rt_name] = self._treat_schema_element(schema["properties"][rt_name],
sheets, [RTname], foreign_keys) sheets, [rt_name], foreign_keys)
return sheets return sheets
def _get_foreign_keys(self, keys: dict, path: list) -> list: def _get_foreign_keys(self, keys: dict, path: list) -> list:
""" returns the foreign keys that are needed at the location to which path points """ """ returns the foreign keys that are needed at the location to which path points """
msg = (f"A foreign key definition is missing for path:\n{path}\n{keys}") msg = f"A foreign key definition is missing for path:\n{path}\n{keys}"
while path: while path:
if keys is None or path[0] not in keys: if keys is None or path[0] not in keys:
raise ValueError(msg) raise ValueError(msg)
...@@ -121,10 +124,9 @@ class TableTemplateGenerator(ABC): ...@@ -121,10 +124,9 @@ class TableTemplateGenerator(ABC):
path = path[1:] path = path[1:]
if isinstance(keys, dict) and "__this__" in keys: if isinstance(keys, dict) and "__this__" in keys:
return keys["__this__"] return keys["__this__"]
elif isinstance(keys, list): if isinstance(keys, list):
return keys return keys
else: raise ValueError(msg)
raise ValueError(msg)
def _treat_schema_element(self, schema: dict, sheets: dict, path: list, def _treat_schema_element(self, schema: dict, sheets: dict, path: list,
foreign_keys: Optional[dict] = None, level_in_sheet_name: int = 1, foreign_keys: Optional[dict] = None, level_in_sheet_name: int = 1,
...@@ -171,21 +173,23 @@ class TableTemplateGenerator(ABC): ...@@ -171,21 +173,23 @@ class TableTemplateGenerator(ABC):
f" is forbidden:{sheetname}") f" is forbidden:{sheetname}")
sheets[sheetname] = self._treat_schema_element( sheets[sheetname] = self._treat_schema_element(
schema['items'], sheets, path, foreign_keys, len(path), schema['items'], sheets, path, foreign_keys, len(path),
array_paths=array_paths+[path] # since this level is an array, we extend the list array_paths=array_paths+[path] # since this level is an array extend the list
) )
# and add the foreign keys that are necessary up to this point # and add the foreign keys that are necessary up to this point
for p in array_paths: for pa in array_paths:
keys = self._get_foreign_keys(foreign_keys, p) keys = self._get_foreign_keys(foreign_keys, pa)
for k in keys: for ke in keys:
if k in sheets[sheetname]: if ke in sheets[sheetname]:
raise ValueError(f"The shema would lead to two columns with the same " raise ValueError(f"The shema would lead to two columns with the same "
f"name which is forbidden:{k}") f"name which is forbidden:{ke}")
sheets[sheetname][k] = (ColumnType.FOREIGN, f"see sheet '{path[0]}'", p+[k]) sheets[sheetname][ke] = (ColumnType.FOREIGN, f"see sheet '{path[0]}'",
pa+[ke])
# columns are added to the new sheet, thus we do not return columns # columns are added to the new sheet, thus we do not return columns
return {} return {}
else: # it is a list of primitive types -> semi colon separated list
schema = schema['items'] # it is a list of primitive types -> semi colon separated list
ctype = ColumnType.LIST schema = schema['items']
ctype = ColumnType.LIST
if 'oneOf' in schema: if 'oneOf' in schema:
for el in schema['oneOf']: for el in schema['oneOf']:
...@@ -194,7 +198,7 @@ class TableTemplateGenerator(ABC): ...@@ -194,7 +198,7 @@ class TableTemplateGenerator(ABC):
if "properties" in schema: # recurse for each property if "properties" in schema: # recurse for each property
cols = {} cols = {}
for pname in schema["properties"].keys(): for pname in schema["properties"]:
col_defs = self._treat_schema_element( col_defs = self._treat_schema_element(
schema["properties"][pname], sheets, path+[pname], foreign_keys, schema["properties"][pname], sheets, path+[pname], foreign_keys,
level_in_sheet_name, array_paths=array_paths) level_in_sheet_name, array_paths=array_paths)
...@@ -210,23 +214,24 @@ class TableTemplateGenerator(ABC): ...@@ -210,23 +214,24 @@ class TableTemplateGenerator(ABC):
default_return = {".".join(path[level_in_sheet_name:]): (ctype, description, path)} default_return = {".".join(path[level_in_sheet_name:]): (ctype, description, path)}
if 'type' not in schema and 'enum' in schema: if 'type' not in schema and 'enum' in schema:
return default_return return default_return
elif 'type' not in schema and 'anyOf' in schema: if 'type' not in schema and 'anyOf' in schema:
for d in schema['anyOf']: for d in schema['anyOf']:
# currently the only case where this occurs is date formats # currently the only case where this occurs is date formats
assert d['type'] == 'string' assert d['type'] == 'string'
assert d['format'] == 'date' or d['format'] == 'date-time' assert d['format'] == 'date' or d['format'] == 'date-time'
return default_return return default_return
elif schema["type"] in ['string', 'number', 'integer', 'boolean']: if schema["type"] in ['string', 'number', 'integer', 'boolean']:
if 'format' in schema and schema['format'] == 'data-url': if 'format' in schema and schema['format'] == 'data-url':
return {} # file; ignore for now return {} # file; ignore for now
return default_return return default_return
else: raise ValueError("Inappropriate JSON schema: The following part should define an"
raise ValueError("Inappropriate JSON schema: The following part should define an" f" object with properties or a primitive type:\n{schema}\n")
f" object with properties or a primitive type:\n{schema}\n")
raise RuntimeError("This should not be reached. Implementation error.") raise RuntimeError("This should not be reached. Implementation error.")
class XLSXTemplateGenerator(TableTemplateGenerator): class XLSXTemplateGenerator(TableTemplateGenerator):
""" class for generating XLSX tables from json schema """
def __init__(self): def __init__(self):
pass pass
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment