Data-Test-Executer Framework speziell zum Test von Datenverarbeitungen mit Datengenerierung, Systemvorbereitungen, Einspielungen, ganzheitlicher diversifizierender Vergleich
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

574 lines
22 KiB

#!/usr/bin/python
# -*- coding: utf-8 -*-
# ---------------------------------------------------------------------------------------------------------
# Author : Ulrich Carmesin
# Source : gitea.ucarmesin.de
# ---------------------------------------------------------------------------------------------------------
import json
import re
import basic.program
import model.factory
import tools.file_abstract
import basic.constants as B
import tools.data_const as D
import tools.file_tool
2 years ago
from basic import toolHandling
import traceback
import tools.data_tool
import tools.file_type
DEFAULT_TTYPE = D.CSV_SPECTYPE_DATA
class FileFcts(tools.file_abstract.FileFcts):
def __init__(self):
pass
2 years ago
def load_file(self, path, ttype=""):
"""
this function parses the text and translates it to dict
:param text:
:return:
"""
lines = tools.file_tool.read_file_lines(self.job, path, self.getMsg())
2 years ago
return self.parseCsv(self.getMsg(), self.job, lines, ttype)
def dump_data_file(self, job, data: dict, path: str, ttype: str =""):
text = self.buildCsv(self.getMsg(), job, data, ttype)
1 year ago
return text
2 years ago
def isEmptyLine(self, msg, job, line, fields):
if (len(fields) < 1) or (len(line.strip().replace(D.CSV_DELIMITER, "")) < 1):
status = "start"
return True
if (fields[0][0:1] == "#"):
return True
return False
1 year ago
def isBlock(self, msg, job, field: str, block: str, status: str) -> bool:
2 years ago
"""
detects the block either on keywords in the field which opens a block
or on status if there is no keyword in the field
Identificator for a new block:
a) change of the type of the block-indicator at field[0] : attribute <-> identificator
b) change of the block-indicator at field[0][0]
Remember: transponing of a table
a) <identificator>:<subname>;<fields...;> (table:adress;london;...)
b) option:<id-field>;<values...;> (option:us-id:US-1234;US-2345...)
2 years ago
:param msg: message-object maybe from component
:param job: job-object with parameter and configuration
:param field: field in the csv-file
:param block:
:param status:
:return:
"""
verify = False
2 years ago
try:
if verify: print("isBlock "+field + " , " + block + " , " + status)
blockPur = tools.data_tool.getPurKeyword(block)
2 years ago
a = field.split(":")
keyPur = tools.data_tool.getPurKeyword(a[0])
statusPur = tools.data_tool.getPurKeyword(status)
1 year ago
if statusPur+"s-" in keyPur:
keyPur = keyPur[keyPur.find("-")+1:]
if verify: print("isBlock "+a[0] + "=" + keyPur +" , " + blockPur + " , " + status)
1 year ago
if (keyPur+"s" in D.LIST_SUBTABLES or keyPur in D.LIST_SUBTABLES) \
and block == D.CSV_BLOCK_SUBTABLES and keyPur != B.SUBJECT_STEP:
1 year ago
return True
if block == D.CSV_BLOCK_SUBTABLES \
and status not in [D.CSV_BLOCK_OPTION, D.CSV_BLOCK_HEAD, D.CSV_BLOCK_TABLES, "status"] \
1 year ago
and keyPur in D.LIST_SUBTABLES_ATTR:
return True
if (keyPur + "s" in D.LIST_SUBTABLES or keyPur in D.LIST_SUBTABLES) \
and block == D.CSV_BLOCK_SUBTABLES and keyPur != B.SUBJECT_STEP:
1 year ago
return True
elif "_"+a[0] == block or a[0] == block or "_"+a[0] == block:
2 years ago
return True
elif "_"+a[0] in [D.CSV_BLOCK_OPTION, D.CSV_BLOCK_HEAD, D.CSV_BLOCK_STEP, D.CSV_BLOCK_TABLES]:
return False
1 year ago
if blockPur == status or blockPur+"s" == status:
2 years ago
return True
if block == D.CSV_BLOCK_ATTR and len(a) == 1 and field[0:1] == "_":
return True
return False
except Exception as e:
print(traceback.format_exc())
2 years ago
print("isBlock "+field + "=?" + block)
def parseCsv(self, msg, job, lines, ttype=""):
"""
:param msg:
:param job:
:param lines:
:param ttype: content
a) catalog: key(s) - values # meta-spec, meta-auto
b) head: key - value # spec-info
c) option: key - value # spec -> job.par
d) step: key=function - values # spec (tp, ts) -> comp.function
e) step: key=usecase - values # spec (tc) -> comp.steps
f) ddl-table: key=field - vaulues=attributes # meta-spec, comp
g) data-table: array: field - values # spec.data, comp.artifacts
:return:
"""
verify = False
2 years ago
tdata = {}
status = "start"
verbose = False
tableAttr = {} # table
tableDict = {} # table
1 year ago
subtable = {}
steps = {}
2 years ago
# Zeilen parsen
for l in lines:
fields = splitFields(l, D.CSV_DELIMITER, job)
if self.isEmptyLine(msg, job, l, fields): continue
a = fields[0].lower().split(":")
# keywords option, step, table
1 year ago
# subtable-Block
if self.isBlock(msg, job, fields[0], D.CSV_BLOCK_SUBTABLES, status): # a[0].lower() in D.LIST_DATA_ATTR:
if verify: print("block "+D.CSV_BLOCK_SUBTABLES+" :: "+l)
subtable = setSubTable(job, subtable, a[0], fields, ttype)
1 year ago
tdata[subtable["actTable"]] = subtable[subtable["actTable"]]
status = subtable["actTable"]
# attribute-Block
elif self.isBlock(msg, job, fields[0], D.CSV_BLOCK_ATTR, status): # a[0].lower() in D.LIST_DATA_ATTR:
if verify: print("block "+D.CSV_BLOCK_ATTR+" :: "+l)
tableAttr = setTableAttribute(job, tableAttr, a[0], fields, ttype)
2 years ago
if ttype == "" and D.DATA_ATTR_TYPE in tableAttr:
ttype = tableAttr[D.DATA_ATTR_TYPE]
elif (D.DATA_ATTR_TYPE in tableAttr and ttype != tableAttr[D.DATA_ATTR_TYPE]
and ttype not in [D.CSV_SPECTYPE_DDL]):
msg.logWarn("System-Type " + ttype + " be overwrite by file-Type " + tableAttr[D.DATA_ATTR_TYPE])
ttype = tableAttr[D.DATA_ATTR_TYPE]
2 years ago
continue
1 year ago
# head-Block
1 year ago
elif self.isBlock(msg, job, fields[0], D.CSV_BLOCK_HEAD, status):
if verify: print("block "+D.CSV_BLOCK_HEAD+" :: "+l)
2 years ago
setTdataLine(tdata, fields, D.CSV_BLOCK_HEAD, job)
status = "start"
continue
1 year ago
# option-Block
1 year ago
elif self.isBlock(msg, job, fields[0], D.CSV_BLOCK_OPTION, status):
if verify: print("block "+D.CSV_BLOCK_OPTION+" :: "+l)
2 years ago
setTdataLine(tdata, fields, D.CSV_BLOCK_OPTION, job)
status = "start"
continue
1 year ago
# step-Block
1 year ago
elif (status != D.CSV_BLOCK_STEP) \
and self.isBlock(msg, job, fields[0], D.CSV_BLOCK_STEP, status):
if verify: print("block "+D.CSV_BLOCK_STEP+" :: "+l)
#h = []
steps = setStepAttribute(job, steps, "", fields)
#h.append(B.DATA_NODE_STEPS)
2 years ago
if verbose: print(">> step "+l)
1 year ago
status = D.CSV_BLOCK_STEP
2 years ago
continue
1 year ago
# table-Header Block
2 years ago
elif self.isBlock(msg, job, fields[0], D.CSV_BLOCK_TABLES, status):
if verify: print("block "+D.CSV_BLOCK_TABLES+" :: "+l)
2 years ago
if verbose: print(">> tables " + l)
h = a
h[0] = B.DATA_NODE_TABLES
if ttype in ["", "csv"]:
ttype = DEFAULT_TTYPE
2 years ago
if ttype == D.CSV_SPECTYPE_CONF:
del h[0]
tableDict = getTdataContent(msg, tdata, h)
setTableHeader(tableDict, tableAttr, fields, ttype, job)
tableDict[tools.data_tool.getSingularAttribut(D.FIELD_NAME)] = h[-1]
2 years ago
status = D.CSV_SPECTYPE_DATA
1 year ago
# table-data-Block
2 years ago
elif (status == D.CSV_SPECTYPE_DATA):
if verify: print("block "+D.CSV_SPECTYPE_DATA+" :: "+l)
2 years ago
tableDict = getTdataContent(msg, tdata, h)
if verbose: print(">> setTableData " + str(h) + " " + str(tableDict))
setTableData(tableDict, fields, ttype, job)
1 year ago
# step-data-Block
1 year ago
elif (status == D.CSV_BLOCK_STEP):
if verify: print("block "+D.CSV_BLOCK_STEP+"2 :: "+l)
if verify: print("step-line "+status+": "+l)
steps = setStepAttribute(job, steps, fields[1], fields)
tdata[B.SUBJECT_STEPS] = steps
1 year ago
else:
if verify: print("block else :: "+l)
1 year ago
print("unbekannter Block "+status+": "+l)
# end for
tfdata = tools.file_type.rebuild_tdata(job, tdata, tableAttr, ttype)
return tfdata
2 years ago
def buildCsv(self, msg, job, data, ttype=""):
""""
d) conf:
_type : conf
_header : [ field_0, ... ]
{ field_0 : { attr_0 : val_0, .. },
field_1 : { ... }, ... }
-->
"_type;conf;;;;;;",
"table:lofts;_field;field;type;acceptance;key",
"lofts;street;a;str;;T:1",
";city;b;str;;F:1",
"#;;;;;;"
"""
out = ""
fields = []
table = ""
header = []
lines = []
tableData = {}
delimiter = D.CSV_DELIMITER
if D.DATA_ATTR_DLIM in data:
delimiter = data[D.DATA_ATTR_DLIM]
if D.DATA_ATTR_TYPE not in data and ttype != "":
data[D.DATA_ATTR_TYPE] = ttype
for f in D.LIST_DATA_ATTR:
if f in data and f == D.DATA_ATTR_TBL:
line = f + delimiter + data[f] + D.CSV_DELIMITER
lines.append(line)
elif ttype != "" and data[D.DATA_ATTR_TYPE] in [D.CSV_SPECTYPE_DDL]:
continue
elif f in data:
out += f + D.CSV_DELIMITER + data[f] + "\n"
if data[D.DATA_ATTR_TYPE] == D.CSV_SPECTYPE_CTLG:
for k in data:
if k in D.LIST_DATA_ATTR:
continue
if k in [B.DATA_NODE_TABLES, B.DATA_NODE_HEADER, "_hit"]:
continue
out += buildHeader(job, data[k][B.DATA_NODE_HEADER], k)
out += buildCtlg(job, data[k][B.DATA_NODE_HEADER], data[k][B.DATA_NODE_KEYS])
1 year ago
elif data[D.DATA_ATTR_TYPE] in [D.CSV_SPECTYPE_DDL, D.CSV_SPECTYPE_CONF]:
2 years ago
for k in data:
if k in D.LIST_DATA_ATTR:
continue
out += buildHeader(job, data[k][B.DATA_NODE_HEADER], k)
out += buildCtlg(job, data[k][B.DATA_NODE_HEADER], data[k])
1 year ago
if B.DATA_NODE_STEPS in data:
out += "step:header"
for h in data[B.DATA_NODE_STEPS][B.DATA_NODE_HEADER]:
out += delimiter + h
out += "\n"
for row in data[B.DATA_NODE_STEPS][B.DATA_NODE_DATA]:
for h in data[B.DATA_NODE_STEPS][B.DATA_NODE_HEADER]:
if h in [B.DATA_NODE_ARGS, "args"]:
for arg in row[B.DATA_NODE_ARGS]:
out += delimiter + arg + ":" + row[B.DATA_NODE_ARGS][arg]
else:
out += delimiter + row[h]
2 years ago
if len(out) > 0:
return out
if B.DATA_NODE_TABLES in data:
print("_tables in data")
for k in data[B.DATA_NODE_TABLES].keys():
tableData[k] = data[B.DATA_NODE_TABLES][k]
else:
for k in data.keys():
if k in D.LIST_DATA_ATTR:
continue
tableData[k] = data[k]
for k in tableData:
fields = []
if B.DATA_NODE_FIELDS in data[k]:
fields = data[k][B.DATA_NODE_FIELDS]
if B.DATA_NODE_HEADER in data[k]:
header = data[k][B.DATA_NODE_HEADER]
line = "table:" + k + D.CSV_DELIMITER + D.CSV_DELIMITER.join(header)
lines.append(line)
continue
if B.DATA_NODE_DATA in data[k]:
for row in data[k][B.DATA_NODE_DATA]:
for h in header:
line += D.CSV_DELIMITER + row[h]
lines.append(line)
else:
line = D.CSV_DELIMITER + k
for f in fields:
for h in header:
line += D.CSV_DELIMITER + tableData[f][h]
lines.append(line)
out = "\n".join(lines)
return out
def buildHeader(job, header, tableName):
return "table:" + tableName + ";" + ";".join(header) + "\n"
def buildCtlg(job, header, table):
out = ""
for k in table:
if k in D.LIST_DATA_ATTR:
continue
1 year ago
if k in [B.DATA_NODE_HEADER, B.DATA_NODE_FIELDS, B.DATA_NODE_DATA, "_hit"]:
2 years ago
continue
for h in header:
1 year ago
if h not in table[k]:
out += D.CSV_DELIMITER
elif isinstance(table[k][h], dict):
2 years ago
text = json.dumps(table[k][h])
out += "\"" + text + "\""
else:
out += D.CSV_DELIMITER + table[k][h]
out += "\n"
return out
def buildDdl(job, header, table):
out = ""
for k in table:
if k in D.LIST_DATA_ATTR:
continue
if k in [B.DATA_NODE_HEADER, B.DATA_NODE_DATA, "_hit"]:
continue
for h in header:
out += D.CSV_DELIMITER + table[k][h]
out += "\n"
return out
def convertRows2Text(job, header, tableData):
text = ""
for f in tableData:
if f in D.LIST_DATA_ATTR:
continue
for h in header:
print(h)
def splitFields(line, delimiter, job):
out = []
fields = line.split(delimiter)
for i in range(0, len(fields)):
if fields[i][0:1] == "#":
break
if re.match(r"^\"(.*)\"$", fields[i]):
fields[i] = fields[i][1:-1]
if fields[i].find("{\"") == 0:
if fields[i].find("{\"\"") == 0:
fields[i] = fields[i].replace("\"\"", "\"")
try:
val = json.loads(fields[i])
fields[i] = val
except Exception as e:
pass
out.append(fields[i])
return out
def setSubTable(job, subtable, key, val, ttype):
1 year ago
"""
:param job:
:param subtable:
:param key:
:param val:
:return:
"""
verify = False
1 year ago
# stories => new subtable
# stories-descriptiom => attribute of actual subtable
# descriptiom => attribute of actual subtable
key = key.lower() # tools.data_tool.getPluralKeyword(key)
1 year ago
subkey = ""
multi = True
newSubtable = False
if tools.data_tool.getPluralKeyword(ttype) in B.LIST_SUBJECTS:
entity = model.factory.get_entity_object(job, ttype)
else:
entity = None
if verify: print("setSubtable "+key+", "+str(val))
1 year ago
if "actTable" in subtable and subtable["actTable"]+"-" in key:
subkey = key[key.find("-")+1:]
if entity is not None and tools.data_tool.getSingularKeyword(key) in entity.LIST_FIELDS:
keyword = tools.data_tool.getSingularKeyword(key)
multi = False
else:
keyword = tools.data_tool.getPluralKeyword(key)
if subkey == "" and keyword not in subtable:
newSubtable = True
subtable[keyword] = {}
subtable["actTable"] = keyword
1 year ago
actTable = subtable["actTable"]
purKey = tools.data_tool.getPurKeyword(key)
if verify: print("setSubtable "+key+" =? "+actTable+ " + "+ purKey +" , "+str(val))
actKeys = list(subtable[actTable].keys())
1 year ago
for i in range(1, len(val)):
if newSubtable and val[i] not in subtable[actTable]:
1 year ago
if val[i] == "":
break
subtable[actTable][val[i]] = {}
subtable[actTable][val[i]]["name"] = val[i]
1 year ago
else:
if i > len(actKeys):
break
subtable[actTable][actKeys[i-1]][purKey] = val[i]
1 year ago
return subtable
def setStepAttribute(job, stepAttr, key, val):
if key == "":
stepAttr[B.DATA_NODE_HEADER] = []
for i in range(1, len(val)):
if len(val[i]) < 1:
continue
stepAttr[B.DATA_NODE_HEADER].append(val[i])
else:
if B.DATA_NODE_HEADER not in stepAttr:
print("Error: header is missing ")
i = 1
step = {}
for h in stepAttr[B.DATA_NODE_HEADER]:
if len(h) < 1:
continue
if tools.data_tool.isStrDict(val[i]):
step[h] = tools.data_tool.getStrDict(val[i])
else:
step[h] = val[i]
i += 1
key = "{:0>2d}_{}".format(int(step["sortnr"]), step["variant"])
step["name"] = step["variant"]
stepAttr[key] = step
return stepAttr
def setTableAttribute(job, tableAttr, key, val, ttype):
key = key.lower()
if key in D.LIST_DATA_ATTR:
if key in D.LIST_ATTR_MULTI:
values = {}
for i in range(1, len(val)):
if len(val[i].strip()) < 1:
continue
values["{:03d}".format(i)] = val[i].strip()
tableAttr[key] = values
else:
tableAttr[key] = val[1].strip()
tableAttr["_hit"] = True
return tableAttr
tableAttr["_hit"] = False
return tableAttr
def setTdataLine(tdata, fields, block, job):
"""
sets field(s) into tdata as a key-value-pair
additional fields will be concatenate to a intern separated list
:param tdata:
:param fields:
:param block:
:param job:
:return:
"""
a = fields[0].lower().split(":")
a[0] = block # normalized key
val = ""
for i in range(1, len(fields)-1):
val += D.INTERNAL_DELIMITER+fields[i]
if len(val) > len(D.INTERNAL_DELIMITER):
val = val[len(D.INTERNAL_DELIMITER):]
setTdataContent(job.m, tdata, val, a)
return tdata
def setTdataContent(msg, data, tabledata, path):
setTdataStructure(msg, data, path)
if len(path) == 2:
data[path[0]][path[1]] = tabledata
elif len(path) == 3:
data[path[0]][path[1]][path[2]] = tabledata
elif len(path) == 4:
data[path[0]][path[1]][path[2]][path[3]] = tabledata
data[tools.data_tool.getSingularAttribut(D.FIELD_NAME)] = path[-1]
def setTdataStructure(msg, data, path):
if len(path) >= 1 and path[0] not in data:
data[path[0]] = {}
if len(path) >= 2 and path[1] not in data[path[0]]:
data[path[0]][path[1]] = {}
if len(path) >= 3 and path[2] not in data[path[0]][path[1]]:
data[path[0]][path[1]][path[2]] = {}
if len(path) >= 4 and path[3] not in data[path[0]][path[1]][path[2]]:
data[path[0]][path[1]][path[2]][path[3]] = {}
return data
def getTdataContent(msg, data, path):
setTdataStructure(msg, data, path)
if len(path) == 2:
return data[path[0]][path[1]]
elif len(path) == 3:
return data[path[0]][path[1]][path[2]]
elif len(path) == 4:
return data[path[0]][path[1]][path[2]][path[3]]
elif len(path) == 1:
return data[path[0]]
else:
return None
def setTableHeader(tableDict, tableAttr, fields, ttype, job):
header = []
for i in range(1, len(fields)):
1 year ago
if len(fields[i].strip()) < 1:
continue
header.append(fields[i].strip())
tableDict[B.DATA_NODE_HEADER] = header
for attr in tableAttr:
tableDict[attr] = tableAttr[attr]
# preparate the sub-structure for row-data
if ttype == D.CSV_SPECTYPE_TREE:
tableDict[B.DATA_NODE_DATA] = {}
elif ttype in [D.CSV_SPECTYPE_KEYS, D.CSV_SPECTYPE_CTLG, D.CSV_SPECTYPE_MDL]:
tableDict[D.CSV_NODETYPE_KEYS] = {}
tableDict[D.DATA_ATTR_KEY] = 1
if D.DATA_ATTR_KEY in tableAttr:
tableDict[D.DATA_ATTR_KEY] = header.index(tableAttr[D.DATA_ATTR_KEY]) + 1
else:
tableDict[B.DATA_NODE_DATA] = []
return tableDict
def setTableData(tableDict: dict, fields: list, ttype: str, job):
"""
sets the fields into the table-dict in order to the specific ttype
precondition: usage from reading table-data, so node _header is set with header of this table-block
:param tableDict:
:param fields:
:param ttype:
a) catalog: key(s) - values # meta-spec, meta-auto
b) head: key - value # spec-info
c) option: key - value # spec -> job.par
d) step: key=function - values # spec (tp, ts) -> comp.function
e) step: key=usecase - values # spec (tc) -> comp.steps
f) ddl-table: key=field - vaulues=attributes # meta-spec, comp
g) data-table: array: field - values # spec.data, comp.artifacts
:param job:
:return:
"""
row = {}
if ttype == D.CSV_SPECTYPE_DATA and ":" not in fields[0] and D.DATA_ATTR_ALIAS in tableDict:
fields = [tableDict[D.DATA_ATTR_ALIAS]] + fields
i = 1
for f in tableDict[B.DATA_NODE_HEADER]:
# --> still not used
1 year ago
if f in [B.DATA_NODE_ARGS, "args"]:
arguments = {}
row[B.DATA_NODE_ARGS] = arguments
if B.DATA_NODE_ARGS in row:
a = fields[i].split(":")
row[B.DATA_NODE_ARGS][a[0]] = a[1]
# <-- still not used
1 year ago
else:
# print(str(i)+" "+f+" "+str(len(fields))+" "+str(len(row)))
1 year ago
row[f] = fields[i]
i += 1
1 year ago
ln = len(tableDict[B.DATA_NODE_HEADER])
for arg in fields[len(tableDict[B.DATA_NODE_HEADER])+1:]:
if len(arg) == 0 or arg.strip()[0:1] == "#":
continue
print("arg "+arg)
a = arg.split(":")
row[B.DATA_NODE_ARGS][a[0]] = a[1]
if ttype == D.CSV_SPECTYPE_DATA or ttype+"s" in B.LIST_SUBJECTS:
tableDict[B.DATA_NODE_DATA].append(row)
2 years ago
elif ttype in [D.CSV_SPECTYPE_KEYS, D.CSV_SPECTYPE_CTLG]:
tableDict[D.CSV_NODETYPE_KEYS][fields[tableDict[D.DATA_ATTR_KEY]].strip()] = row
2 years ago
elif ttype in [D.CSV_SPECTYPE_CONF, D.CSV_SPECTYPE_DDL]:
tableDict[fields[1]] = row
return tableDict
2 years ago