avoid code duplication and inconsistencies
This commit is contained in:
parent
2dfde6997b
commit
f3cf67d3fa
|
@ -2,7 +2,6 @@ import os
|
||||||
import json
|
import json
|
||||||
import functools
|
import functools
|
||||||
import colorsys
|
import colorsys
|
||||||
from pathlib import Path
|
|
||||||
from typing import Union, TextIO
|
from typing import Union, TextIO
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
@ -325,12 +324,7 @@ class Colormap(mpl.colors.ListedColormap):
|
||||||
File handle with write access.
|
File handle with write access.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
if fname is None:
|
return util.open_text(self.name.replace(' ','_')+suffix if fname is None else fname, 'w')
|
||||||
return open(self.name.replace(' ','_')+suffix, 'w', newline='\n')
|
|
||||||
elif isinstance(fname, (str, Path)):
|
|
||||||
return open(Path(fname).expanduser(), 'w', newline='\n')
|
|
||||||
else:
|
|
||||||
return fname
|
|
||||||
|
|
||||||
|
|
||||||
def save_paraview(self,
|
def save_paraview(self,
|
||||||
|
|
|
@ -2,7 +2,6 @@ import copy
|
||||||
from io import StringIO
|
from io import StringIO
|
||||||
from collections.abc import Iterable
|
from collections.abc import Iterable
|
||||||
import abc
|
import abc
|
||||||
from pathlib import Path
|
|
||||||
from typing import Union, Dict, Any, Type, TypeVar
|
from typing import Union, Dict, Any, Type, TypeVar
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
@ -10,6 +9,7 @@ import yaml
|
||||||
|
|
||||||
from ._typehints import FileHandle
|
from ._typehints import FileHandle
|
||||||
from . import Rotation
|
from . import Rotation
|
||||||
|
from . import util
|
||||||
|
|
||||||
MyType = TypeVar('MyType', bound='Config')
|
MyType = TypeVar('MyType', bound='Config')
|
||||||
|
|
||||||
|
@ -144,10 +144,7 @@ class Config(dict):
|
||||||
Configuration from file.
|
Configuration from file.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
fhandle = open(Path(fname).expanduser(),newline='\n') if isinstance(fname, (str, Path)) else \
|
return cls(yaml.safe_load(util.open_text(fname)))
|
||||||
fname
|
|
||||||
|
|
||||||
return cls(yaml.safe_load(fhandle))
|
|
||||||
|
|
||||||
def save(self,
|
def save(self,
|
||||||
fname: FileHandle,
|
fname: FileHandle,
|
||||||
|
@ -163,9 +160,6 @@ class Config(dict):
|
||||||
Keyword arguments parsed to yaml.dump.
|
Keyword arguments parsed to yaml.dump.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
fhandle = open(Path(fname).expanduser(),'w',newline='\n') if isinstance(fname, (str, Path)) else \
|
|
||||||
fname
|
|
||||||
|
|
||||||
if 'width' not in kwargs:
|
if 'width' not in kwargs:
|
||||||
kwargs['width'] = 256
|
kwargs['width'] = 256
|
||||||
if 'default_flow_style' not in kwargs:
|
if 'default_flow_style' not in kwargs:
|
||||||
|
@ -173,6 +167,7 @@ class Config(dict):
|
||||||
if 'sort_keys' not in kwargs:
|
if 'sort_keys' not in kwargs:
|
||||||
kwargs['sort_keys'] = False
|
kwargs['sort_keys'] = False
|
||||||
|
|
||||||
|
fhandle = util.open_text(fname,'w')
|
||||||
try:
|
try:
|
||||||
fhandle.write(yaml.dump(self,Dumper=NiceDumper,**kwargs))
|
fhandle.write(yaml.dump(self,Dumper=NiceDumper,**kwargs))
|
||||||
except TypeError: # compatibility with old pyyaml
|
except TypeError: # compatibility with old pyyaml
|
||||||
|
|
|
@ -1538,7 +1538,7 @@ class Result:
|
||||||
np.prod(shape))}
|
np.prod(shape))}
|
||||||
data_items[-1].text = f'{os.path.split(self.fname)[1]}:{name}'
|
data_items[-1].text = f'{os.path.split(self.fname)[1]}:{name}'
|
||||||
|
|
||||||
with open(self.fname.with_suffix('.xdmf').name,'w',newline='\n') as f:
|
with util.open_text(self.fname.with_suffix('.xdmf').name,'w') as f:
|
||||||
f.write(xml.dom.minidom.parseString(ET.tostring(xdmf).decode()).toprettyxml())
|
f.write(xml.dom.minidom.parseString(ET.tostring(xdmf).decode()).toprettyxml())
|
||||||
|
|
||||||
|
|
||||||
|
@ -1803,7 +1803,7 @@ class Result:
|
||||||
if type(obj) == h5py.Dataset and _match(output,[name]):
|
if type(obj) == h5py.Dataset and _match(output,[name]):
|
||||||
d = obj.attrs['description'] if h5py3 else obj.attrs['description'].decode()
|
d = obj.attrs['description'] if h5py3 else obj.attrs['description'].decode()
|
||||||
if not Path(name).exists() or overwrite:
|
if not Path(name).exists() or overwrite:
|
||||||
with open(name,'w',newline='\n') as f_out: f_out.write(obj[0].decode())
|
with util.open_text(name,'w') as f_out: f_out.write(obj[0].decode())
|
||||||
print(f'Exported {d} to "{name}".')
|
print(f'Exported {d} to "{name}".')
|
||||||
else:
|
else:
|
||||||
print(f'"{name}" exists, {d} not exported.')
|
print(f'"{name}" exists, {d} not exported.')
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import re
|
import re
|
||||||
import copy
|
import copy
|
||||||
from pathlib import Path
|
|
||||||
from typing import Union, Tuple, List
|
from typing import Union, Tuple, List
|
||||||
|
|
||||||
import pandas as pd
|
import pandas as pd
|
||||||
|
@ -260,7 +259,7 @@ class Table:
|
||||||
Table data from file.
|
Table data from file.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
f = open(Path(fname).expanduser(),newline='\n') if isinstance(fname, (str, Path)) else fname
|
f = util.open_text(fname)
|
||||||
f.seek(0)
|
f.seek(0)
|
||||||
|
|
||||||
comments = []
|
comments = []
|
||||||
|
@ -312,7 +311,7 @@ class Table:
|
||||||
Table data from file.
|
Table data from file.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
f = open(Path(fname).expanduser(),newline='\n') if isinstance(fname, (str, Path)) else fname
|
f = util.open_text(fname)
|
||||||
f.seek(0)
|
f.seek(0)
|
||||||
|
|
||||||
content = f.readlines()
|
content = f.readlines()
|
||||||
|
@ -594,7 +593,7 @@ class Table:
|
||||||
labels += [f'{util.srepr(self.shapes[l],"x")}:{i+1}_{l}' \
|
labels += [f'{util.srepr(self.shapes[l],"x")}:{i+1}_{l}' \
|
||||||
for i in range(np.prod(self.shapes[l]))]
|
for i in range(np.prod(self.shapes[l]))]
|
||||||
|
|
||||||
f = open(Path(fname).expanduser(),'w',newline='\n') if isinstance(fname, (str, Path)) else fname
|
f = util.open_text(fname,'w')
|
||||||
|
|
||||||
f.write('\n'.join([f'# {c}' for c in self.comments] + [' '.join(labels)])+('\n' if labels else ''))
|
f.write('\n'.join([f'# {c}' for c in self.comments] + [' '.join(labels)])+('\n' if labels else ''))
|
||||||
self.data.to_csv(f,sep=' ',na_rep='nan',index=False,header=False,line_terminator='\n')
|
self.data.to_csv(f,sep=' ',na_rep='nan',index=False,header=False,line_terminator='\n')
|
||||||
|
|
|
@ -10,20 +10,21 @@ import signal
|
||||||
import fractions
|
import fractions
|
||||||
from collections import abc
|
from collections import abc
|
||||||
from functools import reduce, partial
|
from functools import reduce, partial
|
||||||
from typing import Callable, Union, Iterable, Sequence, Dict, List, Tuple, Literal, Any, Collection
|
from typing import Callable, Union, Iterable, Sequence, Dict, List, Tuple, Literal, Any, Collection, TextIO
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import h5py
|
import h5py
|
||||||
|
|
||||||
from . import version
|
from . import version
|
||||||
from ._typehints import FloatSequence, NumpyRngSeed, IntCollection
|
from ._typehints import FloatSequence, NumpyRngSeed, IntCollection, FileHandle
|
||||||
|
|
||||||
# limit visibility
|
# limit visibility
|
||||||
__all__=[
|
__all__=[
|
||||||
'srepr',
|
'srepr',
|
||||||
'emph', 'deemph', 'warn', 'strikeout',
|
'emph', 'deemph', 'warn', 'strikeout',
|
||||||
'run',
|
'run',
|
||||||
|
'open_text',
|
||||||
'natural_sort',
|
'natural_sort',
|
||||||
'show_progress',
|
'show_progress',
|
||||||
'scale_to_coprime',
|
'scale_to_coprime',
|
||||||
|
@ -206,7 +207,24 @@ def run(cmd: str,
|
||||||
return stdout, stderr
|
return stdout, stderr
|
||||||
|
|
||||||
|
|
||||||
execute = run
|
def open_text(fname: FileHandle,
|
||||||
|
mode: Literal['r','w'] = 'r') -> TextIO:
|
||||||
|
"""
|
||||||
|
Open a text file.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
fname : file, str, or pathlib.Path
|
||||||
|
Name or handle of file.
|
||||||
|
mode: {'r','w'}, optional
|
||||||
|
Access mode: 'r'ead or 'w'rite, defaults to 'r'.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
f : file handle
|
||||||
|
|
||||||
|
"""
|
||||||
|
return open(Path(fname).expanduser(),mode,newline='\n') if isinstance(fname, (str, Path)) else fname
|
||||||
|
|
||||||
|
|
||||||
def natural_sort(key: str) -> List[Union[int, str]]:
|
def natural_sort(key: str) -> List[Union[int, str]]:
|
||||||
|
|
|
@ -12,19 +12,19 @@ from damask import util
|
||||||
class TestUtil:
|
class TestUtil:
|
||||||
|
|
||||||
@pytest.mark.xfail(sys.platform == 'win32', reason='echo is not a Windows command')
|
@pytest.mark.xfail(sys.platform == 'win32', reason='echo is not a Windows command')
|
||||||
def test_execute_direct(self):
|
def test_run_direct(self):
|
||||||
out,err = util.execute('echo test')
|
out,err = util.run('echo test')
|
||||||
assert out=='test\n' and err==''
|
assert out=='test\n' and err==''
|
||||||
|
|
||||||
@pytest.mark.xfail(sys.platform == 'win32', reason='echo is not a Windows command')
|
@pytest.mark.xfail(sys.platform == 'win32', reason='echo is not a Windows command')
|
||||||
def test_execute_env(self):
|
def test_run_env(self):
|
||||||
out,err = util.execute('sh -c "echo $test_for_execute"',env={'test_for_execute':'test'})
|
out,err = util.run('sh -c "echo $test_for_execute"',env={'test_for_execute':'test'})
|
||||||
assert out=='test\n' and err==''
|
assert out=='test\n' and err==''
|
||||||
|
|
||||||
@pytest.mark.xfail(sys.platform == 'win32', reason='false is not a Windows command')
|
@pytest.mark.xfail(sys.platform == 'win32', reason='false is not a Windows command')
|
||||||
def test_execute_runtime_error(self):
|
def test_run_runtime_error(self):
|
||||||
with pytest.raises(RuntimeError):
|
with pytest.raises(RuntimeError):
|
||||||
util.execute('false')
|
util.run('false')
|
||||||
|
|
||||||
@pytest.mark.parametrize('input,output',
|
@pytest.mark.parametrize('input,output',
|
||||||
[
|
[
|
||||||
|
|
Loading…
Reference in New Issue