From 099f244892c91762f5735fdef7a3f017e305efef Mon Sep 17 00:00:00 2001 From: Ulrich Date: Fri, 19 May 2023 12:58:38 +0200 Subject: [PATCH] example of entity-class: user --- basic/Testserver.py | 4 +- basic/compexec.py | 4 +- basic/constants.py | 1 + basic/toolHandling.py | 2 +- make_workspace.py | 113 ------------------- model/Entity.py | 143 ----------------------- model/entity.py | 129 +++++++++++++++++++-- model/user.csv | 9 ++ model/user.py | 255 ++++++++++++++++++++++++++++++++++++++++++ test/test_09git.py | 23 ++-- test/test_10job.py | 2 +- test/test_15user.py | 131 ++++++++++++++++++++++ tools/config_tool.py | 30 ++++- tools/data_const.py | 1 + tools/db_abstract.py | 104 +++++++++++------ tools/dbcsv_tool.py | 10 +- tools/dbmysql_tool.py | 28 +++-- tools/dbrel_tool.py | 28 +---- tools/path_const.py | 5 + 19 files changed, 661 insertions(+), 361 deletions(-) delete mode 100644 make_workspace.py delete mode 100644 model/Entity.py create mode 100644 model/user.csv create mode 100644 model/user.py create mode 100644 test/test_15user.py diff --git a/basic/Testserver.py b/basic/Testserver.py index 9d1c552..3e94eaf 100644 --- a/basic/Testserver.py +++ b/basic/Testserver.py @@ -10,7 +10,7 @@ import tools.file_tool import tools.filecsv_fcts import model.table -COMP_NAME = "testserver" +COMP_NAME = B.ATTR_INST_TESTSERVER COMP_TABLES = ["application", "ap_component", "ap_project", "ap_application", "environment", "en_component", "en_project"] @@ -70,7 +70,7 @@ class Testserver(basic.component.Component): print("model "+m) modelPath = os.path.join(path, m) modelDoc = fct.load_file(modelPath, D.CSV_SPECTYPE_DATA) - table = model.table.Table(job, project="", application="", component="Testserver", name=m[:-4]) + table = model.table.Table(job, project="", application="", component=COMP_NAME, name=m[:-4]) sql = table.get_schema(tableName=m[:-4], tableObject=table) # [B.DATA_NODE_TABLES][m[:-4]] job.m.logInfo(sql) tables[m[:-4]] = modelDoc diff --git a/basic/compexec.py b/basic/compexec.py index dedb8c8..f681830 100644 --- a/basic/compexec.py +++ b/basic/compexec.py @@ -156,7 +156,7 @@ class Testexecuter(): def composeFileClauses(self, job, pattern): #job = basic.program.Job.getInstance() out = {} - attr = tools.db_abstract.getDbAttributes(self, job, "null") + attr = tools.db_abstract.getDbAttributes(job, self, job, "null") while "{" in pattern: pre = pattern[0:pattern.index("{")] pat = pattern[pattern.index("{"):pattern.index("}")] @@ -198,7 +198,7 @@ class Testexecuter(): print("table "+table) sql_new = sql[0:sql.upper().index(" FROM ")+5] print("sql_new "+sql_new) - attr = tools.db_abstract.getDbAttributes(self, table) + attr = tools.db_abstract.getDbAttributes(job, self, table) if attr[B.ATTR_DB_TABNAME] != "": table = attr[B.ATTR_DB_TABNAME] if attr[B.ATTR_DB_SCHEMA] != "": diff --git a/basic/constants.py b/basic/constants.py index 850de85..ee8e6e7 100644 --- a/basic/constants.py +++ b/basic/constants.py @@ -226,6 +226,7 @@ ATTR_INST_SGL = "single" LIST_INST_ATTR = [ATTR_INST_CNT, ATTR_INST_SGL] SUBJECT_COMPS = "components" ATTR_INST_SUBCOMP = SUBJECT_COMPS +ATTR_INST_TESTSERVER = "Testserver" #SUBJECT_FCT = "function" # | | | | x | main-programs """ diff --git a/basic/toolHandling.py b/basic/toolHandling.py index 86268fb..653ee67 100644 --- a/basic/toolHandling.py +++ b/basic/toolHandling.py @@ -74,7 +74,7 @@ def getDbTool(job, comp, dbtype=""): filepath = os.path.join(job.conf[B.SUBJECT_PATH][B.ATTR_PATH_PROGRAM], "tools", toolname + ".py") # comp.m.debug(verify, "toolname "+filepath) if not os.path.exists(filepath): - raise FileNotFoundError("file for tool " + toolname + " does not exist " + filepath) + raise FileNotFoundError("dbi for tool " + toolname + " does not exist " + filepath) cmodul = importlib.import_module("tools." + toolname) class_ = getattr(cmodul, "DbFcts") c = class_() diff --git a/make_workspace.py b/make_workspace.py deleted file mode 100644 index 61ddf06..0000000 --- a/make_workspace.py +++ /dev/null @@ -1,113 +0,0 @@ -# program to iinitialize the workspace -# pre: 1. program cloned -# 2. components are cloned, optional with path_const in config-folder -# post: 1. all folder are made with special name like components/const/path_const.py - otherwise with defaults -# 2. basic-configuration is created if it does not exist -# 3. necessary python-packages will be installed -# 4. git repos will be always updated -# ------------------------------------------------------------------------------------------------------------- -""" - -""" -import os - -import basic.program -import tools.path_tool -import tools.file_tool -import basic.constants as B -# look if the path-constanst are specific defined. -home = os.getcwd() -if os.path.exists(os.path.join(home, "components", "config", "path_const.py")): - import components.config.path_const as P -else: - import tools.path_const as P -# import always the keyword. -import tools.path_const as Q - -print("# ----------------------------------------------------------------------------------- ") -dirs = {} -dirs[Q.ATTR_PATH_HOME] = home -dirs[Q.ATTR_PATH_PROGRAM] = home -dirs[Q.ATTR_PATH_COMPONENTS] = os.path.join(home, "components") -pval = [P.ATTR_PATH_ARCHIV, P.ATTR_PATH_ENV, P.ATTR_PATH_DEBUG, P.ATTR_PATH_TEMP] -qkey = [Q.ATTR_PATH_ARCHIV, Q.ATTR_PATH_ENV, Q.ATTR_PATH_DEBUG, Q.ATTR_PATH_TEMP] -dirkey = [Q.ATTR_PATH_PROGRAM, Q.ATTR_PATH_COMPONENTS, Q.ATTR_PATH_HOME, Q.VAL_BASE_DATA] + qkey -home = tools.path_tool.getHome() -print("mkdirs in home " + home) -dirname = os.path.join(home, P.VAL_BASE_DATA) -dirs[Q.VAL_BASE_DATA] = dirname -if not os.path.exists(dirname): - os.makedirs(dirname, exist_ok=True) - print(" - "+dirname) -else: - print(" - " + dirname + " exists ") -dirname = os.path.join(home, P.VAL_CONFIG) -if not os.path.exists(dirname): - os.makedirs(dirname, exist_ok=True) - print(" - "+dirname) -else: - print(" - " + dirname + " exists ") - -for i in range(0, len(pval)): - dirname = os.path.join(home, P.VAL_BASE_DATA, pval[i]) - dirs[qkey[i]] = dirname - if not os.path.exists(dirname): - os.makedirs(dirname, exist_ok=True) - print(" - "+dirname) - else: - print(" - " + dirname + " exists ") - -print("\n# ----------------------------------------------------------------------------------- ") -for format in ["yml", "json", "xml"]: - filename = os.path.join(home, Q.VAL_CONFIG, B.BASIS_FILE+"."+format) - if os.path.isfile(filename): - break - filename = "" -if len(filename) < 1: - filename = os.path.join(home, Q.VAL_CONFIG, B.BASIS_FILE+".yml") - text = "basic:\n" - text += " language: en\n" - text += " paths:\n" - for d in dirkey: - text += " "+d+": "+dirs[d]+"\n" - print(text) - print(filename) - with open(filename, 'w') as file: - file.write(text) - file.close() - print("create basis-config in "+filename) - print(text) -else: - print("basis-config exists "+filename) - -print("\n# ----------------------------------------------------------------------------------- ") -print("please install requirements ") -# install requirements -# sudo apt install python3.10-venv -# python3 -m venv venv -# . venv/bin/activate -# pip install Flask - -job = basic.program.Job("unit") -print("\n# ----------------------------------------------------------------------------------- ") -import tools.git_tool -for repo in ["program", "components", "testdata"]: - tools.git_tool.gitPull(job, repo) - -print("\n# ----------------------------------------------------------------------------------- ") -if "db" in job.conf: - import basic.connection - entity = basic.connection.Connection(job) - entity.createSchema() - import model.testcase - entity = model.testcase.Testcase(job) - entity.createSchema() - import model.testsuite - entity = model.testsuite.Testsuite(job) - entity.createSchema() - import model.testplan - entity = model.testplan.Testplan(job) - entity.createSchema() - import basic.testexecution - entity = basic.testexecution.Testexecution(job) - entity.createSchema() diff --git a/model/Entity.py b/model/Entity.py deleted file mode 100644 index 2a40d72..0000000 --- a/model/Entity.py +++ /dev/null @@ -1,143 +0,0 @@ -import getpass -import os -import re -import basic.toolHandling -import tools.data_const as D -import basic.constants as B -import tools.date_tool -import tools.file_tool - -class Entity: - def __int__(self, job): - self.job = job - self.table = "" - self.testserver = None - - def get_schema(self): - """ - gets schema/ddl-informations in order to create the database - """ - raise Exception(B.EXCEPT_NOT_IMPLEMENT) - - def read_entity(self, job, name): - """ - reads the entity from the file-system - :param job: - :param name: - :return: - """ - raise Exception(B.EXCEPT_NOT_IMPLEMENT) - - def select_entity(self, job, name): - """ - reads the entity from the database - it should get the same result like read_entity - :param job: - :param name: - :return: - """ - raise Exception(B.EXCEPT_NOT_IMPLEMENT) - - def write_entity(self, job, name): - """ - writes the entity into the database - it similar to update_entity - :param job: - :param name: - :return: - """ - raise Exception(B.EXCEPT_NOT_IMPLEMENT) - - def update_entity(self, job, name): - """ - writes the entity into the database - it similar to update_entity - :param job: - :param name: - :return: - """ - raise Exception(B.EXCEPT_NOT_IMPLEMENT) - - def getDbAttr(self, job): - out = {} - for attr in [B.ATTR_DB_HOST, B.ATTR_DB_USER, B.ATTR_DB_DATABASE, B.ATTR_DB_PASSWD]: - out[attr] = job.conf[B.TOPIC_NODE_DB][attr] - return out - - def getDdl(self, job, ddl): - out = {} - for t in ddl: - out[t] = {} - for f in ddl[t]: - out[t][f] = {} - for a in ddl[t][f]: - print("entity-23 "+f+", "+a+" "+str(ddl)) - out[t][f][a] = ddl[t][f][a] - out[t][f][D.DDL_FIELD] = f - out[t][B.DATA_NODE_HEADER] = list(ddl[t].keys()) - return out - - def createSchema(self, testserver): - if B.TOPIC_NODE_DB in self.job.conf: - dbi = basic.toolHandling.getDbTool(self.job, testserver, self.job.conf[B.TOPIC_NODE_DB][B.ATTR_TYPE]) - else: - return "No DB in job-config" - sql = self.get_schema() - print(sql) - for s in sql.split(";\n"): - if len(s) < 3: continue - try: - dbi.execStatement(s+";", self.job.conf[B.TOPIC_NODE_DB]) - print("SQL executed: "+s) - except Exception as e: - raise Exception("Fehler bei createSchema "+s) - - - - - def getHistoryFields(self): - dbtype = self.job.conf[B.TOPIC_NODE_DB][B.ATTR_TYPE] - dbi = basic.toolHandling.getDbTool(self.job, None, dbtype) - sql = dbi.getSchemaAttribut("inscommit", D.TYPE_STR)+"," - sql += dbi.getSchemaAttribut("insauthor", D.TYPE_STR)+"," - sql += dbi.getSchemaAttribut("instime", D.TYPE_TIME)+"," - sql += dbi.getSchemaAttribut("updcommit", D.TYPE_STR)+"," - sql += dbi.getSchemaAttribut("updauthor", D.TYPE_STR)+"," - sql += dbi.getSchemaAttribut("updtime", D.TYPE_TIME)+"," - sql += dbi.getSchemaAttribut("actual", D.TYPE_INT) - return sql - - def selectHistoryFields(self): - if B.TOPIC_NODE_DB in self.job.conf: - dbi = basic.toolHandling.getDbTool(self.job, self.testserver, self.job.conf[B.TOPIC_NODE_DB][B.ATTR_TYPE]) - else: - return "No DB in job-config" - dbi.selectRows - - def getHistoryIndex(self, table): - dbtype = self.job.conf[B.TOPIC_NODE_DB][B.ATTR_TYPE] - dbi = basic.toolHandling.getDbTool(self.job, None, dbtype) - sql = dbi.getSchemaIndex(table, "actual") + "\n" - return sql - - -def read_spec(job, testentity, testgran, specpath): - if not os.path.isfile(specpath): - return - text = tools.file_tool.read_file_text(job, specpath, job.m) - if re.match(r".*?depricated;[jJyY]", text): - return None - spec = {} - regex = re.compile(r".*\nhead:(.*?);(.+)") - for res in regex.finditer(text): - #res = re.search(r".*head:(.*?);(.+)\n", text) - key = res.group(1) - if key == B.SUBJECT_DESCRIPTION: - spec[B.SUBJECT_DESCRIPTION] = res.group(2).replace(";", "") - elif key in [B.SUBJECT_APPS, B.PAR_APP]: - apps = res.group(2).replace(";", ",").split(",") - spec[B.SUBJECT_APPS] = apps - else: - val = res.group(2).replace(";", "") - spec[key] = val - return spec diff --git a/model/entity.py b/model/entity.py index d6bf722..784f032 100644 --- a/model/entity.py +++ b/model/entity.py @@ -2,6 +2,7 @@ import getpass import os import re import basic.toolHandling +import model.entity import tools.data_const as D import basic.constants as B import tools.date_tool @@ -25,6 +26,10 @@ SYNC_HEAD_GIT2DB = "head-git-db" SYNC_COPY_FILE2DB = "copy-file-db" SYNC_ONLY_GIT = "only-git" SYNC_ONLY_DB = "only-db" + +STORAGE_DB = B.TOPIC_NODE_DB +STORAGE_FILE = B.TOPIC_NODE_FILE + LIST_ENTITY_SYNC = [SYNC_ONLY_GIT, SYNC_FULL_GIT2DB, SYNC_HEAD_GIT2DB, SYNC_COPY_FILE2DB, SYNC_ONLY_DB] @@ -51,17 +56,96 @@ class Entity: self.table = "" self.testserver = None + def get_unique_names(self, job, storage="", project="", application="", gran="", args={}): + """ + gets the entity-names from the defined storage - the field name must be an unique identifier + :param job: + :param opt. storage: values db / files - default files + :param opt. project: select-criteria if used and defined + :param opt. application: select-criteria if used and defined + :param opt. gran: granularity values testcase / testsuite / testplan + :param opt. args additional args + :return: list of entity-names + """ + entityNames = [] + if storage == STORAGE_DB: + entityNames = self.select_unique_names(job, project, application, gran, args) + elif storage == STORAGE_FILE: + entityNames = self.read_unique_names(job, project, application, gran, args) + else: + entityNames = self.read_unique_names(job, project, application, gran, args) + return entityNames + + def get_entities(self, job, storage="", project="", application="", gran="", args={}): + """ + gets the entity-names from the defined storage + :param job: + :param opt. storage: values db / files - default files + :param opt. project: select-criteria if used and defined + :param opt. application: select-criteria if used and defined + :param opt. gran: granularity values testcase / testsuite / testplan + :param opt. args additional args + :return: list of entity-names + """ + entities = [] + entityNames = self.get_unique_names(job, storage=storage, project=project, application=application, + gran=gran, args=args) + for k in entityNames: + if storage == STORAGE_DB: + entity = self.select_entity(job, k) + elif storage == STORAGE_FILE: + entity = self.read_entity(job, k) + else: + entity = self.read_entity(job, k) + entities.append(entity) + return entities + + def read_unique_names(self, job, project, application, gran, args): + """ + reads the entity-names from file-storage + :param job: + :param opt. project: select-criteria if used and defined + :param opt. application: select-criteria if used and defined + :param opt. gran: granularity values testcase / testsuite / testplan + :param opt. args additional args + :return: list of entity-names + """ + raise Exception(B.EXCEPT_NOT_IMPLEMENT) + + def select_unique_names(self, job, project, application, gran, args): + """ + reads the entity-names from file-storage + :param job: + :param opt. project: select-criteria if used and defined + :param opt. application: select-criteria if used and defined + :param opt. gran: granularity values testcase / testsuite / testplan + :param opt. args additional args + :return: list of entity-names + """ + raise Exception(B.EXCEPT_NOT_IMPLEMENT) + + def setDbAttributes(self, job, tables): + """ + set the db-attributes like connection and ddl + :param job: + :param tables: list of table-names + :return: + """ + setattr(self, "m", job.m) + config = {} + config[B.SUBJECT_CONN] = job.conf[B.TOPIC_NODE_DB] + config[B.DATA_NODE_DDL] = {} + for t in tables: + ddl = tools.db_abstract.get_ddl(job, B.ATTR_INST_TESTSERVER, t) + config[B.DATA_NODE_DDL][t] = ddl + setattr(self, "conf", config) + def getEntity(self, job, name): if B.TOPIC_NODE_DB in job.conf: self.select_entity(job, name) #self.read_entity(job, name) else: self.read_entity(job, name) - def get_schema(self, tableName="", tableObject=None): - """ - gets schema/ddl-informations in order to create the database - """ - raise Exception(B.EXCEPT_NOT_IMPLEMENT) def read_entity(self, job, name): """ @@ -84,7 +168,17 @@ class Entity: def write_entity(self, job, name): """ - writes the entity into the database + writes the entity into the file-system + it similar to update_entity + :param job: + :param name: + :return: + """ + raise Exception(B.EXCEPT_NOT_IMPLEMENT) + + def insert_entity(self, job, name): + """ + inserts the entity into the database it similar to update_entity :param job: :param name: @@ -112,7 +206,26 @@ class Entity: """ raise Exception(B.EXCEPT_NOT_IMPLEMENT) - def delete_entity(self, job, name): + def removeEntity(self, job, name, storagepath, ext): + """ + removes the entity from the file-system + it similar to delete_entity + :param job: + :param name: single substring or list of name or dict of names with the keys as + :return: + """ + nameList = [] + if isinstance(name, dict): + nameList = name.keys() + elif isinstance(name, list): + nameList = name + else: + nameList.append(name) + for name in nameList: + pathname = os.path.join(storagepath, name + "." + ext) + os.remove(pathname) + + def delete_entity(self, job, name, table): """ deletes the entity into the database it similar to update_entity @@ -151,7 +264,7 @@ class Entity: for s in sql.split(";\n"): if len(s) < 3: continue try: - dbi.execStatement(s+";", self.job.conf[B.TOPIC_NODE_DB]) + # dbi.execStatement(s+";", self.job.conf[B.TOPIC_NODE_DB]) print("SQL executed: "+s) except Exception as e: raise Exception("Fehler bei createSchema "+s) diff --git a/model/user.csv b/model/user.csv new file mode 100644 index 0000000..5f8cfec --- /dev/null +++ b/model/user.csv @@ -0,0 +1,9 @@ +table:user;_field;type;format;index;generic;aggregat;key;acceptance;alias;description +;id;pk;autoint;N;;;T:1;;; +;username;str;vchar(256);N;;;F:1;;; +;name;str;vchar(256);N;;;;;; +;famname;str;vchar(256);N;;;;;; +;email;string;vchar(256);N;;;;;; +;password;string;vchar(256);N;;;;;; +;project;string;vchar(256);N;;;;;; +;role;string;vchar(256);N;;;;;; diff --git a/model/user.py b/model/user.py new file mode 100644 index 0000000..79f8b44 --- /dev/null +++ b/model/user.py @@ -0,0 +1,255 @@ +# --------------------------------------------------------------------------------------------------------- +# Author : Ulrich Carmesin +# Source : gitea.ucarmesin.de +# --------------------------------------------------------------------------------------------------------- +import os +import basic.toolHandling +import basic.constants as B +import model.entity +import tools.path_const as P +import tools.data_const as D +import tools.config_tool +import tools.file_tool +import tools.db_abstract +import tools.git_tool + +TABLE_NAME = "user" +""" system-name for this entity """ +FIELD_ID = "id" +FIELD_USERNAME = "username" +FIELD_NAME = "name" +FIELD_FAMNAME = "famname" +FIELD_EMAIL = "email" +FIELD_PASSWORD = "password" +FIELD_PROJECT = "project" +FIELD_ROLE = "role" +LIST_FIELDS = [FIELD_ID, FIELD_ROLE, FIELD_PROJECT, FIELD_PASSWORD, FIELD_EMAIL, FIELD_FAMNAME, FIELD_NAME, FIELD_USERNAME] +""" list of object-attributes """ + +FILE_EXTENSION = D.DFILE_TYPE_YML +UNIQUE_FIELDS = [FIELD_USERNAME] +""" unique business field as human identifer """ +IDENTIFYER_FIELDS = [FIELD_ID] +""" unique technical field as technical identifer """ + +class User(model.entity.Entity): + id = 0 + username = "" + name = "" + famname = "" + email = "" + password = "" + project = "" + role = "" + + def __int__(self, job, name=""): + self.job = job + if len(name) > 1: + self.getEntity(job, name) + + def read_unique_names(self, job, project, application, gran, args): + """ + reads the entity-names from file-storage + :param job: + :param opt. project: select-criteria if used and defined + :param opt. application: select-criteria if used and defined + :param opt. gran: granularity values testcase / testsuite / testplan + :param opt. args additional args + :return: list of entity-names + """ + outList = [] + path = os.path.join(job.conf[B.SUBJECT_PATH][B.ATTR_PATH_HOME], P.VAL_CONFIG, "user") + for k in os.listdir(path): + filename = tools.config_tool.get_plain_filename(job, k) + if "default" == filename: + continue + outList.append(filename) + return outList + + def select_unique_names(self, job, project, application, gran, args): + """ + reads the entity-names from file-storage + :param job: + :param opt. project: select-criteria if used and defined + :param opt. application: select-criteria if used and defined + :param opt. gran: granularity values testcase / testsuite / testplan + :param opt. args additional args + :return: list of entity-names + """ + outList = [] + self.setDbAttributes(job, [TABLE_NAME]) + dbi = basic.toolHandling.getDbTool(job, self, job.conf[B.TOPIC_NODE_DB]["type"]) + data = dbi.selectRows(TABLE_NAME, job) + checkList = {} + for row in data[B.DATA_NODE_DATA]: + key = "" + for f in UNIQUE_FIELDS: + key += "_" + row[f] + if key in checkList: + continue + else: + checkList[key] = key + fields = [] + for f in UNIQUE_FIELDS: + fields.append(row[f]) + outList.append(fields) + return outList + + def read_entity(self, job, name): + """ + reads the entity from the file-system + :param job: + :param name: + :return: + """ + print("name "+name) + config = model.user.User.getUserConfig(job, tools.config_tool.get_plain_filename(job, name)) + for k in LIST_FIELDS: + if k not in config: + continue + setattr(self, k, config[k]) + return self + + def select_entity(self, job, name, row={}): + """ + reads the entity from the database + it should get the same result like read_entity + :param job: + :param name: unique field as string, unique fields as list + the unique-fields are defined in the class + :return: itself with filled object-attributes + """ + if row is None or len(row) == 0: + self.setDbAttributes(job, [TABLE_NAME]) + dbi = basic.toolHandling.getDbTool(job, self, job.conf[B.TOPIC_NODE_DB]["type"]) + if type(name) is list: + names = name + elif type(name) is str: + names = [name] + condition = "where " + for v in names: + condition += " and " + "" + data = dbi.selectRows(TABLE_NAME, job, "where username = \'" + names[0] + "\'") + if len(data[B.DATA_NODE_DATA]) > 1: + raise Exception("single selection with more than one result: "+names[0]) + elif len(data[B.DATA_NODE_DATA]) == 1: + row = data[B.DATA_NODE_DATA][0] + else: + raise Exception("no result for: "+names[0]) + for k in LIST_FIELDS: + if k not in row: + continue + setattr(self, k, row[k]) + return self + + def write_entity(self, job, name): + """ + writes the entity into the file-system + it similar to update_entity + :param job: + :param name: + :return: + """ + config = {} + config[model.user.TABLE_NAME] = {} + pathname = os.path.join(job.conf[B.SUBJECT_PATH][P.ATTR_PATH_HOME], P.VAL_CONFIG, + P.VAL_USER, name + ".yml") + for k in LIST_FIELDS: + if getattr(self, k, "") == "" \ + or k == FIELD_ID: + continue + config[model.user.TABLE_NAME][k] = getattr(self, k, "") + tools.file_tool.write_file_dict(job.m, job, pathname, config) + return self + + def insert_entity(self, job, name, table="", rows={}): + """ + inserts the entity into the database + it similar to update_entity + :param job: + :param name: + :return: + """ + self.setDbAttributes(job, [TABLE_NAME]) + dbi = basic.toolHandling.getDbTool(job, self, job.conf[B.TOPIC_NODE_DB]["type"]) + condition = "where" + for f in UNIQUE_FIELDS: + # TODO other db-formats than string has to be implemented + condition += " and " + f + " = \'" + getattr(self, f, "") + "\'" + condition = condition.replace("where and", "where ") + data = dbi.selectRows(TABLE_NAME, job, condition) + if len(data[B.DATA_NODE_DATA]) > 0: + print("update statt insert") + return + if rows is None or len(rows) == 0: + insheader = dbi.getInsertFields(self.conf[B.DATA_NODE_DDL][table]) + rows = [] + row = {} + for f in insheader: + row[f] = getattr(self, f) + rows.append(row) + dbi.insertRows(job, table, rows) + + def update_entity(self, job, name): + """ + writes the entity into the database + it similar to update_entity + :param job: + :param name: + :return: + """ + raise Exception(B.EXCEPT_NOT_IMPLEMENT) + + def remove_entity(self, job, name): + """ + removes the entity from the file-system + it similar to delete_entity + :param job: + :param name: single substring or list of name or dict of names with the keys as + :return: + """ + self.removeEntity(job, name, os.path.join(job.conf[B.SUBJECT_PATH][P.ATTR_PATH_HOME], P.VAL_CONFIG, P.VAL_USER), "yml") + + def delete_entity(self, job, name, table): + """ + deletes the entity into the database + it similar to update_entity + :param job: + :param name: + :return: + """ + self.setDbAttributes(job, [TABLE_NAME]) + dbi = basic.toolHandling.getDbTool(job, self, job.conf[B.TOPIC_NODE_DB]["type"]) + condition = "where" + for f in IDENTIFYER_FIELDS: + # TODO other db-formats than string has to be implemented + val = dbi.getDbValue(self.conf[B.DATA_NODE_DDL][table][f], getattr(self, f, "")) + condition += " and " + f + " = " + val + "" + condition = condition.replace("where and", "where ") + dbi.deleteRows(job, table, condition) + + @staticmethod + def getUserConfig(job, name): + """ + reads the entity from the database + it should get the same result like read_entity + :param job: + :param name: + :return: + """ + config = tools.config_tool.getConfig(job, P.KEY_USER, name) + if config is not None: + return config + if name == model.user.User.getCurrentUser(job): + config = tools.config_tool.getConfig(job, P.KEY_USER, "default") + if "user" in config: + config = config["user"] + if config is not None: + config["username"] = name + return config + raise Exception("keine Config zu "+name) + + @staticmethod + def getCurrentUser(job): + return os.environ.get("USERNAME") + diff --git a/test/test_09git.py b/test/test_09git.py index 120c1a5..6482132 100644 --- a/test/test_09git.py +++ b/test/test_09git.py @@ -1,14 +1,11 @@ import unittest -import os import inspect -import utils.path_tool -import basic.message -import basic.program +import tools.path_tool import basic.constants as B import test.constants import test.testtools -import utils.path_const as P -import utils.git_tool +import tools.path_const as P +import tools.git_tool HOME_PATH = test.constants.HOME_PATH OS_SYSTEM = test.constants.OS_SYSTEM @@ -28,7 +25,7 @@ class MyTestCase(unittest.TestCase): if actfunction not in TEST_FUNCTIONS: return job = test.testtools.getJob() - result = utils.git_tool.runGit(job, B.ATTR_PATH_PROGRAM, "git status") + result = tools.git_tool.runGit(job, B.ATTR_PATH_PROGRAM, "git status") MyTestCase.mymsg += "\n----- "+actfunction+" : "+str(cnttest) def test_02status(self): @@ -38,7 +35,7 @@ class MyTestCase(unittest.TestCase): if actfunction not in TEST_FUNCTIONS: return job = test.testtools.getJob() - result = utils.git_tool.gitStatus(job, B.ATTR_PATH_PROGRAM) + result = tools.git_tool.gitStatus(job, B.ATTR_PATH_PROGRAM) MyTestCase.mymsg += "\n----- "+actfunction+" : "+str(cnttest) def test_03log(self): @@ -48,13 +45,13 @@ class MyTestCase(unittest.TestCase): if actfunction not in TEST_FUNCTIONS: return job = test.testtools.getJob() - result = utils.git_tool.gitLog(job, B.ATTR_PATH_COMPS) + result = tools.git_tool.gitLog(job, B.ATTR_PATH_COMPS) self.assertGreaterEqual(10, len(result)) - result = utils.git_tool.gitLog(job, B.ATTR_PATH_COMPS, cnt=1) + result = tools.git_tool.gitLog(job, B.ATTR_PATH_COMPS, cnt=1) self.assertEqual(1, len(result)) - apppath = utils.config_tool.getConfigPath(job, P.KEY_BASIC, B.SUBJECT_APPS, "") - repopath = apppath[len(job.conf.confs[B.SUBJECT_PATH][B.ATTR_PATH_COMPS])+1:] - result = utils.git_tool.gitLog(job, B.ATTR_PATH_COMPS, repopath, 1) + apppath = tools.config_tool.select_config_path(job, P.KEY_BASIC, B.SUBJECT_APPS, "") + repopath = apppath[len(job.conf[B.SUBJECT_PATH][B.ATTR_PATH_COMPS])+1:] + result = tools.git_tool.gitLog(job, B.ATTR_PATH_COMPS, repopath, 1) self.assertEqual(1, len(result)) MyTestCase.mymsg += "\n----- "+actfunction+" : "+str(cnttest) diff --git a/test/test_10job.py b/test/test_10job.py index 8ac0914..852c5d6 100644 --- a/test/test_10job.py +++ b/test/test_10job.py @@ -16,7 +16,7 @@ import tools.file_tool HOME_PATH = test.constants.HOME_PATH PYTHON_CMD = "python" TEST_FUNCTIONS = ["test_00init", "test_30startActJob"] -TEST_FUNCTIONS = ["test_30startActJob"] +TEST_FUNCTIONS = ["test_00init"] PROGRAM_NAME = "clean_workspace" diff --git a/test/test_15user.py b/test/test_15user.py new file mode 100644 index 0000000..1c42338 --- /dev/null +++ b/test/test_15user.py @@ -0,0 +1,131 @@ +import unittest +import os +import inspect +import shutil + +import tools.path_tool +import basic.program +import test.testtools +import basic.constants as B +import test.constants as T +import tools.file_tool +import model.user +import model.entity + +HOME_PATH = test.constants.HOME_PATH +PYTHON_CMD = "python" +TEST_FUNCTIONS = ["test_10getEntityNames", "test_11getEntities", "test_12getEntity", + "test_13writeEntity", "test_14insertEntity"] +TEST_FUNCTIONS = ["test_14insertEntity"] +PROGRAM_NAME = "clean_workspace" + +class MyTestCase(unittest.TestCase): + mymsg = "--------------------------------------------------------------" + + + def test_10getEntityNames(self): + global mymsg + global jobObject + actfunction = str(inspect.currentframe().f_code.co_name) + cnttest = 0 + if actfunction not in TEST_FUNCTIONS: + return + job = test.testtools.getJob() + user = model.user.User() + entityNames = [] + entityNames = user.read_unique_names(job, "", "", "", {}) + self.assertEquals(type(entityNames), list) + entityNames = user.select_unique_names(job, "", "", "", {}) + self.assertEquals(type(entityNames), list) + + def test_11getEntities(self): + global mymsg + global jobObject + actfunction = str(inspect.currentframe().f_code.co_name) + cnttest = 0 + if actfunction not in TEST_FUNCTIONS: + return + job = test.testtools.getJob() + user = model.user.User() + entityNames = [] + entityNames = user.get_entities(job, storage=model.entity.STORAGE_FILE) + self.assertEqual(type(entityNames), list) + entityNames = user.get_entities(job, storage=model.entity.STORAGE_DB) + self.assertEqual(type(entityNames), list) + + def test_12getEntity(self): + global mymsg + global jobObject + actfunction = str(inspect.currentframe().f_code.co_name) + cnttest = 0 + if actfunction not in TEST_FUNCTIONS: + return + job = test.testtools.getJob() + user = model.user.User() + name = "ulrich" + actUser = user.read_entity(job, name) + self.assertEqual(getattr(actUser, model.user.FIELD_USERNAME), name) + self.assertRaises(Exception, user.read_entity, job, "xyzxyz") + # + actUser = user.select_entity(job, name) + self.assertEqual(getattr(actUser, model.user.FIELD_USERNAME), name) + self.assertRaises(Exception, user.select_entity, job, ["xyzxyz"]) + + def test_13writeEntity(self): + global mymsg + global jobObject + actfunction = str(inspect.currentframe().f_code.co_name) + cnttest = 0 + if actfunction not in TEST_FUNCTIONS: + return + job = test.testtools.getJob() + username = "hans_xyz" + user = model.user.User() + entityNames = user.get_unique_names(job, storage=model.entity.STORAGE_FILE) + self.assertNotIn(username, entityNames) + user.username = username + user.name = "Hans" + user.famname = "im Glueck" + user.project = "TESTPROJ" + user.write_entity(job, username) + entityNames = user.get_unique_names(job, storage=model.entity.STORAGE_FILE) + self.assertIn(username, entityNames) + actUser = user.read_entity(job, username) + self.assertEquals(getattr(actUser, model.user.FIELD_USERNAME), username) + actUser.remove_entity(job, username) + entityNames = user.get_unique_names(job, storage=model.entity.STORAGE_FILE) + self.assertNotIn(username, entityNames) + + def test_14insertEntity(self): + global mymsg + global jobObject + actfunction = str(inspect.currentframe().f_code.co_name) + cnttest = 0 + if actfunction not in TEST_FUNCTIONS: + return + job = test.testtools.getJob() + username = "hans_xyz" + user = model.user.User() + entityNames = collectInnerList(user.get_unique_names(job, storage=model.entity.STORAGE_DB)) + #self.assertNotIn(username, entityNames) + user.username = username + user.name = "Hans" + user.famname = "im Glueck" + user.project = "TESTPROJ" + #user.insert_entity(job, username, table="user") + entityNames = collectInnerList(user.get_unique_names(job, storage=model.entity.STORAGE_DB)) + self.assertIn(username, entityNames) + actUser = user.select_entity(job, username) + self.assertEquals(getattr(actUser, model.user.FIELD_USERNAME), username) + actUser.delete_entity(job, username, "user") + entityNames = collectInnerList(user.get_unique_names(job, storage=model.entity.STORAGE_DB)) + self.assertNotIn(username, entityNames) + +def collectInnerList(inList): + outList = [] + for r in inList: + outList += r + return outList + +if __name__ == '__main__': + unittest.main() diff --git a/tools/config_tool.py b/tools/config_tool.py index aa11059..08dd33c 100644 --- a/tools/config_tool.py +++ b/tools/config_tool.py @@ -84,6 +84,8 @@ def select_config_path(job, modul, name, subname=""): return getTestPath(job, name, D.DFILE_TESTSUITE_NAME) elif modul == P.KEY_CATALOG: return getCatalogPath(job, name) + elif modul == P.KEY_USER: + return getUserPath(job, name) else: pathname = tools.path_tool.compose_path(job, P.P_TCPARFILE) if verify: job.debug(verify, "7 " + pathname) @@ -153,11 +155,11 @@ def getCompPath(job, name, subname, filename): configpath = getExistingPath(job, pathnames) if configpath is not None: return configpath - if name == "Testserver": + if name == B.ATTR_INST_TESTSERVER: print(name) for format in CONFIG_FORMAT: pathname = os.path.join(job.conf[B.SUBJECT_PATH][P.ATTR_PATH_PROGRAM], - "model", subname + "." + format) + P.ATTR_PATH_MODEL, subname + "." + format) print(pathname) if os.path.exists(pathname): return pathname @@ -215,6 +217,28 @@ def getCatalogPath(job, name): return path raise Exception(P.EXP_CONFIG_MISSING, name) +def getUserPath(job, name): + for ext in CONFIG_FORMAT: + pathname = os.path.join(job.conf[B.SUBJECT_PATH][P.ATTR_PATH_HOME], P.VAL_CONFIG, + P.VAL_USER, name + "." + ext) + if os.path.exists(pathname): + return pathname + return None + +def get_plain_filename(job, path): + """ + the function extracts the plain filename without directory-name and extension + :param job: + :param path: + :return: + """ + names = list(os.path.split(path)) + filename = names.pop() + for ext in CONFIG_FORMAT: + if filename[-len(ext):] == ext: + filename = filename[:-len(ext)-1] + return filename + return filename def getConfValue(attribute, comp): if attribute == B.ATTR_CONN_DBTYPE: @@ -262,6 +286,8 @@ def getConfig(job, modul, name, subname=""): if hasattr(job, "m"): msg = job.m pathname = select_config_path(job, modul, name, subname) confs = {} + if pathname is None: + return None job.debug(verify, "getConfig " + pathname) if len(pathname) < 1: return confs diff --git a/tools/data_const.py b/tools/data_const.py index 7e64bc1..5ca54ea 100644 --- a/tools/data_const.py +++ b/tools/data_const.py @@ -16,6 +16,7 @@ TYPE_DOUBLE = "double" TYPE_DATE = "date" TYPE_TIME = "time" TYPE_PK = "pk" +TYPE_AUTOINT = "autoint" # fields in DDL # _field;comment;format;acceptance;generate;nullable diff --git a/tools/db_abstract.py b/tools/db_abstract.py index 6461b6a..8e4c5de 100644 --- a/tools/db_abstract.py +++ b/tools/db_abstract.py @@ -49,9 +49,40 @@ import tools.data_const as D import tools.date_tool import os +def get_ddl(job, compName, table): + """ + this function read the ddl from the right config + :param job: + :param compName: + :param table: + :return: ddl in correct format + """ + out = {} + conf = tools.config_tool.getConfig(job, D.DDL_FILENAME, compName, table) + if B.DATA_NODE_TABLES in conf and table in conf[B.DATA_NODE_TABLES]: + ddl = conf[B.DATA_NODE_TABLES][table] + elif table in conf: + ddl = conf[table] + else: + ddl = conf + # workaround because a csv-file is loaded in wrong format + if B.DATA_NODE_DATA in ddl: + header = [] + for e in ddl[B.DATA_NODE_DATA]: + k = e[D.DDL_FIELD] + e.pop(D.DDL_FIELD) + header.append(k) + out[k] = e + for k in D.LIST_DATA_ATTR: + if k not in ddl: + continue + out[k] = ddl[k] + out[B.DATA_NODE_HEADER] = header + else: + out = ddl + return out - -def getDbAttributes(comp, table): +def getDbAttributes(job, comp, table): """ this function collects all relevant db-attributes from any location where it can be set. The location could be @@ -69,27 +100,34 @@ def getDbAttributes(comp, table): B.ATTR_DB_CONN_JAR: D.DEFAULT_DB_CONN_JAR } for attr in out.keys(): - if (B.SUBJECT_ARTS in comp.conf and table in comp.conf[B.SUBJECT_ARTS][B.TOPIC_NODE_DB]) \ - and (attr in comp.conf[B.SUBJECT_ARTS][B.TOPIC_NODE_DB][table]): - out[attr] = comp.conf[B.SUBJECT_ARTS][B.TOPIC_NODE_DB][table][attr] - print("a " + attr + " " + out[attr]) - elif (B.SUBJECT_ARTS in comp.conf and attr in comp.conf[B.SUBJECT_ARTS][B.TOPIC_NODE_DB]): - out[attr] = comp.conf[B.SUBJECT_ARTS][B.TOPIC_NODE_DB][attr] - print("b " + attr + " " + out[attr]) - elif (B.TOPIC_NODE_DB in comp.conf[B.SUBJECT_CONN]) \ - and (table in comp.conf[B.SUBJECT_CONN][B.TOPIC_NODE_DB]) \ - and (attr in comp.conf[B.SUBJECT_CONN][table][B.TOPIC_NODE_DB]): - out[attr] = comp.conf[B.SUBJECT_CONN][table][B.TOPIC_NODE_DB][attr] - print("c " + attr + " " + out[attr]) - elif (B.TOPIC_NODE_DB in comp.conf[B.SUBJECT_CONN]) \ - and (attr in comp.conf[B.SUBJECT_CONN][B.TOPIC_NODE_DB]): - out[attr] = comp.conf[B.SUBJECT_CONN][B.TOPIC_NODE_DB][attr] - print("d " + attr + " " + out[attr]) - elif (attr in comp.conf[B.SUBJECT_CONN]): - out[attr] = comp.conf[B.SUBJECT_CONN][attr] - print("e " + attr + " " + out[attr]) + if comp is None or not hasattr(comp, "conf"): + print("dbi ohne comp") + if B.TOPIC_NODE_DB not in job.conf: + raise Exception("Keine DB-Attribute in job") + if (attr in job.conf[B.TOPIC_NODE_DB]): + out[attr] = job.conf[B.TOPIC_NODE_DB][attr] else: - print("f " + attr + " " + out[attr]) + if (B.SUBJECT_ARTS in comp.conf and table in comp.conf[B.SUBJECT_ARTS][B.TOPIC_NODE_DB]) \ + and (attr in comp.conf[B.SUBJECT_ARTS][B.TOPIC_NODE_DB][table]): + out[attr] = comp.conf[B.SUBJECT_ARTS][B.TOPIC_NODE_DB][table][attr] + print("a " + attr + " " + out[attr]) + elif (B.SUBJECT_ARTS in comp.conf and attr in comp.conf[B.SUBJECT_ARTS][B.TOPIC_NODE_DB]): + out[attr] = comp.conf[B.SUBJECT_ARTS][B.TOPIC_NODE_DB][attr] + print("b " + attr + " " + out[attr]) + elif (B.TOPIC_NODE_DB in comp.conf[B.SUBJECT_CONN]) \ + and (table in comp.conf[B.SUBJECT_CONN][B.TOPIC_NODE_DB]) \ + and (attr in comp.conf[B.SUBJECT_CONN][table][B.TOPIC_NODE_DB]): + out[attr] = comp.conf[B.SUBJECT_CONN][table][B.TOPIC_NODE_DB][attr] + print("c " + attr + " " + out[attr]) + elif (B.TOPIC_NODE_DB in comp.conf[B.SUBJECT_CONN]) \ + and (attr in comp.conf[B.SUBJECT_CONN][B.TOPIC_NODE_DB]): + out[attr] = comp.conf[B.SUBJECT_CONN][B.TOPIC_NODE_DB][attr] + print("d " + attr + " " + out[attr]) + elif (attr in comp.conf[B.SUBJECT_CONN]): + out[attr] = comp.conf[B.SUBJECT_CONN][attr] + print("e " + attr + " " + out[attr]) + else: + print("f " + attr + " " + out[attr]) return out @@ -157,14 +195,14 @@ def parseSQLwhere(condition, ddl=None): return "WHERE "+dbwhere.strip() -def getSqlTable(comp, table): +def getSqlTable(job, comp, table): """ the function gets the technical tablename inclusive necessary schema information :param comp: :param table: :return: """ - attr = getDbAttributes(comp, table) + attr = getDbAttributes(job, comp, table) if attr[B.ATTR_DB_TABNAME] != "": sqltable = attr[B.ATTR_DB_TABNAME] else: @@ -240,7 +278,7 @@ def formatDbVal(msg, val, dtyp): if not isinstance(val, str): msg.logError("field must be " + dtyp + ", " + str(val)) return tools.date_tool.getFormatDatetupel(tools.date_tool.parseDate(val), tools.date_tool.F_DB_TIME) - if dtyp == D.TYPE_INT: + if dtyp in [D.TYPE_INT, D.TYPE_PK]: if not (isinstance(val, int) or re.match(r"^\d+$", val)): msg.logError("field must be " + dtyp + ", " + str(val)) return 0 @@ -282,14 +320,14 @@ class DbFcts(): self.job = job self.comp = comp - def getDbAttributes(self, table): + def getDbAttributes(self, job, table): """ this function collects all relevant db-attributes from any location where it can be set. The location could be * comp.artifact.db.[table].attr * comp.artifact.[db].[table].attr """ - return getDbAttributes(self.comp, table) + return getDbAttributes(job, self.comp, table) def selectTables(self, subdir, job): @@ -321,9 +359,9 @@ class DbFcts(): self.loadDdl(job) for t in self.comp.conf[B.DATA_NODE_DDL]: print("zu loeschende Tabelle "+t) - self.deleteRows(t, job) + self.deleteRows(job, t) - def deleteRows(self, table, job): + def deleteRows(self, job, table): """ method to delete rows from a database statement written in sql """ raise Exception(B.EXCEPT_NOT_IMPLEMENT) @@ -348,12 +386,12 @@ class DbFcts(): for t in tdata[B.DATA_NODE_TABLES]: print("einzufuegende Tabelle "+self.comp.name+" "+t) if isCompTable(self.comp, job, tdata, t): - self.insertRows(t, tdata[B.DATA_NODE_TABLES][t][B.DATA_NODE_DATA], job) + self.insertRows(job, t, tdata[B.DATA_NODE_TABLES][t][B.DATA_NODE_DATA]) self.comp.m.logMsg("in Tabelle {} {} Zeilen eingefuegt".format( t, len(tdata[B.DATA_NODE_TABLES][t][B.DATA_NODE_DATA]))) - def insertRows(self, rows): + def insertRows(self, job, table, rows): """ method to insert rows into a database the rows will be interpreted by the ddl of the component """ @@ -386,8 +424,8 @@ class DbFcts(): if D.DDL_CONSTRAINT not in fo or fo[D.DDL_CONSTRAINT] == B.SVAL_YES: return self.getDbNull() if fo[D.DATA_NODE_TYPE] == D.TYPE_STRING or fo[D.DATA_NODE_TYPE] == D.TYPE_STR: - return value.strip() - elif fo[D.DATA_NODE_TYPE] == D.TYPE_INT: + return "\'"+value.strip()+"\'" + elif fo[D.DATA_NODE_TYPE] in [D.TYPE_INT, D.TYPE_PK]: return value.strip() elif fo[D.DATA_NODE_TYPE] == D.TYPE_DOUBLE: return self.getDbDouble(value) diff --git a/tools/dbcsv_tool.py b/tools/dbcsv_tool.py index 5f018bf..6d36e36 100644 --- a/tools/dbcsv_tool.py +++ b/tools/dbcsv_tool.py @@ -23,7 +23,7 @@ class DbFcts(tools.db_abstract.DbFcts): def selectRows(self, table, job): """ method to select rows from a database statement written in sql """ - sqlTable = tools.db_abstract.getSqlTable(self.comp, table) + sqlTable = tools.db_abstract.getSqlTable(job, self.comp, table) header = "" path = utils.path_tool.composePattern(job, "{env.dompath}/"+sqlTable+".csv", self.comp) print(path) @@ -39,11 +39,11 @@ class DbFcts(tools.db_abstract.DbFcts): return tdata - def deleteRows(self, table, job): + def deleteRows(self, job, table): """ method to delete rows from a database statement written in sql """ verify = -1+job.getDebugLevel("db_tool") - sqlTable = tools.db_abstract.getSqlTable(self.comp, table) + sqlTable = tools.db_abstract.getSqlTable(job, self.comp, table) header = "" path = utils.path_tool.composePattern(job, "{env.dompath}/"+sqlTable+".csv", self.comp) for h in self.comp.conf[B.DATA_NODE_DDL][table][B.DATA_NODE_HEADER]: @@ -60,12 +60,12 @@ class DbFcts(tools.db_abstract.DbFcts): raise Exception(B.EXCEPT_NOT_IMPLEMENT) - def insertRows(self, table, rows, job): + def insertRows(self, job, table, rows): """ method to insert rows into a database the rows will be interpreted by the ddl of the component """ verify = -1+job.getDebugLevel("db_tool") - sqlTable = tools.db_abstract.getSqlTable(self.comp, table) + sqlTable = tools.db_abstract.getSqlTable(job, self.comp, table) header = "" path = utils.path_tool.composePattern(job, "{env.dompath}/"+sqlTable+".csv", self.comp) if len(rows) == 0: diff --git a/tools/dbmysql_tool.py b/tools/dbmysql_tool.py index 54789e2..03708e4 100644 --- a/tools/dbmysql_tool.py +++ b/tools/dbmysql_tool.py @@ -25,7 +25,7 @@ class DbFcts(tools.dbrel_tool.DbFcts): statement written in sql """ tdata = {} verify = -1+job.getDebugLevel("db_tool") - attr = self.getDbAttributes(B.SVAL_NULL) + attr = self.getDbAttributes(job, B.SVAL_NULL) sql = "SELECT * FROM "+attr[B.ATTR_DB_DATABASE]+"."+table if len(where) > 3: sql += " "+where @@ -43,20 +43,23 @@ class DbFcts(tools.dbrel_tool.DbFcts): r = {} i = 0 for f in self.comp.conf[B.DATA_NODE_DDL][table][B.DATA_NODE_HEADER]: - if self.comp.conf[B.DATA_NODE_DDL][table][f][D.DDL_TYPE] in [D.TYPE_TIME, D.TYPE_DATE]: - r[f] = tools.date_tool.getFormatdate(x[i], tools.date_tool.F_DIR) - else: - r[f] = str(x[i]) + try: + if self.comp.conf[B.DATA_NODE_DDL][table][f][D.DDL_TYPE] in [D.TYPE_TIME, D.TYPE_DATE]: + r[f] = tools.date_tool.getFormatdate(x[i], tools.date_tool.F_DIR) + else: + r[f] = str(x[i]) + except: + pass i += 1 tdata[B.DATA_NODE_DATA].append(r) self.comp.m.logInfo(str(tdata)) return tdata - def deleteRows(self, table, job, where=""): + def deleteRows(self, job, table, where=""): """ method to delete rows from a database statement written in sql """ verify = -1+job.getDebugLevel("db_tool") - attr = self.getDbAttributes(B.SVAL_NULL) + attr = self.getDbAttributes(job, B.SVAL_NULL) sql = "DELETE FROM "+attr[B.ATTR_DB_DATABASE]+"."+table if len(where) > 3: sql += " "+where @@ -69,12 +72,12 @@ class DbFcts(tools.dbrel_tool.DbFcts): statement written in sql """ raise Exception(B.EXCEPT_NOT_IMPLEMENT) - def insertRows(self, table, rows, job): + def insertRows(self, job, table, rows): """ method to insert rows into a database the rows will be interpreted by the ddl of the component """ verify = -1+job.getDebugLevel("db_tool") - attr = self.getDbAttributes(B.SVAL_NULL) + attr = self.getDbAttributes(job, B.SVAL_NULL) insheader = self.getInsertFields(self.comp.conf[B.DATA_NODE_DDL][table]) if len(insheader) < len(self.comp.conf[B.DATA_NODE_DDL][table][B.DATA_NODE_HEADER]): lastid = 1 @@ -89,9 +92,10 @@ class DbFcts(tools.dbrel_tool.DbFcts): rowvalues = [] for h in insheader: if (h in r): - rowvalues.append("\'"+self.getDbValue(self.comp.conf[B.DATA_NODE_DDL][table][h], r[h])+"\'") + #rowvalues.append("\'"+self.getDbValue(self.comp.conf[B.DATA_NODE_DDL][table][h], r[h])+"\'") + rowvalues.append(self.getDbValue(self.comp.conf[B.DATA_NODE_DDL][table][h], r[h])) else: - rowvalues.append("\'"+self.getDbValue(self.comp.conf[B.DATA_NODE_DDL][table][h], "")+"\'") + rowvalues.append(self.getDbValue(self.comp.conf[B.DATA_NODE_DDL][table][h], "")) sql += "("+",".join(rowvalues)+"), " values.append(tuple(rowvalues)) sql = sql[0:-2] @@ -129,7 +133,7 @@ class DbFcts(tools.dbrel_tool.DbFcts): this method should only called by the class itself """ job = self.job # basic.program.Job.getInstance() if conn is None: - conn = self.getDbAttributes(B.SVAL_NULL) + conn = self.getDbAttributes(job, B.SVAL_NULL) cnx = mysql.connector.connect( host=conn[B.ATTR_DB_HOST], user=conn[B.ATTR_DB_USER], diff --git a/tools/dbrel_tool.py b/tools/dbrel_tool.py index ecdb176..c333902 100644 --- a/tools/dbrel_tool.py +++ b/tools/dbrel_tool.py @@ -35,7 +35,7 @@ class DbFcts(tools.db_abstract.DbFcts): self.comp.m.logInfo(cmd) return tdata - def deleteRows(self, table, job): + def deleteRows(self, job, table): """ method to delete rows from a database statement written in sql """ verify = -1+job.getDebugLevel("db_tool") @@ -47,7 +47,7 @@ class DbFcts(tools.db_abstract.DbFcts): statement written in sql """ raise Exception(B.EXCEPT_NOT_IMPLEMENT) - def insertRows(self, table, rows, job): + def insertRows(self, job, table, rows): """ method to insert rows into a database the rows will be interpreted by the ddl of the component """ @@ -75,17 +75,6 @@ class DbFcts(tools.db_abstract.DbFcts): cmd = cmd[0:-1]+";" self.comp.m.logInfo(cmd) - def getConnector(self): - """ add-on-method to get the connector - this method should only called by the class itself """ - job = self.job # basic.program.Job.getInstance() - mydb = mysql.connector.connect( - host = "localhost", - user = "datest", - password = "Advent!2021", - database = "datest" - ) - return mysql def getCreateTable(self, table): sql = "CREATE TABLE IF NOT EXISTS " + self.job.conf[B.TOPIC_NODE_DB][B.ATTR_DB_DATABASE] + "."+table+" (" return sql @@ -127,19 +116,6 @@ class DbFcts(tools.db_abstract.DbFcts): sql += " ( " + attr + " );" return sql - - def getConnector(self, job): - """ add-on-method to get the connector - this method should only called by the class itself """ - job = self.job # basic.program.Job.getInstance() - mydb = mysql.connector.connect( - host = "localhost", - user = "datest", - password = "Advent!2021", - database = "datest" - ) - return mysql - @staticmethod def execStatement(self, statement, conn=None): """ add-on-method to execute the statement diff --git a/tools/path_const.py b/tools/path_const.py index fd07711..dcc5062 100644 --- a/tools/path_const.py +++ b/tools/path_const.py @@ -14,6 +14,7 @@ KEY_REFFILE = "reffile" KEY_TESTCASE = "tc" KEY_TESTSUITE = "ts" KEY_CATALOG = "catalog" +KEY_USER = "user" KEY_DEBUGNAME = "debugname" KEY_LOGNAME = "logname" KEY_BASIC = "basic" @@ -28,6 +29,8 @@ VAL_CONFIG = "config" """ subdir for any place of config-files """ VAL_COMPS = "components" """ subdir for the plugin components """ +VAL_USER = "user" +""" subdir for the created user """ VAL_BASIC = "basic" """ subdir for the basic job-framework """ VAL_BASE_DATA = "data" @@ -73,6 +76,8 @@ ATTR_PATH_PROGRAM = "program" """ This constant defines the program-folder in the workspace """ ATTR_PATH_COMPONENTS = "components" """ This constant defines the program-folder in the workspace """ +ATTR_PATH_MODEL = "model" +""" This constant defines the folder in model """ ATTR_PATH_ENV = "environment" """ This constant defines the folder in testing-filesystem, used for configs related to environments """ ATTR_PATH_RELEASE = "release"