testsuit 0.1.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. testsuit/__init__.py +15 -0
  2. testsuit/cli/__init__.py +0 -0
  3. testsuit/cli/apply_clock_correction.py +167 -0
  4. testsuit/cli/data2db.py +82 -0
  5. testsuit/cli/data2h5.py +168 -0
  6. testsuit/cli/datapack.py +46 -0
  7. testsuit/cli/evalfile.py +88 -0
  8. testsuit/cli/exploit_runner.py +122 -0
  9. testsuit/cli/extract_data_any.py +307 -0
  10. testsuit/cli/extract_data_flags.py +249 -0
  11. testsuit/cli/mxp.py +75 -0
  12. testsuit/cli/notebooks.py +42 -0
  13. testsuit/datatools/DataFileMgrs/AFileMgr.py +443 -0
  14. testsuit/datatools/DataFileMgrs/CsvFileMgr.py +671 -0
  15. testsuit/datatools/DataFileMgrs/DxdFileMgr.py +183 -0
  16. testsuit/datatools/DataFileMgrs/FolderParamMgr.py +553 -0
  17. testsuit/datatools/DataFileMgrs/H5FileMgr.py +644 -0
  18. testsuit/datatools/DataFileMgrs/InfluxDbFileMgr.py +838 -0
  19. testsuit/datatools/DataFileMgrs/MdfFileMgr.py +175 -0
  20. testsuit/datatools/DataFileMgrs/TdmsFileMgr.py +177 -0
  21. testsuit/datatools/DataFileMgrs/UdbfFileMgr.py +204 -0
  22. testsuit/datatools/DataFileMgrs/__init__.py +0 -0
  23. testsuit/datatools/DataFileMgrs/formats.py +262 -0
  24. testsuit/datatools/DataframeToHdf5.py +139 -0
  25. testsuit/datatools/__init__.py +1 -0
  26. testsuit/datatools/data2db.py +977 -0
  27. testsuit/datatools/datapack/ADataImporter.py +52 -0
  28. testsuit/datatools/datapack/GitImporter.py +72 -0
  29. testsuit/datatools/datapack/__init__.py +0 -0
  30. testsuit/datatools/datapack/datapack_tools.py +565 -0
  31. testsuit/datatools/datapack/evalfiles/evalfile.py +328 -0
  32. testsuit/datatools/datapack/evalfiles/evalincludes.py +343 -0
  33. testsuit/datatools/datapack/evalfiles/evalkeys.py +309 -0
  34. testsuit/datatools/datapack/evalfiles/evalpath.py +373 -0
  35. testsuit/datatools/datapack/evalfiles/libdictionary.py +255 -0
  36. testsuit/datatools/datapack/importers.py +75 -0
  37. testsuit/datatools/datapack/processors/basickeys.py +62 -0
  38. testsuit/datatools/datapack/processors/filterkeys.py +33 -0
  39. testsuit/datatools/datapack/processors/finalize.py +42 -0
  40. testsuit/datatools/datapack/processors/replace.py +53 -0
  41. testsuit/datatools/datatoolbox.py +496 -0
  42. testsuit/datatools/h5diff.py +154 -0
  43. testsuit/datatools/plotHelpers.py +973 -0
  44. testsuit/exploit/mexploit/__init__.py +0 -0
  45. testsuit/exploit/mexploit/conftest.py +461 -0
  46. testsuit/exploit/mexploit/conftest_scn_template.py +25 -0
  47. testsuit/exploit/mexploit/criteria.py +1202 -0
  48. testsuit/exploit/mexploit/helpers.py +509 -0
  49. testsuit/exploit/mexploit/mexploit.py +229 -0
  50. testsuit/exploit/mexploit/registry.py +98 -0
  51. testsuit/exploit/runner/__init__.py +0 -0
  52. testsuit/exploit/runner/exploit_runner.py +483 -0
  53. testsuit/exploit/runner/report.py +153 -0
  54. testsuit/exploit/runner/report_html.py +1688 -0
  55. testsuit/exploit/runner/runProcess.py +241 -0
  56. testsuit/exploit/runner/utils.py +333 -0
  57. testsuit/jupytertools/FileDialog.py +38 -0
  58. testsuit/jupytertools/JupyterGui.py +404 -0
  59. testsuit/jupytertools/MexploitJupyterGui.py +297 -0
  60. testsuit/jupytertools/PlotJupyterGui.py +537 -0
  61. testsuit/jupytertools/__init__.py +6 -0
  62. testsuit/jupytertools/h5ConvertJupyterGui.py +235 -0
  63. testsuit/jupytertools/install.py +56 -0
  64. testsuit/jupytertools/notebooks/__init__.py +1 -0
  65. testsuit/jupytertools/notebooks/data_plot.ipynb +28 -0
  66. testsuit/jupytertools/notebooks/h5_convert.ipynb +28 -0
  67. testsuit/jupytertools/notebooks/mexploit.ipynb +29 -0
  68. testsuit/misc/MonitorProgress.py +457 -0
  69. testsuit/misc/__init__.py +0 -0
  70. testsuit/misc/files.py +99 -0
  71. testsuit/misc/logger.py +120 -0
  72. testsuit/plugins.py +77 -0
  73. testsuit-0.1.1.dist-info/METADATA +165 -0
  74. testsuit-0.1.1.dist-info/RECORD +78 -0
  75. testsuit-0.1.1.dist-info/WHEEL +5 -0
  76. testsuit-0.1.1.dist-info/entry_points.txt +11 -0
  77. testsuit-0.1.1.dist-info/licenses/LICENSE +201 -0
  78. testsuit-0.1.1.dist-info/top_level.txt +1 -0
