From 76dbe4d9a44823aca5e7e56b357d64d84db64f66 Mon Sep 17 00:00:00 2001 From: Anthony Geay Date: Fri, 28 Oct 2016 16:00:59 +0200 Subject: [PATCH] Serialization of DataArrayByte. Serialization of MEDFileData objects. But still some bugs during loading of DataArrayByte. --- src/MEDCoupling_Swig/MEDCoupling.i | 3 + .../MEDCouplingDataArrayTypemaps.i | 135 ++++++++++++++++++ src/MEDCoupling_Swig/MEDCouplingFinalize.i | 3 + src/MEDCoupling_Swig/MEDCouplingMemArray.i | 98 ++++++------- src/MEDCoupling_Swig/MEDCouplingNumPyTest.py | 93 ++++++++++++ src/MEDCoupling_Swig/MEDCouplingPickleTest.py | 14 ++ src/MEDCoupling_Swig/MEDCouplingRemapper.i | 6 +- src/MEDCoupling_Swig/MEDCouplingTypemaps.i | 41 ++---- src/MEDLoader/MEDFileUtilities.cxx | 15 +- src/MEDLoader/MEDFileUtilities.hxx | 1 + src/MEDLoader/MEDFileUtilities.txx | 3 +- src/MEDLoader/MEDLoader.cxx | 5 + src/MEDLoader/Swig/MEDLoader.i | 14 +- src/MEDLoader/Swig/MEDLoaderCommon.i | 34 +++++ src/MEDLoader/Swig/MEDLoaderTest3.py | 5 +- 15 files changed, 375 insertions(+), 95 deletions(-) diff --git a/src/MEDCoupling_Swig/MEDCoupling.i b/src/MEDCoupling_Swig/MEDCoupling.i index 1a28048c1..c96a45ad1 100644 --- a/src/MEDCoupling_Swig/MEDCoupling.i +++ b/src/MEDCoupling_Swig/MEDCoupling.i @@ -77,6 +77,9 @@ def MEDCouplingDataArrayIntImod(self,*args): def MEDCouplingDataArrayIntIpow(self,*args): import _MEDCoupling return _MEDCoupling.DataArrayInt____ipow___(self, self, *args) +def MEDCouplingDataArrayBytenew(cls,*args): + import _MEDCoupling + return _MEDCoupling.DataArrayByte____new___(cls,args) def MEDCouplingDataArrayDoubleTupleIadd(self,*args): import _MEDCoupling return _MEDCoupling.DataArrayDoubleTuple____iadd___(self, self, *args) diff --git a/src/MEDCoupling_Swig/MEDCouplingDataArrayTypemaps.i b/src/MEDCoupling_Swig/MEDCouplingDataArrayTypemaps.i index 1d0463727..675dd12c4 100644 --- a/src/MEDCoupling_Swig/MEDCouplingDataArrayTypemaps.i +++ b/src/MEDCoupling_Swig/MEDCouplingDataArrayTypemaps.i @@ -18,6 +18,9 @@ // // Author : Anthony Geay (CEA/DEN) +#ifndef __MEDCOUPLINGDATAARRAYTYPEMAPS_I__ +#define __MEDCOUPLINGDATAARRAYTYPEMAPS_I__ + #include "InterpKernelAutoPtr.hxx" /*! @@ -107,6 +110,7 @@ struct PyCallBackDataArraySt { MCData *_pt_mc; }; +typedef struct PyCallBackDataArraySt PyCallBackDataArrayChar; typedef struct PyCallBackDataArraySt PyCallBackDataArrayInt; typedef struct PyCallBackDataArraySt PyCallBackDataArrayDouble; @@ -114,6 +118,12 @@ extern "C" { static int callbackmcdataarray___init__(PyObject *self, PyObject *args, PyObject *kwargs) { return 0; } + static PyObject *callbackmcdataarraychar___new__(PyTypeObject *type, PyObject *args, PyObject *kwargs) + { + PyCallBackDataArrayChar *self = (PyCallBackDataArrayChar *) ( type->tp_alloc(type, 0) ); + return (PyObject *)self; + } + static PyObject *callbackmcdataarrayint___new__(PyTypeObject *type, PyObject *args, PyObject *kwargs) { PyCallBackDataArrayInt *self = (PyCallBackDataArrayInt *) ( type->tp_alloc(type, 0) ); @@ -130,7 +140,21 @@ extern "C" { Py_TYPE(self)->tp_free(self); } + + // real callback called when a numpy arr having more than one DataArray instance client on it is destroyed. + // In this case, all the "weak" clients, except the first one, invoke this call back that desable the content of these "weak" clients. + static PyObject *callbackmcdataarraychar_call(PyCallBackDataArrayChar *self, PyObject *args, PyObject *kw) + { + if(self->_pt_mc) + { + MEDCoupling::MemArray& mma=self->_pt_mc->accessToMemArray(); + mma.destroy(); + } + Py_XINCREF(Py_None); + return Py_None; + } + // real callback called when a numpy arr having more than one DataArray instance client on it is destroyed. // In this case, all the "weak" clients, except the first one, invoke this call back that desable the content of these "weak" clients. static PyObject *callbackmcdataarrayint_call(PyCallBackDataArrayInt *self, PyObject *args, PyObject *kw) @@ -158,6 +182,49 @@ extern "C" } } +PyTypeObject PyCallBackDataArrayChar_RefType = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "callbackmcdataarraychar", + sizeof(PyCallBackDataArrayChar), + 0, + callbackmcdataarray_dealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash*/ + (ternaryfunc)callbackmcdataarraychar_call, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE, /*tp_flags*/ + 0, /*tp_doc*/ + 0, /*tp_traverse*/ + 0, /*tp_clear*/ + 0, /*tp_richcompare*/ + 0, /*tp_weaklistoffset*/ + 0, /*tp_iter*/ + 0, /*tp_iternext*/ + 0, /*tp_methods*/ + 0, /*tp_members*/ + 0, /*tp_getset*/ + 0, /*tp_base*/ + 0, /*tp_dict*/ + 0, /*tp_descr_get*/ + 0, /*tp_descr_set*/ + 0, /*tp_dictoffset*/ + callbackmcdataarray___init__, /*tp_init*/ + PyType_GenericAlloc, /*tp_alloc*/ + callbackmcdataarraychar___new__, /*tp_new*/ + PyObject_GC_Del, /*tp_free*/ +}; + + PyTypeObject PyCallBackDataArrayInt_RefType = { PyVarObject_HEAD_INIT(&PyType_Type, 0) "callbackmcdataarrayint", @@ -2527,3 +2594,71 @@ static MEDCoupling::DataArray *CheckAndRetrieveDataArrayInstance(PyObject *obj, } return reinterpret_cast< MEDCoupling::DataArray * >(aBasePtrVS); } + +static PyObject *NewMethWrapCallInitOnlyIfEmptyDictInInput(PyObject *cls, PyObject *args, const char *clsName) +{ + if(!PyTuple_Check(args)) + { + std::ostringstream oss; oss << clsName << ".__new__ : the args in input is expected to be a tuple !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + PyObject *builtinsd(PyEval_GetBuiltins());//borrowed + PyObject *obj(PyDict_GetItemString(builtinsd,"object"));//borrowed + PyObject *selfMeth(PyObject_GetAttrString(obj,"__new__")); + // + PyObject *tmp0(PyTuple_New(1)); + PyTuple_SetItem(tmp0,0,cls); Py_XINCREF(cls); + PyObject *instance(PyObject_CallObject(selfMeth,tmp0)); + Py_DECREF(tmp0); + Py_DECREF(selfMeth); + if(PyTuple_Size(args)==2 && PyDict_Check(PyTuple_GetItem(args,1)) && PyDict_Size(PyTuple_GetItem(args,1))==0 ) + {// NOT general case. only true if in unpickeling context ! call __init__. Because for all other cases, __init__ is called right after __new__ ! + PyObject *initMeth(PyObject_GetAttrString(instance,"__init__")); + PyObject *tmp3(PyTuple_New(0)); + PyObject *tmp2(PyObject_CallObject(initMeth,tmp3)); + Py_XDECREF(tmp2); + Py_DECREF(tmp3); + Py_DECREF(initMeth); + } + return instance; +} + +static PyObject *NewMethWrapCallInitOnlyIfDictWithSingleEltInInput(PyObject *cls, PyObject *args, const char *clsName) +{ + if(!PyTuple_Check(args)) + { + std::ostringstream oss; oss << clsName << ".__new__ : the args in input is expected to be a tuple !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + PyObject *builtinsd(PyEval_GetBuiltins());//borrowed + PyObject *obj(PyDict_GetItemString(builtinsd,"object"));//borrowed + PyObject *selfMeth(PyObject_GetAttrString(obj,"__new__")); + // + PyObject *tmp0(PyTuple_New(1)); + PyTuple_SetItem(tmp0,0,cls); Py_XINCREF(cls); + PyObject *instance(PyObject_CallObject(selfMeth,tmp0)); + Py_DECREF(tmp0); + Py_DECREF(selfMeth); + if(PyTuple_Size(args)==2 && PyDict_Check(PyTuple_GetItem(args,1)) && PyDict_Size(PyTuple_GetItem(args,1))==1 ) + {// NOT general case. only true if in unpickeling context ! call __init__. Because for all other cases, __init__ is called right after __new__ ! + PyObject *initMeth(PyObject_GetAttrString(instance,"__init__")); + PyObject *zeNumpyRepr(0); + { + PyObject *tmp1(PyInt_FromLong(0)); + zeNumpyRepr=PyDict_GetItem(PyTuple_GetItem(args,1),tmp1);//borrowed + Py_DECREF(tmp1); + } + { + PyObject *tmp3(PyTuple_New(1)); + PyTuple_SetItem(tmp3,0,zeNumpyRepr); Py_XINCREF(zeNumpyRepr); + PyObject *tmp2(PyObject_CallObject(initMeth,tmp3)); + Py_XDECREF(tmp2); + Py_DECREF(tmp3); + } + Py_DECREF(initMeth); + } + return instance; +} + +#endif + diff --git a/src/MEDCoupling_Swig/MEDCouplingFinalize.i b/src/MEDCoupling_Swig/MEDCouplingFinalize.i index 6279b3c8d..1640bc63b 100644 --- a/src/MEDCoupling_Swig/MEDCouplingFinalize.i +++ b/src/MEDCoupling_Swig/MEDCouplingFinalize.i @@ -34,6 +34,8 @@ DataArrayInt.__idiv__=MEDCouplingDataArrayIntIdiv DataArrayInt.__imod__=MEDCouplingDataArrayIntImod DataArrayInt.__ipow__=MEDCouplingDataArrayIntIpow +DataArrayByte.__new__=classmethod(MEDCouplingDataArrayBytenew) + MEDCouplingFieldDouble.__iadd__=MEDCouplingFieldDoubleIadd MEDCouplingFieldDouble.__isub__=MEDCouplingFieldDoubleIsub MEDCouplingFieldDouble.__imul__=MEDCouplingFieldDoubleImul @@ -80,6 +82,7 @@ del MEDCouplingDataArrayIntIsub del MEDCouplingDataArrayIntImul del MEDCouplingDataArrayIntIdiv del MEDCouplingDataArrayIntImod +del MEDCouplingDataArrayBytenew del MEDCouplingDataArrayDoubleTupleIadd del MEDCouplingDataArrayDoubleTupleIsub del MEDCouplingDataArrayDoubleTupleImul diff --git a/src/MEDCoupling_Swig/MEDCouplingMemArray.i b/src/MEDCoupling_Swig/MEDCouplingMemArray.i index bb63fbb5b..2424e9821 100644 --- a/src/MEDCoupling_Swig/MEDCouplingMemArray.i +++ b/src/MEDCoupling_Swig/MEDCouplingMemArray.i @@ -2256,35 +2256,7 @@ namespace MEDCoupling // serialization static PyObject *___new___(PyObject *cls, PyObject *args) throw(INTERP_KERNEL::Exception) { - static const char MSG[]="DataArrayDouble.__new__ : the args in input is expected to be a tuple !"; - if(!PyTuple_Check(args)) - throw INTERP_KERNEL::Exception(MSG); - PyObject *builtinsd(PyEval_GetBuiltins());//borrowed - PyObject *obj(PyDict_GetItemString(builtinsd,"object"));//borrowed - PyObject *selfMeth(PyObject_GetAttrString(obj,"__new__")); - // - PyObject *tmp0(PyTuple_New(1)); - PyTuple_SetItem(tmp0,0,cls); Py_XINCREF(cls); - PyObject *instance(PyObject_CallObject(selfMeth,tmp0)); - Py_DECREF(tmp0); - Py_DECREF(selfMeth); - PyObject *initMeth(PyObject_GetAttrString(instance,"__init__")); - int sz(PyTuple_Size(args)); - - if(PyTuple_Size(args)==2 && PyDict_Check(PyTuple_GetItem(args,1)) && PyDict_Size(PyTuple_GetItem(args,1))==1 ) - {// NOT general case. only true if in unpickeling context ! call __init__. Because for all other cases, __init__ is called right after __new__ ! - PyObject *zeNumpyRepr(0); - PyObject *tmp1(PyInt_FromLong(0)); - zeNumpyRepr=PyDict_GetItem(PyTuple_GetItem(args,1),tmp1);//borrowed - Py_DECREF(tmp1); - PyObject *tmp3(PyTuple_New(1)); - PyTuple_SetItem(tmp3,0,zeNumpyRepr); Py_XINCREF(zeNumpyRepr); - PyObject *tmp2(PyObject_CallObject(initMeth,tmp3)); - Py_XDECREF(tmp2); - Py_DECREF(tmp3); - } - Py_DECREF(initMeth); - return instance; + return NewMethWrapCallInitOnlyIfDictWithSingleEltInInput(cls,args,"DataArrayDouble"); } PyObject *__getnewargs__() throw(INTERP_KERNEL::Exception) @@ -4614,35 +4586,7 @@ namespace MEDCoupling // serialization static PyObject *___new___(PyObject *cls, PyObject *args) throw(INTERP_KERNEL::Exception) { - static const char MSG[]="DataArrayInt.__new__ : the args in input is expected to be a tuple !"; - if(!PyTuple_Check(args)) - throw INTERP_KERNEL::Exception(MSG); - PyObject *builtinsd(PyEval_GetBuiltins());//borrowed - PyObject *obj(PyDict_GetItemString(builtinsd,"object"));//borrowed - PyObject *selfMeth(PyObject_GetAttrString(obj,"__new__")); - // - PyObject *tmp0(PyTuple_New(1)); - PyTuple_SetItem(tmp0,0,cls); Py_XINCREF(cls); - PyObject *instance(PyObject_CallObject(selfMeth,tmp0)); - Py_DECREF(tmp0); - Py_DECREF(selfMeth); - PyObject *initMeth(PyObject_GetAttrString(instance,"__init__")); - int sz(PyTuple_Size(args)); - - if(PyTuple_Size(args)==2 && PyDict_Check(PyTuple_GetItem(args,1)) && PyDict_Size(PyTuple_GetItem(args,1))==1 ) - {// NOT general case. only true if in unpickeling context ! call __init__. Because for all other cases, __init__ is called right after __new__ ! - PyObject *zeNumpyRepr(0); - PyObject *tmp1(PyInt_FromLong(0)); - zeNumpyRepr=PyDict_GetItem(PyTuple_GetItem(args,1),tmp1);//borrowed - Py_DECREF(tmp1); - PyObject *tmp3(PyTuple_New(1)); - PyTuple_SetItem(tmp3,0,zeNumpyRepr); Py_XINCREF(zeNumpyRepr); - PyObject *tmp2(PyObject_CallObject(initMeth,tmp3)); - Py_XDECREF(tmp2); - Py_DECREF(tmp3); - } - Py_DECREF(initMeth); - return instance; + return NewMethWrapCallInitOnlyIfDictWithSingleEltInInput(cls,args,"DataArrayInt"); } PyObject *__getnewargs__() throw(INTERP_KERNEL::Exception) @@ -5246,6 +5190,12 @@ namespace MEDCoupling return ret.retn(); } } +#ifdef WITH_NUMPY + else if(PyArray_Check(elt0) && nbOfTuples==NULL && nbOfComp==NULL) + {//DataArrayDouble.New(numpyArray) + return BuildNewInstance(elt0,NPY_INT8,&PyCallBackDataArrayChar_RefType,"INT8"); + } +#endif else throw INTERP_KERNEL::Exception(msg); } @@ -5416,6 +5366,38 @@ namespace MEDCoupling return MEDCoupling_DataArrayByte_presenceOfTuple(self,obj); } } + +#ifdef WITH_NUMPY + PyObject *toNumPyArray() throw(INTERP_KERNEL::Exception) // not const. It is not a bug ! + { + return ToNumPyArray(self,NPY_INT8,"DataArrayByte"); + } +#endif + + // serialization + static PyObject *___new___(PyObject *cls, PyObject *args) throw(INTERP_KERNEL::Exception) + { + return NewMethWrapCallInitOnlyIfDictWithSingleEltInInput(cls,args,"DataArrayByte"); + } + + PyObject *__getnewargs__() throw(INTERP_KERNEL::Exception) + { +#ifdef WITH_NUMPY + if(!self->isAllocated()) + throw INTERP_KERNEL::Exception("PyWrap of DataArrayByte.__getnewargs__ : self is not allocated !"); + PyObject *ret(PyTuple_New(1)); + PyObject *ret0(PyDict_New()); + PyObject *numpyArryObj(MEDCoupling_DataArrayByte_toNumPyArray(self)); + {// create a dict to discriminite in __new__ if __init__ should be called. Not beautiful but not idea ... + PyObject *tmp1(PyInt_FromLong(0)); + PyDict_SetItem(ret0,tmp1,numpyArryObj); Py_DECREF(tmp1); Py_DECREF(numpyArryObj); + PyTuple_SetItem(ret,0,ret0); + } + return ret; +#else + throw INTERP_KERNEL::Exception("PyWrap of DataArrayByte.__getnewargs__ : not implemented because numpy is not active in your configuration ! No serialization/unserialization available without numpy !"); +#endif + } DataArrayByte *__setitem__(PyObject *obj, PyObject *value) throw(INTERP_KERNEL::Exception) { diff --git a/src/MEDCoupling_Swig/MEDCouplingNumPyTest.py b/src/MEDCoupling_Swig/MEDCouplingNumPyTest.py index b2f23dd64..7b2036343 100644 --- a/src/MEDCoupling_Swig/MEDCouplingNumPyTest.py +++ b/src/MEDCoupling_Swig/MEDCouplingNumPyTest.py @@ -663,6 +663,99 @@ class MEDCouplingNumPyTest(unittest.TestCase): self.assertEqual(m0np.tolist(),[[2.0,3.0,4.0],[5.0,1.0,6.0]]) pass + @unittest.skipUnless(MEDCouplingHasNumPyBindings(),"requires numpy") + def test28(self): + """Test on DataArrayBytes""" + # use case 1 + d=DataArrayByte(256) + for i in xrange(len(d)): + d[i]=-128+i + pass + arr=d.toNumPyArray() + for i in xrange(len(d)): + self.assertEqual(int(arr[i]),-128+i) + pass + d[0]=7 + self.assertEqual(int(arr[0]),7) + arr[0]=8 + self.assertEqual(int(d.getIJ(0,0)),8) + del arr + gc.collect() + del d + gc.collect() + # use case 2 + d=DataArrayByte(256) + for i in xrange(len(d)): + d[i]=-128+i + pass + arr=d.toNumPyArray() + for i in xrange(len(d)): + self.assertEqual(int(arr[i]),-128+i) + pass + del d + gc.collect() + del arr + gc.collect() + # use case 3 + d=DataArrayByte(256) + for i in xrange(len(d)): + d[i]=-128+i + pass + arr1=d.toNumPyArray() + arr2=d.toNumPyArray() + arr3=d.toNumPyArray() + d[0]=10 + self.assertEqual(int(arr1[0]),10) ; self.assertEqual(int(arr2[0]),10) ; self.assertEqual(int(arr3[0]),10) + arr2[0]=15 ; self.assertEqual(int(d.getIJ(0,0)),15) ; self.assertEqual(int(arr1[0]),15) ; self.assertEqual(int(arr3[0]),15) + arr1[0]=-128 + for i in xrange(len(d)): + self.assertEqual(int(arr1[i]),-128+i) + self.assertEqual(int(arr2[i]),-128+i) + self.assertEqual(int(arr3[i]),-128+i) + pass + del arr2 + gc.collect() + for i in xrange(len(d)): + self.assertEqual(int(arr1[i]),-128+i) + self.assertEqual(int(arr3[i]),-128+i) + pass + del arr1 + gc.collect() + for i in xrange(len(d)): + self.assertEqual(int(arr3[i]),-128+i) + pass + del arr3 + gc.collect() + # use case 4 + arr=array(0,dtype=int8) + arr.resize(256) + for i in xrange(256): + arr[i]=-128+i + pass + d=DataArrayByte(arr) + for i in xrange(256): + self.assertEqual(int(d.getIJ(i,0)),-128+i) + pass + del arr + gc.collect() + del d + gc.collect() + # use case 5 + arr=array(0,dtype=int8) + arr.resize(256) + for i in xrange(256): + arr[i]=-128+i + pass + d=DataArrayByte(arr) + for i in xrange(256): + self.assertEqual(int(d.getIJ(i,0)),-128+i) + pass + del d + gc.collect() + del arr + gc.collect() + pass + def setUp(self): pass pass diff --git a/src/MEDCoupling_Swig/MEDCouplingPickleTest.py b/src/MEDCoupling_Swig/MEDCouplingPickleTest.py index 89a2f60c7..a34420d8a 100644 --- a/src/MEDCoupling_Swig/MEDCouplingPickleTest.py +++ b/src/MEDCoupling_Swig/MEDCouplingPickleTest.py @@ -292,6 +292,20 @@ class MEDCouplingPickleTest(unittest.TestCase): self.assertEqual(e2.what(),eStr) pass + @unittest.skipUnless(MEDCouplingHasNumPyBindings(),"requires numpy") + def test14(self): + """Pickelization of DataArrayBytes""" + x=DataArrayByte(256,1) + for i in xrange(256): + x[i]=-128+i + pass + x.rearrange(2) ; x.setInfoOnComponents(["aa","bbb"]) + x.setName("toto") + st=cPickle.dumps(x,cPickle.HIGHEST_PROTOCOL) + x2=cPickle.loads(st) + self.assertTrue(x2.isEqual(x)) + pass + def setUp(self): pass pass diff --git a/src/MEDCoupling_Swig/MEDCouplingRemapper.i b/src/MEDCoupling_Swig/MEDCouplingRemapper.i index 11089250b..d170e1469 100644 --- a/src/MEDCoupling_Swig/MEDCouplingRemapper.i +++ b/src/MEDCoupling_Swig/MEDCouplingRemapper.i @@ -139,12 +139,12 @@ def MEDCouplingFieldDoubleIdiv(self,*args): def MEDCouplingFieldDoubleIpow(self,*args): import _MEDCouplingRemapper return _MEDCouplingRemapper.MEDCouplingFieldDouble____ipow___(self, self, *args) +def MEDCouplingDataArrayBytenew(cls,*args): + import _MEDCouplingRemapper + return _MEDCouplingRemapper.DataArrayByte____new___(cls,args) def MEDCouplingDataArrayIntnew(cls,*args): import _MEDCouplingRemapper return _MEDCouplingRemapper.DataArrayInt____new___(cls,args) -def MEDCouplingDataArrayIntnew(cls,*args): - import _MEDCoupling - return _MEDCoupling.DataArrayInt____new___(cls,args) def MEDCouplingDataArrayIntIadd(self,*args): import _MEDCouplingRemapper return _MEDCouplingRemapper.DataArrayInt____iadd___(self, self, *args) diff --git a/src/MEDCoupling_Swig/MEDCouplingTypemaps.i b/src/MEDCoupling_Swig/MEDCouplingTypemaps.i index ea4b14273..ae568df97 100644 --- a/src/MEDCoupling_Swig/MEDCouplingTypemaps.i +++ b/src/MEDCoupling_Swig/MEDCouplingTypemaps.i @@ -18,7 +18,20 @@ // // Author : Anthony Geay (CEA/DEN) +#ifndef __MEDCOUPLINGTYPEMAPS_I__ +#define __MEDCOUPLINGTYPEMAPS_I__ + #include "MEDCouplingDataArrayTypemaps.i" +#include "MEDCouplingUMesh.hxx" +#include "MEDCouplingCMesh.hxx" +#include "MEDCouplingIMesh.hxx" +#include "MEDCouplingCurveLinearMesh.hxx" +#include "MEDCouplingMappedExtrudedMesh.hxx" +#include "MEDCoupling1GTUMesh.hxx" +#include "MEDCouplingFieldDiscretization.hxx" +#include "MEDCouplingMultiFields.hxx" +#include "MEDCouplingPartDefinition.hxx" +#include "MEDCouplingCartesianAMRMesh.hxx" static PyObject *convertMesh(MEDCoupling::MEDCouplingMesh *mesh, int owner) throw(INTERP_KERNEL::Exception) { @@ -428,30 +441,4 @@ MEDCoupling::MEDCouplingFieldDouble *MEDCoupling_MEDCouplingFieldDouble___rdiv__ } } -static PyObject *NewMethWrapCallInitOnlyIfEmptyDictInInput(PyObject *cls, PyObject *args, const char *clsName) -{ - if(!PyTuple_Check(args)) - { - std::ostringstream oss; oss << clsName << ".__new__ : the args in input is expected to be a tuple !"; - throw INTERP_KERNEL::Exception(oss.str().c_str()); - } - PyObject *builtinsd(PyEval_GetBuiltins());//borrowed - PyObject *obj(PyDict_GetItemString(builtinsd,"object"));//borrowed - PyObject *selfMeth(PyObject_GetAttrString(obj,"__new__")); - // - PyObject *tmp0(PyTuple_New(1)); - PyTuple_SetItem(tmp0,0,cls); Py_XINCREF(cls); - PyObject *instance(PyObject_CallObject(selfMeth,tmp0)); - Py_DECREF(tmp0); - Py_DECREF(selfMeth); - if(PyTuple_Size(args)==2 && PyDict_Check(PyTuple_GetItem(args,1)) && PyDict_Size(PyTuple_GetItem(args,1))==0 ) - {// NOT general case. only true if in unpickeling context ! call __init__. Because for all other cases, __init__ is called right after __new__ ! - PyObject *initMeth(PyObject_GetAttrString(instance,"__init__")); - PyObject *tmp3(PyTuple_New(0)); - PyObject *tmp2(PyObject_CallObject(initMeth,tmp3)); - Py_XDECREF(tmp2); - Py_DECREF(tmp3); - Py_DECREF(initMeth); - } - return instance; -} +#endif diff --git a/src/MEDLoader/MEDFileUtilities.cxx b/src/MEDLoader/MEDFileUtilities.cxx index 44c4a776b..673f0a69e 100644 --- a/src/MEDLoader/MEDFileUtilities.cxx +++ b/src/MEDLoader/MEDFileUtilities.cxx @@ -205,10 +205,21 @@ MEDCoupling::MCAuto MEDCoupling::MEDFileWritableStan memfile.app_image_ptr=0; memfile.app_image_size=0; // - MEDFileUtilities::AutoFid fid(MEDmemFileOpen(DFT_FILENAME_IN_MEM,&memfile,MED_FALSE,MED_ACC_CREAT)); + std::string dftFileName(GenerateUniqueDftFileNameInMem()); + MEDFileUtilities::AutoFid fid(MEDmemFileOpen(dftFileName.c_str(),&memfile,MED_FALSE,MED_ACC_CREAT)); writeLL(fid); // MEDCoupling::MCAuto ret(MEDCoupling::DataArrayByte::New()); - ret->useArray(reinterpret_cast(memfile.app_image_ptr),true,C_DEALLOC,memfile.app_image_size,1); + //ret->useArray(reinterpret_cast(memfile.app_image_ptr),true,C_DEALLOC,memfile.app_image_size,1); + ret->alloc(memfile.app_image_size,1); + const char *srcData(reinterpret_cast(memfile.app_image_ptr)); + std::copy(srcData,srcData+memfile.app_image_size,ret->getPointer()); return ret; } + +std::string MEDCoupling::MEDFileWritableStandAlone::GenerateUniqueDftFileNameInMem() +{ + static int ii=0; + std::ostringstream oss; oss << DFT_FILENAME_IN_MEM << "_" << ii++; + return oss.str(); +} diff --git a/src/MEDLoader/MEDFileUtilities.hxx b/src/MEDLoader/MEDFileUtilities.hxx index a89260fbc..32ed5d47e 100644 --- a/src/MEDLoader/MEDFileUtilities.hxx +++ b/src/MEDLoader/MEDFileUtilities.hxx @@ -71,6 +71,7 @@ namespace MEDCoupling MEDLOADER_EXPORT virtual void write(const std::string& fileName, int mode) const; MEDLOADER_EXPORT virtual void write30(const std::string& fileName, int mode) const; MEDLOADER_EXPORT MCAuto serialize() const; + MEDLOADER_EXPORT static std::string GenerateUniqueDftFileNameInMem(); public: MEDLOADER_EXPORT static const char DFT_FILENAME_IN_MEM[]; template diff --git a/src/MEDLoader/MEDFileUtilities.txx b/src/MEDLoader/MEDFileUtilities.txx index 9e3f8bada..a8417d3ac 100644 --- a/src/MEDLoader/MEDFileUtilities.txx +++ b/src/MEDLoader/MEDFileUtilities.txx @@ -32,7 +32,8 @@ T *MEDCoupling::MEDFileWritableStandAlone::BuildFromMemoryChunk(MEDCoupling::Dat med_memfile memfile=MED_MEMFILE_INIT; memfile.app_image_ptr=db->getPointer(); memfile.app_image_size=db->getNbOfElems(); - MEDFileUtilities::AutoFid fid(MEDmemFileOpen(MEDCoupling::MEDFileWritableStandAlone::DFT_FILENAME_IN_MEM,&memfile,MED_FALSE,MED_ACC_RDONLY)); + std::string dftFileName(MEDCoupling::MEDFileWritableStandAlone::GenerateUniqueDftFileNameInMem()); + MEDFileUtilities::AutoFid fid(MEDmemFileOpen(dftFileName.c_str(),&memfile,MED_FALSE,MED_ACC_RDONLY)); return T::New(fid); } diff --git a/src/MEDLoader/MEDLoader.cxx b/src/MEDLoader/MEDLoader.cxx index 4cd9823b2..c8248fd11 100644 --- a/src/MEDLoader/MEDLoader.cxx +++ b/src/MEDLoader/MEDLoader.cxx @@ -294,6 +294,7 @@ std::string MEDCoupling::MEDFileVersionStr() std::string MEDCoupling::MEDFileVersionOfFileStr(const std::string& fileName) { +#if MED_NUM_MAJEUR>=3 && MED_NUM_MINEUR>=2 && MED_NUM_RELEASE>=1 MEDFileUtilities::AutoFid fid(MEDCoupling::OpenMEDFileForRead(fileName)); const int SZ=20; const char START_EXPECTED[]="MED-"; @@ -308,6 +309,10 @@ std::string MEDCoupling::MEDFileVersionOfFileStr(const std::string& fileName) throw INTERP_KERNEL::Exception(oss.str()); } return ret.substr(sizeof(START_EXPECTED)-1,std::string::npos); +#else + std::ostringstream oss; oss << "MEDFileVersionOfFileStr : is implemented with MEDFile " << MEDFileVersionStr() << " ! If you need this feature please use version >= 3.2.1."; + throw INTERP_KERNEL::Exception(oss.str()); +#endif } void MEDCoupling::MEDFileVersion(int& major, int& minor, int& release) diff --git a/src/MEDLoader/Swig/MEDLoader.i b/src/MEDLoader/Swig/MEDLoader.i index cabcb5be2..c5dce740f 100644 --- a/src/MEDLoader/Swig/MEDLoader.i +++ b/src/MEDLoader/Swig/MEDLoader.i @@ -57,6 +57,9 @@ def MEDCouplingFieldDoubleIdiv(self,*args): def MEDCouplingFieldDoubleIpow(self,*args): import _MEDLoader return _MEDLoader.MEDCouplingFieldDouble____ipow___(self, self, *args) +def MEDCouplingDataArrayBytenew(cls,*args): + import _MEDLoader + return _MEDLoader.DataArrayByte____new___(cls,args) def MEDCouplingDataArrayIntnew(cls,*args): import _MEDLoader return _MEDLoader.DataArrayInt____new___(cls,args) @@ -135,14 +138,19 @@ def MEDCouplingExtrudedMeshnew(cls,*args): %} %pythoncode %{ -def ParaMEDMEMMEDFileUMeshnew(cls,*args): +def MEDCouplingMEDFileUMeshnew(cls,*args): import _MEDLoader return _MEDLoader.MEDFileUMesh____new___(cls,args) +def MEDCouplingMEDFileDatanew(cls,*args): + import _MEDLoader + return _MEDLoader.MEDFileData____new___(cls,args) %} %include "MEDCouplingFinalize.i" %pythoncode %{ -MEDFileUMesh.__new__=classmethod(ParaMEDMEMMEDFileUMeshnew) -del ParaMEDMEMMEDFileUMeshnew +MEDFileUMesh.__new__=classmethod(MEDCouplingMEDFileUMeshnew) +del MEDCouplingMEDFileUMeshnew +MEDFileData.__new__=classmethod(MEDCouplingMEDFileDatanew) +del MEDCouplingMEDFileDatanew %} diff --git a/src/MEDLoader/Swig/MEDLoaderCommon.i b/src/MEDLoader/Swig/MEDLoaderCommon.i index 810045d92..19c1f2b5a 100644 --- a/src/MEDLoader/Swig/MEDLoaderCommon.i +++ b/src/MEDLoader/Swig/MEDLoaderCommon.i @@ -546,6 +546,24 @@ namespace MEDCoupling MCAuto ret(self->serialize()); return ret.retn(); } + + PyObject *__getnewargs__() throw(INTERP_KERNEL::Exception) + { +#ifdef WITH_NUMPY + PyObject *ret(PyTuple_New(1)); + PyObject *ret0(PyDict_New()); + DataArrayByte *retCpp(MEDCoupling_MEDFileWritableStandAlone_serialize(self)); + PyObject *numpyArryObj=SWIG_NewPointerObj(SWIG_as_voidptr(retCpp),SWIGTYPE_p_MEDCoupling__DataArrayByte, SWIG_POINTER_OWN | 0 ); + {// create a dict to discriminite in __new__ if __init__ should be called. Not beautiful but not idea ... + PyObject *tmp1(PyInt_FromLong(0)); + PyDict_SetItem(ret0,tmp1,numpyArryObj); Py_DECREF(tmp1); Py_DECREF(numpyArryObj); + PyTuple_SetItem(ret,0,ret0); + } + return ret; +#else + throw INTERP_KERNEL::Exception("PyWrap of MEDFileData.__getnewargs__ : not implemented because numpy is not active in your configuration ! No serialization/unserialization available without numpy !"); +#endif + } } }; @@ -3567,6 +3585,22 @@ namespace MEDCoupling MCAuto ret(MEDFileData::Aggregate(mfdsCpp)); return ret.retn(); } + + // serialization + static PyObject *___new___(PyObject *cls, PyObject *args) throw(INTERP_KERNEL::Exception) + { + return NewMethWrapCallInitOnlyIfDictWithSingleEltInInput(cls,args,"MEDFileData"); + } + + PyObject *__getstate__() throw(INTERP_KERNEL::Exception) + { + PyObject *ret(PyList_New(0)); + return ret; + } + + void __setstate__(PyObject *inp) throw(INTERP_KERNEL::Exception) + { + } } }; diff --git a/src/MEDLoader/Swig/MEDLoaderTest3.py b/src/MEDLoader/Swig/MEDLoaderTest3.py index 93aaf60aa..bd37a82e2 100644 --- a/src/MEDLoader/Swig/MEDLoaderTest3.py +++ b/src/MEDLoader/Swig/MEDLoaderTest3.py @@ -5752,7 +5752,6 @@ class MEDLoaderTest3(unittest.TestCase): ex=MEDCouplingMappedExtrudedMesh(mesh3D) mm=MEDFileUMesh(ex) mm.write(fname,2) - assert(LooseVersion(MEDFileVersionOfFileStr(fname)).version[:2]==list(MEDFileVersion()[:2])) # checks that MED file version of written mesh is thoose of the current MED file lib ex2=mm.convertToExtrudedMesh() mm2=MEDFileMesh.New(fname) ex3=mm2.convertToExtrudedMesh() @@ -5763,6 +5762,7 @@ class MEDLoaderTest3(unittest.TestCase): @unittest.skipUnless(LooseVersion(MEDFileVersionStr())>=LooseVersion('3.2.1'),"This test requires at least MEDFile version 3.2.1") def testWriteInto30(self): fname="Pyfile108.med" + fname2="Pyfile109.med" m=MEDCouplingUMesh("mesh",1) ; m.setCoords(DataArrayDouble([0,0,1,1],2,2)) ; m.allocateCells() ; m.insertNextCell(NORM_SEG2,[1,0]) mm=MEDFileUMesh() ; mm[0]=m mm.setFamilyId("FAMILLE_ZERO",0) @@ -5771,6 +5771,9 @@ class MEDLoaderTest3(unittest.TestCase): assert(LooseVersion(MEDFileVersionOfFileStr(fname)).version[:2]==[3,0]) # checks that just written MED file has a version == 3.0.x mm2=MEDFileUMesh(fname) self.assertTrue(mm.isEqual(mm2,1e-12)) + # + mm.write(fname2,2) + assert(LooseVersion(MEDFileVersionOfFileStr(fname2)).version[:2]==list(MEDFileVersion()[:2])) # checks that MED file version of written mesh is thoose of the current MED file lib pass pass -- 2.39.2