From 88111dfab48ab5324a529bcf2a88ff93e4547afa Mon Sep 17 00:00:00 2001 From: Gilles DAVID Date: Wed, 31 May 2017 18:31:32 +0200 Subject: [PATCH] Python 3: PoC to correctly manage unicode strings from Python MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit The following use case does not work because of the caracter 'é': >>> import salome >>> salome.salome_study_init('/tmp/étude.hdf') The solution here is to consider Unicode strings coming from all the interfaces of SALOME modules, and then to convert them to encoded strings. To do that: - all IDL "string" parameters should be changed into "wstring". - all C++ interfaces should have wchar_t* instead of char* - wchar_t* inputs should then be encoded to char* using an ENCODE function (to be written) - wchar_t* outputs should be decoded from char* using a DECODE function (to be written) --- bin/salome_utils.py | 5 +-- idl/SALOMEDS.idl | 2 +- src/HDFPersist/HDFfile.cc | 47 ++++++++++++++---------- src/KERNEL_PY/salome_study.py | 5 ++- src/SALOMEDS/SALOMEDS_StudyManager.cxx | 3 +- src/SALOMEDS/SALOMEDS_StudyManager_i.cxx | 19 ++++++++-- src/SALOMEDS/SALOMEDS_StudyManager_i.hxx | 2 +- 7 files changed, 51 insertions(+), 32 deletions(-) diff --git a/bin/salome_utils.py b/bin/salome_utils.py index 67c352f99..f292943c4 100644 --- a/bin/salome_utils.py +++ b/bin/salome_utils.py @@ -56,10 +56,9 @@ def _try_bool( arg ): are supported. If does not represent a boolean, an exception is raised. """ - import types - if type( arg ) == bool : + if isinstance(arg, bool) : return arg - elif type( arg ) == bytes : + elif isinstance(arg, (str, bytes)): v = str( arg ).lower() if v in [ "yes", "y", "true" ]: return True elif v in [ "no", "n", "false" ]: return False diff --git a/idl/SALOMEDS.idl b/idl/SALOMEDS.idl index 3303ac682..f7fb5d260 100644 --- a/idl/SALOMEDS.idl +++ b/idl/SALOMEDS.idl @@ -878,7 +878,7 @@ Searches for a definite %SObject with a definite GUID and returns True if it fin See \ref example1 for an example of this method usage in batchmode of %SALOME application. */ - Study Open (in URL aStudyUrl) raises (SALOME::SALOME_Exception); + Study Open (in wstring aStudyUrl) raises (SALOME::SALOME_Exception); /*! \brief Closing the study diff --git a/src/HDFPersist/HDFfile.cc b/src/HDFPersist/HDFfile.cc index 71b44e112..d372e460c 100644 --- a/src/HDFPersist/HDFfile.cc +++ b/src/HDFPersist/HDFfile.cc @@ -58,29 +58,36 @@ void HDFfile::CreateOnDisk() void HDFfile::OpenOnDisk(hdf_access_mode access_mode) { - _access_mode = access_mode; + _access_mode = access_mode; + std::string msgerr; - switch (_access_mode) - { - case HDF_RDWR : - if (access(_name,F_OK)) + switch (_access_mode) { - if ((_id = HDFfileCreate(_name)) < 0) - throw HDFexception("Can't open HDF file"); + case HDF_RDWR: + if (access(_name, F_OK)) + { + if ((_id = HDFfileCreate(_name)) < 0) { + msgerr = "Can't create HDF in RW mode file" + std::string(_name); + throw HDFexception(msgerr.c_str()); + } + } + else if ((_id = HDFfileOpen(_name, _access_mode)) < 0) { + msgerr = "Can't open HDF in RW mode file " + std::string(_name); + throw HDFexception(msgerr.c_str()); + } + break; + + case HDF_RDONLY: + if ((_id = HDFfileOpen(_name, _access_mode)) < 0) { + msgerr = "Can't open HDF in RO mode file " + std::string(_name); + throw HDFexception(msgerr.c_str()); + } + break; + + default: + msgerr = "Can't open HDF file " + std::string(_name) + " : bad acces option"; + throw HDFexception(msgerr.c_str()); } - else - if ((_id = HDFfileOpen(_name,_access_mode)) < 0) - throw HDFexception("Can't open HDF file"); - break; - - case HDF_RDONLY : - if ((_id = HDFfileOpen(_name,_access_mode)) < 0) - throw HDFexception("Can't open HDF file"); - break; - - default : - throw HDFexception("Can't open HDF file : bad acces option"); - } } void HDFfile::CloseOnDisk() diff --git a/src/KERNEL_PY/salome_study.py b/src/KERNEL_PY/salome_study.py index b31fad899..503dff8fd 100755 --- a/src/KERNEL_PY/salome_study.py +++ b/src/KERNEL_PY/salome_study.py @@ -399,8 +399,9 @@ def salome_study_init(theStudyPath=None): myStudy = None myStudyId = getActiveStudy() if myStudyId == None : - import types - if theStudyPath and (type(theStudyPath) == bytes or type(theStudyPath) == str): + if theStudyPath and isinstance(theStudyPath, (str, bytes)): + if isinstance(theStudyPath, bytes): + theStudyPath = str(theStudyPath, 'UTF8') myStudyId = openStudy(theStudyPath) else: myStudyId = createNewStudy() diff --git a/src/SALOMEDS/SALOMEDS_StudyManager.cxx b/src/SALOMEDS/SALOMEDS_StudyManager.cxx index ba0a8f206..4dc29e939 100644 --- a/src/SALOMEDS/SALOMEDS_StudyManager.cxx +++ b/src/SALOMEDS/SALOMEDS_StudyManager.cxx @@ -117,7 +117,8 @@ _PTR(Study) SALOMEDS_StudyManager::Open(const std::string& theStudyUrl) //SRN: Pure CORBA Open as it does more initialization than the local one SALOMEDSClient_Study* aStudy = NULL; - SALOMEDS::Study_var aStudy_impl = _corba_impl->Open((char*)theStudyUrl.c_str()); + std::wstring wtheStudyUrl = std::wstring(theStudyUrl.begin(), theStudyUrl.end()); + SALOMEDS::Study_var aStudy_impl = _corba_impl->Open((wchar_t*)theStudyUrl.c_str()); if(CORBA::is_nil(aStudy_impl)) return _PTR(Study)(aStudy); aStudy = new SALOMEDS_Study(aStudy_impl.in()); diff --git a/src/SALOMEDS/SALOMEDS_StudyManager_i.cxx b/src/SALOMEDS/SALOMEDS_StudyManager_i.cxx index 6113ccc98..3826e4f69 100644 --- a/src/SALOMEDS/SALOMEDS_StudyManager_i.cxx +++ b/src/SALOMEDS/SALOMEDS_StudyManager_i.cxx @@ -159,13 +159,22 @@ SALOMEDS::Study_ptr SALOMEDS_StudyManager_i::NewStudy(const char* study_name) * Purpose : Open a Study from it's persistent reference */ //============================================================================ -SALOMEDS::Study_ptr SALOMEDS_StudyManager_i::Open(const char* aUrl) +SALOMEDS::Study_ptr SALOMEDS_StudyManager_i::Open(const wchar_t* aWUrl) throw(SALOME::SALOME_Exception) { SALOMEDS::Locker lock; Unexpect aCatch(SalomeException); - MESSAGE("Begin of SALOMEDS_StudyManager_i::Open"); + + // Converts UTF8 url to encoded version + setlocale(LC_ALL, ""); + char aUrl[256]; + int ret; + memset( aUrl, 0, 256); + ret = wcstombs(aUrl, aWUrl, 255); + if (ret==256) aUrl[255]='\0'; + MESSAGE("Begin of SALOMEDS_StudyManager_i::Open " << aUrl); + #ifndef ALLOW_MULTI_STUDIES std::vector anOpened = _impl->GetOpenStudies(); @@ -180,8 +189,10 @@ SALOMEDS::Study_ptr SALOMEDS_StudyManager_i::Open(const char* aUrl) SALOMEDSImpl_Study* aStudyImpl = _impl->Open(std::string(aUrl)); - if ( !aStudyImpl ) - THROW_SALOME_CORBA_EXCEPTION("Impossible to Open study from file", SALOME::BAD_PARAM) + if ( !aStudyImpl ) { + std::string errmsg = "Impossible to Open study from file " + std::string(aUrl); + THROW_SALOME_CORBA_EXCEPTION(errmsg.c_str(), SALOME::BAD_PARAM) + } MESSAGE("Open : Creating the CORBA servant holding it... "); diff --git a/src/SALOMEDS/SALOMEDS_StudyManager_i.hxx b/src/SALOMEDS/SALOMEDS_StudyManager_i.hxx index ba1daf0eb..51830f941 100644 --- a/src/SALOMEDS/SALOMEDS_StudyManager_i.hxx +++ b/src/SALOMEDS/SALOMEDS_StudyManager_i.hxx @@ -89,7 +89,7 @@ public: \param char* arguments, the study URL \return Study_ptr arguments */ - virtual SALOMEDS::Study_ptr Open(const char* aStudyUrl) throw (SALOME::SALOME_Exception); + virtual SALOMEDS::Study_ptr Open(const wchar_t* aStudyUrl) throw (SALOME::SALOME_Exception); //! method to close a Study -- 2.39.2