Merge branch 'PythonImprovements' into pytest

This commit is contained in:
Martin Diehl 2019-11-22 15:42:27 +01:00
commit e5e3db8286
4 changed files with 46 additions and 45 deletions

View File

@ -2,7 +2,7 @@
import os import os
with open(os.path.join(os.path.dirname(__file__),'VERSION')) as f: with open(os.path.join(os.path.dirname(__file__),'VERSION')) as f:
version = f.readline()[1:-1] version = f.readline()[1:-1]
name = 'damask' name = 'damask'

View File

@ -15,7 +15,7 @@ except NameError:
# ------------------------------------------------------------------ # ------------------------------------------------------------------
class ASCIItable(): class ASCIItable():
"""Read and write to ASCII tables""" """Read and write to ASCII tables."""
tmpext = '_tmp' # filename extension for in-place access tmpext = '_tmp' # filename extension for in-place access
@ -27,6 +27,7 @@ class ASCIItable():
labeled = True, # assume table has labels labeled = True, # assume table has labels
readonly = False, # no reading from file readonly = False, # no reading from file
): ):
"""Read and write to ASCII tables."""
self.__IO__ = {'output': [], self.__IO__ = {'output': [],
'buffered': buffered, 'buffered': buffered,
'labeled': labeled, # header contains labels 'labeled': labeled, # header contains labels
@ -72,7 +73,7 @@ class ASCIItable():
# ------------------------------------------------------------------ # ------------------------------------------------------------------
def _removeCRLF(self, def _removeCRLF(self,
string): string):
"""Delete any carriage return and line feed from string""" """Delete any carriage return and line feed from string."""
try: try:
return string.replace('\n','').replace('\r','') return string.replace('\n','').replace('\r','')
except AttributeError: except AttributeError:
@ -82,7 +83,7 @@ class ASCIItable():
# ------------------------------------------------------------------ # ------------------------------------------------------------------
def _quote(self, def _quote(self,
what): what):
"""Quote empty or white space-containing output""" """Quote empty or white space-containing output."""
return '{quote}{content}{quote}'.format( return '{quote}{content}{quote}'.format(
quote = ('"' if str(what)=='' or re.search(r"\s",str(what)) else ''), quote = ('"' if str(what)=='' or re.search(r"\s",str(what)) else ''),
content = what) content = what)
@ -103,7 +104,7 @@ class ASCIItable():
# ------------------------------------------------------------------ # ------------------------------------------------------------------
def output_write(self, def output_write(self,
what): what):
"""Aggregate a single row (string) or list of (possibly containing further lists of) rows into output""" """Aggregate a single row (string) or list of (possibly containing further lists of) rows into output."""
if isinstance(what, (str, unicode)): if isinstance(what, (str, unicode)):
self.__IO__['output'] += [what] self.__IO__['output'] += [what]
else: else:
@ -143,7 +144,7 @@ class ASCIItable():
# ------------------------------------------------------------------ # ------------------------------------------------------------------
def head_read(self): def head_read(self):
""" """
Get column labels Get column labels.
by either reading the first row or, by either reading the first row or,
if keyword "head[*]" is present, the last line of the header if keyword "head[*]" is present, the last line of the header
@ -154,7 +155,7 @@ class ASCIItable():
pass pass
firstline = self.__IO__['in'].readline().strip() firstline = self.__IO__['in'].readline().strip()
m = re.search('(\d+)\s+head', firstline.lower()) # search for "head" keyword m = re.search(r'(\d+)\s+head', firstline.lower()) # search for "head" keyword
if m: # proper ASCIItable format if m: # proper ASCIItable format
@ -194,7 +195,7 @@ class ASCIItable():
# ------------------------------------------------------------------ # ------------------------------------------------------------------
def head_write(self, def head_write(self,
header = True): header = True):
"""Write current header information (info + labels)""" """Write current header information (info + labels)."""
head = ['{}\theader'.format(len(self.info)+self.__IO__['labeled'])] if header else [] head = ['{}\theader'.format(len(self.info)+self.__IO__['labeled'])] if header else []
head.append(self.info) head.append(self.info)
if self.__IO__['labeled']: if self.__IO__['labeled']:
@ -205,7 +206,7 @@ class ASCIItable():
# ------------------------------------------------------------------ # ------------------------------------------------------------------
def head_getGeom(self): def head_getGeom(self):
"""Interpret geom header""" """Interpret geom header."""
identifiers = { identifiers = {
'grid': ['a','b','c'], 'grid': ['a','b','c'],
'size': ['x','y','z'], 'size': ['x','y','z'],
@ -247,7 +248,7 @@ class ASCIItable():
def labels_append(self, def labels_append(self,
what, what,
reset = False): reset = False):
"""Add item or list to existing set of labels (and switch on labeling)""" """Add item or list to existing set of labels (and switch on labeling)."""
if isinstance(what, (str, unicode)): if isinstance(what, (str, unicode)):
self.tags += [self._removeCRLF(what)] self.tags += [self._removeCRLF(what)]
else: else:
@ -261,7 +262,7 @@ class ASCIItable():
# ------------------------------------------------------------------ # ------------------------------------------------------------------
def labels_clear(self): def labels_clear(self):
"""Delete existing labels and switch to no labeling""" """Delete existing labels and switch to no labeling."""
self.tags = [] self.tags = []
self.__IO__['labeled'] = False self.__IO__['labeled'] = False
@ -392,7 +393,7 @@ class ASCIItable():
# ------------------------------------------------------------------ # ------------------------------------------------------------------
def info_append(self, def info_append(self,
what): what):
"""Add item or list to existing set of infos""" """Add item or list to existing set of infos."""
if isinstance(what, (str, unicode)): if isinstance(what, (str, unicode)):
self.info += [self._removeCRLF(what)] self.info += [self._removeCRLF(what)]
else: else:
@ -403,7 +404,7 @@ class ASCIItable():
# ------------------------------------------------------------------ # ------------------------------------------------------------------
def info_clear(self): def info_clear(self):
"""Delete any info block""" """Delete any info block."""
self.info = [] self.info = []
# ------------------------------------------------------------------ # ------------------------------------------------------------------
@ -416,7 +417,7 @@ class ASCIItable():
# ------------------------------------------------------------------ # ------------------------------------------------------------------
def data_skipLines(self, def data_skipLines(self,
count): count):
"""Wind forward by count number of lines""" """Wind forward by count number of lines."""
for i in range(count): for i in range(count):
alive = self.data_read() alive = self.data_read()
@ -426,7 +427,7 @@ class ASCIItable():
def data_read(self, def data_read(self,
advance = True, advance = True,
respectLabels = True): respectLabels = True):
"""Read next line (possibly buffered) and parse it into data array""" """Read next line (possibly buffered) and parse it into data array."""
self.line = self.__IO__['readBuffer'].pop(0) if len(self.__IO__['readBuffer']) > 0 \ self.line = self.__IO__['readBuffer'].pop(0) if len(self.__IO__['readBuffer']) > 0 \
else self.__IO__['in'].readline().strip() # take buffered content or get next data row from file else self.__IO__['in'].readline().strip() # take buffered content or get next data row from file
@ -446,9 +447,11 @@ class ASCIItable():
# ------------------------------------------------------------------ # ------------------------------------------------------------------
def data_readArray(self, def data_readArray(self,
labels = []): labels = []):
"""Read whole data of all (given) labels as numpy array""" """Read whole data of all (given) labels as numpy array."""
try: self.data_rewind() # try to wind back to start of data try:
except: pass # assume/hope we are at data start already... self.data_rewind() # try to wind back to start of data
except IOError:
pass # assume/hope we are at data start already...
if labels is None or labels == []: if labels is None or labels == []:
use = None # use all columns (and keep labels intact) use = None # use all columns (and keep labels intact)
@ -480,7 +483,7 @@ class ASCIItable():
# ------------------------------------------------------------------ # ------------------------------------------------------------------
def data_write(self, def data_write(self,
delimiter = '\t'): delimiter = '\t'):
"""Write current data array and report alive output back""" """Write current data array and report alive output back."""
if len(self.data) == 0: return True if len(self.data) == 0: return True
if isinstance(self.data[0],list): if isinstance(self.data[0],list):
@ -492,16 +495,16 @@ class ASCIItable():
def data_writeArray(self, def data_writeArray(self,
fmt = None, fmt = None,
delimiter = '\t'): delimiter = '\t'):
"""Write whole numpy array data""" """Write whole numpy array data."""
for row in self.data: for row in self.data:
try: try:
output = [fmt % value for value in row] if fmt else list(map(repr,row)) output = [fmt % value for value in row] if fmt else list(map(repr,row))
except: except Exception:
output = [fmt % row] if fmt else [repr(row)] output = [fmt % row] if fmt else [repr(row)]
try: try:
self.__IO__['out'].write(delimiter.join(output) + '\n') self.__IO__['out'].write(delimiter.join(output) + '\n')
except: except Exception:
pass pass
# ------------------------------------------------------------------ # ------------------------------------------------------------------
@ -545,7 +548,7 @@ class ASCIItable():
grid, grid,
type = 'i', type = 'i',
strict = False): strict = False):
"""Read microstructure data (from .geom format)""" """Read microstructure data (from .geom format)."""
def datatype(item): def datatype(item):
return int(item) if type.lower() == 'i' else float(item) return int(item) if type.lower() == 'i' else float(item)

View File

@ -15,7 +15,7 @@ class Test():
variants = [] variants = []
def __init__(self, **kwargs): def __init__(self, **kwargs):
"""New test."""
defaults = {'description': '', defaults = {'description': '',
'keep': False, 'keep': False,
'accept': False, 'accept': False,
@ -118,22 +118,22 @@ class Test():
"""Delete directory tree containing current results.""" """Delete directory tree containing current results."""
try: try:
shutil.rmtree(self.dirCurrent()) shutil.rmtree(self.dirCurrent())
except: except FileNotFoundError:
logging.warning('removal of directory "{}" not possible...'.format(self.dirCurrent())) logging.warning('removal of directory "{}" not possible...'.format(self.dirCurrent()))
try: try:
os.mkdir(self.dirCurrent()) os.mkdir(self.dirCurrent())
return True return True
except: except FileExistsError:
logging.critical('creation of directory "{}" failed.'.format(self.dirCurrent())) logging.critical('creation of directory "{}" failed.'.format(self.dirCurrent()))
return False return False
def prepareAll(self): def prepareAll(self):
"""Do all necessary preparations for the whole test""" """Do all necessary preparations for the whole test."""
return True return True
def prepare(self,variant): def prepare(self,variant):
"""Do all necessary preparations for the run of each test variant""" """Do all necessary preparations for the run of each test variant."""
return True return True
@ -205,9 +205,9 @@ class Test():
for source,target in zip(list(map(mapA,A)),list(map(mapB,B))): for source,target in zip(list(map(mapA,A)),list(map(mapB,B))):
try: try:
shutil.copy2(source,target) shutil.copy2(source,target)
except: except FileNotFoundError:
logging.critical('error copying {} to {}'.format(source,target)) logging.critical('error copying {} to {}'.format(source,target))
raise raise FileNotFoundError
def copy_Reference2Current(self,sourcefiles=[],targetfiles=[]): def copy_Reference2Current(self,sourcefiles=[],targetfiles=[]):
@ -216,9 +216,9 @@ class Test():
for i,f in enumerate(sourcefiles): for i,f in enumerate(sourcefiles):
try: try:
shutil.copy2(self.fileInReference(f),self.fileInCurrent(targetfiles[i])) shutil.copy2(self.fileInReference(f),self.fileInCurrent(targetfiles[i]))
except: except FileNotFoundError:
logging.critical('Reference2Current: Unable to copy file "{}"'.format(f)) logging.critical('Reference2Current: Unable to copy file "{}"'.format(f))
raise raise FileNotFoundError
def copy_Base2Current(self,sourceDir,sourcefiles=[],targetfiles=[]): def copy_Base2Current(self,sourceDir,sourcefiles=[],targetfiles=[]):
@ -228,10 +228,10 @@ class Test():
for i,f in enumerate(sourcefiles): for i,f in enumerate(sourcefiles):
try: try:
shutil.copy2(os.path.join(source,f),self.fileInCurrent(targetfiles[i])) shutil.copy2(os.path.join(source,f),self.fileInCurrent(targetfiles[i]))
except: except FileNotFoundError:
logging.error(os.path.join(source,f)) logging.error(os.path.join(source,f))
logging.critical('Base2Current: Unable to copy file "{}"'.format(f)) logging.critical('Base2Current: Unable to copy file "{}"'.format(f))
raise raise FileNotFoundError
def copy_Current2Reference(self,sourcefiles=[],targetfiles=[]): def copy_Current2Reference(self,sourcefiles=[],targetfiles=[]):
@ -240,9 +240,9 @@ class Test():
for i,f in enumerate(sourcefiles): for i,f in enumerate(sourcefiles):
try: try:
shutil.copy2(self.fileInCurrent(f),self.fileInReference(targetfiles[i])) shutil.copy2(self.fileInCurrent(f),self.fileInReference(targetfiles[i]))
except: except FileNotFoundError:
logging.critical('Current2Reference: Unable to copy file "{}"'.format(f)) logging.critical('Current2Reference: Unable to copy file "{}"'.format(f))
raise raise FileNotFoundError
def copy_Proof2Current(self,sourcefiles=[],targetfiles=[]): def copy_Proof2Current(self,sourcefiles=[],targetfiles=[]):
@ -251,9 +251,9 @@ class Test():
for i,f in enumerate(sourcefiles): for i,f in enumerate(sourcefiles):
try: try:
shutil.copy2(self.fileInProof(f),self.fileInCurrent(targetfiles[i])) shutil.copy2(self.fileInProof(f),self.fileInCurrent(targetfiles[i]))
except: except FileNotFoundError:
logging.critical('Proof2Current: Unable to copy file "{}"'.format(f)) logging.critical('Proof2Current: Unable to copy file "{}"'.format(f))
raise raise FileNotFoundError
def copy_Current2Current(self,sourcefiles=[],targetfiles=[]): def copy_Current2Current(self,sourcefiles=[],targetfiles=[]):
@ -261,9 +261,10 @@ class Test():
for i,f in enumerate(sourcefiles): for i,f in enumerate(sourcefiles):
try: try:
shutil.copy2(self.fileInReference(f),self.fileInCurrent(targetfiles[i])) shutil.copy2(self.fileInReference(f),self.fileInCurrent(targetfiles[i]))
except: except FileNotFoundError:
logging.critical('Current2Current: Unable to copy file "{}"'.format(f)) logging.critical('Current2Current: Unable to copy file "{}"'.format(f))
raise raise FileNotFoundError
def execute_inCurrentDir(self,cmd,streamIn=None,env=None): def execute_inCurrentDir(self,cmd,streamIn=None,env=None):
@ -437,7 +438,7 @@ class Test():
stdTol = 1.0e-6, stdTol = 1.0e-6,
preFilter = 1.0e-9): preFilter = 1.0e-9):
""" """
Calculate statistics of tables Calculate statistics of tables.
threshold can be used to ignore small values (a negative number disables this feature) threshold can be used to ignore small values (a negative number disables this feature)
""" """
@ -490,7 +491,7 @@ class Test():
rtol = 1e-5, rtol = 1e-5,
atol = 1e-8, atol = 1e-8,
debug = False): debug = False):
"""Compare multiple tables with np.allclose""" """Compare multiple tables with np.allclose."""
if not (isinstance(files, Iterable) and not isinstance(files, str)): # check whether list of files is requested if not (isinstance(files, Iterable) and not isinstance(files, str)): # check whether list of files is requested
files = [str(files)] files = [str(files)]

View File

@ -1,3 +0,0 @@
"""Test functionality."""
from .test import Test # noqa