testsuit/__init__.py ADDED
@@ -0,0 +1,15 @@
1
+ """Toolbox for preparing and analysing test data.
2
+
3
+ Subpackages:
4
+ datatools load data files into pandas, convert to HDF5, push to a DB, datapacks
5
+ exploit mexploit YAML scenario checks and the exploit runner
6
+ jupytertools ipywidgets GUIs for notebooks
7
+ misc logging, progress reporting, file helpers
8
+ cli command-line entry points (see [project.scripts] in pyproject.toml)
9
+ """
10
+ from importlib.metadata import PackageNotFoundError, version
11
+
12
+ try:
13
+ __version__ = version("testsuit")
14
+ except PackageNotFoundError: # running from a source tree without install
15
+ __version__ = "0+unknown"
File without changes
@@ -0,0 +1,167 @@
1
+
2
+ import os
3
+ import argparse
4
+ import concurrent.futures
5
+ import sys
6
+
7
+
8
+ from testsuit.datatools.datatoolbox import loadDataframeFromFile
9
+ from testsuit.datatools.DataFileMgrs.AFileMgr import enable_pandas_display_helpers
10
+ from testsuit.datatools.DataFileMgrs.FolderParamMgr import FolderParamMgr
11
+ from testsuit.datatools.DataframeToHdf5 import DataframeToHdf5
12
+
13
+ from testsuit.misc.logger import get_logger
14
+ from testsuit.misc.logger import create_logger
15
+ from testsuit.misc.MonitorProgress import MonitorProgress,consoleRichProgressCb
16
+
17
+ CORRECTED_CLOCK_FILE_SUFFIX="clock_corrected"
18
+
19
+ NB_WORKERS=8
20
+
21
+ def _process_file_with_clock_correction(fpath, clock_correction_file, shiftDateSec, shiftDateRegex, monitorProgress, deleteIfExists=True):
22
+ """Worker function for multithreaded clock correction processing."""
23
+ monitorProgress.msg(msg=f"applying dates correction on file: {fpath}")
24
+
25
+ if clock_correction_file:
26
+ mgr = FolderParamMgr([fpath, clock_correction_file], shiftDateSec=shiftDateSec, shiftDateRegex=shiftDateRegex, shiftDateInverted=True,continueOnError=True)
27
+ else:
28
+ mgr = FolderParamMgr([fpath], shiftDateSec=shiftDateSec, shiftDateRegex=shiftDateRegex, shiftDateInverted=True,continueOnError=True)
29
+ try:
30
+ dfs = mgr.findParams(os.path.basename(fpath) + "::", monitorProgress=monitorProgress)#,silent=True)
31
+ except Exception as e:
32
+ import traceback
33
+ traceback.print_exc()
34
+ monitorProgress.msg(msg=f"could not apply clock correction to {fpath} : " + str(e), msgSeverity="error")
35
+ return
36
+
37
+ comment = {}
38
+ comment["Comments"] = "Extracted from original data"
39
+
40
+ if len(dfs) == 0:
41
+ monitorProgress.msg(msg=f"No param in {os.path.basename(fpath)}", msgSeverity="warning")
42
+ return
43
+
44
+ targetFile = dfs[0].origin.replace(".h5", f".{CORRECTED_CLOCK_FILE_SUFFIX}.h5")
45
+ if deleteIfExists and os.path.exists(targetFile):
46
+ os.remove(targetFile)
47
+
48
+ h5GroupName = os.path.basename(dfs[0].origin)
49
+ for df in dfs:
50
+ if "clock corrected" in df.attrs:
51
+ DataframeToHdf5(targetFile, h5GroupName, df, comment=comment, chunk_size=True)
52
+
53
+ monitorProgress.msg(msg=f"written {targetFile}")
54
+
55
+ def apply_clock_correction(target_folder,
56
+ shiftDateSec, shiftDateRegex, shiftDateSrcFile, shiftDateInverted=False,
57
+ monitorProgress=None,deleteIfExist=True):
58
+ """
59
+ Apply given clock correction (either constant litteral or a param name to be loaded.
60
+ Actual processing is planned to be applicable on-the-fly, and thus is implemented in
61
+ FolderParamMgr::findParams() and AFileMgr::finalizeParam() methods."""
62
+
63
+ monitorProgress.msg(msg=[f"correcting clock for {shiftDateRegex}",
64
+ f"clock correction from {shiftDateSec} in {shiftDateSrcFile} "])
65
+
66
+
67
+ # try to interpret provided shitDateSec as a float litteral, if not, it is considered as a param name
68
+ try: shiftDateSec=float(shiftDateSec)
69
+ except (TypeError, ValueError): pass
70
+
71
+ clock_correction_file=None
72
+
73
+ totalSteps=3 if isinstance(shiftDateSec,str) else 2
74
+
75
+ monitorProgress.set_total_items(totalSteps)
76
+ subFindMatchingDfmP = monitorProgress.child("find matching params")
77
+
78
+ # early check of availability of provided shitDateSec param name
79
+ # if not str, it is a float litteral constant correction value
80
+ if isinstance(shiftDateSec,str):
81
+
82
+ clock_correction_file = shiftDateSrcFile
83
+ if not os.path.exists(clock_correction_file) and not clock_correction_file.startswith(os.sep):
84
+ clock_correction_file = os.path.join(target_folder, shiftDateSrcFile)
85
+ monitorProgress.msg(msg=f"Using file {clock_correction_file} to get clock correction info '{shiftDateSec}'.",
86
+ msgSeverity="info")
87
+ if not os.path.exists(clock_correction_file):
88
+ monitorProgress.msg(msg=f"File {clock_correction_file} not reachable. Cannot apply clock correction '{shiftDateSec}'.",
89
+ msgSeverity="error")
90
+ return False
91
+
92
+ shiftdatefilemgr = FolderParamMgr(clock_correction_file)
93
+ shiftDateMatchingParams = shiftdatefilemgr.findParams(shiftDateSec, dryRun=True, silent=True, monitorProgress=subFindMatchingDfmP)
94
+ shiftDateParamNames = [df.name for df in shiftDateMatchingParams]
95
+ if len(shiftDateParamNames) == 0:
96
+ monitorProgress.msg(msg=f"No param matching shiftDateSec='{shiftDateSec}' not found in {clock_correction_file}.",
97
+ msgSeverity="error")
98
+ return False
99
+ if len(shiftDateParamNames) > 1:
100
+ monitorProgress.msg(msg=f"more than one param matching shiftDateSec='{shiftDateSec}' in {clock_correction_file}: {shiftDateParamNames}",
101
+ msgSeverity="error")
102
+ return False
103
+
104
+ subLoadMatchingDfmP = monitorProgress.child("load matching params")
105
+
106
+ # list all params matching given regex, to identify corresponding files
107
+ matching_dfs = loadDataframeFromFile(sourceFolderOrFile=target_folder, paramRegexes=shiftDateRegex,
108
+ indices=None, dryRun=True, silent=True, monitorProgress=subLoadMatchingDfmP)
109
+ if len(matching_dfs) == 0:
110
+ monitorProgress.msg(msg=["found no data needing clock correction", f"pattern: {shiftDateRegex}"], msgSeverity="warning")
111
+ return False
112
+
113
+ files_to_process = list(set(df.origin for df in matching_dfs if (df.origin and CORRECTED_CLOCK_FILE_SUFFIX not in df.origin)))
114
+ subApplyClockmP = monitorProgress.child("apply clock correction",len(files_to_process))
115
+
116
+ # Parallelize file processing with multithreading
117
+ with concurrent.futures.ThreadPoolExecutor(max_workers=NB_WORKERS) as executor:
118
+ futures = {
119
+ executor.submit(
120
+ _process_file_with_clock_correction,
121
+ fpath,
122
+ clock_correction_file,
123
+ shiftDateSec,
124
+ shiftDateRegex,
125
+ subApplyClockmP.child(fpath),
126
+ deleteIfExist
127
+ ): fpath
128
+ for fpath in files_to_process
129
+ }
130
+ for future in concurrent.futures.as_completed(futures):
131
+ fpath = futures[future]
132
+ try:
133
+ future.result()
134
+ except Exception as e:
135
+ monitorProgress.msg(msg=f"unexpected error processing {fpath}: {e}", msgSeverity="error")
136
+ return True
137
+
138
+
139
+
140
+ def main():
141
+ enable_pandas_display_helpers()
142
+ parser = argparse.ArgumentParser(
143
+ description="Apply clock correction to extracted data files."
144
+ )
145
+ parser.add_argument('target_folder', help="Path to the folder containing the extracted data files")
146
+ parser.add_argument('--shiftDateSec', help="Float value, or name of param containing clock diff to apply at each timestamp.", default="/ParamClockRef$")
147
+ parser.add_argument('--shiftDateRegex', help="Filter which params/files to apply date shift", default="ref_.*::")
148
+ parser.add_argument('--shiftDateInverted', action='store_true', default=False, help="Inverse logic if your clock diff is based on the other clock")
149
+ parser.add_argument('--update', action='store_true', default=False, help="Update existing file if any, rather than deleting it. (useful to add manually a new param in a file)")
150
+ parser.add_argument('--shiftDateSrcFile', help="Name of file containing the shiftDateSec if it is a param name", default="ref_data.h5")
151
+
152
+ args = parser.parse_args()
153
+
154
+
155
+ create_logger("apply_clock_correction")
156
+
157
+ monitorProgress=MonitorProgress(name="apply_clock_correction",progressCb=consoleRichProgressCb)
158
+
159
+ rst = apply_clock_correction(args.target_folder, args.shiftDateSec, args.shiftDateRegex, args.shiftDateSrcFile,
160
+ shiftDateInverted=args.shiftDateInverted,monitorProgress=monitorProgress, deleteIfExist=not args.update)
161
+ if not rst:
162
+ get_logger().error(f"failed to fix clock based on {args.shiftDateSec}.")
163
+ sys.exit(1)
164
+
165
+
166
+ if __name__ == "__main__":
167
+ main()
@@ -0,0 +1,82 @@
1
+
2
+ import argparse,os,sys,json,logging
3
+
4
+
5
+ from testsuit.datatools.datatoolbox import SUPPORTED_DATAFILE_EXTENSIONS
6
+ from testsuit.plugins import load_plugins
7
+ from testsuit.datatools.DataFileMgrs.AFileMgr import enable_pandas_display_helpers
8
+ from testsuit.misc.MonitorProgress import MonitorProgress,consoleRichProgressCb
9
+ from testsuit.datatools.data2db import create_data2db
10
+ from testsuit.misc.logger import create_logger,get_logger
11
+
12
+
13
+ create_logger("data2db")
14
+
15
+ ## check if the given file is accessible
16
+ def isInputReadable(f):
17
+ if not os.access(f,os.R_OK):
18
+ get_logger().error(f"{f} does not exist or is not reachable")
19
+ sys.exit(1)
20
+
21
+ return f
22
+
23
+ # override the parsing error message using logger
24
+ class HelpParser(argparse.ArgumentParser):
25
+ def error(self, message):
26
+ get_logger().error("Input Arguments Error : "+message)
27
+ sys.exit(1)
28
+
29
+ ## the main function
30
+ def main():
31
+ # external formats (entry points, TESTSUIT_PLUGINS) show up in --extensions help
32
+ load_plugins()
33
+ enable_pandas_display_helpers()
34
+ parser = HelpParser(description=
35
+ """Extract given parameters from data files or DB.
36
+
37
+ To extract into a db, you must provide a json file as follow:
38
+ {
39
+ "params" : ["No2"],
40
+ "indices" : [],
41
+ "db" : {
42
+ "dbtype" : "influxdb",
43
+ "url" : "http://influxdb:8086",
44
+ "org" : "_sandbox_",
45
+ "bucket" : "testBucket",
46
+ "measurement" :"testMeas",
47
+ "rename_params_re" : ".*([^/]+)$",
48
+ "dateUnit" : "s"
49
+ }
50
+ }
51
+
52
+ Return 1 if something went wrong, 0 otherwise
53
+ """,
54
+ formatter_class=argparse.RawTextHelpFormatter)
55
+ parser.add_argument('sourceFolderOrFile', metavar="FolderOrFile", help="source folder or file where to scan data files",type=isInputReadable)
56
+ parser.add_argument('confJson', help="Conf for DB parameters. See up there of details about expected contents",type=isInputReadable)
57
+ parser.add_argument('-t','--token',help="DB password or token")
58
+ parser.add_argument("--test",action='store_true', default=False, help="Dry-run: does not actually inject data")
59
+ parser.add_argument('-d',"--debug",action='store_true', default=False, help="Show debug messages")
60
+ parser.add_argument('--extensions',type=lambda s: s.split(","),metavar='ext1,ext2,...',
61
+ help="File extensions to use as input (default: "+",".join(SUPPORTED_DATAFILE_EXTENSIONS)+")")
62
+ args = parser.parse_args()
63
+
64
+ if args.debug:
65
+ get_logger().setLevel(logging.DEBUG)
66
+
67
+ conf=None
68
+ with open(args.confJson) as f:
69
+ conf=json.load(f)
70
+
71
+ monitorProgress=MonitorProgress(progressCb=consoleRichProgressCb,name="data2db")
72
+ dbHandler = create_data2db(conf["db"]["dbtype"])
73
+ rst = dbHandler.data2db(args.sourceFolderOrFile,conf,args.extensions,token=args.token,dryRun=args.test,monitorProgress=monitorProgress,silent=True)
74
+
75
+ if rst == True:
76
+ sys.exit(0)
77
+ else:
78
+ sys.exit(1)
79
+
80
+
81
+ if __name__ == "__main__":
82
+ main()
@@ -0,0 +1,168 @@
1
+
2
+ import argparse
3
+ import sys,os,logging
4
+
5
+
6
+ from testsuit.misc.logger import create_logger
7
+ from testsuit.datatools.DataFileMgrs.AFileMgr import enable_pandas_display_helpers, pretty_str
8
+ from testsuit.misc.logger import get_logger
9
+ from testsuit.misc.MonitorProgress import MonitorProgress,consoleRichProgressCb,consoleSilentProgressCb
10
+
11
+ from testsuit.datatools.datatoolbox import SUPPORTED_DATAFILE_EXTENSIONS
12
+ from testsuit.plugins import load_plugins
13
+ from testsuit.datatools.datatoolbox import loadDataframeFromFile,getDateParser
14
+ from testsuit.datatools.DataframeToHdf5 import DataframeToHdf5
15
+
16
+ sys.stdout.reconfigure(encoding='utf-8')
17
+ sys.stderr.reconfigure(encoding='utf-8')
18
+
19
+ create_logger("data2h5")
20
+
21
+ ## check if the given file is accessible
22
+ def isInputReadable(f):
23
+ if not os.access(f,os.R_OK):
24
+ get_logger().error(f"{f} does not exist or is not reachable")
25
+ sys.exit(1)
26
+
27
+ return f
28
+
29
+ # override the parsing error message using logger
30
+ class HelpParser(argparse.ArgumentParser):
31
+ def error(self, message):
32
+ get_logger().error("Input Arguments Error : "+message)
33
+ sys.exit(1)
34
+
35
+
36
+ def extract_to_hdf5(h5fileName,paramsDfList):
37
+
38
+ for df in paramsDfList:
39
+ get_logger().info("extracting params "+str(df.columns)+"")
40
+ DataframeToHdf5(h5fileName,os.path.basename(df.origin),df,comment="",chunk_size=True)
41
+
42
+ return True
43
+
44
+ def data2h5(sourceFolderOrFile,paramRegexes,indices=None,targetFile=None,extensions=None,
45
+ excludeParamsRegex=None, minDate=None, maxDate=None, mergeParams=True,
46
+ shiftDateSec=None,shiftDateRegex=None, shiftDateInverted=None,
47
+ listOnly=False, silent=False,
48
+ monitorProgress=None):
49
+ """Extract data into H5 file.
50
+ See __main__ args list for parameters list and usage."""
51
+
52
+ minDateSec=None
53
+ maxDateSec=None
54
+ if minDate:
55
+ convFunc=getDateParser(minDate)
56
+ minDateSec=convFunc(minDate).timestamp() if convFunc else minDateSec
57
+ if maxDate:
58
+ convFunc=getDateParser(maxDate)
59
+ maxDateSec=convFunc(maxDate).timestamp() if convFunc else maxDateSec
60
+
61
+
62
+ def cbPrintName(df):
63
+ print(df.name)
64
+
65
+ def cbSaveDfAsH5File(df,monitorProgress=None):
66
+
67
+ if df is None:
68
+ get_logger().warning(f"skipping H5 writing of None param from {targetFile}")
69
+ return True
70
+
71
+ monitorProgress.set_total_items(1)
72
+ monitorProgress.msg("writing H5 data for "+str(df.name)+"")
73
+
74
+ h5GroupName=os.path.basename(df.origin)
75
+ if len(h5GroupName)==0:
76
+ h5GroupName=os.path.basename(os.path.dirname(df.origin))
77
+ comment={}
78
+ comment["Comments"]="Generated by data2h5"
79
+ if minDate: comment["Min Date"]=minDate
80
+ if maxDate: comment["Max Date"]=maxDate
81
+ try:
82
+ DataframeToHdf5(targetFile,h5GroupName,df,comment=comment,chunk_size=True)
83
+ except Exception as e:
84
+ monitorProgress.msg(msg=f"while writing file '{targetFile}' for {df.name} : {str(e)}",msgSeverity="error")
85
+ return False
86
+
87
+ monitorProgress.msg(msg=f"generated/updated file '{targetFile}' for {df.name}")
88
+
89
+ monitorProgress.complete_n(1)
90
+ return True
91
+
92
+ def cbprintDf(df,name=None,origin=None):
93
+ if df is not None:
94
+ print(pretty_str(df))
95
+ return True
96
+
97
+
98
+ cbToUse = None
99
+ if listOnly:
100
+ cbToUse=cbPrintName
101
+ elif targetFile is None:
102
+ cbToUse=cbprintDf
103
+ else:
104
+ cbToUse=cbSaveDfAsH5File
105
+
106
+ dfListRst=loadDataframeFromFile(sourceFolderOrFile,paramRegexes,indices,extensions,
107
+ minDateSec=minDateSec,maxDateSec=maxDateSec,
108
+ excludeParamsRegex=excludeParamsRegex,mergeParams=mergeParams,
109
+ shiftDateSec=shiftDateSec,shiftDateRegex=shiftDateRegex,
110
+ shiftDateInverted=shiftDateInverted,
111
+ dryRun=False,monitorProgress=monitorProgress,
112
+ silent=silent,callback=cbToUse)
113
+
114
+ if len(dfListRst)==0:
115
+ return False, dfListRst
116
+
117
+ return True, dfListRst
118
+
119
+
120
+ ## the main function
121
+ def main():
122
+ # external formats (entry points, TESTSUIT_PLUGINS) show up in --extensions help
123
+ load_plugins()
124
+ enable_pandas_display_helpers()
125
+
126
+
127
+ parser = HelpParser(description=
128
+ """Extract given parameters into an HDF5 file.
129
+ If target file is not provided, simply list matching fields found.
130
+ If params list is empty, list all param names found.
131
+
132
+ Return 1 if something went wrong, 0 otherwise
133
+ """,
134
+ formatter_class=argparse.RawTextHelpFormatter)
135
+ parser.add_argument('sourceFolderOrFile', metavar="FolderOrFile", help="source folder or file where to scan data files",type=isInputReadable)
136
+ parser.add_argument('target', nargs='?',metavar="Target", help="Target of params contents: xxx.h5")
137
+ parser.add_argument('-l','--list',action='store_true', default=False, help="list all params found in given datasources" )
138
+ parser.add_argument('-p','--params',metavar='param1,param2,...', help="list of params (regexes) to extract into and HDF5 file. You can use python regex. Ex: 'param_02,my_.*4$'",default=".*")
139
+ parser.add_argument('--indices',metavar='paramIdx1,paramIdx2,...', help="use provided params as indices, 'auto' for trying to automatically identify one. Ex: 'param_02_timestamp,auto'")
140
+ parser.add_argument('-d',"--debug",action='store_true', default=False, help="Show debug messages")
141
+ parser.add_argument('-s',"--silent",action='store_true', default=False, help="Only show relevant output messages, no progress.")
142
+ parser.add_argument('--extensions',type=lambda s: s.split(","),metavar='ext1,ext2,...',
143
+ help="File extensions to use as input (default: "+",".join(SUPPORTED_DATAFILE_EXTENSIONS)+")")
144
+ parser.add_argument('--minDate', help="Minimal date of data to record in file")
145
+ parser.add_argument('--maxDate', help="Maximal date of data to record in file")
146
+
147
+ args = parser.parse_args()
148
+
149
+ if args.debug:
150
+ get_logger().setLevel(logging.DEBUG)
151
+
152
+ get_logger().debug(args.target)
153
+
154
+ monitorProgress=MonitorProgress(progressCb=consoleSilentProgressCb if args.silent else consoleRichProgressCb,
155
+ name="data2h5")
156
+
157
+ rst, dfList = data2h5(args.sourceFolderOrFile,args.params,args.indices,args.target,args.extensions,
158
+ args.minDate,args.maxDate,listOnly=args.list,silent=args.silent,
159
+ monitorProgress=monitorProgress)
160
+
161
+ if rst == True:
162
+ sys.exit(0)
163
+ else:
164
+ sys.exit(1)
165
+
166
+
167
+ if __name__ == "__main__":
168
+ main()
@@ -0,0 +1,46 @@
1
+
2
+ import argparse
3
+ import os
4
+ import sys
5
+
6
+ from colorama import Fore, Style
7
+
8
+ from testsuit import misc
9
+ from testsuit.datatools.datapack.datapack_tools import datapack
10
+
11
+ ## check if the given file is accessible
12
+ def _isInputReadable(f):
13
+ if not os.access(misc.files.expandPath(f),os.R_OK):
14
+ raise argparse.ArgumentTypeError(f"{misc.files.expandPath(f)} does not exist or is not reachable")
15
+ return f
16
+
17
+ # override the parsing error message using logger
18
+ class _HelpParser(argparse.ArgumentParser):
19
+ def error(self, message):
20
+ print(Fore.RED+"ERROR: Input Arguments Error : "+message+Style.RESET_ALL)
21
+ sys.exit(1)
22
+
23
+ ## the main function
24
+ def main():
25
+ parser = _HelpParser(description=
26
+ """Generate datapack from given test definition file.
27
+
28
+ Dictionaries listed in test definition are applied to the test definition file itself and also to pointed datapack config.
29
+ Dictionaries listed in datapack config are applied to datapack config itself, but *not* to test definition.
30
+
31
+ Return 1 if something went wrong, 0 otherwise
32
+ """,
33
+ formatter_class=argparse.RawTextHelpFormatter)
34
+ parser.add_argument('testdef_file',nargs='?',default="datapack.xml",help="the YAML file containing datapack definition",type=_isInputReadable)
35
+ parser.add_argument('--nocheck',action='store_true',help="Ignore warnings and consistency checks (git tags etc.) for test procedure and Setup folders.")
36
+ args = parser.parse_args()
37
+
38
+ success = datapack(misc.files.expandPath(args.testdef_file),args.nocheck)
39
+ if success:
40
+ sys.exit(0)
41
+ else:
42
+ sys.exit(1)
43
+
44
+
45
+ if __name__ == "__main__":
46
+ main()
@@ -0,0 +1,88 @@
1
+
2
+
3
+ ## @package evalfile
4
+ # Evaluate given file both for includes and keys replacement, based on given dictionaries.
5
+ # This script is based on 'evalkeys.py' and 'evalincludes.py' algorithms.
6
+ #
7
+ # Performs several replacement and includes as long as some replacements are done, which means that key value can be a reference to another key,
8
+ # and include can contain a key value.
9
+ #
10
+ # Result lines are displayed on STDOUT.
11
+ #
12
+ #
13
+ # USAGE: evalfile.py [-h] targetfile dico [dico ...]
14
+ #
15
+ #
16
+ import sys,os
17
+
18
+
19
+
20
+ import argparse
21
+ import os.path
22
+
23
+ from testsuit.datatools.datapack.evalfiles.evalfile import evalfile,finalizeLines
24
+ from testsuit.datatools.datapack.evalfiles import evalkeys
25
+ from testsuit.datatools.datapack.evalfiles import evalincludes
26
+
27
+
28
+ ## check if the given file is accessible
29
+ def _isInputReadable(f):
30
+ if not os.access(f,os.R_OK):
31
+ raise argparse.ArgumentTypeError(f"{f} does not exist or is not readable")
32
+ return f
33
+
34
+ # override the parsing error message using logger
35
+ class _HelpParser(argparse.ArgumentParser):
36
+ def error(self, message):
37
+ print("Input Arguments Error : "+message)
38
+ sys.exit(1)
39
+
40
+ ## the main function
41
+ def main():
42
+ parser = _HelpParser(description=
43
+ """Evaluate given file for includes and keys replacement, based on given dictionnaries.
44
+ This script is based on 'evalkeys' and 'evalincludes' algorithms.
45
+
46
+ Performs several processing cycles as long as some replacements are done.
47
+ This means that key value can be a reference to another key, and an include can contain a key value.
48
+
49
+ When option '-o' is used, generates also an HTML view of performed key replacements and a '.<file>.keys' file containing the list of used keys and their provenance.
50
+ Otherwise result lines are displayed on STDOUT by default.
51
+
52
+ Result is displayed in <stdout>.
53
+
54
+ Return:
55
+ 3 a problem occured during processing
56
+ 2 if circular inclusion or key reference detected,
57
+ 1 if unreacheable included file or key referene (and no circular include or key ref. detected)
58
+ 0 if okay""",
59
+ formatter_class=argparse.RawTextHelpFormatter)
60
+ parser.add_argument('targetfile',help="the text file to be processed",type=_isInputReadable,metavar="targetfile")
61
+ parser.add_argument('dico',nargs='+', help="dictionary file(s) to be used for keys replacement, most important one first",type=_isInputReadable)
62
+ parser.add_argument('--output', '-o',help="output in the given file, generating also the '.<file>.html' and '.<file>.keys' associated files")
63
+ parser.add_argument('--partial','-p',action='store_true',help="Partial replace : ignore unknown keys, process only defined ones")
64
+
65
+
66
+ args = parser.parse_args()
67
+
68
+ lines, usedkeys=evalfile(args.targetfile, args.dico, args.partial)
69
+ if not lines :
70
+ sys.exit(3)
71
+
72
+ finalizeLines(lines, usedkeys, args.partial, args.output)
73
+
74
+ if args.output is not None:
75
+ print("generated "+str(args.output)+" and associated 'keys' and 'html' files.")
76
+
77
+ if evalkeys.nbInfinateRecursion>0 or evalincludes.nbCircularRecursions>0:
78
+ sys.exit(2)
79
+ if evalincludes.nbNotFoundIncludes>0:
80
+ sys.exit(1)
81
+ if not args.partial and evalkeys.nbUndefined>0:
82
+ sys.exit(1)
83
+
84
+ sys.exit(0)
85
+
86
+
87
+ if __name__ == "__main__":
88
+ main()