[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:
Ray Speth 2014-03-04 17:39:21 +00:00
parent c7ba8bfb84
commit c5eb2f57dd
8 changed files with 82 additions and 0 deletions

View file

@ -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:

View file

@ -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')

View file

@ -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):
"""

View file

@ -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')

View file

@ -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)

View file

@ -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

View file

@ -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

View file

@ -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):