diff --git a/sohstationviewer/conf/constants.py b/sohstationviewer/conf/constants.py index 0d53139ae6799e804d66dfd7c1a257ac2fb423e6..a22967c58363f036b5dfa57d4691549069e8e523 100644 --- a/sohstationviewer/conf/constants.py +++ b/sohstationviewer/conf/constants.py @@ -4,8 +4,7 @@ HIGHEST_INT = 1E100 # warn user if file bigger than this size BIG_FILE_SIZE = 10**8 -# Perfomance will be slow if data point total > than this limit -# => downsampled +# Matplotlib's performance be slow if data point total > than this limit CHAN_SIZE_LIMIT = 10**6 # If total waveform datapoint > than this limit, not recalculate diff --git a/sohstationviewer/controller/plottingData.py b/sohstationviewer/controller/plottingData.py index c6900d424a9d6a02ad363d9ee708c96471180906..76fa3cb18100190b45ce640782fadd08169095b6 100755 --- a/sohstationviewer/controller/plottingData.py +++ b/sohstationviewer/controller/plottingData.py @@ -1,9 +1,8 @@ """ -Functions that process data before plotting +Functions that process data for plotting """ import math -import numpy as np from obspy import UTCDateTime from sohstationviewer.conf import constants as const @@ -19,25 +18,32 @@ MassPosColorPallets = {"B": ["C", "G", "Y", "R", "M"], "W": ["B", "B", "B", "B", "B"]} -def getMassposValueColors(rangeOpt, chan, cMode, errors, retType='str'): +def getMassposValueColors(rangeOpt, chan_id, cMode, errors, retType='str'): + """ + Create a map between value and color based on given rangeOpt and cMode to + display mass possition plots. + :param rangeOpt: massPosVoltRangeOpt got from Options Menu - MP coloring + in Main Window to define different values for mass position. + (regular/trillium) + :param chan_id: str - ID of the channel + :param cMode: str - color mode (B/W) + :param errors: list of str - error list + :param retType: str - request return type + :return: [(float, str), ] - [(value, color), (value, color) ...] + if retType is 'str', return "value:color|value:color" + """ + if rangeOpt.lower() not in MassPosVoltRanges.keys(): errors.append("%s: The current selected Mass Position color range " "is '%s' isn't allowable. The accept ranges are: %s" - % (chan, rangeOpt, ', '.join(MassPosVoltRanges.keys()))) + % (chan_id, rangeOpt, + ', '.join(MassPosVoltRanges.keys()))) print("ERRORS:", errors) return massPosVoltRange = MassPosVoltRanges[rangeOpt] massPosColorPallet = MassPosColorPallets[cMode] - mul = -1 valueColors = [] - """ - remove size for masspos because there are two many points for one plot - which make the line thicks - TODO: show something to let user know that it is clickable. - """ for i in range(len(massPosVoltRange)): - if i % 2 == 0: - mul += 1 if retType == 'str': valueColors.append( "%s:%s" % (massPosVoltRange[i], massPosColorPallet[i])) @@ -57,11 +63,11 @@ def getMassposValueColors(rangeOpt, chan, cMode, errors, retType='str'): def formatTime(time, dateMode, timeMode=None): """ - :param parent: parent GUI to display tracking info + Format time according to date_mode and time_mode :param time: time to be format, can be UTCDateTime or epoch time - :param dateMode: the format of date - :param timeMode: the format of time - :return: the formated time string + :param dateMode: str - the format of date + :param timeMode: str - the format of time + :return: the formatted time string - str """ if isinstance(time, UTCDateTime): t = time @@ -84,21 +90,19 @@ def formatTime(time, dateMode, timeMode=None): return ret -def getTitle(staID, minTime, maxTime, dateMode): +def getTitle(key, minTime, maxTime, dateMode): """ - :param setID: (netID, statID, locID) - :param plottingData: a ditionary including: - { gaps: [(t1,t2),(t1,t2),...] (in epoch time) - channels:[cha: {netID, statID, locID, chanID, times, data, - startTmEpoch, endTmEpoch} - earliestUTC: the earliest time of all channels - latestUTC: the latest time of all channels - :return: title for the plot + Create title for the plot. + :param key: str or (str, str) sta_id for mseed, (unit_id, exp_no) for rt130 + :param minTime: float - start time of the plot + :param maxTime: float - end time of the plot + :param dateMode: str - format of date + :return: title for the plot - str """ diff = maxTime - minTime hours = diff/3600 - return ("Station: %s %s to %s (%s)" % - (staID, + return ("%s %s to %s (%s)" % + (key, formatTime(minTime, dateMode, "HH:MM:SS"), formatTime(maxTime, dateMode, "HH:MM:SS"), round(hours, 2)) @@ -107,8 +111,8 @@ def getTitle(staID, minTime, maxTime, dateMode): def getGaps(gaps, gapMin): """ - :param gaps: list of gaps - :param gapMin: minimum of gaps count in minutes + :param gaps: [[float, float],] - list of gaps + :param gapMin: int - minimum of gaps count in minutes return list of gaps of which gaps smaller than gapMin have been removed """ gapMinSec = gapMin * 60 @@ -117,17 +121,18 @@ def getGaps(gaps, gapMin): def getTimeTicks(earliest, latest, dateFormat, labelTotal): """ - split time range into parts to use for tick labels + split time range to use for tick labels Ex: getTimeTicks(1595542860.0, 1595607663.91, 'YYYY-MM-DD', 3) - :param earliest: earliest epoch time - :param latest: latest epoch time - :param dateFormat: YYYY:DOY, YYYY-MM-DD or YYYYMMMDD - :param labelTotal: number of time label to be displayed, - others will show as ticks oly + :param earliest: float - earliest epoch time + :param latest: float - latest epoch time + :param dateFormat: str - (YYYY:DOY, YYYY-MM-DD or YYYYMMMDD) + (selected in Menu Options - Date Format) + :param labelTotal: int - number of time label to be displayed, + others will show as ticks oly :return: - times: list of times - majorTimes: list of time of lables to be displayed - majorTimelabels: list of labels displayed + times: [float,] - list of times to show ticks + majorTimes: [float,] - list of times for displayed labels + majorTimelabels: [str,] - list of labels displayed """ timeRange = latest - earliest if timeRange >= 2592000.0: @@ -176,6 +181,15 @@ def getTimeTicks(earliest, latest, dateFormat, labelTotal): def getDayTicks(): + """ + Get information for displaying time on plotting widget. + :return: + times: [int,] - list of indexes of every hour in each_day_5_min_list + majorTimes: [int,] - list of indexes of every 4 hours in + each_day_5_min_list + majorTimeLabels: [str,] - 2 digit numbers of every 4 hours in a day + """ + times = list(range(const.NO_5M_1H, const.NO_5M_DAY, const.NO_5M_1H)) majorTimes = list(range(4*const.NO_5M_1H, const.NO_5M_DAY, @@ -184,15 +198,17 @@ def getDayTicks(): return times, majorTimes, majorTimeLabels -def getUnitBitweight(chanDB, bitweightOpt, isWF=False): +def getUnitBitweight(chanDB, bitweightOpt): """ - :param chanDB: channel's info got from database - :param bitweightOpt: qpeek's OPTBitWeightRVar - Commands: Show Seismic Data In Counts - None - Use Q330 Low Gain - Low - Use Q330 High Gain - High - :return: unit with fixed point decimal and bitweight if applicable + Get the format to diplay value including fixed point decimal and unit based + on the information from the database. + :param chanDB: dict - channel's info got from database + :param bitweightOpt: str - option for bitweight (none, low, high) + (Menu Options - Q330 Gain) + :return unitBitweight: str - format for displayed value on the left of each + plot with fixed point decimal and unit """ + plotType = chanDB['plotType'] # Not all channels use/have this field. unit = chanDB['unit'] @@ -217,14 +233,3 @@ def getUnitBitweight(chanDB, bitweightOpt, isWF=False): else: unitBitweight = "{}%s" % unit return unitBitweight - - -def convertWFactor(cData, convertFactor): - """ - convertFactor = 150mV/count = 150V/1000count - => unit data * convertFactor= data *150/1000 V - convert data in numpy arrays to a reduced list - according to max number of datapoint needed - """ - cData['decData'] = np.multiply(cData['data'], [convertFactor]) - return cData diff --git a/sohstationviewer/controller/processing.py b/sohstationviewer/controller/processing.py index 09ebab228c9fb53534efe779b3c18a2d5e82e1ce..b9a89925031175924a4ca59807902509e8308378 100644 --- a/sohstationviewer/controller/processing.py +++ b/sohstationviewer/controller/processing.py @@ -1,6 +1,12 @@ +""" +Function that ignite from MainWindow, Dialogs to read data files for data, +channels, datatype +""" + import os import json import re +from pathlib import Path from obspy.core import read as read_ms from obspy.io.reftek.core import Reftek130Exception @@ -11,29 +17,37 @@ from sohstationviewer.database.extractData import signatureChannels from sohstationviewer.controller.util import validateFile, displayTrackingInfo -def loadData(dataType, parent, listOfDir, reqWFChans=[], reqSOHChans=[], +def loadData(dataType, tracking_box, listOfDir, reqWFChans=[], reqSOHChans=[], readStart=None, readEnd=None): """ Go through root dir and read all files in that dir and its subdirs + :param dataType: str - type of data read + :param tracking_box: QTextBrowser - widget to display tracking info + :param listOfDir: [str,] - list of directories selected by users + :param reqWFChans: [str,] - requested waveform channel list + :param reqSOHChans: [str,] - requested soh channel list + :param readStart: [float,] - start time of read data + :param readEnd: [float,] - finish time of read data + :return dataObject: DataTypeModel - object that keep the data read from + listOfDir """ - print("dataType:", dataType) dataObject = None for d in listOfDir: if dataObject is None: if dataType == 'RT130': dataObject = RT130( - parent, d, reqWFChans=reqWFChans, reqSOHChans=reqSOHChans, + tracking_box, d, + reqWFChans=reqWFChans, reqSOHChans=reqSOHChans, readStart=readStart, readEnd=readEnd) - print("dataObject:", dataObject) else: try: dataObject = MSeed( - parent, d, reqWFChans=reqWFChans, + tracking_box, d, reqWFChans=reqWFChans, reqSOHChans=reqSOHChans, readStart=readStart, readEnd=readEnd) except Exception as e: msg = f"Dir {d} can't be read due to error: {str(e)}" - displayTrackingInfo(parent, msg, "Warning") + displayTrackingInfo(tracking_box, msg, "Warning") pass # if dataObject.hasData(): # continue @@ -47,10 +61,14 @@ def loadData(dataType, parent, listOfDir, reqWFChans=[], reqSOHChans=[], return dataObject -def readChannels(parent, listOfDir): +def readChannels(tracking_box, listOfDir): """ - TODO: have to solve this later for changes of data type - Scan available channels for channel prefer dialog + Scan available channels (to be used in channel preferences dialog). Since + channels for RT130 is hard code, this function won't be applied for it. + :param tracking_box: QTextBrowser - widget to display tracking info + :param listOfDir: [str,] - list of directories selected by users + :return dataObject: DataTypeModel - object that keep the data read from + listOfDir """ dataObject = None for d in listOfDir: @@ -60,7 +78,7 @@ def readChannels(parent, listOfDir): # continue # dataObject = MSeed_Text(parent, d, readChanOnly=True) - dataObject = MSeed(parent, d, readChanOnly=True) + dataObject = MSeed(tracking_box, d, readChanOnly=True) if len(dataObject.channels) == 0: # If no data can be read from the first dir, throw exception raise Exception("No data can be read from ", d) @@ -69,14 +87,19 @@ def readChannels(parent, listOfDir): return dataObject.channels -def detectDataType(parent, listOfDir): +def detectDataType(tracking_box, listOfDir): """ - For each dir in listOfDir, use getDataTypeFromFile to identify the type - of data for that dir if find a signature channel - return: - + None if there are more than one types of data detected - + dataType found, Unknown data maybe return + Detect data type for the given directories using getDataTypeFromFile + :param tracking_box: QTextBrowser - widget to display tracking info + :param listOfDir: [str,] - list of directories selected by users + :return: None/str - + + if there are more than one data types detected, + return None with a warning message + + if only Unknown data type detected, + return None with a warning message + + if data type found, return data_type, """ + sign_chan_dataType_dict = signatureChannels() dirDataTypeDict = {} @@ -84,7 +107,7 @@ def detectDataType(parent, listOfDir): dataType = "Unknown" for path, subdirs, files in os.walk(d): for fileName in files: - path2file = os.path.join(path, fileName) + path2file = Path(path).joinpath(fileName) if not validateFile(path2file, fileName): continue ret = getDataTypeFromFile(path2file, sign_chan_dataType_dict) @@ -105,18 +128,32 @@ def detectDataType(parent, listOfDir): msg = (f"There are more than one types of data detected:\n" f"{dirDataTypeStr}\n\n" f"Please have only data that related to each other.") - displayTrackingInfo(parent, msg, "error") + displayTrackingInfo(tracking_box, msg, "error") + return + + elif dataTypeList == [('Unknown', '_')]: + msg = ("There are no known data detected.\n" + "Please select different folder(s).") + displayTrackingInfo(tracking_box, msg, "error") return - # elif list(dirDataTypeDict.values())[0] == "Can't be identified.": - # msg = (f"There are no known data detected.\n" - # f"Please select different folder(s).") - # displayTrackingInfo(parent, msg, "error") - # return + return list(dirDataTypeDict.values())[0] -def getDataTypeFromFile(path2file, sign_chan_dataType_dict): - stream = None +def getDataTypeFromFile(path2file, sign_chan_data_type_dict): + """ + + Try to read mseed data from given file + if catch TypeError: no data type detected => return None + if catch Reftek130Exception: data type => return data type RT130 + otherwise data type is mseed which includes: q330, pegasus, centaur + + Continue to identify data type for a file by checking if the channel + in that file is a unique channel of a data type. + :param path2file: str - absolute path to processed file + :param sign_chan_data_type_dict: {str: str} - dict of unique chan for data + type + :return: str, str - detected data type, channel from which data type is + detected + """ try: stream = read_ms(path2file) except TypeError: @@ -126,5 +163,5 @@ def getDataTypeFromFile(path2file, sign_chan_dataType_dict): for trace in stream: chan = trace.stats['channel'] - if chan in sign_chan_dataType_dict.keys(): - return sign_chan_dataType_dict[chan], chan + if chan in sign_chan_data_type_dict.keys(): + return sign_chan_data_type_dict[chan], chan diff --git a/sohstationviewer/controller/util.py b/sohstationviewer/controller/util.py index acd18017bcac211556c4e3cb4ee565f2825f6213..8a21a9905d30e3ada1fe646ad2d00937dd422f29 100644 --- a/sohstationviewer/controller/util.py +++ b/sohstationviewer/controller/util.py @@ -1,3 +1,7 @@ +""" +basic functions: format, validate, display tracking +""" + import os import re from datetime import datetime @@ -5,16 +9,31 @@ from obspy import UTCDateTime def validateFile(path2file, fileName): + """ + Check if fileName given is a file and not info file + :param path2file: str - absolute path to file + :param fileName: str - name of the file + :return: bool - True if pass checking, False if not. + """ + if fileName.strip() == '.DS_Store' or fileName.startswith('._'): # skip mac's info file return False - if not os.path.isfile(os.path.join(path2file)): + if not os.path.isfile(path2file): return False return True def displayTrackingInfo(trackingBox, text, type='info'): + """ + Display text in the given widget with different background and text colors + :param trackingBox: QTextBrowser - widget to display tracking info + :param text: str - info to be displayed + :param type: str - (info/warning/error) type of info to be displayed in + different color + """ + if trackingBox is None: print(f"{type}: {text}") return @@ -40,6 +59,14 @@ def displayTrackingInfo(trackingBox, text, type='info'): def getDirSize(dir): + """ + Get size of directory and size of file. + :param dir: str - absolute path to directory + :return: + totalSize: int - total size of the directory + totalFile: int - total file of the directory + """ + totalSize = 0 totalFile = 0 for path, subdirs, files in os.walk(dir): @@ -55,7 +82,11 @@ def getDirSize(dir): def getTime6(timeStr): """ - Get time from 6 parts string.Ex: 01:251:09:41:35:656/2001:251:09:41:35:656 + Get time from 6 parts string. + (year:day of year:hour:minute:second:millisecond) + Ex: 01:251:09:41:35:656/ 2001:251:09:41:35:656 + in which year in the first part can be 2 digits or 6 digits + :param timeStr: str - 6 part time string """ year = timeStr.split(':')[0] if len(year) == 2: @@ -66,7 +97,9 @@ def getTime6(timeStr): def getTime6_2y(timeStr): """ - Get time from 6 parts string.Ex: 01:251:09:41:35:656 + Get time from 6 parts string in which year has 2 digits. + Ex: 01:251:09:41:35:656 + :param timeStr: str - 6 part time string with 2 digits for year """ # pad 0 so the last part has 6 digits to match with the format str timeStr = timeStr.ljust(22, "0") @@ -77,7 +110,9 @@ def getTime6_2y(timeStr): def getTime6_4y(timeStr): """ - Get time from 6 parts string.Ex: 2001:251:09:41:35:656 + Get time from 6 parts string in which year has 4 digits. + Ex: 2001:251:09:41:35:656 + :param timeStr: str - 6 part time string with 4 digits for year """ # pad 0 so the last part has 6 digits to match with the format str timeStr = timeStr.ljust(24, "0") @@ -88,7 +123,15 @@ def getTime6_4y(timeStr): def getTime4(timeStr, trackingYear, yAdded): """ - Get time from 4 parts string. Ex: 253:19:41:42 + Get time from 4 parts string. (day of year:hour:minute:second) + Ex: 253:19:41:42 + :param timeStr: str - time string + :param trackingYear: int - year that has been detected + :param yAdded: bool - flag to tell if year has been plussed 1 or not + :return: + + utcTime.timestamp: float: epoch time + + time.year: int: year + + yAdded: bool - flag to tell if year has been plussed 1 or not """ if not yAdded: # first day => move to next year @@ -104,26 +147,33 @@ def getTime4(timeStr, trackingYear, yAdded): def getVal(text): """ - return value part including +/-, remove str that follows + Get the value part of a string with non-number substring following. + :param text: str - value string including unit + :return: value part including +/-, remove str that follows - float """ REVal = '^\+?\-?[0-9]+\.?[0-9]?' # noqa: W605 return float(re.search(REVal, text).group()) def isBinaryStr(text): + """ + :param text: str: text to check + :return: bool - True if text is a binary string or False if not + """ + return lambda b: bool(b.translate(None, text)) -###################################### -# BEGIN: rtnPattern(In, Upper = False) -# LIB:rtnPattern():2006.114 - Logpeek def rtnPattern(text, upper=False): """ - return format of the string with: + This function is from logpeek's rtnPattern. + return routine pattern of the string with: + 0 for digit + a for lowercase + A for upper case + remain special character + :param text: str - text to get format + :return rtn: str - routine pattern of the string """ rtn = "" for c in text: @@ -139,15 +189,15 @@ def rtnPattern(text, upper=False): if upper is True: return rtn.upper() return rtn -# END: rtnPattern -#################### -# BEGIN: fmti(Value) -# LIB:fmti():2018.235 -# Just couldn't rely on the system to do this, although this won't handle -# European-style numbers. def fmti(Value): + """ + This function is from logpeek's fmti + Given Value will be convert to a string integer with thousand separators + :param Value: str - string of value with unit + :return NewValue: str - new value with no unit and with thousand separators + """ Value = int(Value) if Value > -1000 and Value < 1000: return str(Value) @@ -170,4 +220,3 @@ def fmti(Value): NewValue = NewValue[1:] NewValue = Value[0] + NewValue return NewValue -# END: fmti diff --git a/sohstationviewer/database/extractData.py b/sohstationviewer/database/extractData.py index affffad6a432923e7ae9c5e4385b36f9542f5cbd..f12209bc00bf7cf9410b8d87efd25323cc13dcb2 100755 --- a/sohstationviewer/database/extractData.py +++ b/sohstationviewer/database/extractData.py @@ -1,12 +1,19 @@ +""" +Read DB for necessary information +""" from sohstationviewer.database.proccessDB import executeDB_dict, executeDB from sohstationviewer.conf.dbSettings import dbConf -def getChanPlotInfo(orgChan, dataType): +def getChanPlotInfo(orgChan, data_type): """ - Given chanID read from raw data file and detected dataType - Return plotting info from DB for that channel + Given chanID read from raw data file and detected dataType + Return plotting info from DB for that channel + + :param orgChan: str - channel ID from raw data file + :param data_type: str - data type detected + :return chanInfo: dict - plotting info from DB for that channel """ chan = orgChan if orgChan.startswith('EX'): @@ -27,11 +34,11 @@ def getChanPlotInfo(orgChan, dataType): o_sql = ("SELECT channel, plotType, height, unit, linkedChan," " convertFactor, label, fixPoint, valueColors " "FROM Channels as C, Parameters as P") - if dataType == 'Unknown': + if data_type == 'Unknown': sql = f"{o_sql} WHERE channel='{chan}' and C.param=P.param" else: sql = (f"{o_sql} WHERE channel='{chan}' and C.param=P.param" - f" and dataType='{dataType}'") + f" and dataType='{data_type}'") # print("SQL:", sql) chanInfo = executeDB_dict(sql) @@ -60,15 +67,27 @@ def getChanPlotInfo(orgChan, dataType): def getWFPlotInfo(orgChan): + """ + Similar to getChanPlotInfo but for waveform channel (param=Seismic data) + :param orgChan: str - channel ID from raw data file + :return chanInfo: dict - plotting info from DB for that waveform channel + """ chanInfo = executeDB_dict( - "SELECT * FROM Parameters WHERE param='Seismic data'") - chanInfo[0]['label'] = getChanLabel(orgChan) - chanInfo[0]['unit'] = '' - chanInfo[0]['channel'] = 'SEISMIC' - return chanInfo[0] + "SELECT * FROM Parameters WHERE param='Seismic data'")[0] + chanInfo['label'] = getChanLabel(orgChan) + chanInfo['unit'] = '' + chanInfo['channel'] = 'SEISMIC' + return chanInfo def getChanLabel(chanID): + """ + Get waveform channel label for the given chan_id in which: + + RT130's start with DS, remain unchanged + + MSEED's need to change last character according to dbConf[seisLabel] + :param chanID: str - channel name + :return label: str - plot's label for the channel + """ if chanID.startswith("DS"): label = chanID else: @@ -78,7 +97,9 @@ def getChanLabel(chanID): def signatureChannels(): """ - return the dict {channel: dataType} in which channel is unique for dataType + Get channels that are unique for datatype. + :return: {str: str,} - the dict {channel: dataType,} + in which channel is unique for dataType """ sql = ("SELECT channel, dataType FROM Channels where channel in" "(SELECT channel FROM Channels GROUP BY channel" @@ -89,12 +110,23 @@ def signatureChannels(): def getColorDef(): + """ + Get TPS Color definition from DB + :return [str,]: list of color names + """ sql = "SELECT color FROM TPS_ColorDefinition ORDER BY name ASC" rows = executeDB(sql) return [r[0] for r in rows] def getColorRanges(): + """ + Get TPS color range from DB + :return rangeNames: [str,] - 'antarctica'/'low'/'med'/'high' + :return allSquareCounts: [[int,],] - time-power-squared range + (base_count * 10 ** (level-1)) ** 2 + :return clrLabels: [str,] - labels that define count range for colors + """ sql = "SELECT name, baseCounts FROM TPS_ColorRange" rows = executeDB(sql) rangeNames = [r[0] for r in rows] diff --git a/sohstationviewer/database/proccessDB.py b/sohstationviewer/database/proccessDB.py index 6533e82b16ef00d438b5c485851d05aa42ac090a..b28756639950b3d7c7adf0d8b5880c35d31aafb0 100755 --- a/sohstationviewer/database/proccessDB.py +++ b/sohstationviewer/database/proccessDB.py @@ -1,3 +1,6 @@ +""" +basic executing database functions +""" import sqlite3 from sohstationviewer.conf.dbSettings import dbConf @@ -5,7 +8,9 @@ from sohstationviewer.conf.dbSettings import dbConf def executeDB(sql): """ - used for both execute and query data + Execute or fetch data from DB + :param sql: str - request string to execute or fetch data from database + :return rows: [(str/int,] - result of querying DB """ conn = sqlite3.connect(dbConf['dbpath']) cur = conn.cursor() @@ -22,7 +27,9 @@ def executeDB(sql): def executeDB_dict(sql): """ - query data and return rows in dictionary with fields as keys + Fetch data and return rows in dictionary with fields as keys + :param sql: str - request string to fetch data from database + :return: [dict,] - result of fetching DB in which each row is a dict """ conn = sqlite3.connect(dbConf['dbpath']) conn.row_factory = sqlite3.Row @@ -39,7 +46,11 @@ def executeDB_dict(sql): def trunc_addDB(table, sqls): """ - truncate table and refill with new data + Truncate table and refill with new data + :param table: str - name of data table to process + :param sqls: [str, ] - list of INSERT query to add values to table + :return: str: error message if not successful + or bool(True): if successful """ try: conn = sqlite3.connect(dbConf['dbpath']) @@ -47,7 +58,6 @@ def trunc_addDB(table, sqls): cur.execute('BEGIN') cur.execute(f'DELETE FROM {table}') for sql in sqls: - print("sql:", sql) cur.execute(sql) cur.execute('COMMIT') except sqlite3.Error as e: