diff --git a/interfaces/cython/cantera/__init__.py b/interfaces/cython/cantera/__init__.py index 023fa3883fd..e0fe4e9c40e 100644 --- a/interfaces/cython/cantera/__init__.py +++ b/interfaces/cython/cantera/__init__.py @@ -11,10 +11,11 @@ import os import sys +from pathlib import Path import warnings warnings.filterwarnings('default', module='cantera') -add_directory(os.path.join(os.path.dirname(__file__), 'data')) +add_directory(Path(__file__).parent / "data") add_directory('.') # Move current working directory to the front of the path # Python interpreter used for converting mechanisms diff --git a/interfaces/cython/cantera/base.pyx b/interfaces/cython/cantera/base.pyx index f3a60801d63..652585ee623 100644 --- a/interfaces/cython/cantera/base.pyx +++ b/interfaces/cython/cantera/base.pyx @@ -2,6 +2,7 @@ # at https://cantera.org/license.txt for license and copyright information. from collections import defaultdict as _defaultdict +from pathlib import PurePath cdef class _SolutionBase: def __cinit__(self, infile='', name='', adjacent=(), origin=None, @@ -53,6 +54,8 @@ cdef class _SolutionBase: self.transport = NULL # Parse inputs + if isinstance(infile, PurePath): + infile = str(infile) if infile.endswith('.yml') or infile.endswith('.yaml') or yaml: self._init_yaml(infile, name, adjacent, yaml) elif infile or source: diff --git a/interfaces/cython/cantera/ck2yaml.py b/interfaces/cython/cantera/ck2yaml.py index 8173c0ac884..eef92ed9153 100644 --- a/interfaces/cython/cantera/ck2yaml.py +++ b/interfaces/cython/cantera/ck2yaml.py @@ -1375,8 +1375,9 @@ def load_extra_file(self, path): """ Load YAML-formatted entries from ``path`` on disk. """ + yaml_ = yaml.YAML() with open(path, 'rt', encoding="utf-8") as stream: - yml = yaml.round_trip_load(stream) + yml = yaml_.load(stream) # do not overwrite reserved field names reserved = {'generator', 'input-files', 'cantera-version', 'date', diff --git a/interfaces/cython/cantera/onedim.pyx b/interfaces/cython/cantera/onedim.pyx index b2437b763fe..87964b28887 100644 --- a/interfaces/cython/cantera/onedim.pyx +++ b/interfaces/cython/cantera/onedim.pyx @@ -1411,7 +1411,7 @@ cdef class Sim1D: ... description='solution with energy eqn. disabled') """ - self.sim.save(stringify(filename), stringify(name), + self.sim.save(stringify(str(filename)), stringify(name), stringify(description), loglevel) def restore(self, filename='soln.xml', name='solution', loglevel=2): @@ -1427,7 +1427,7 @@ cdef class Sim1D: >>> s.restore(filename='save.xml', name='energy_off') """ - self.sim.restore(stringify(filename), stringify(name), loglevel) + self.sim.restore(stringify(str(filename)), stringify(name), loglevel) self._initialized = True def restore_time_stepping_solution(self): diff --git a/interfaces/cython/cantera/test/__init__.py b/interfaces/cython/cantera/test/__init__.py index 14f938347a5..4476c62b0f1 100644 --- a/interfaces/cython/cantera/test/__init__.py +++ b/interfaces/cython/cantera/test/__init__.py @@ -1,4 +1,4 @@ -import os +from pathlib import Path import cantera from .test_composite import * @@ -15,5 +15,5 @@ from .test_transport import * from .test_utils import * -cantera.add_directory(os.path.join(os.path.dirname(__file__), 'data')) -cantera.add_directory(os.path.join(os.path.dirname(__file__), '..', 'examples', 'surface_chemistry')) +cantera.add_directory(Path(__file__) / "data") +cantera.add_directory(Path(__file__).parents[1] / "examples" / "surface_chemistry") diff --git a/interfaces/cython/cantera/test/test_composite.py b/interfaces/cython/cantera/test/test_composite.py index 51fdb1c5cb1..0ae19a2dbf8 100644 --- a/interfaces/cython/cantera/test/test_composite.py +++ b/interfaces/cython/cantera/test/test_composite.py @@ -1,16 +1,7 @@ -from os.path import join as pjoin -import os import sys import numpy as np from collections import OrderedDict -import warnings - -try: - import ruamel_yaml as yaml -except ImportError: - from ruamel import yaml - import cantera as ct from cantera.composite import _h5py, _pandas @@ -22,9 +13,8 @@ class TestModels(utilities.CanteraTest): @classmethod def setUpClass(cls): utilities.CanteraTest.setUpClass() - cls.yml_file = pjoin(cls.test_data_dir, "thermo-models.yaml") - with open(cls.yml_file, 'rt', encoding="utf-8") as stream: - cls.yml = yaml.safe_load(stream) + cls.yml_file = cls.test_data_path / "thermo-models.yaml" + cls.yml = utilities.load_yaml(cls.yml_file) def test_load_thermo_models(self): for ph in self.yml['phases']: @@ -150,7 +140,7 @@ def test_write_csv(self): states.TPX = np.linspace(300, 1000, 7), 2e5, 'H2:0.5, O2:0.4' states.equilibrate('HP') - outfile = pjoin(self.test_work_dir, 'solutionarray.csv') + outfile = self.test_work_path / "solutionarray.csv" states.write_csv(outfile) data = np.genfromtxt(outfile, names=True, delimiter=',') @@ -167,7 +157,7 @@ def test_write_csv(self): def test_write_csv_str_column(self): states = ct.SolutionArray(self.gas, 3, extra={'spam': 'eggs'}) - outfile = pjoin(self.test_work_dir, 'solutionarray.csv') + outfile = self.test_work_path / "solutionarray.csv" states.write_csv(outfile) b = ct.SolutionArray(self.gas, extra={'spam'}) @@ -177,7 +167,7 @@ def test_write_csv_str_column(self): def test_write_csv_multidim_column(self): states = ct.SolutionArray(self.gas, 3, extra={'spam': np.zeros((3, 5,))}) - outfile = pjoin(self.test_work_dir, 'solutionarray.csv') + outfile = self.test_work_path / "solutionarray.csv" with self.assertRaisesRegex(NotImplementedError, 'not supported'): states.write_csv(outfile) @@ -194,9 +184,10 @@ def test_to_pandas(self): @utilities.unittest.skipIf(isinstance(_h5py, ImportError), "h5py is not installed") def test_write_hdf(self): - outfile = pjoin(self.test_work_dir, 'solutionarray.h5') - if os.path.exists(outfile): - os.remove(outfile) + outfile = self.test_work_path / "solutionarray.h5" + # In Python >= 3.8, this can be replaced by the missing_ok argument + if outfile.is_file(): + outfile.unlink() extra = {'foo': range(7), 'bar': range(7)} meta = {'spam': 'eggs', 'hello': 'world'} @@ -239,9 +230,10 @@ def test_write_hdf(self): @utilities.unittest.skipIf(isinstance(_h5py, ImportError), "h5py is not installed") def test_write_hdf_str_column(self): - outfile = pjoin(self.test_work_dir, 'solutionarray.h5') - if os.path.exists(outfile): - os.remove(outfile) + outfile = self.test_work_path / "solutionarray.h5" + # In Python >= 3.8, this can be replaced by the missing_ok argument + if outfile.is_file(): + outfile.unlink() states = ct.SolutionArray(self.gas, 3, extra={'spam': 'eggs'}) states.write_hdf(outfile, mode='w') @@ -252,9 +244,10 @@ def test_write_hdf_str_column(self): @utilities.unittest.skipIf(isinstance(_h5py, ImportError), "h5py is not installed") def test_write_hdf_multidim_column(self): - outfile = pjoin(self.test_work_dir, 'solutionarray.h5') - if os.path.exists(outfile): - os.remove(outfile) + outfile = self.test_work_path / "solutionarray.h5" + # In Python >= 3.8, this can be replaced by the missing_ok argument + if outfile.is_file(): + outfile.unlink() states = ct.SolutionArray(self.gas, 3, extra={'spam': [[1, 2], [3, 4], [5, 6]]}) states.write_hdf(outfile, mode='w') @@ -478,8 +471,7 @@ def test_yaml_simple(self): gas.equilibrate('HP') gas.TP = 1500, ct.one_atm gas.write_yaml('h2o2-generated.yaml') - with open('h2o2-generated.yaml', 'r') as infile: - generated = yaml.safe_load(infile) + generated = utilities.load_yaml("h2o2-generated.yaml") for key in ('generator', 'date', 'phases', 'species', 'reactions'): self.assertIn(key, generated) self.assertEqual(generated['phases'][0]['transport'], 'mixture-averaged') @@ -503,10 +495,8 @@ def test_yaml_outunits(self): gas.TP = 1500, ct.one_atm units = {'length': 'cm', 'quantity': 'mol', 'energy': 'cal'} gas.write_yaml('h2o2-generated.yaml', units=units) - with open('h2o2-generated.yaml') as infile: - generated = yaml.safe_load(infile) - with open(pjoin(self.cantera_data, "h2o2.yaml")) as infile: - original = yaml.safe_load(infile) + generated = utilities.load_yaml("h2o2-generated.yaml") + original = utilities.load_yaml(self.cantera_data_path / "h2o2.yaml") self.assertEqual(generated['units'], units) for r1, r2 in zip(original['reactions'], generated['reactions']): @@ -529,8 +519,7 @@ def test_yaml_surface(self): surf.coverages = np.ones(surf.n_species) surf.write_yaml('ptcombust-generated.yaml') - with open('ptcombust-generated.yaml') as infile: - generated = yaml.safe_load(infile) + generated = utilities.load_yaml("ptcombust-generated.yaml") for key in ('phases', 'species', 'gas-reactions', 'Pt_surf-reactions'): self.assertIn(key, generated) self.assertEqual(len(generated['gas-reactions']), gas.n_reactions) diff --git a/interfaces/cython/cantera/test/test_convert.py b/interfaces/cython/cantera/test/test_convert.py index 24ba4900a60..7ae4c871019 100644 --- a/interfaces/cython/cantera/test/test_convert.py +++ b/interfaces/cython/cantera/test/test_convert.py @@ -1,40 +1,33 @@ -import os -from os.path import join as pjoin import itertools from pathlib import Path import logging import io -import sys from . import utilities import cantera as ct from cantera import ck2cti, ck2yaml, cti2yaml, ctml2yaml -try: - import ruamel_yaml as yaml -except ImportError: - from ruamel import yaml - class converterTestCommon: def convert(self, inputFile, thermo=None, transport=None, surface=None, output=None, extra=None, quiet=True, permissive=None): if output is None: - output = inputFile[:-4] # strip '.inp' + output = Path(inputFile).stem # strip '.inp' if inputFile is not None: - inputFile = pjoin(self.test_data_dir, inputFile) + inputFile = self.test_data_path / inputFile if thermo is not None: - thermo = pjoin(self.test_data_dir, thermo) + thermo = self.test_data_path / thermo if transport is not None: - transport = pjoin(self.test_data_dir, transport) + transport = self.test_data_path / transport if surface is not None: - surface = pjoin(self.test_data_dir, surface) + surface = self.test_data_path / surface if extra is not None: - extra = pjoin(self.test_data_dir, extra) - output = pjoin(self.test_work_dir, output + self.ext) - if os.path.exists(output): - os.remove(output) + extra = self.test_data_path / extra + output = self.test_work_path / (output + self.ext) + # In Python >= 3.8, this can be replaced by the missing_ok argument + if output.is_file(): + output.unlink() self._convert(inputFile, thermo=thermo, transport=transport, surface=surface, output=output, extra=extra, quiet=quiet, permissive=permissive) @@ -367,14 +360,14 @@ def test_empty_reaction_section(self): def test_reaction_comments1(self): output = self.convert('pdep-test.inp') - text = Path(output).read_text() + text = output.read_text() self.assertIn('Generic mechanism header', text) self.assertIn('Single PLOG reaction', text) self.assertIn('Multiple PLOG expressions at the same pressure', text) def test_reaction_comments2(self): output = self.convert('explicit-third-bodies.inp', thermo='dummy-thermo.dat') - text = Path(output).read_text() + text = output.read_text() self.assertIn('An end of line comment', text) self.assertIn('A comment after the last reaction', text) @@ -478,26 +471,24 @@ def test_extra(self): transport='gri30_tran.dat', output='gri30_extra', extra='extra.yaml') - output = pjoin(self.test_work_dir, 'gri30_extra' + self.ext) - with open(output, 'rt', encoding="utf-8") as stream: - yml = yaml.safe_load(stream) + output = self.test_work_path / ("gri30_extra" + self.ext) + yml = utilities.load_yaml(output) desc = yml['description'].split('\n')[-1] self.assertEqual(desc, 'This is an alternative description.') for key in ['foo', 'bar']: self.assertIn(key, yml.keys()) - # This test tests it can convert the SRI parameters when D or E equal to 0 - + def test_sri_zero(self): + # This test tests it can convert the SRI parameters when D or E equal to 0 self.convert('sri_convert_test.txt') - output = pjoin(self.test_work_dir, 'sri_convert_test' + self.ext) - with open(output, 'r') as f: - mech = yaml.safe_load(f) + output = self.test_work_path / ("sri_convert_test" + self.ext) + mech = utilities.load_yaml(output) D = mech['reactions'][0]['SRI']['D'] E = mech['reactions'][0]['SRI']['E'] self.assertEqual(D, 0) self.assertEqual(E, 0) - + def test_duplicate_reactions(self): # Running a test this way instead of using the convertMech function # tests the behavior of the ck2yaml.main function and the mechanism @@ -517,8 +508,8 @@ def test_duplicate_reactions(self): with self.assertRaises(SystemExit): ck2yaml.main([ - '--input={}/undeclared-duplicate-reactions.inp'.format(self.test_data_dir), - '--thermo={}/dummy-thermo.dat'.format(self.test_data_dir)]) + f"--input={self.test_data_path}/undeclared-duplicate-reactions.inp", + f"--thermo={self.test_data_path}/dummy-thermo.dat"]) # Put the original logger back in place logger.handlers.clear() @@ -579,8 +570,7 @@ def test_long_source_input(self): gas = ct.Solution('pdep-test.yaml') - with open(pjoin(self.test_data_dir, 'pdep-test.cti'), 'r') as f: - data = f.read() + data = (self.test_data_path / "pdep-test.cti").read_text() data_size_2048kB = data + ' '*2048*1024 gas2 = ct.Solution(source=data_size_2048kB) @@ -594,8 +584,7 @@ def test_short_source_input(self): gas = ct.Solution('pdep-test.yaml') - with open(pjoin(self.test_data_dir, 'pdep-test.cti'), 'r') as f: - data = f.read() + data = (self.test_data_path / "pdep-test.cti").read_text() data_size_32kB = data + ' '*18000 gas2 = ct.Solution(source=data_size_32kB) @@ -674,8 +663,10 @@ def checkTransport(self, ctiPhase, yamlPhase, temperatures, @utilities.slow_test def test_gri30(self): - cti2yaml.convert(Path(self.cantera_data).joinpath('gri30.cti'), - Path(self.test_work_dir).joinpath('gri30.yaml')) + cti2yaml.convert( + self.cantera_data_path / "gri30.cti", + self.test_work_path / "gri30.yaml", + ) ctiPhase, yamlPhase = self.checkConversion('gri30') X = {'O2': 0.3, 'H2': 0.1, 'CH4': 0.2, 'CO2': 0.4} ctiPhase.X = X @@ -685,15 +676,19 @@ def test_gri30(self): self.checkTransport(ctiPhase, yamlPhase, [298, 1001, 2400]) def test_pdep(self): - cti2yaml.convert(Path(self.test_data_dir).joinpath('pdep-test.cti'), - Path(self.test_work_dir).joinpath('pdep-test.yaml')) + cti2yaml.convert( + self.test_data_path / "pdep-test.cti", + self.test_work_path / "pdep-test.yaml", + ) ctiPhase, yamlPhase = self.checkConversion('pdep-test') self.checkKinetics(ctiPhase, yamlPhase, [300, 1000, 2200], [100, ct.one_atm, 2e5, 2e6, 9.9e6]) def test_ptcombust(self): - cti2yaml.convert(Path(self.cantera_data).joinpath('ptcombust.cti'), - Path(self.test_work_dir).joinpath('ptcombust.yaml')) + cti2yaml.convert( + self.cantera_data_path / "ptcombust.cti", + self.test_work_path / "ptcombust.yaml", + ) ctiGas, yamlGas = self.checkConversion('ptcombust') ctiSurf, yamlSurf = self.checkConversion('ptcombust', ct.Interface, name='Pt_surf', ctiphases=[ctiGas], yamlphases=[yamlGas]) @@ -704,8 +699,10 @@ def test_ptcombust(self): @utilities.slow_test def test_ptcombust_motzwise(self): - cti2yaml.convert(Path(self.test_data_dir).joinpath('ptcombust-motzwise.cti'), - Path(self.test_work_dir).joinpath('ptcombust-motzwise.yaml')) + cti2yaml.convert( + self.test_data_path / "ptcombust-motzwise.cti", + self.test_work_path / "ptcombust-motzwise.yaml", + ) ctiGas, yamlGas = self.checkConversion('ptcombust-motzwise') ctiSurf, yamlSurf = self.checkConversion('ptcombust-motzwise', ct.Interface, name='Pt_surf', ctiphases=[ctiGas], yamlphases=[yamlGas]) @@ -716,8 +713,10 @@ def test_ptcombust_motzwise(self): self.checkKinetics(ctiSurf, yamlSurf, [900], [101325]) def test_sofc(self): - cti2yaml.convert(Path(self.cantera_data).joinpath('sofc.cti'), - Path(self.test_work_dir).joinpath('sofc.yaml')) + cti2yaml.convert( + self.cantera_data_path / "sofc.cti", + self.test_work_path / "sofc.yaml", + ) ctiGas, yamlGas = self.checkConversion('sofc') ctiMetal, yamlMetal = self.checkConversion('sofc', name='metal') ctiOxide, yamlOxide = self.checkConversion('sofc', name='oxide_bulk') @@ -740,9 +739,11 @@ def test_sofc(self): @utilities.slow_test def test_liquidvapor(self): - output_file = Path(self.test_work_dir).joinpath('liquidvapor.yaml') - cti2yaml.convert(Path(self.cantera_data).joinpath('liquidvapor.cti'), - output_file) + output_file = self.test_work_path / "liquidvapor.yaml" + cti2yaml.convert( + self.cantera_data_path / "liquidvapor.cti", + output_file, + ) for name in ['water', 'nitrogen', 'methane', 'hydrogen', 'oxygen', 'hfc134a', 'carbondioxide', 'heptane']: ctiPhase, yamlPhase = self.checkConversion('liquidvapor', name=name) @@ -753,8 +754,10 @@ def test_liquidvapor(self): output_file.unlink() def test_Redlich_Kwong_CO2(self): - cti2yaml.convert(Path(self.test_data_dir).joinpath('co2_RK_example.cti'), - Path(self.test_work_dir).joinpath('co2_RK_example.yaml')) + cti2yaml.convert( + self.test_data_path / "co2_RK_example.cti", + self.test_work_path / "co2_RK_example.yaml", + ) ctiGas, yamlGas = self.checkConversion('co2_RK_example') for P in [1e5, 2e6, 1.3e7]: yamlGas.TP = ctiGas.TP = 300, P @@ -762,16 +765,20 @@ def test_Redlich_Kwong_CO2(self): @utilities.slow_test def test_Redlich_Kwong_ndodecane(self): - cti2yaml.convert(Path(self.cantera_data).joinpath('nDodecane_Reitz.cti'), - Path(self.test_work_dir).joinpath('nDodecane_Reitz.yaml')) + cti2yaml.convert( + self.cantera_data_path / "nDodecane_Reitz.cti", + self.test_work_path / "nDodecane_Reitz.yaml", + ) ctiGas, yamlGas = self.checkConversion('nDodecane_Reitz') self.checkThermo(ctiGas, yamlGas, [300, 400, 500]) self.checkKinetics(ctiGas, yamlGas, [300, 500, 1300], [1e5, 2e6, 1.4e7], 1e-6) def test_diamond(self): - cti2yaml.convert(Path(self.cantera_data).joinpath('diamond.cti'), - Path(self.test_work_dir).joinpath('diamond.yaml')) + cti2yaml.convert( + self.cantera_data_path / "diamond.cti", + self.test_work_path / "diamond.yaml", + ) ctiGas, yamlGas = self.checkConversion('diamond', name='gas') ctiSolid, yamlSolid = self.checkConversion('diamond', name='diamond') ctiSurf, yamlSurf = self.checkConversion('diamond', @@ -782,8 +789,10 @@ def test_diamond(self): self.checkKinetics(ctiSurf, yamlSurf, [400, 800], [2e5]) def test_lithium_ion_battery(self): - cti2yaml.convert(Path(self.cantera_data).joinpath('lithium_ion_battery.cti'), - Path(self.test_work_dir).joinpath('lithium_ion_battery.yaml')) + cti2yaml.convert( + self.cantera_data_path / "lithium_ion_battery.cti", + self.test_work_path / "lithium_ion_battery.yaml", + ) name = 'lithium_ion_battery' ctiAnode, yamlAnode = self.checkConversion(name, name='anode') ctiCathode, yamlCathode = self.checkConversion(name, name='cathode') @@ -819,8 +828,10 @@ def test_lithium_ion_battery(self): self.checkKinetics(ctiCathodeInt, yamlCathodeInt, [300], [1e5]) def test_ch4_ion(self): - cti2yaml.convert(Path(self.test_data_dir).joinpath("ch4_ion.cti"), - Path(self.test_work_dir).joinpath("ch4_ion.yaml")) + cti2yaml.convert( + self.test_data_path / "ch4_ion.cti", + self.test_work_path / "ch4_ion.yaml", + ) ctiGas, yamlGas = self.checkConversion("ch4_ion") self.checkThermo(ctiGas, yamlGas, [300, 500, 1300, 2000]) self.checkKinetics(ctiGas, yamlGas, [900, 1800], [2e5, 20e5]) @@ -900,8 +911,8 @@ def checkTransport(self, ctmlPhase, yamlPhase, temperatures, @utilities.slow_test def test_gri30(self): ctml2yaml.convert( - Path(self.cantera_data).joinpath('gri30.xml'), - Path(self.test_work_dir).joinpath('gri30.yaml'), + self.cantera_data_path / "gri30.xml", + self.test_work_path / "gri30.yaml", ) ctmlPhase, yamlPhase = self.checkConversion('gri30') X = {'O2': 0.3, 'H2': 0.1, 'CH4': 0.2, 'CO2': 0.4} @@ -913,8 +924,8 @@ def test_gri30(self): def test_pdep(self): ctml2yaml.convert( - Path(self.test_data_dir).joinpath('pdep-test.xml'), - Path(self.test_work_dir).joinpath('pdep-test.yaml'), + self.test_data_path / "pdep-test.xml", + self.test_work_path / "pdep-test.yaml", ) ctmlPhase, yamlPhase = self.checkConversion('pdep-test') self.checkKinetics(ctmlPhase, yamlPhase, [300, 1000, 2200], @@ -922,8 +933,8 @@ def test_pdep(self): def test_ptcombust(self): ctml2yaml.convert( - Path(self.cantera_data).joinpath('ptcombust.xml'), - Path(self.test_work_dir).joinpath('ptcombust.yaml'), + self.cantera_data_path / "ptcombust.xml", + self.test_work_path / "ptcombust.yaml", ) ctmlGas, yamlGas = self.checkConversion('ptcombust') ctmlSurf, yamlSurf = self.checkConversion('ptcombust', ct.Interface, @@ -935,8 +946,8 @@ def test_ptcombust(self): def test_ptcombust_motzwise(self): ctml2yaml.convert( - Path(self.test_data_dir).joinpath('ptcombust-motzwise.xml'), - Path(self.test_work_dir).joinpath('ptcombust-motzwise.yaml'), + self.test_data_path / "ptcombust-motzwise.xml", + self.test_work_path / "ptcombust-motzwise.yaml", ) ctmlGas, yamlGas = self.checkConversion('ptcombust-motzwise') ctmlSurf, yamlSurf = self.checkConversion('ptcombust-motzwise', ct.Interface, @@ -948,8 +959,8 @@ def test_ptcombust_motzwise(self): def test_sofc(self): ctml2yaml.convert( - Path(self.cantera_data).joinpath('sofc.xml'), - Path(self.test_work_dir).joinpath('sofc.yaml'), + self.cantera_data_path / "sofc.xml", + self.test_work_path / "sofc.yaml", ) ctmlGas, yamlGas = self.checkConversion('sofc') ctmlMetal, yamlMetal = self.checkConversion('sofc', name='metal') @@ -972,9 +983,9 @@ def test_sofc(self): self.checkKinetics(ctml_tpb, yaml_tpb, [900, 1000, 1100], [1e5]) def test_liquidvapor(self): - output_file = Path(self.test_work_dir).joinpath('liquidvapor.yaml') + output_file = self.test_work_path / "liquidvapor.yaml" ctml2yaml.convert( - Path(self.cantera_data).joinpath('liquidvapor.xml'), output_file, + self.cantera_data_path / "liquidvapor.xml", output_file, ) for name in ['water', 'nitrogen', 'methane', 'hydrogen', 'oxygen', 'hfc134a', 'carbondioxide', 'heptane']: @@ -987,8 +998,8 @@ def test_liquidvapor(self): def test_Redlich_Kwong_CO2(self): ctml2yaml.convert( - Path(self.test_data_dir).joinpath('co2_RK_example.xml'), - Path(self.test_work_dir).joinpath('co2_RK_example.yaml'), + self.test_data_path / "co2_RK_example.xml", + self.test_work_path / "co2_RK_example.yaml", ) ctmlGas, yamlGas = self.checkConversion('co2_RK_example') for P in [1e5, 2e6, 1.3e7]: @@ -998,8 +1009,8 @@ def test_Redlich_Kwong_CO2(self): @utilities.slow_test def test_Redlich_Kwong_ndodecane(self): ctml2yaml.convert( - Path(self.cantera_data).joinpath('nDodecane_Reitz.xml'), - Path(self.test_work_dir).joinpath('nDodecane_Reitz.yaml'), + self.cantera_data_path / "nDodecane_Reitz.xml", + self.test_work_path / "nDodecane_Reitz.yaml", ) ctmlGas, yamlGas = self.checkConversion('nDodecane_Reitz') self.checkThermo(ctmlGas, yamlGas, [300, 400, 500]) @@ -1008,8 +1019,8 @@ def test_Redlich_Kwong_ndodecane(self): def test_diamond(self): ctml2yaml.convert( - Path(self.cantera_data).joinpath('diamond.xml'), - Path(self.test_work_dir).joinpath('diamond.yaml'), + self.cantera_data_path / "diamond.xml", + self.test_work_path / "diamond.yaml", ) ctmlGas, yamlGas = self.checkConversion('diamond', name='gas') ctmlSolid, yamlSolid = self.checkConversion('diamond', name='diamond') @@ -1023,8 +1034,8 @@ def test_diamond(self): def test_lithium_ion_battery(self): name = 'lithium_ion_battery' ctml2yaml.convert( - Path(self.cantera_data).joinpath(name + ".xml"), - Path(self.test_work_dir).joinpath(name + ".yaml"), + self.cantera_data_path / (name + ".xml"), + self.test_work_path / (name + ".yaml"), ) ctmlAnode, yamlAnode = self.checkConversion(name, name='anode') ctmlCathode, yamlCathode = self.checkConversion(name, name='cathode') @@ -1061,8 +1072,8 @@ def test_lithium_ion_battery(self): def test_noxNeg(self): ctml2yaml.convert( - Path(self.test_data_dir).joinpath('noxNeg.xml'), - Path(self.test_work_dir).joinpath('noxNeg.yaml'), + self.test_data_path / "noxNeg.xml", + self.test_work_path / "noxNeg.yaml", ) ctmlGas, yamlGas = self.checkConversion('noxNeg') self.checkThermo(ctmlGas, yamlGas, [300, 1000]) @@ -1070,8 +1081,8 @@ def test_noxNeg(self): def test_ch4_ion(self): ctml2yaml.convert( - Path(self.test_data_dir).joinpath("ch4_ion.xml"), - Path(self.test_work_dir).joinpath("ch4_ion.yaml"), + self.test_data_path / "ch4_ion.xml", + self.test_work_path / "ch4_ion.yaml", ) ctmlGas, yamlGas = self.checkConversion("ch4_ion") self.checkThermo(ctmlGas, yamlGas, [300, 500, 1300, 2000]) @@ -1080,16 +1091,16 @@ def test_ch4_ion(self): def test_nasa9(self): ctml2yaml.convert( - Path(self.test_data_dir).joinpath("nasa9-test.xml"), - Path(self.test_work_dir).joinpath("nasa9-test.yaml"), + self.test_data_path / "nasa9-test.xml", + self.test_work_path / "nasa9-test.yaml", ) ctmlGas, yamlGas = self.checkConversion("nasa9-test") self.checkThermo(ctmlGas, yamlGas, [300, 500, 1300, 2000]) def test_chemically_activated(self): ctml2yaml.convert( - Path(self.test_data_dir).joinpath("chemically-activated-reaction.xml"), - Path(self.test_work_dir).joinpath("chemically-activated-reaction.yaml"), + self.test_data_path / "chemically-activated-reaction.xml", + self.test_work_path / "chemically-activated-reaction.yaml", ) ctmlGas, yamlGas = self.checkConversion("chemically-activated-reaction") self.checkThermo(ctmlGas, yamlGas, [300, 500, 1300, 2000]) @@ -1097,24 +1108,26 @@ def test_chemically_activated(self): def test_explicit_forward_order(self): ctml2yaml.convert( - Path(self.test_data_dir).joinpath("explicit-forward-order.xml"), - Path(self.test_work_dir).joinpath("explicit-forward-order.yaml"), + self.test_data_path / "explicit-forward-order.xml", + self.test_work_path / "explicit-forward-order.yaml", ) ctmlGas, yamlGas = self.checkConversion("explicit-forward-order") self.checkThermo(ctmlGas, yamlGas, [300, 500, 1300, 2000]) self.checkKinetics(ctmlGas, yamlGas, [900, 1800], [2e5, 20e5]) def test_explicit_reverse_rate(self): - ctml2yaml.convert(Path(self.test_data_dir).joinpath("explicit-reverse-rate.xml"), - Path(self.test_work_dir).joinpath("explicit-reverse-rate.yaml")) + ctml2yaml.convert( + self.test_data_path / "explicit-reverse-rate.xml", + self.test_work_path / "explicit-reverse-rate.yaml", + ) ctmlGas, yamlGas = self.checkConversion("explicit-reverse-rate") self.checkThermo(ctmlGas, yamlGas, [300, 500, 1300, 2000]) self.checkKinetics(ctmlGas, yamlGas, [900, 1800], [2e5, 20e5]) def test_explicit_third_bodies(self): ctml2yaml.convert( - Path(self.test_data_dir).joinpath("explicit-third-bodies.xml"), - Path(self.test_work_dir).joinpath("explicit-third-bodies.yaml"), + self.test_data_path / "explicit-third-bodies.xml", + self.test_work_path / "explicit-third-bodies.yaml", ) ctmlGas, yamlGas = self.checkConversion("explicit-third-bodies") self.checkThermo(ctmlGas, yamlGas, [300, 500, 1300, 2000]) @@ -1122,8 +1135,8 @@ def test_explicit_third_bodies(self): def test_fractional_stoich_coeffs(self): ctml2yaml.convert( - Path(self.test_data_dir).joinpath("frac.xml"), - Path(self.test_work_dir).joinpath("frac.yaml"), + self.test_data_path / "frac.xml", + self.test_work_path / "frac.yaml", ) ctmlGas, yamlGas = self.checkConversion("frac") self.checkThermo(ctmlGas, yamlGas, [300, 500, 1300, 2000]) @@ -1131,8 +1144,8 @@ def test_fractional_stoich_coeffs(self): def test_water_IAPWS95_thermo(self): ctml2yaml.convert( - Path(self.test_data_dir).joinpath("liquid-water.xml"), - Path(self.test_work_dir).joinpath("liquid-water.yaml"), + self.test_data_path / "liquid-water.xml", + self.test_work_path / "liquid-water.yaml", ) ctmlWater, yamlWater = self.checkConversion("liquid-water") self.checkThermo(ctmlWater, yamlWater, [300, 500, 1300, 2000], pressure=22064000.0) @@ -1147,8 +1160,8 @@ def test_water_IAPWS95_thermo(self): def test_hmw_nacl_phase(self): basename = "HMW_NaCl_sp1977_alt" - xml_file = Path(self.test_data_dir).joinpath(basename).with_suffix(".xml") - yaml_file = Path(self.test_data_dir).joinpath(basename).with_suffix(".yaml") + xml_file = self.test_data_path / (basename + ".xml") + yaml_file = self.test_data_path / (basename + ".yaml") ctml2yaml.convert(xml_file, yaml_file) # Can only be loaded by ThermoPhase due to a bug in TransportFactory @@ -1162,16 +1175,16 @@ def test_hmw_nacl_phase(self): def test_NaCl_solid_phase(self): ctml2yaml.convert( - Path(self.test_data_dir).joinpath("NaCl_Solid.xml"), - Path(self.test_work_dir).joinpath("NaCl_Solid.yaml"), + self.test_data_path / "NaCl_Solid.xml", + self.test_work_path / "NaCl_Solid.yaml", ) ctmlPhase, yamlPhase = self.checkConversion("NaCl_Solid") self.checkThermo(ctmlPhase, yamlPhase, [300, 500, 1300, 2000]) def test_DH_NaCl_phase(self): ctml2yaml.convert( - Path(self.test_data_dir).joinpath("debye-huckel-all.xml"), - Path(self.test_work_dir).joinpath("debye-huckel-all.yaml"), + self.test_data_path / "debye-huckel-all.xml", + self.test_work_path / "debye-huckel-all.yaml", ) for name in [ "debye-huckel-dilute", @@ -1191,8 +1204,8 @@ def test_DH_NaCl_phase(self): def test_Maskell_solid_soln(self): ctml2yaml.convert( - Path(self.test_data_dir).joinpath("MaskellSolidSolnPhase_valid.xml"), - Path(self.test_work_dir).joinpath("MaskellSolidSolnPhase_valid.yaml"), + self.test_data_path / "MaskellSolidSolnPhase_valid.xml", + self.test_work_path / "MaskellSolidSolnPhase_valid.yaml", ) ctmlPhase, yamlPhase = self.checkConversion("MaskellSolidSolnPhase_valid") @@ -1204,8 +1217,8 @@ def test_Maskell_solid_soln(self): def test_mock_ion(self): ctml2yaml.convert( - Path(self.test_data_dir).joinpath("mock_ion.xml"), - Path(self.test_work_dir).joinpath("mock_ion.yaml"), + self.test_data_path / "mock_ion.xml", + self.test_work_path / "mock_ion.yaml", ) ctmlPhase = ct.ThermoPhase("mock_ion.xml") yamlPhase = ct.ThermoPhase("mock_ion.yaml") @@ -1225,8 +1238,8 @@ def test_mock_ion(self): def test_Redlich_Kister(self): ctml2yaml.convert( - Path(self.test_data_dir).joinpath("RedlichKisterVPSSTP_valid.xml"), - Path(self.test_work_dir).joinpath("RedlichKisterVPSSTP_valid.yaml"), + self.test_data_path / "RedlichKisterVPSSTP_valid.xml", + self.test_work_path / "RedlichKisterVPSSTP_valid.yaml", ) ctmlPhase, yamlPhase = self.checkConversion("RedlichKisterVPSSTP_valid") @@ -1234,16 +1247,16 @@ def test_Redlich_Kister(self): def test_species_names(self): ctml2yaml.convert( - Path(self.test_data_dir).joinpath('species-names.xml'), - Path(self.test_work_dir).joinpath('species-names.yaml'), + self.test_data_path / "species-names.xml", + self.test_work_path / "species-names.yaml", ) ctmlGas, yamlGas = self.checkConversion('species-names') self.checkThermo(ctmlGas, yamlGas, [300, 500, 1300, 2000]) def test_sri_falloff_reaction(self): ctml2yaml.convert( - Path(self.test_data_dir).joinpath("sri-falloff.xml"), - Path(self.test_work_dir).joinpath("sri-falloff.yaml"), + self.test_data_path / "sri-falloff.xml", + self.test_work_path / "sri-falloff.yaml", ) ctmlGas, yamlGas = self.checkConversion("sri-falloff") self.checkThermo(ctmlGas, yamlGas, [300, 500, 1300, 2000]) @@ -1251,8 +1264,8 @@ def test_sri_falloff_reaction(self): def test_vpss_and_hkft(self): ctml2yaml.convert( - Path(self.test_data_dir).joinpath("pdss_hkft.xml"), - Path(self.test_work_dir).joinpath("pdss_hkft.yaml"), + self.test_data_path / "pdss_hkft.xml", + self.test_work_path / "pdss_hkft.yaml", ) ctmlPhase = ct.ThermoPhase("pdss_hkft.xml") yamlPhase = ct.ThermoPhase("pdss_hkft.yaml") @@ -1268,8 +1281,8 @@ def test_vpss_and_hkft(self): def test_lattice_solid(self): ctml2yaml.convert( - Path(self.test_data_dir).joinpath("Li7Si3_ls.xml"), - Path(self.test_work_dir).joinpath("Li7Si3_ls.yaml"), + self.test_data_path / "Li7Si3_ls.xml", + self.test_work_path / "Li7Si3_ls.yaml", ) # Use ThermoPhase to avoid constructing a default Transport object which # throws an error for the LatticeSolidPhase @@ -1283,8 +1296,8 @@ def test_lattice_solid(self): def test_margules(self): ctml2yaml.convert( - Path(self.test_data_dir).joinpath("LiKCl_liquid.xml"), - Path(self.test_work_dir).joinpath("LiKCl_liquid.yaml"), + self.test_data_path / "LiKCl_liquid.xml", + self.test_work_path / "LiKCl_liquid.yaml", ) ctmlPhase, yamlPhase = self.checkConversion("LiKCl_liquid") self.checkThermo(ctmlPhase, yamlPhase, [300, 500]) @@ -1292,8 +1305,8 @@ def test_margules(self): def test_idealsolidsoln(self): with self.assertWarnsRegex(UserWarning, "SolidKinetics type is not implemented"): ctml2yaml.convert( - Path(self.test_data_dir).joinpath("IdealSolidSolnPhaseExample.xml"), - Path(self.test_work_dir).joinpath("IdealSolidSolnPhaseExample.yaml"), + self.test_data_path / "IdealSolidSolnPhaseExample.xml", + self.test_work_path / "IdealSolidSolnPhaseExample.yaml", ) # SolidKinetics is not implemented, so can't create a Kinetics class instance. @@ -1307,8 +1320,8 @@ def test_idealsolidsoln(self): def test_idealmolalsoln(self): ctml2yaml.convert( - Path(self.test_data_dir).joinpath("IdealMolalSolnPhaseExample.xml"), - Path(self.test_work_dir).joinpath("IdealMolalSolnPhaseExample.yaml"), + self.test_data_path / "IdealMolalSolnPhaseExample.xml", + self.test_work_path / "IdealMolalSolnPhaseExample.yaml", ) ctmlPhase, yamlPhase = self.checkConversion("IdealMolalSolnPhaseExample") @@ -1316,8 +1329,8 @@ def test_idealmolalsoln(self): def test_transport_models(self): ctml2yaml.convert( - Path(self.test_data_dir).joinpath("transport_models_test.xml"), - Path(self.test_work_dir).joinpath("transport_models_test.yaml"), + self.test_data_path / "transport_models_test.xml", + self.test_work_path / "transport_models_test.yaml", ) for name in ["UnityLewis", "CK_Mix", "CK_Multi", "HighP"]: ctmlPhase, yamlPhase = self.checkConversion("transport_models_test", name=name) @@ -1325,8 +1338,8 @@ def test_transport_models(self): def test_nonreactant_orders(self): ctml2yaml.convert( - Path(self.test_data_dir).joinpath("reaction-orders.xml"), - Path(self.test_work_dir).joinpath("reaction-orders.yaml"), + self.test_data_path / "reaction-orders.xml", + self.test_work_path / "reaction-orders.yaml", ) ctmlPhase, yamlPhase = self.checkConversion("reaction-orders") @@ -1335,8 +1348,8 @@ def test_nonreactant_orders(self): def test_species_ss_temperature_polynomials(self): ctml2yaml.convert( - Path(self.test_data_dir).joinpath("Li_Liquid.xml"), - Path(self.test_work_dir).joinpath("Li_Liquid.yaml"), + self.test_data_path / "Li_Liquid.xml", + self.test_work_path / "Li_Liquid.yaml", ) ctmlPhase, yamlPhase = self.checkConversion("Li_Liquid") @@ -1345,11 +1358,11 @@ def test_species_ss_temperature_polynomials(self): def test_duplicate_section_ids(self): with self.assertWarnsRegex(UserWarning, "Duplicate 'speciesData' id"): ctml2yaml.convert( - Path(self.test_data_dir).joinpath("duplicate-speciesData-ids.xml"), - Path(self.test_work_dir).joinpath("duplicate-speciesData-ids.yaml") + self.test_data_path / "duplicate-speciesData-ids.xml", + self.test_work_path / "duplicate-speciesData-ids.yaml", ) with self.assertWarnsRegex(UserWarning, "Duplicate 'reactionData' id"): ctml2yaml.convert( - Path(self.test_data_dir).joinpath("duplicate-reactionData-ids.xml"), - Path(self.test_work_dir).joinpath("duplicate-reactionData-ids.yaml") + self.test_data_path / "duplicate-reactionData-ids.xml", + self.test_work_path / "duplicate-reactionData-ids.yaml", ) diff --git a/interfaces/cython/cantera/test/test_equilibrium.py b/interfaces/cython/cantera/test/test_equilibrium.py index eea5cbb76ff..f0a236e580b 100644 --- a/interfaces/cython/cantera/test/test_equilibrium.py +++ b/interfaces/cython/cantera/test/test_equilibrium.py @@ -1,5 +1,4 @@ import unittest -from os.path import join as pjoin import numpy as np @@ -153,7 +152,7 @@ def test_equil_TP(self): data[i,1:] = self.mix.species_moles - self.compare(data, pjoin(self.test_data_dir, 'koh-equil-TP.csv')) + self.compare(data, self.test_data_path / "koh-equil-TP.csv") @utilities.slow_test def test_equil_HP(self): @@ -177,7 +176,7 @@ def test_equil_HP(self): data[i,1] = self.mix.T # equilibrated temperature data[i,2:] = self.mix.species_moles - self.compare(data, pjoin(self.test_data_dir, 'koh-equil-HP.csv')) + self.compare(data, self.test_data_path / "koh-equil-HP.csv") class TestEquil_GasCarbon(utilities.CanteraTest): @@ -207,7 +206,7 @@ def solve(self, solver, **kwargs): data[i,:2] = (phi[i], mix.T) data[i,2:] = mix.species_moles - self.compare(data, pjoin(self.test_data_dir, 'gas-carbon-equil.csv')) + self.compare(data, self.test_data_path / "gas-carbon-equil.csv") @utilities.slow_test def test_gibbs(self): diff --git a/interfaces/cython/cantera/test/test_func1.py b/interfaces/cython/cantera/test/test_func1.py index 3efa0a2e324..dd91a5f32f4 100644 --- a/interfaces/cython/cantera/test/test_func1.py +++ b/interfaces/cython/cantera/test/test_func1.py @@ -2,7 +2,6 @@ import cantera as ct from . import utilities -from .utilities import unittest class TestFunc1(utilities.CanteraTest): def test_function(self): diff --git a/interfaces/cython/cantera/test/test_kinetics.py b/interfaces/cython/cantera/test/test_kinetics.py index 55000f3c039..a5e035ec8c1 100644 --- a/interfaces/cython/cantera/test/test_kinetics.py +++ b/interfaces/cython/cantera/test/test_kinetics.py @@ -1,8 +1,6 @@ import numpy as np import re import itertools -from os.path import join as pjoin -import os import cantera as ct from . import utilities @@ -816,7 +814,7 @@ def cathode_curr(E): cathode_bulk.electric_potential - anode_bulk.electric_potential]) - self.compare(data, pjoin(self.test_data_dir, 'sofc-test.csv'), rtol=1e-7) + self.compare(data, self.test_data_path / "sofc-test.csv", rtol=1e-7) class TestDuplicateReactions(utilities.CanteraTest): @@ -889,8 +887,7 @@ def test_fromCti(self): def test_fromXml(self): import xml.etree.ElementTree as ET - p = os.path.dirname(__file__) - root = ET.parse(pjoin(p, '..', 'data', 'h2o2.xml')).getroot() + root = ET.parse(self.cantera_data_path / "h2o2.xml").getroot() rxn_node = root.find('.//reaction[@id="0001"]') r = ct.Reaction.fromXml(ET.tostring(rxn_node)) @@ -925,18 +922,14 @@ def test_listFromFile(self): def test_listFromCti(self): gas = ct.Solution("h2o2.xml", transport_model=None) - p = os.path.dirname(__file__) - with open(pjoin(p, '..', 'data', 'h2o2.cti')) as f: - R = ct.Reaction.listFromCti(f.read()) + R = ct.Reaction.listFromCti((self.cantera_data_path / "h2o2.cti").read_text()) eq1 = [r.equation for r in R] eq2 = [r.equation for r in gas.reactions()] self.assertEqual(eq1, eq2) def test_listFromXml(self): gas = ct.Solution("h2o2.xml", transport_model=None) - p = os.path.dirname(__file__) - with open(pjoin(p, '..', 'data', 'h2o2.xml')) as f: - R = ct.Reaction.listFromXml(f.read()) + R = ct.Reaction.listFromXml((self.cantera_data_path / "h2o2.xml").read_text()) eq1 = [r.equation for r in R] eq2 = [r.equation for r in gas.reactions()] self.assertEqual(eq1, eq2) diff --git a/interfaces/cython/cantera/test/test_onedim.py b/interfaces/cython/cantera/test/test_onedim.py index 753ce16a3e5..5cc10f45315 100644 --- a/interfaces/cython/cantera/test/test_onedim.py +++ b/interfaces/cython/cantera/test/test_onedim.py @@ -1,8 +1,6 @@ import cantera as ct from . import utilities import numpy as np -import os -from os.path import join as pjoin from cantera.composite import _h5py @@ -510,9 +508,10 @@ def test_save_restore(self): self.create_sim(p, Tin, reactants) self.solve_fixed_T() - filename = pjoin(self.test_work_dir, 'onedim-fixed-T.xml') - if os.path.exists(filename): - os.remove(filename) + filename = self.test_work_path / "onedim-fixed-T.xml" + # In Python >= 3.8, this can be replaced by the missing_ok argument + if filename.is_file(): + filename.unlink() Y1 = self.sim.Y u1 = self.sim.velocity @@ -577,9 +576,10 @@ def test_save_restore_add_species(self): p = 2 * ct.one_atm Tin = 400 - filename = pjoin(self.test_work_dir, 'onedim-add-species.xml') - if os.path.exists(filename): - os.remove(filename) + filename = self.test_work_path / "onedim-add-species.xml" + # In Python >= 3.8, this can be replaced by the missing_ok argument + if filename.is_file(): + filename.unlink() self.create_sim(p, Tin, reactants, mech='h2o2.xml') gas1 = self.gas @@ -606,9 +606,10 @@ def test_save_restore_remove_species(self): p = 2 * ct.one_atm Tin = 400 - filename = pjoin(self.test_work_dir, 'onedim-add-species.xml') - if os.path.exists(filename): - os.remove(filename) + filename = self.test_work_path / "onedim-add-species.xml" + # In Python >= 3.8, this can be replaced by the missing_ok argument + if filename.is_file(): + filename.unlink() self.create_sim(p, Tin, reactants, mech='h2o2-plus.xml') gas1 = self.gas @@ -630,9 +631,10 @@ def test_save_restore_remove_species(self): self.assertArrayNear(Y1[k1], Y2[k2]) def test_write_csv(self): - filename = pjoin(self.test_work_dir, 'onedim-write_csv.csv') - if os.path.exists(filename): - os.remove(filename) + filename = self.test_work_path / "onedim-write_csv.csv" + # In Python >= 3.8, this can be replaced by the missing_ok argument + if filename.is_file(): + filename.unlink() self.create_sim(2e5, 350, 'H2:1.0, O2:2.0', mech='h2o2.xml') self.sim.write_csv(filename) @@ -645,9 +647,10 @@ def test_write_csv(self): @utilities.unittest.skipIf(isinstance(_h5py, ImportError), "h5py is not installed") def test_write_hdf(self): - filename = pjoin(self.test_work_dir, 'onedim-write_hdf.h5') - if os.path.exists(filename): - os.remove(filename) + filename = self.test_work_path / "onedim-write_hdf.h5" + # In Python >= 3.8, this can be replaced by the missing_ok argument + if filename.is_file(): + filename.unlink() self.run_mix(phi=1.1, T=350, width=2.0, p=2.0, refine=False) desc = 'mixture-averaged simulation' @@ -771,7 +774,7 @@ def solve_mix(self, ratio=3.0, slope=0.1, curve=0.12, prune=0.0): @utilities.slow_test def test_mixture_averaged(self, saveReference=False): - referenceFile = pjoin(self.test_data_dir, 'DiffusionFlameTest-h2-mix.csv') + referenceFile = self.test_data_path / "DiffusionFlameTest-h2-mix.csv" self.create_sim(p=ct.one_atm) nPoints = len(self.sim.grid) @@ -796,7 +799,7 @@ def test_mixture_averaged(self, saveReference=False): self.assertFalse(bad, bad) def test_auto(self, saveReference=False): - referenceFile = pjoin(self.test_data_dir, 'DiffusionFlameTest-h2-auto.csv') + referenceFile = self.test_data_path / "DiffusionFlameTest-h2-auto.csv" self.create_sim(p=ct.one_atm, mdot_fuel=2, mdot_ox=3) nPoints = [] @@ -885,7 +888,7 @@ def test_restart(self): self.assertNear(mdot[-1], -self.sim.oxidizer_inlet.mdot, 1e-4) def test_mixture_averaged_rad(self, saveReference=False): - referenceFile = pjoin(self.test_data_dir, 'DiffusionFlameTest-h2-mix-rad.csv') + referenceFile = self.test_data_path / "DiffusionFlameTest-h2-mix-rad.csv" self.create_sim(p=ct.one_atm) nPoints = len(self.sim.grid) @@ -916,12 +919,15 @@ def test_mixture_averaged_rad(self, saveReference=False): rtol=1e-2, atol=1e-8, xtol=1e-2) self.assertFalse(bad, bad) - filename = pjoin(self.test_work_dir, 'DiffusionFlameTest-h2-mix-rad.csv') + filename = self.test_work_path / "DiffusionFlameTest-h2-mix-rad.csv" + # In Python >= 3.8, this can be replaced by the missing_ok argument + if filename.is_file(): + filename.unlink() + self.sim.write_csv(filename) # check output - self.assertTrue(os.path.exists(filename)) + self.assertTrue(filename.is_file()) csv_data = np.genfromtxt(filename, dtype=float, delimiter=',', names=True) self.assertIn('qdot', csv_data.dtype.names) - os.remove(filename) def test_strain_rate(self): # This doesn't test that the values are correct, just that they can be @@ -1006,7 +1012,7 @@ def test_mixture_averaged(self, saveReference=False): data[:,3] = sim.T data[:,4:] = sim.Y.T - referenceFile = pjoin(self.test_data_dir, 'CounterflowPremixedFlame-h2-mix.csv') + referenceFile = self.test_data_path / "CounterflowPremixedFlame-h2-mix.csv" if saveReference: np.savetxt(referenceFile, data, '%11.6e', ', ') else: @@ -1014,12 +1020,15 @@ def test_mixture_averaged(self, saveReference=False): rtol=1e-2, atol=1e-8, xtol=1e-2) self.assertFalse(bad, bad) - filename = pjoin(self.test_work_dir, 'CounterflowPremixedFlame-h2-mix.csv') + filename = self.test_work_path / "CounterflowPremixedFlame-h2-mix.csv" + # In Python >= 3.8, this can be replaced by the missing_ok argument + if filename.is_file(): + filename.unlink() + sim.write_csv(filename) # check output - self.assertTrue(os.path.exists(filename)) + self.assertTrue(filename.is_file()) csv_data = np.genfromtxt(filename, dtype=float, delimiter=',', names=True) self.assertNotIn('qdot', csv_data.dtype.names) - os.remove(filename) def run_case(self, phi, T, width, P): gas = ct.Solution('h2o2.xml') @@ -1190,9 +1199,10 @@ def test_reacting_surface_case3(self): @utilities.unittest.skipIf(isinstance(_h5py, ImportError), "h5py is not installed") def test_write_hdf(self): - filename = pjoin(self.test_work_dir, 'impingingjet-write_hdf.h5') - if os.path.exists(filename): - os.remove(filename) + filename = self.test_work_path / "impingingjet-write_hdf.h5" + # In Python >= 3.8, this can be replaced by the missing_ok argument + if filename.is_file(): + filename.unlink() self.run_reacting_surface(xch4=0.095, tsurf=900.0, mdot=0.06, width=0.1) self.sim.write_hdf(filename) diff --git a/interfaces/cython/cantera/test/test_purefluid.py b/interfaces/cython/cantera/test/test_purefluid.py index 9f1ee9bbb83..b2e4a73f990 100644 --- a/interfaces/cython/cantera/test/test_purefluid.py +++ b/interfaces/cython/cantera/test/test_purefluid.py @@ -1,6 +1,5 @@ import itertools import numpy as np -import warnings import cantera as ct from . import utilities diff --git a/interfaces/cython/cantera/test/test_reactor.py b/interfaces/cython/cantera/test/test_reactor.py index 7ca13a34404..67a5e784827 100644 --- a/interfaces/cython/cantera/test/test_reactor.py +++ b/interfaces/cython/cantera/test/test_reactor.py @@ -1,7 +1,5 @@ import math import re -from os.path import join as pjoin -import os import numpy as np from .utilities import unittest @@ -9,8 +7,6 @@ import cantera as ct from . import utilities -import warnings - class TestReactor(utilities.CanteraTest): reactorClass = ct.Reactor @@ -1145,8 +1141,8 @@ def test_coverages_regression1(self): surf1.coverages = C self.assertArrayNear(surf1.coverages, C) data = [] - test_file = pjoin(self.test_work_dir, 'test_coverages_regression1.csv') - reference_file = pjoin(self.test_data_dir, 'WallKinetics-coverages-regression1.csv') + test_file = self.test_work_path / "test_coverages_regression1.csv" + reference_file = self.test_data_path / "WallKinetics-coverages-regression1.csv" data = [] for t in np.linspace(1e-6, 1e-3): self.net.advance(t) @@ -1170,8 +1166,8 @@ def test_coverages_regression2(self): surf.coverages = C self.assertArrayNear(surf.coverages, C) data = [] - test_file = pjoin(self.test_work_dir, 'test_coverages_regression2.csv') - reference_file = pjoin(self.test_data_dir, 'WallKinetics-coverages-regression2.csv') + test_file = self.test_work_path / "test_coverages_regression2.csv" + reference_file = self.test_data_path / "WallKinetics-coverages-regression2.csv" data = [] for t in np.linspace(1e-6, 1e-3): self.net.advance(t) @@ -1516,7 +1512,7 @@ class CombustorTestImplementation: """ def setUp(self): - self.referenceFile = pjoin(os.path.dirname(__file__), 'data', 'CombustorTest-integrateWithAdvance.csv') + self.referenceFile = utilities.TEST_DATA_PATH / "CombustorTest-integrateWithAdvance.csv" self.gas = ct.Solution('h2o2.yaml', transport_model=None) # create a reservoir for the fuel inlet, and set to pure methane. @@ -1622,7 +1618,7 @@ class WallTestImplementation: """ def setUp(self): - self.referenceFile = pjoin(os.path.dirname(__file__), 'data', 'WallTest-integrateWithAdvance.csv') + self.referenceFile = utilities.TEST_DATA_PATH / "WallTest-integrateWithAdvance.csv" # reservoir to represent the environment self.gas0 = ct.Solution('air.xml') self.gas0.TP = 300, ct.one_atm diff --git a/interfaces/cython/cantera/test/test_thermo.py b/interfaces/cython/cantera/test/test_thermo.py index b7b34349b6b..6d5cbcd9a77 100644 --- a/interfaces/cython/cantera/test/test_thermo.py +++ b/interfaces/cython/cantera/test/test_thermo.py @@ -1,10 +1,6 @@ -from os.path import join as pjoin -from pathlib import Path from collections import OrderedDict -import os import numpy as np import gc -import warnings import cantera as ct from . import utilities @@ -1113,8 +1109,7 @@ def test_fromCti(self): def test_fromXml(self): import xml.etree.ElementTree as ET - p = os.path.dirname(__file__) - root = ET.parse(pjoin(p, '..', 'data', 'h2o2.xml')).getroot() + root = ET.parse(self.cantera_data_path / "h2o2.xml").getroot() h2_node = root.find('.//species[@name="H2"]') h2_string = ET.tostring(h2_node) @@ -1138,10 +1133,7 @@ def test_listfromFile_yaml(self): self.assertEqual({sp.name for sp in S}, set(self.gas.species_names)) def test_listFromCti(self): - p = os.path.dirname(__file__) - with open(pjoin(p, '..', 'data', 'h2o2.cti')) as f: - S = ct.Species.listFromCti(f.read()) - + S = ct.Species.listFromCti((self.cantera_data_path / "h2o2.cti").read_text()) self.assertEqual(S[3].name, self.gas.species_name(3)) def test_listFomYaml(self): @@ -1160,17 +1152,14 @@ def test_listFomYaml(self): def test_listFromYaml_section(self): species = ct.Species.listFromYaml( - Path(__file__).parent.joinpath('data', 'ideal-gas.yaml').read_text(), + (self.test_data_path / "ideal-gas.yaml").read_text(), 'species') self.assertEqual(species[0].name, 'O2') self.assertEqual(species[1].composition, {'N': 1, 'O': 1}) def test_listFromXml(self): - p = os.path.dirname(__file__) - with open(pjoin(p, '..', 'data', 'h2o2.xml')) as f: - S = ct.Species.listFromXml(f.read()) - + S = ct.Species.listFromXml((self.cantera_data_path / "h2o2.xml").read_text()) self.assertEqual(S[4].name, self.gas.species_name(4)) def test_modify_thermo(self): diff --git a/interfaces/cython/cantera/test/utilities.py b/interfaces/cython/cantera/test/utilities.py index cbb0bebb6d2..3a10a07120c 100644 --- a/interfaces/cython/cantera/test/utilities.py +++ b/interfaces/cython/cantera/test/utilities.py @@ -1,14 +1,29 @@ import numpy as np -import sys -import os +from os import environ import warnings -import shutil import tempfile import unittest -import errno +from pathlib import Path, PurePath + +try: + import ruamel_yaml as yaml +except ImportError: + from ruamel import yaml + import cantera -slow_test = unittest.skipIf(os.environ.get("CT_SKIP_SLOW", "0") == "1", "slow test") +slow_test = unittest.skipIf(environ.get("CT_SKIP_SLOW", "0") == "1", "slow test") + +TEST_DATA_PATH = Path(__file__).parent / "data" +CANTERA_DATA_PATH = Path(__file__).parents[1] / "data" + + +def load_yaml(yml_file, typ="safe"): + # Load YAML data from file. The YAML loader defaults to "safe". + yaml_ = yaml.YAML(typ=typ) + with open(yml_file, "rt", encoding="utf-8") as stream: + return yaml_.load(stream) + class CanteraTest(unittest.TestCase): @classmethod @@ -17,37 +32,34 @@ def setUpClass(cls): # an in-source test, create the directory in the root # test/work directory. Otherwise, create a system level # temporary directory - root_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), - '..', '..', '..', '..')) - if os.path.exists(os.path.join(root_dir, 'SConstruct')): - cls.test_work_dir = os.path.join(root_dir, 'test', 'work', 'python') + root_dir = Path(__file__).parents[4].resolve() + if (root_dir / "SConstruct").is_file(): + cls.test_work_path = root_dir / "test" / "work" / "python" cls.using_tempfile = False try: - os.makedirs(cls.test_work_dir) - except OSError as e: - if e.errno == errno.EEXIST: - pass - elif e.errno == errno.EACCES: - cls.test_work_dir = tempfile.mkdtemp() - else: - raise + cls.test_work_path.mkdir(exist_ok=True) + except FileNotFoundError: + cls.test_work_path = Path(tempfile.mkdtemp()) + cls.using_tempfile = True else: - cls.test_work_dir = tempfile.mkdtemp() + cls.test_work_path = Path(tempfile.mkdtemp()) cls.using_tempfile = True cantera.make_deprecation_warnings_fatal() - cantera.add_directory(cls.test_work_dir) - cls.test_data_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), 'data')) - cls.cantera_data = os.path.abspath(os.path.join( - os.path.dirname(__file__), '..', 'data')) + cantera.add_directory(cls.test_work_path) + cls.test_data_path = TEST_DATA_PATH + cls.cantera_data_path = CANTERA_DATA_PATH + @classmethod def tearDownClass(cls): # Remove the working directory after testing, but only if its a temp directory if getattr(cls, "using_tempfile", False): try: - shutil.rmtree(cls.test_work_dir) - except OSError: + for f in cls.test_work_path.glob("*.*"): + f.unlink() + cls.test_work_path.rmdir() + except FileNotFoundError: pass def assertNear(self, a, b, rtol=1e-8, atol=1e-12, msg=None): @@ -87,7 +99,7 @@ def compare(self, data, reference_file, rtol=1e-8, atol=1e-12): file if it does not exist. """ data = np.array(data) - if os.path.exists(reference_file): + if Path(reference_file).is_file(): # Compare with existing output file ref = np.genfromtxt(reference_file) self.assertEqual(data.shape, ref.shape) @@ -96,7 +108,7 @@ def compare(self, data, reference_file, rtol=1e-8, atol=1e-12): else: # Generate the output file for the first time warnings.warn('Generating test data file:' + - os.path.abspath(reference_file)) + Path(reference_file).resolve()) np.savetxt(reference_file, data, fmt='%.10e') @@ -117,12 +129,12 @@ def compareProfiles(reference, sample, rtol=1e-5, atol=1e-12, xtol=1e-5): If the comparison succeeds, this function returns `None`. If the comparison fails, a formatted report of the differing elements is returned. """ - if isinstance(reference, str): + if isinstance(reference, (str, PurePath)): reference = np.genfromtxt(reference, delimiter=',').T else: reference = np.asarray(reference).T - if isinstance(sample, str): + if isinstance(sample, (str, PurePath)): sample = np.genfromtxt(sample, delimiter=',').T else: sample = np.asarray(sample).T diff --git a/interfaces/cython/cantera/utils.pyx b/interfaces/cython/cantera/utils.pyx index 79b91e330cf..7388f55d81f 100644 --- a/interfaces/cython/cantera/utils.pyx +++ b/interfaces/cython/cantera/utils.pyx @@ -23,7 +23,7 @@ cdef pystr(string x): def add_directory(directory): """ Add a directory to search for Cantera data files. """ - CxxAddDirectory(stringify(directory)) + CxxAddDirectory(stringify(str(directory))) def get_data_directories(): """ Get a list of the directories Cantera searches for data files. """