this repo has no description
1import timeit, re, sys, os
2import utils, json_config
3
4## TODO Keyline/value dictionaries: entries == json_config.s_CommentKey are ignored. Make it a parameter
5
6class Output:
7 def __init__( self ):
8 stdout = ""
9 stderr = ""
10
11def on_terminate(proc):
12 print("process {} terminated with exit code {}".format(proc, proc.returncode))
13
14##############################################################################################
15###################### MZN instance execution + result parsing low-level #####################
16##############################################################################################
17## runCmdCmdline using system(). Actually used for checking as well.
18## run the specified shell command string and return the time.
19## can add ulimit etc.
20## s1, s2: filenames for strout, stderr
21## dictCmd: commands for Win and non-Win
22## meml: list of 2 values, soft & hard limits as N bytes
23def runCmdCmdline( s_Cmd, s1, s2, dictCmd, timeo, bVerbose=False, meml=None ):
24 tm = timeit.default_timer()
25 setCmd = dictCmd["windows"] if "win" in sys.platform and "cygwin" not in sys.platform else dictCmd["non-windows"]
26 sCmd = setCmd["runVerbose" if bVerbose else "runSilent"].format(meml[1], timeo, s_Cmd, s1, s2)
27 print( "\n RUNNING:", sCmd )
28 os.system(sCmd)
29 tm = timeit.default_timer() - tm
30 return tm
31
32
33## runCmd using psutils. Actually should be used for checking as well.
34## run the specified shell command string and return the popen result.
35## TODO catch intermediate solutions if needed
36## meml: list of 2 values, soft & hard limits as N bytes
37def runCmd( s_Cmd, b_Shell=False, timeo=None, meml=None ):
38 import psutil, shlex, subprocess, resource
39 if b_Shell:
40 l_Cmd = s_Cmd
41 else:
42 l_Cmd = shlex.split( s_Cmd )
43 tm = timeit.default_timer()
44 ################# In the following, the subprocess.RUN method fails to kill shell calls on Linux
45 #try:
46 # completed = subprocess.run( l_Cmd, shell=b_Shell,
47 # universal_newlines=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, timeout=timeo )
48 #except subprocess.TimeoutExpired as te:
49 # completed = te
50 ################# Using psutils
51 proc = psutil.Popen(l_Cmd, shell=b_Shell,
52 universal_newlines=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
53 if None!=meml:
54 if hasattr( psutil, 'RLIMIT_AS' ): ## TODO move into preexec_fn for parallel tests?
55 proc.rlimit( resource.RLIMIT_AS, ( meml[0]*1000, meml[1]*1000 ) )
56 else:
57 print( " ... but the OS doesn't support RLIMIT_AS." )
58 completed = Output()
59 try:
60 completed.stdout, completed.stderr = proc.communicate(timeout=timeo)
61 except subprocess.TimeoutExpired:
62 print ( " soft_kill. ", end='' )
63 procs = psutil.Process().children(recursive=True)
64 for p in procs:
65 p.terminate()
66 try:
67 completed.stdout, completed.stderr = proc.communicate(timeout=1)
68 except subprocess.TimeoutExpired as te:
69 print ( " hard_kill. ", end='' )
70 procs = psutil.Process().children(recursive=True)
71 for p in procs:
72 p.kill()
73 completed.stdout, completed.stderr = proc.communicate()
74 ### Clean up: (does psutil.Process.communicate() wait for all descendants?) -----------------------------------
75 procs = psutil.Process().children(recursive=True)
76 for p in procs:
77 p.kill()
78 ### OR: even Queue?
79# with psutil.Popen(["ifconfig"], stdout=subprocess.PIPE) as proc:
80# log.write(proc.stdout.read())
81#
82# procs = psutil.Process().children()
83# for p in procs:
84# p.terminate()
85# gone, still_alive = psutil.wait_procs(procs, timeout=3, callback=on_terminate)
86# for p in still_alive:
87# p.kill()
88 tm = timeit.default_timer() - tm
89 return completed, tm
90
91def parseStderr( f, result, mapKL, mapKV ):
92# result["ProbSense"] = None
93# result["TimeFlt"] = None
94 for line in f:
95 line = line.strip()
96 checkKeylines( line, mapKL, result )
97 checkKeyvalues( line, mapKV, result )
98
99## Puts feasible solutions into solList if it's not None
100def parseStdout( f, result, mapKL, mapKV, solList ):
101 l_SolLast = ""
102 n_SolStatus = 0
103 result["Number_Solutions"] = 0
104 for line in f:
105 line = line.rstrip() ## To remove \n and spaces on the right
106 res00 = {} ## A temporary to see if we get a feasible solution separator
107 checkKeylines( line, mapKL, res00 )
108 utils.mergeDict( result, res00 )
109 checkKeyvalues( line, mapKV, result )
110 ## See if it's a solution status
111 if "Sol_Status" in res00:
112 if 1==res00[ "Sol_Status" ][0]:
113 result["Number_Solutions"] += 1
114## result["Solution_Last"] = l_SolLast ## Or save it? Need from a file then but might be great to have here
115 if None!=solList:
116 solList.append( l_SolLast )
117 l_SolLast = "" ## Clean up
118 else:
119 l_SolLast += line
120 l_SolLast += '\n'
121
122## Check if any keylines of the given 2-level dictionary equal the given line
123## The 1st level gives variable name, 2nd level gives the line->value map
124def checkKeylines( line, dict2, result ):
125 assert dict==type(dict2) ## What if we use OrderedDict??? TODO
126 assert isinstance(result, dict)
127 for key in dict2:
128 if json_config.s_CommentKey!=key:
129 val1 = dict2[key]
130 assert dict==type(val1), "checkKeylines: key '%s': '%s'==type (%s)" % \
131 ( key, type(val1), val1.__str__() )
132 if line in val1:
133 result[ key ] = [ val1[ line ], line ]
134
135## Check if any search pattern of the given dict values is in the given line
136## The key gives variable name, value gives the line->value mapping
137def checkKeyvalues( line, dictVal, result ):
138 assert dict==type(dictVal) ## What if we use OrderedDict??? TODO
139 assert isinstance(result, dict)
140 for key in dictVal:
141 if json_config.s_CommentKey!=key:
142 paramArray = dictVal[ key ]
143 assert 3<=len( paramArray ), \
144 "Key '%s': param list should have >=3 elements, now: %s" % (key, paramArray.__str__())
145 if None!=re.search( paramArray[0], line ):
146 try:
147 lineSubst = re.sub( paramArray[1], ' ', line )
148 except:
149 print(" WARNING: failed to substitute regex '", paramArray[1],
150 "' by ' ' in string '", line, "': ", sys.exc_info()[0:2]
151 , sep='')
152 else:
153 lSL = lineSubst.split()
154 if len( lSL )>paramArray[2]-1:
155 s_Val = lSL[ paramArray[2]-1 ]
156 ## d_Val = try_float( s_Val )
157 result[key] = s_Val ### [ d_Val, s_Val ] Need here?
158## print( " checkKeyval: result[{}] = '{}'".format(key, s_Val) )
159 else:
160 print( "ERROR: Parsing output line ", lSL,
161 ": regex key '", paramArray[0],
162 "' found, but the split line too short for index ", paramArray[2],
163 sep='' )