def extract_data(self, input_file, args, verbose=1): '''Extract data from output file. Assume function is executed in self.path.''' tp_ptr = self.test_program if tp_ptr.data_tag: # Using internal data extraction function. data_files = [ tp_ptr.select_benchmark_file(self.path, input_file, args), util.testcode_filename(FILESTEM['test'], tp_ptr.test_id, input_file, args), ] if verbose > 2: print(('Analysing output using data_tag %s in %s on files %s.' % (tp_ptr.data_tag, self.path, ' and '.join(data_files)))) outputs = [util.extract_tagged_data(tp_ptr.data_tag, dfile) for dfile in data_files] else: # Using external data extraction script. # Get extraction commands. extract_cmds = tp_ptr.extract_cmd(self.path, input_file, args) # Extract data. outputs = [] for cmd in extract_cmds: try: if verbose > 2: print(('Analysing output using %s in %s.' % (cmd, self.path))) extract_popen = subprocess.run(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) except OSError: # slightly odd syntax in order to be compatible with python # 2.5 and python 2.6/3 err = 'Analysing output failed: %s' % (sys.exc_info()[1],) raise exceptions.AnalysisError(err) # Convert data string from extract command to dictionary format. if extract_popen.returncode != 0: err = extract_popen.communicate()[1].decode('utf-8') err = 'Analysing output failed: %s' % (err) raise exceptions.AnalysisError(err) data_string = extract_popen.stdout.decode('utf-8') if self.test_program.extract_fmt == 'table': outputs.append(util.dict_table_string(data_string)) elif self.test_program.extract_fmt == 'yaml': outputs.append({}) # convert values to be in a tuple so the format matches # that from dict_table_string. # ensure all keys are strings so they can be sorted # (different data types cause problems!) for (key, val) in list(yaml.safe_load(data_string).items()): if isinstance(val, list): outputs[-1][str(key)] = tuple(val) else: outputs[-1][str(key)] = tuple((val,)) return tuple(outputs)
def verify_job_external(self, input_file, args, verbose=1): '''Run user-supplied verifier script. Assume function is executed in self.path.''' verify_cmd, = self.test_program.extract_cmd(self.path, input_file, args) try: if verbose > 2: print('Analysing test using %s in %s.' % (verify_cmd, self.path)) verify_popen = subprocess.Popen(verify_cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) verify_popen.wait() except OSError: # slightly odd syntax in order to be compatible with python 2.5 # and python 2.6/3 err = 'Analysis of test failed: %s' % (sys.exc_info()[1], ) raise exceptions.AnalysisError(err) output = verify_popen.communicate()[0].decode('utf-8') if verbose < 2: # Suppress output. (hackhack) output = '' if verify_popen.returncode == 0: return (validation.Status([True]), output) else: return (validation.Status([False]), output)
def dict_table_string(table_string): '''Read a data table from a string into a dictionary. The first row and any subsequent rows containing no numbers are assumed to form headers of a subtable, and so form the keys for the subsequent subtable. Values, where possible, are converted to floats. e.g. a b c a -> {'a':(1,4,7,8), 'b':(2,5), 'c':(3,6)} 1 2 3 7 4 5 6 8 and a b c -> {'a':(1,4,7), 'b':(2,5,8), 'c':(3,6), 'd':(9), 'e':(6)} 1 2 3 4 5 6 a b d e 7 8 9 6 ''' data = [i.split() for i in table_string.splitlines()] # Convert to numbers where appropriate data = [[try_floatify(val) for val in dline] for dline in data] data_dict = {} head = [] for dline in data: # Test if all items are strings; if so start a new subtable. # We actually test if all items are not floats, as python 3 can return # a bytes variable from subprocess whereas (e.g.) python 2.4 returns a # str. Testing for this is problematic as the bytes type does not # exist in python 2.4. Fortunately we have converted all items to # floats if possible, so can just test for the inverse condition... if compat.compat_all(type(val) is not float for val in dline): # header of new subtable head = dline for val in head: if val not in data_dict: data_dict[val] = [] else: if len(dline) > len(head): err = 'Table missing column heading(s):\n%s' % (table_string) raise exceptions.AnalysisError(err) for (ind, val) in enumerate(dline): # Add data to appropriate key. # Note that this handles the case where the same column heading # occurs multiple times in the same subtable and does not # overwrite the previous column with the same heading. data_dict[head[ind]].append(val) # We shouldn't change the data from this point: convert entries to tuples. for (key, val) in data_dict.items(): data_dict[key] = tuple(val) return data_dict
def extract_tagged_data(data_tag, filename): '''Extract data from lines marked by the data_tag in filename.''' if not os.path.exists(filename): err = 'Cannot extract data: file %s does not exist.' % (filename) raise exceptions.AnalysisError(err) data_file = open(filename) # Data tag is the first non-space character in the line. # e.g. extract data from lines: # data_tag Energy: 1.256743 a.u. data_tag_regex = re.compile('^ *%s' % (re.escape(data_tag))) data = {} for line in data_file.readlines(): if data_tag_regex.match(line): # This is a line containing info to be tested. words = line.split() key = [] # name of data is string after the data_tag and preceeding the # (numerical) data. only use the first number in the line, with # the key taken from all proceeding information. for word in words[1:]: val = try_floatify(word) if val != word: break else: key.append(word) if key[-1] in ("=", ':'): key.pop() key = '_'.join(key) if key[-1] in ("=", ':'): key = key[:-1] if not key: key = 'data' if key in data: data[key].append(val) else: data[key] = [val] # We shouldn't change the data from this point: convert entries to tuples. for (key, val) in data.items(): data[key] = tuple(val) return data
def skip_job(self, input_file, args, verbose=1): '''TODO ''' status = validation.Status() if self.test_program.skip_program: cmd = self.test_program.skip_cmd(input_file, args) try: if verbose > 2: print('Testing whether to skip test using %s in %s.' % (cmd, self.path)) skip_popen = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) skip_popen.wait() except OSError: # slightly odd syntax in order to be compatible with python # 2.5 and python 2.6/3 err = 'Test to skip test: %s' % (sys.exc_info()[1], ) raise exceptions.AnalysisError(err) if skip_popen.returncode == 0: # skip this test status = validation.Status(name='skipped') return (status, '')
def extract_data(self, input_file, args, verbose=1): '''Extract data from output file. Assume function is executed in self.path.''' tp_ptr = self.test_program if tp_ptr.data_tag: # Using internal data extraction function. data_files = [ tp_ptr.select_benchmark_file(self.path, input_file, args), util.testcode_filename(FILESTEM['test'], tp_ptr.test_id, input_file, args), ] if verbose > 2: print('Analysing output using data_tag %s in %s on files %s.' % (tp_ptr.data_tag, self.path, ' and '.join(data_files))) outputs = [ util.extract_tagged_data(tp_ptr.data_tag, dfile) for dfile in data_files ] else: # Using external data extraction script. # Get extraction commands. extract_cmds = tp_ptr.extract_cmd(self.path, input_file, args) # Extract data. outputs = [] for cmd in extract_cmds: try: if verbose > 2: print('Analysing output using %s in %s.' % (cmd, self.path)) # Samuel Ponce: Popen.wait() creates deadlock if the data is too large # See documented issue for example in: # https://docs.python.org/2/library/subprocess.html#subprocess.Popen.returncode # # Previous code that create deadlock: #extract_popen = subprocess.Popen(cmd, shell=True, # stdout=subprocess.PIPE, stderr=subprocess.PIPE) #extract_popen.wait() # # New code (this might not be the best but work for me): extract_popen = subprocess.Popen(cmd, bufsize=1, shell=True, stdin=open(os.devnull), stdout=subprocess.PIPE, stderr=subprocess.PIPE) lines = [] for line in iter(extract_popen.stdout.readline, ''): #print line, lines.append(line) except OSError: # slightly odd syntax in order to be compatible with python # 2.5 and python 2.6/3 err = 'Analysing output failed: %s' % (sys.exc_info()[1], ) raise exceptions.AnalysisError(err) # Convert data string from extract command to dictionary format. # SP: Because of the above change, the test below cannot be done: #if extract_popen.returncode != 0: # err = extract_popen.communicate()[1].decode('utf-8') # err = 'Analysing output failed: %s' % (err) # raise exceptions.AnalysisError(err) #data_string = extract_popen.communicate()[0].decode('utf-8') data_string = ''.join(lines) if self.test_program.extract_fmt == 'table': outputs.append(util.dict_table_string(data_string)) elif self.test_program.extract_fmt == 'yaml': outputs.append({}) # convert values to be in a tuple so the format matches # that from dict_table_string. # ensure all keys are strings so they can be sorted # (different data types cause problems!) for (key, val) in yaml.safe_load(data_string).items(): if isinstance(val, list): outputs[-1][str(key)] = tuple(val) else: outputs[-1][str(key)] = tuple((val, )) return tuple(outputs)