[Python] Make Cantera objects explicitly non-picklable and uncopyable.
Attempting to copy or pickle Cantera objects with an underlying C++ object previously led to unexpected errors. These operations will not raise excptions indicating the unimplemented feature. Resolves Issue 205.
This commit is contained in:
parent
c7ba8bfb84
commit
c5eb2f57dd
8 changed files with 82 additions and 0 deletions
|
|
@ -76,6 +76,12 @@ cdef class _SolutionBase:
|
|||
for i,spec in enumerate(species):
|
||||
self._selected_species[i] = self.species_index(spec)
|
||||
|
||||
def __reduce__(self):
|
||||
raise NotImplementedError('Solution object is not picklable')
|
||||
|
||||
def __copy__(self):
|
||||
raise NotImplementedError('Solution object is not copyable')
|
||||
|
||||
def __dealloc__(self):
|
||||
# only delete the C++ objects if this is the parent object
|
||||
if self.parent is None:
|
||||
|
|
|
|||
|
|
@ -71,3 +71,9 @@ cdef class Func1:
|
|||
|
||||
def __call__(self, t):
|
||||
return self.func.eval(t)
|
||||
|
||||
def __reduce__(self):
|
||||
raise NotImplementedError('Func1 object is not picklable')
|
||||
|
||||
def __copy__(self):
|
||||
raise NotImplementedError('Func1 object is not copyable')
|
||||
|
|
|
|||
|
|
@ -160,6 +160,11 @@ cdef class Domain1D:
|
|||
def __set__(self, desc):
|
||||
self.domain.setDesc(stringify(desc))
|
||||
|
||||
def __reduce__(self):
|
||||
raise NotImplementedError('Domain1D object is not picklable')
|
||||
|
||||
def __copy__(self):
|
||||
raise NotImplementedError('Domain1D object is not copyable')
|
||||
|
||||
cdef class Boundary1D(Domain1D):
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -115,6 +115,12 @@ cdef class ReactorBase:
|
|||
"""
|
||||
self._walls.append(wall)
|
||||
|
||||
def __reduce__(self):
|
||||
raise NotImplementedError('Reactor object is not picklable')
|
||||
|
||||
def __copy__(self):
|
||||
raise NotImplementedError('Reactor object is not copyable')
|
||||
|
||||
|
||||
cdef class Reactor(ReactorBase):
|
||||
"""
|
||||
|
|
@ -888,3 +894,9 @@ cdef class ReactorNet:
|
|||
"""
|
||||
def __get__(self):
|
||||
return self.net.neq()
|
||||
|
||||
def __reduce__(self):
|
||||
raise NotImplementedError('ReactorNet object is not picklable')
|
||||
|
||||
def __copy__(self):
|
||||
raise NotImplementedError('ReactorNet object is not copyable')
|
||||
|
|
|
|||
|
|
@ -39,3 +39,15 @@ class TestFunc1(utilities.CanteraTest):
|
|||
|
||||
f = ct.Func1(fails)
|
||||
self.assertRaises(ValueError, f, 0.1)
|
||||
|
||||
def test_unpicklable(self):
|
||||
import pickle
|
||||
f = ct.Func1(np.sin)
|
||||
with self.assertRaises(NotImplementedError):
|
||||
pickle.dumps(f)
|
||||
|
||||
def test_uncopyable(self):
|
||||
import copy
|
||||
f = ct.Func1(np.sin)
|
||||
with self.assertRaises(NotImplementedError):
|
||||
copy.copy(f)
|
||||
|
|
|
|||
|
|
@ -47,6 +47,20 @@ class TestOnedim(utilities.CanteraTest):
|
|||
self.assertArrayNear(inlet.X, Xref)
|
||||
self.assertArrayNear(inlet.Y, Yref)
|
||||
|
||||
def test_unpicklable(self):
|
||||
import pickle
|
||||
gas = ct.Solution('h2o2.xml')
|
||||
flame = ct.FreeFlow(gas)
|
||||
with self.assertRaises(NotImplementedError):
|
||||
pickle.dumps(flame)
|
||||
|
||||
def test_uncopyable(self):
|
||||
import copy
|
||||
gas = ct.Solution('h2o2.xml')
|
||||
flame = ct.FreeFlow(gas)
|
||||
with self.assertRaises(NotImplementedError):
|
||||
copy.copy(flame)
|
||||
|
||||
|
||||
class TestFreeFlame(utilities.CanteraTest):
|
||||
tol_ss = [1.0e-5, 1.0e-14] # [rtol atol] for steady-state problem
|
||||
|
|
|
|||
|
|
@ -474,6 +474,23 @@ class TestReactor(utilities.CanteraTest):
|
|||
self.assertNear(p1a, p1b)
|
||||
self.assertNear(p2a, p2b)
|
||||
|
||||
def test_unpicklable(self):
|
||||
self.make_reactors()
|
||||
import pickle
|
||||
with self.assertRaises(NotImplementedError):
|
||||
pickle.dumps(self.r1)
|
||||
with self.assertRaises(NotImplementedError):
|
||||
pickle.dumps(self.net)
|
||||
|
||||
def test_uncopyable(self):
|
||||
self.make_reactors()
|
||||
import copy
|
||||
with self.assertRaises(NotImplementedError):
|
||||
copy.copy(self.r1)
|
||||
with self.assertRaises(NotImplementedError):
|
||||
copy.copy(self.net)
|
||||
|
||||
|
||||
class TestIdealGasReactor(TestReactor):
|
||||
reactorClass = ct.IdealGasReactor
|
||||
|
||||
|
|
|
|||
|
|
@ -307,6 +307,16 @@ class TestThermoPhase(utilities.CanteraTest):
|
|||
self.assertNear(self.phase.min_temp, 300.0)
|
||||
self.assertNear(self.phase.max_temp, 3500.0)
|
||||
|
||||
def test_unpicklable(self):
|
||||
import pickle
|
||||
with self.assertRaises(NotImplementedError):
|
||||
pickle.dumps(self.phase)
|
||||
|
||||
def test_uncopyable(self):
|
||||
import copy
|
||||
with self.assertRaises(NotImplementedError):
|
||||
copy.copy(self.phase)
|
||||
|
||||
|
||||
class TestThermo(utilities.CanteraTest):
|
||||
def setUp(self):
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue