diff --git a/src/caosadvancedtools/table_json_conversion/table_generator.py b/src/caosadvancedtools/table_json_conversion/table_generator.py index e4a17a57edc388b1c24899116895a2fa0e7d50e1..fb2a5149184f4d84e0704f1b3c2c0d427383508f 100644 --- a/src/caosadvancedtools/table_json_conversion/table_generator.py +++ b/src/caosadvancedtools/table_json_conversion/table_generator.py @@ -23,16 +23,16 @@ This module allows to generate template tables from JSON schemas. """ import re -import sys from abc import ABC, abstractmethod from enum import Enum -from typing import Dict, List, Optional, Tuple, Union +from typing import Dict, Optional, Tuple from openpyxl import Workbook from openpyxl.workbook.child import INVALID_TITLE_REGEX class ColumnType(Enum): + """ column types enum """ SCALAR = 1 LIST = 2 FOREIGN = 3 @@ -40,12 +40,15 @@ class ColumnType(Enum): class RowType(Enum): + """ row types enum """ COL_TYPE = 1 PATH = 2 IGNORE = 3 class TableTemplateGenerator(ABC): + """ base class for generating tables from json schema """ + def __init__(self): pass @@ -69,10 +72,10 @@ class TableTemplateGenerator(ABC): Example: {"Training": {"__this__": ["date"], "Person": [key1, key2]}} Here, "date" is the sole key for Training. """ - pass 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 Parameters @@ -106,14 +109,14 @@ class TableTemplateGenerator(ABC): if "properties" not in schema: raise ValueError("Inappropriate JSON schema: The following part should contain " f"the 'properties' key:\n{schema}\n") - for RTname in schema["properties"].keys(): - sheets[RTname] = self._treat_schema_element(schema["properties"][RTname], - sheets, [RTname], foreign_keys) + for rt_name in schema["properties"].keys(): + sheets[rt_name] = self._treat_schema_element(schema["properties"][rt_name], + sheets, [rt_name], foreign_keys) return sheets def _get_foreign_keys(self, keys: dict, path: list) -> list: """ 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: if keys is None or path[0] not in keys: raise ValueError(msg) @@ -121,10 +124,9 @@ class TableTemplateGenerator(ABC): path = path[1:] if isinstance(keys, dict) and "__this__" in keys: return keys["__this__"] - elif isinstance(keys, list): + if isinstance(keys, list): return keys - else: - raise ValueError(msg) + raise ValueError(msg) def _treat_schema_element(self, schema: dict, sheets: dict, path: list, foreign_keys: Optional[dict] = None, level_in_sheet_name: int = 1, @@ -171,21 +173,23 @@ class TableTemplateGenerator(ABC): f" is forbidden:{sheetname}") sheets[sheetname] = self._treat_schema_element( 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 - for p in array_paths: - keys = self._get_foreign_keys(foreign_keys, p) - for k in keys: - if k in sheets[sheetname]: + for pa in array_paths: + keys = self._get_foreign_keys(foreign_keys, pa) + for ke in keys: + if ke in sheets[sheetname]: raise ValueError(f"The shema would lead to two columns with the same " - f"name which is forbidden:{k}") - sheets[sheetname][k] = (ColumnType.FOREIGN, f"see sheet '{path[0]}'", p+[k]) + f"name which is forbidden:{ke}") + 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 return {} - else: # it is a list of primitive types -> semi colon separated list - schema = schema['items'] - ctype = ColumnType.LIST + + # it is a list of primitive types -> semi colon separated list + schema = schema['items'] + ctype = ColumnType.LIST if 'oneOf' in schema: for el in schema['oneOf']: @@ -194,7 +198,7 @@ class TableTemplateGenerator(ABC): if "properties" in schema: # recurse for each property cols = {} - for pname in schema["properties"].keys(): + for pname in schema["properties"]: col_defs = self._treat_schema_element( schema["properties"][pname], sheets, path+[pname], foreign_keys, level_in_sheet_name, array_paths=array_paths) @@ -210,23 +214,24 @@ class TableTemplateGenerator(ABC): default_return = {".".join(path[level_in_sheet_name:]): (ctype, description, path)} if 'type' not in schema and 'enum' in schema: 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']: # currently the only case where this occurs is date formats assert d['type'] == 'string' assert d['format'] == 'date' or d['format'] == 'date-time' 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': return {} # file; ignore for now return default_return - else: - raise ValueError("Inappropriate JSON schema: The following part should define an" - f" object with properties or a primitive type:\n{schema}\n") + raise ValueError("Inappropriate JSON schema: The following part should define an" + f" object with properties or a primitive type:\n{schema}\n") raise RuntimeError("This should not be reached. Implementation error.") class XLSXTemplateGenerator(TableTemplateGenerator): + """ class for generating XLSX tables from json schema """ + def __init__(self): pass