Salome HOME
Merge from BR_plugins_pbyacs 03/04/2013
[modules/smesh.git] / src / SMESH_I / SMESH_DumpPython.cxx
1 // Copyright (C) 2007-2013  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22 //  File    : SMESH_DumpPython.cxx
23 //  Created : Thu Mar 24 17:17:59 2005
24 //  Author  : Julia DOROVSKIKH
25 //  Module  : SMESH
26
27 #include "SMESH_PythonDump.hxx"
28
29 #include "SMESH_2smeshpy.hxx"
30 #include "SMESH_Comment.hxx"
31 #include "SMESH_Filter_i.hxx"
32 #include "SMESH_Gen_i.hxx"
33 #include "SMESH_MeshEditor_i.hxx"
34
35 #include <SALOMEDS_wrap.hxx>
36
37 #include <TColStd_HSequenceOfInteger.hxx>
38 #include <TCollection_AsciiString.hxx>
39
40 #ifdef _DEBUG_
41 static int MYDEBUG = 0;
42 #else
43 static int MYDEBUG = 0;
44 #endif
45
46 namespace SMESH
47 {
48
49   size_t TPythonDump::myCounter = 0;
50   const char theNotPublishedObjectName[] = "__NOT__Published__Object__";
51
52   TVar::TVar(CORBA::Double value):myVals(1) { myVals[0] = SMESH_Comment(value); }
53   TVar::TVar(CORBA::Long   value):myVals(1) { myVals[0] = SMESH_Comment(value); }
54   TVar::TVar(CORBA::Short  value):myVals(1) { myVals[0] = SMESH_Comment(value); }
55   TVar::TVar(const SMESH::double_array& value):myVals(value.length())
56   {
57     for ( size_t i = 0; i < value.length(); i++)
58       myVals[i] = SMESH_Comment(value[i]);
59   }
60
61   TPythonDump::
62   TPythonDump():myVarsCounter(0)
63   {
64     ++myCounter;
65   }
66   TPythonDump::
67   ~TPythonDump()
68   {
69     if(--myCounter == 0){
70       SMESH_Gen_i* aSMESHGen = SMESH_Gen_i::GetSMESHGen();
71       std::string aString = myStream.str();
72       TCollection_AsciiString aCollection(Standard_CString(aString.c_str()));
73       SALOMEDS::Study_var aStudy = aSMESHGen->GetCurrentStudy();
74       if(!aStudy->_is_nil() && !aCollection.IsEmpty())
75       {
76         const std::string & objEntry = SMESH_Gen_i::GetSMESHGen()->GetLastObjEntry();
77         if ( !objEntry.empty() )
78           aCollection += (TVar::ObjPrefix() + objEntry ).c_str();
79         aSMESHGen->AddToPythonScript(aStudy->StudyId(),aCollection);
80         if(MYDEBUG) MESSAGE(aString);
81         // prevent misuse of already treated variables
82         aSMESHGen->UpdateParameters(CORBA::Object_var().in(),"");
83       }
84     }
85   }
86
87   TPythonDump& //!< store a variable value. Write either a value or '$varID$'
88   TPythonDump::
89   operator<<(const TVar& theVarValue)
90   {
91     const std::vector< int >& varIDs = SMESH_Gen_i::GetSMESHGen()->GetLastParamIndices();
92     if ( theVarValue.myVals.size() != 1 )
93     {
94       myStream << "[ ";
95       for ( size_t i = 1; i <= theVarValue.myVals.size(); ++i )
96       {
97         if ( myVarsCounter < varIDs.size() && varIDs[ myVarsCounter ] >= 0 )
98           myStream << TVar::Quote() << varIDs[ myVarsCounter ] << TVar::Quote();
99         else
100           myStream << theVarValue.myVals[i-1];
101         if ( i < theVarValue.myVals.size() )
102           myStream << ", ";
103         ++myVarsCounter;
104       }
105       myStream << " ]";
106     }
107     else
108     {
109       if ( myVarsCounter < varIDs.size() && varIDs[ myVarsCounter ] >= 0 )
110         myStream << TVar::Quote() << varIDs[ myVarsCounter ] << TVar::Quote();
111       else
112         myStream << theVarValue.myVals[0];
113       ++myVarsCounter;
114     }
115     return *this;
116   }
117
118   TPythonDump&
119   TPythonDump::
120   operator<<(long int theArg){
121     myStream<<theArg;
122     return *this;
123   }
124
125   TPythonDump&
126   TPythonDump::
127   operator<<(int theArg){
128     myStream<<theArg;
129     return *this;
130   }
131
132   TPythonDump&
133   TPythonDump::
134   operator<<(double theArg){
135     myStream<<theArg;
136     return *this;
137   }
138
139   TPythonDump&
140   TPythonDump::
141   operator<<(float theArg){
142     myStream<<theArg;
143     return *this;
144   }
145
146   TPythonDump&
147   TPythonDump::
148   operator<<(const void* theArg){
149     myStream<<theArg;
150     return *this;
151   }
152
153   TPythonDump&
154   TPythonDump::
155   operator<<(const char* theArg){
156     if ( theArg )
157       myStream<<theArg;
158     return *this;
159   }
160
161   TPythonDump&
162   TPythonDump::
163   operator<<(const SMESH::ElementType& theArg)
164   {
165     myStream<<"SMESH.";
166     switch(theArg){
167     case ALL:    myStream<<"ALL";    break;
168     case NODE:   myStream<<"NODE";   break;
169     case EDGE:   myStream<<"EDGE";   break;
170     case FACE:   myStream<<"FACE";   break;
171     case VOLUME: myStream<<"VOLUME"; break;
172     case ELEM0D: myStream<<"ELEM0D"; break;
173     case BALL:   myStream<<"BALL";   break;
174     default:     myStream<<"__UNKNOWN__ElementType: " << theArg;
175     }
176     return *this;
177   }
178
179   TPythonDump&
180   TPythonDump::
181   operator<<(const SMESH::GeometryType& theArg)
182   {
183     myStream<<"SMESH.";
184     switch(theArg){
185     case Geom_POINT:      myStream<<"Geom_POINT";      break;
186     case Geom_EDGE:       myStream<<"Geom_EDGE";       break;
187     case Geom_TRIANGLE:   myStream<<"Geom_TRIANGLE";   break;
188     case Geom_QUADRANGLE: myStream<<"Geom_QUADRANGLE"; break;
189     case Geom_POLYGON:    myStream<<"Geom_POLYGON";    break;
190     case Geom_TETRA:      myStream<<"Geom_TETRA";      break;
191     case Geom_PYRAMID:    myStream<<"Geom_PYRAMID";    break;
192     case Geom_HEXA:       myStream<<"Geom_HEXA";       break;
193     case Geom_PENTA:      myStream<<"Geom_PENTA";      break;
194     case Geom_POLYHEDRA:  myStream<<"Geom_POLYHEDRA";  break;
195     case Geom_BALL:       myStream<<"Geom_BALL";       break;
196     default:    myStream<<"__UNKNOWN__GeometryType: " << theArg;
197     }
198     return *this;
199   }
200   TPythonDump&
201   TPythonDump::
202   operator<<(const SMESH::EntityType& theArg)
203   {
204     myStream<<"SMESH.";
205     switch(theArg){
206     case Entity_0D:                myStream<<"Entity_0D";                break;
207     case Entity_Edge:              myStream<<"Entity_Edge";              break;
208     case Entity_Quad_Edge:         myStream<<"Entity_Quad_Edge";         break;
209     case Entity_Triangle:          myStream<<"Entity_Triangle";          break;
210     case Entity_Quad_Triangle:     myStream<<"Entity_Quad_Triangle";     break;
211     case Entity_Quadrangle:        myStream<<"Entity_Quadrangle";        break;
212     case Entity_Quad_Quadrangle:   myStream<<"Entity_Quad_Quadrangle";   break;
213     case Entity_BiQuad_Quadrangle: myStream<<"Entity_BiQuad_Quadrangle"; break;
214     case Entity_Polygon:           myStream<<"Entity_Polygon";           break;
215     case Entity_Quad_Polygon:      myStream<<"Entity_Quad_Polygon";      break;
216     case Entity_Tetra:             myStream<<"Entity_Tetra";             break;
217     case Entity_Quad_Tetra:        myStream<<"Entity_Quad_Tetra";        break;
218     case Entity_Pyramid:           myStream<<"Entity_Pyramid";           break;
219     case Entity_Quad_Pyramid:      myStream<<"Entity_Quad_Pyramid";      break;
220     case Entity_Hexa:              myStream<<"Entity_Hexa";              break;
221     case Entity_Quad_Hexa:         myStream<<"Entity_Quad_Hexa";         break;
222     case Entity_TriQuad_Hexa:      myStream<<"Entity_TriQuad_Hexa";      break;
223     case Entity_Penta:             myStream<<"Entity_Penta";             break;
224     case Entity_Quad_Penta:        myStream<<"Entity_Quad_Penta";        break;
225     case Entity_Hexagonal_Prism:   myStream<<"Entity_Hexagonal_Prism";   break;
226     case Entity_Polyhedra:         myStream<<"Entity_Polyhedra";         break;
227     case Entity_Quad_Polyhedra:    myStream<<"Entity_Quad_Polyhedra";    break;
228     case Entity_Ball:              myStream<<"Entity_Ball";              break;
229     case Entity_Last:              myStream<<"Entity_Last";              break;
230     default:    myStream<<"__UNKNOWN__EntityType: " << theArg;
231     }
232     return *this;
233   }
234
235   template<class TArray>
236   void DumpArray(const TArray& theArray, TPythonDump & theStream)
237   {
238     theStream << "[ ";
239     for (int i = 1; i <= theArray.length(); i++) {
240       theStream << theArray[i-1];
241       if ( i < theArray.length() )
242         theStream << ", ";
243     }
244     theStream << " ]";
245   }
246
247   TPythonDump&
248   TPythonDump::operator<<(const SMESH::long_array& theArg)
249   {
250     DumpArray( theArg, *this );
251     return *this;
252   }
253
254   TPythonDump&
255   TPythonDump::operator<<(const SMESH::double_array& theArg)
256   {
257     DumpArray( theArg, *this );
258     return *this;
259   }
260
261   TPythonDump&
262   TPythonDump::operator<<(const SMESH::string_array& theArray)
263   {
264     myStream << "[ ";
265     for (int i = 1; i <= theArray.length(); i++) {
266       myStream << "'" << theArray[i-1] << "'";
267       if ( i < theArray.length() )
268         myStream << ", ";
269     }
270     myStream << " ]";
271     return *this;
272   }
273
274   TPythonDump&
275   TPythonDump::
276   operator<<(SALOMEDS::SObject_ptr aSObject)
277   {
278     if ( !aSObject->_is_nil() ) {
279       CORBA::String_var entry = aSObject->GetID();
280       myStream << entry.in();
281     }
282     else {
283       myStream << theNotPublishedObjectName;
284     }
285     return *this;
286   }
287
288   TPythonDump&
289   TPythonDump::
290   operator<<(CORBA::Object_ptr theArg)
291   {
292     SMESH_Gen_i*          aSMESHGen = SMESH_Gen_i::GetSMESHGen();
293     SALOMEDS::Study_var      aStudy = aSMESHGen->GetCurrentStudy();
294     SALOMEDS::SObject_wrap aSObject = SMESH_Gen_i::ObjectToSObject(aStudy,theArg);
295     if(!aSObject->_is_nil()) {
296       CORBA::String_var id = aSObject->GetID();
297       myStream << id;
298     } else if ( !CORBA::is_nil(theArg)) {
299       if ( aSMESHGen->CanPublishInStudy( theArg )) // not published SMESH object
300         myStream << "smeshObj_" << size_t(theArg);
301       else
302         myStream << theNotPublishedObjectName;
303     }
304     else
305       myStream << "None";
306     return *this;
307   }
308
309   TPythonDump&
310   TPythonDump::
311   operator<<(SMESH::SMESH_Hypothesis_ptr theArg)
312   {
313     SALOMEDS::Study_var     aStudy = SMESH_Gen_i::GetSMESHGen()->GetCurrentStudy();
314     SALOMEDS::SObject_wrap aSObject = SMESH_Gen_i::ObjectToSObject(aStudy,theArg);
315     if(aSObject->_is_nil() && !CORBA::is_nil(theArg))
316       myStream << "hyp_" << theArg->GetId();
317     else
318       *this << aSObject;
319     return *this;
320   }
321
322   TPythonDump&
323   TPythonDump::
324   operator<<(SMESH::SMESH_IDSource_ptr theArg)
325   {
326     if ( CORBA::is_nil( theArg ) )
327       return *this << "None";
328     SMESH_Gen_i*          aSMESHGen = SMESH_Gen_i::GetSMESHGen();
329     SALOMEDS::Study_var      aStudy = aSMESHGen->GetCurrentStudy();
330     SALOMEDS::SObject_wrap aSObject = SMESH_Gen_i::ObjectToSObject(aStudy,theArg);
331     if(!aSObject->_is_nil())
332     {
333       return *this << aSObject;
334     }
335     if ( SMESH::Filter_i* filter = SMESH::DownCast<SMESH::Filter_i*>( theArg ))
336     {
337       return *this << filter;
338     }
339     if ( SMESH_MeshEditor_i::IsTemporaryIDSource( theArg ))
340     {
341       SMESH::SMESH_Mesh_var            mesh = theArg->GetMesh();
342       SMESH::long_array_var    anElementsId = theArg->GetIDs();
343       SMESH::array_of_ElementType_var types = theArg->GetTypes();
344       SMESH::ElementType type = types->length() ? types[0] : SMESH::ALL;
345       return *this << mesh << ".GetIDSource(" << anElementsId << ", " << type << ")";
346     }
347     return *this << theNotPublishedObjectName;
348   }
349
350   TPythonDump&
351   TPythonDump::
352   operator<<(SMESH::FilterLibrary_i* theArg)
353   {
354     myStream<<"aFilterLibrary"<<theArg;
355     return *this;
356   }
357
358   TPythonDump&
359   TPythonDump::
360   operator<<(SMESH::FilterManager_i* theArg)
361   {
362     myStream<<"aFilterManager";
363     return *this;
364   }
365
366   TPythonDump&
367   TPythonDump::
368   operator<<(SMESH::Filter_i* theArg)
369   {
370     myStream<<"aFilter"<<theArg;
371     return *this;
372   }
373
374   TPythonDump&
375   TPythonDump::
376   operator<<(SMESH::Functor_i* theArg)
377   {
378     if ( theArg ) {
379       FunctorType aFunctorType = theArg->GetFunctorType();
380       switch(aFunctorType){
381       case FT_AspectRatio:           myStream<< "anAspectRatio";          break;
382       case FT_AspectRatio3D:         myStream<< "anAspectRatio3D";        break;
383       case FT_Warping:               myStream<< "aWarping";               break;
384       case FT_MinimumAngle:          myStream<< "aMinimumAngle";          break;
385       case FT_Taper:                 myStream<< "aTaper";                 break;
386       case FT_Skew:                  myStream<< "aSkew";                  break;
387       case FT_Area:                  myStream<< "aArea";                  break;
388       case FT_Volume3D:              myStream<< "aVolume3D";              break;
389       case FT_MaxElementLength2D:    myStream<< "aMaxElementLength2D";    break;
390       case FT_MaxElementLength3D:    myStream<< "aMaxElementLength3D";    break;
391       case FT_FreeBorders:           myStream<< "aFreeBorders";           break;
392       case FT_FreeEdges:             myStream<< "aFreeEdges";             break;
393       case FT_FreeNodes:             myStream<< "aFreeNodes";             break;
394       case FT_FreeFaces:             myStream<< "aFreeFaces";             break;
395       case FT_MultiConnection:       myStream<< "aMultiConnection";       break;
396       case FT_MultiConnection2D:     myStream<< "aMultiConnection2D";     break;
397       case FT_Length:                myStream<< "aLength";                break;
398       case FT_Length2D:              myStream<< "aLength2D";              break;
399       case FT_BelongToGeom:          myStream<< "aBelongToGeom";          break;
400       case FT_BelongToPlane:         myStream<< "aBelongToPlane";         break;
401       case FT_BelongToCylinder:      myStream<< "aBelongToCylinder";      break;
402       case FT_BelongToGenSurface:    myStream<< "aBelongToGenSurface";    break;
403       case FT_LyingOnGeom:           myStream<< "aLyingOnGeom";           break;
404       case FT_CoplanarFaces:         myStream<< "aCoplanarFaces";         break;
405       case FT_RangeOfIds:            myStream<< "aRangeOfIds";            break;
406       case FT_BadOrientedVolume:     myStream<< "aBadOrientedVolume";     break;
407       case FT_BareBorderVolume:      myStream<< "aBareBorderVolume";      break;
408       case FT_BareBorderFace:        myStream<< "aBareBorderFace";        break;
409       case FT_OverConstrainedVolume: myStream<< "aOverConstrainedVolume"; break;
410       case FT_OverConstrainedFace:   myStream<< "aOverConstrainedFace";   break;
411       case FT_LinearOrQuadratic:     myStream<< "aLinearOrQuadratic";     break;
412       case FT_GroupColor:            myStream<< "aGroupColor";            break;
413       case FT_ElemGeomType:          myStream<< "anElemGeomType";         break;
414       case FT_LessThan:              myStream<< "aLessThan";              break;
415       case FT_MoreThan:              myStream<< "aMoreThan";              break;
416       case FT_EqualTo:               myStream<< "anEqualTo";              break;
417       case FT_LogicalNOT:            myStream<< "aLogicalNOT";            break;
418       case FT_LogicalAND:            myStream<< "aLogicalAND";            break;
419       case FT_LogicalOR:             myStream<< "aLogicalOR";             break;
420       case FT_Undefined:
421       default:                       myStream<< "anUndefined";            break;
422       }
423       myStream<<theArg;
424     }
425     return *this;
426   }
427
428   TPythonDump&
429   TPythonDump::
430   operator<<(SMESH::Measurements_i* theArg)
431   {
432     myStream<<"aMeasurements";
433     return *this;
434   }
435
436
437   TPythonDump& TPythonDump:: operator<<(SMESH_Gen_i* theArg)
438   {
439     myStream << SMESHGenName(); return *this;
440   }
441
442   TPythonDump& TPythonDump::operator<<(SMESH_MeshEditor_i* theArg)
443   {
444     myStream << MeshEditorName() << "_" << ( theArg ? theArg->GetMeshId() : -1 ); return *this;
445   }
446
447   TPythonDump& TPythonDump::operator<<(const TCollection_AsciiString & theStr)
448   {
449     myStream << theStr; return *this;
450   }
451
452
453   TPythonDump& TPythonDump::operator<<(SMESH::MED_VERSION theVersion)
454   {
455     switch (theVersion) {
456     case SMESH::MED_V2_1: myStream << "SMESH.MED_V2_1"; break;
457     case SMESH::MED_V2_2: myStream << "SMESH.MED_V2_2"; break;
458     default: myStream << theVersion;
459     }
460     return *this;
461   }
462
463   TPythonDump& TPythonDump::operator<<(const SMESH::AxisStruct & theAxis)
464   {
465     *this << "SMESH.AxisStruct( "
466           << TVar( theAxis.x  ) << ", "
467           << TVar( theAxis.y  ) << ", "
468           << TVar( theAxis.z  ) << ", "
469           << TVar( theAxis.vx ) << ", "
470           << TVar( theAxis.vy ) << ", "
471           << TVar( theAxis.vz ) << " )";
472     return *this;
473   }
474
475   TPythonDump& TPythonDump::operator<<(const SMESH::DirStruct & theDir)
476   {
477     const SMESH::PointStruct & P = theDir.PS;
478     *this << "SMESH.DirStruct( SMESH.PointStruct ( "
479           << TVar( P.x ) << ", "
480           << TVar( P.y ) << ", "
481           << TVar( P.z ) << " ))";
482     return *this;
483   }
484
485   TPythonDump& TPythonDump::operator<<(const SMESH::PointStruct & P)
486   {
487     *this << "SMESH.PointStruct ( "
488           << TVar( P.x ) << ", "
489           << TVar( P.y ) << ", "
490           << TVar( P.z ) << " )";
491     return *this;
492   }
493
494   TPythonDump& TPythonDump::operator<<(const SMESH::ListOfGroups& theList)
495   {
496     DumpArray( theList, *this );
497     return *this;
498   }
499   TPythonDump& TPythonDump::operator<<(const SMESH::ListOfGroups * theList)
500   {
501     DumpArray( *theList, *this );
502     return *this;
503   }
504   TPythonDump& TPythonDump::operator<<(const SMESH::ListOfIDSources& theList)
505   {
506     DumpArray( theList, *this );
507     return *this;
508   }
509   const char* TPythonDump::NotPublishedObjectName()
510   {
511     return theNotPublishedObjectName;
512   }
513
514   TCollection_AsciiString myLongStringStart( "TPythonDump::LongStringStart" );
515   TCollection_AsciiString myLongStringEnd  ( "TPythonDump::LongStringEnd" );
516
517   //================================================================================
518   /*!
519    * \brief Return marker of long string literal beginning
520    * \param type - a name of functionality producing the string literal
521    * \retval TCollection_AsciiString - the marker string to be written into
522    * a raw python script
523    */
524   //================================================================================
525
526   TCollection_AsciiString TPythonDump::LongStringStart(const char* type)
527   {
528     return
529       myLongStringStart +
530       (Standard_Integer) strlen(type) +
531       " " +
532       (char*) type;
533   }
534
535   //================================================================================
536   /*!
537      * \brief Return marker of long string literal end
538       * \retval TCollection_AsciiString - the marker string to be written into
539       * a raw python script
540    */
541   //================================================================================
542
543   TCollection_AsciiString TPythonDump::LongStringEnd()
544   {
545     return myLongStringEnd;
546   }
547
548   //================================================================================
549   /*!
550      * \brief Cut out a long string literal from a string
551       * \param theText - text possibly containing string literals
552       * \param theFrom - position in the text to search from
553       * \param theLongString - the retrieved literal
554       * \param theStringType - a name of functionality produced the literal
555       * \retval bool - true if a string literal found
556      *
557      * The literal is removed from theText; theFrom points position right after
558      * the removed literal
559    */
560   //================================================================================
561
562   bool  TPythonDump::CutoutLongString( TCollection_AsciiString & theText,
563                                        int                     & theFrom,
564                                        TCollection_AsciiString & theLongString,
565                                        TCollection_AsciiString & theStringType)
566   {
567     if ( theFrom < 1 || theFrom > theText.Length() )
568       return false;
569
570     // ...script \  beg marker    \ \ type \       literal              \  end marker  \ script...
571     //  "theText myLongStringStart7 Pattern!!! SALOME Mesh Pattern file myLongStringEndtextEnd"
572     //  012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
573     //  0         1         2         3         4         5         6         7         8
574
575     theFrom = theText.Location( myLongStringStart, theFrom, theText.Length() ); // = 09
576     if ( !theFrom )
577       return false;
578
579     // find where literal begins
580     int literalBeg = theFrom + myLongStringStart.Length(); // = 26
581     char* typeLenStr = (char*) theText.ToCString() + literalBeg - 1; // = "7 Pattern!!! SALO...."
582     int typeLen = atoi ( typeLenStr ); // = 7
583     while ( *typeLenStr != ' ' ) { // look for ' ' after typeLen
584       literalBeg++; // 26 -> 27
585       typeLenStr++;
586     }
587     literalBeg += typeLen + 1; // = 35
588     if ( literalBeg > theText.Length() )
589       return false;
590
591     // where literal ends (i.e. end marker begins)
592     int literalEnd = theText.Location( myLongStringEnd, literalBeg, theText.Length() ); // = 64
593     if ( !literalEnd )
594       literalEnd = theText.Length();
595
596     // literal
597     theLongString = theText.SubString( literalBeg, literalEnd - 1); // "!!! SALOME Mesh Pattern file "
598     // type
599     theStringType = theText.SubString( literalBeg - typeLen, literalBeg - 1 ); // "Pattern"
600     // cut off literal
601     literalEnd += myLongStringEnd.Length(); // = 79
602     TCollection_AsciiString textEnd = theText.SubString( literalEnd, theText.Length() ); // "textE..."
603     theText = theText.SubString( 1, theFrom - 1 ) + textEnd;
604
605     return true;
606   }
607 }
608
609 //=======================================================================
610 //function : RemoveTabulation
611 //purpose  : 
612 //=======================================================================
613 void RemoveTabulation( TCollection_AsciiString& theScript )
614 {
615   std::string aString( theScript.ToCString() );
616   std::string::size_type aPos = 0;
617   while( aPos < aString.length() )
618   {
619     aPos = aString.find( "\n\t", aPos );
620     if( aPos == std::string::npos )
621       break;
622     aString.replace( aPos, 2, "\n" );
623     aPos++;
624   }
625   theScript = aString.c_str();
626 }
627
628 //=======================================================================
629 //function : DumpPython
630 //purpose  :
631 //=======================================================================
632 Engines::TMPFile* SMESH_Gen_i::DumpPython (CORBA::Object_ptr theStudy,
633                                            CORBA::Boolean isPublished,
634                                            CORBA::Boolean isMultiFile,
635                                            CORBA::Boolean& isValidScript)
636 {
637   SALOMEDS::Study_var aStudy = SALOMEDS::Study::_narrow(theStudy);
638   if (CORBA::is_nil(aStudy))
639     return new Engines::TMPFile(0);
640
641   CORBA::String_var compDataType = ComponentDataType();
642   SALOMEDS::SObject_wrap aSO = aStudy->FindComponent( compDataType.in() );
643   if (CORBA::is_nil(aSO))
644     return new Engines::TMPFile(0);
645
646   // Map study entries to object names
647   Resource_DataMapOfAsciiStringAsciiString aMap;
648   Resource_DataMapOfAsciiStringAsciiString aMapNames;
649   //TCollection_AsciiString s ("qwertyuioplkjhgfdsazxcvbnmQWERTYUIOPLKJHGFDSAZXCVBNM0987654321_");
650
651   SALOMEDS::ChildIterator_wrap Itr = aStudy->NewChildIterator(aSO);
652   for (Itr->InitEx(true); Itr->More(); Itr->Next()) {
653     SALOMEDS::SObject_wrap aValue = Itr->Value();
654     CORBA::String_var anID = aValue->GetID();
655     CORBA::String_var aName = aValue->GetName();
656     TCollection_AsciiString aGUIName ( (char*) aName.in() );
657     TCollection_AsciiString anEnrty ( (char*) anID.in() );
658     if (aGUIName.Length() > 0) {
659       aMapNames.Bind( anEnrty, aGUIName );
660       aMap.Bind( anEnrty, aGUIName );
661     }
662   }
663
664   // Get trace of restored study
665   SALOMEDS::StudyBuilder_var aStudyBuilder = aStudy->NewBuilder();
666   SALOMEDS::GenericAttribute_wrap anAttr =
667     aStudyBuilder->FindOrCreateAttribute(aSO, "AttributePythonObject");
668
669   SALOMEDS::AttributePythonObject_var pyAttr =
670     SALOMEDS::AttributePythonObject::_narrow(anAttr);
671   CORBA::String_var oldValue = pyAttr->GetObject();
672   TCollection_AsciiString aSavedTrace (oldValue.in());
673
674   // Add trace of API methods calls and replace study entries by names
675   TCollection_AsciiString aScript;
676   aScript += DumpPython_impl(aStudy, aMap, aMapNames, isPublished, isMultiFile,
677                              myIsHistoricalPythonDump, isValidScript, aSavedTrace);
678
679   int aLen = aScript.Length();
680   unsigned char* aBuffer = new unsigned char[aLen+1];
681   strcpy((char*)aBuffer, aScript.ToCString());
682
683   CORBA::Octet* anOctetBuf =  (CORBA::Octet*)aBuffer;
684   Engines::TMPFile_var aStreamFile = new Engines::TMPFile(aLen+1, aLen+1, anOctetBuf, 1);
685
686   bool hasNotPublishedObjects = aScript.Location( SMESH::theNotPublishedObjectName, 1, aLen);
687   isValidScript = isValidScript && !hasNotPublishedObjects;
688
689   return aStreamFile._retn();
690 }
691
692 //=============================================================================
693 /*!
694  *  AddToPythonScript
695  */
696 //=============================================================================
697 void SMESH_Gen_i::AddToPythonScript (int theStudyID, const TCollection_AsciiString& theString)
698 {
699   if (myPythonScripts.find(theStudyID) == myPythonScripts.end()) {
700     myPythonScripts[theStudyID] = new TColStd_HSequenceOfAsciiString;
701   }
702   myPythonScripts[theStudyID]->Append(theString);
703 }
704
705 //=============================================================================
706 /*!
707  *  RemoveLastFromPythonScript
708  */
709 //=============================================================================
710 void SMESH_Gen_i::RemoveLastFromPythonScript (int theStudyID)
711 {
712   if (myPythonScripts.find(theStudyID) != myPythonScripts.end()) {
713     int aLen = myPythonScripts[theStudyID]->Length();
714     myPythonScripts[theStudyID]->Remove(aLen);
715   }
716 }
717
718 //=======================================================================
719 //function : SavePython
720 //purpose  :
721 //=======================================================================
722 void SMESH_Gen_i::SavePython (SALOMEDS::Study_ptr theStudy)
723 {
724   // Dump trace of API methods calls
725   TCollection_AsciiString aScript = GetNewPythonLines(theStudy->StudyId());
726
727   // Check contents of PythonObject attribute
728   CORBA::String_var compDataType = ComponentDataType();
729   SALOMEDS::SObject_wrap aSO = theStudy->FindComponent( compDataType.in() );
730   SALOMEDS::StudyBuilder_var aStudyBuilder = theStudy->NewBuilder();
731   SALOMEDS::GenericAttribute_wrap anAttr =
732     aStudyBuilder->FindOrCreateAttribute(aSO, "AttributePythonObject");
733
734   SALOMEDS::AttributePythonObject_var pyAttr =
735     SALOMEDS::AttributePythonObject::_narrow(anAttr);
736   CORBA::String_var oldValue = pyAttr->GetObject();
737   TCollection_AsciiString oldScript (oldValue.in());
738
739   if (oldScript.Length() > 0) {
740     oldScript += "\n";
741     oldScript += aScript;
742   } else {
743     oldScript = aScript;
744   }
745
746   // Store in PythonObject attribute
747   pyAttr->SetObject(oldScript.ToCString(), 1);
748
749   // Clean trace of API methods calls
750   CleanPythonTrace(theStudy->StudyId());
751 }
752
753
754 // impl
755
756
757 //=============================================================================
758 /*!
759  *  FindEntries: Returns a sequence of start/end positions of entries in the string
760  */
761 //=============================================================================
762 Handle(TColStd_HSequenceOfInteger) FindEntries (TCollection_AsciiString& theString)
763 {
764   Handle(TColStd_HSequenceOfInteger) aSeq = new TColStd_HSequenceOfInteger;
765   Standard_Integer aLen = theString.Length();
766   Standard_Boolean isFound = Standard_False;
767
768   char* arr = (char*) theString.ToCString();
769   Standard_Integer i = 0, j;
770
771   while(i < aLen) {
772     int c = (int)arr[i];
773     j = i+1;
774     if ( isdigit( c )) { //Is digit?
775
776       isFound = Standard_False;
777       while((j < aLen) && ( isdigit(c) || c == ':' )) { //Check if it is an entry
778         c = (int)arr[j++];
779         if(c == ':') isFound = Standard_True;
780       }
781
782       if (isFound) {
783         int prev = (i < 1) ? 0 : (int)arr[i - 1];
784         // to distinguish from a sketcher command:
785         // last char should be a digit, not ":",
786         // previous char should not be '"'.
787         if (arr[j-2] != ':' && prev != '"') {
788           aSeq->Append(i+1); // +1 because AsciiString starts from 1
789           aSeq->Append(j-1);
790         }
791       }
792     }
793
794     i = j;
795   }
796
797   return aSeq;
798 }
799
800 namespace {
801
802   //================================================================================
803   /*!
804    * \brief Make a string be a valid python name
805     * \param aName - a string to fix
806     * \retval bool - true if aName was not modified
807    */
808   //================================================================================
809
810   bool fixPythonName(TCollection_AsciiString & aName )
811   {
812     const TCollection_AsciiString allowedChars =
813       "qwertyuioplkjhgfdsazxcvbnmQWERTYUIOPLKJHGFDSAZXCVBNM0987654321_";
814     bool isValidName = true;
815     int nbUnderscore = 0;
816     int p=1; // replace not allowed chars by underscore
817     while (p <= aName.Length() &&
818            (p = aName.FirstLocationNotInSet(allowedChars, p, aName.Length())))
819     {
820       if ( p == 1 || p == aName.Length() || aName.Value(p-1) == '_')
821         aName.Remove( p, 1 ); // remove double _ from the start and the end
822       else
823         aName.SetValue(p, '_'), nbUnderscore++;
824       isValidName = false;
825     }
826     if ( aName.IsIntegerValue() ) { // aName must not start with a digit
827       aName.Insert( 1, 'a' );
828       isValidName = false;
829     }
830     // shorten names like CartesianParameters3D_400_400_400_1000000_1
831     const int nbAllowedUnderscore = 3; /* changed from 2 to 3 by an user request
832                                           posted to SALOME Forum */
833     if ( aName.Length() > 20 && nbUnderscore > nbAllowedUnderscore )
834     {
835       p = aName.Location( "_", 20, aName.Length());
836       if ( p > 1 )
837         aName.Trunc( p-1 );
838     }
839     return isValidName;
840   }
841 }
842
843 //=============================================================================
844 /*!
845  *  DumpPython
846  */
847 //=============================================================================
848 TCollection_AsciiString SMESH_Gen_i::DumpPython_impl
849                         (SALOMEDS::Study_ptr                       theStudy,
850                          Resource_DataMapOfAsciiStringAsciiString& theObjectNames,
851                          Resource_DataMapOfAsciiStringAsciiString& theNames,
852                          bool                                      isPublished,
853                          bool                                      isMultiFile,
854                          bool                                      isHistoricalDump,
855                          bool&                                     aValidScript,
856                          const TCollection_AsciiString&            theSavedTrace)
857 {
858   int aStudyID = theStudy->StudyId();
859
860   TCollection_AsciiString helper; // to comfortably concatenate C strings
861   TCollection_AsciiString aSmeshpy( SMESH_2smeshpy::SmeshpyName() );
862   TCollection_AsciiString aSMESHGen( SMESH_2smeshpy::GenName() );
863   TCollection_AsciiString anOldGen( SMESH::TPythonDump::SMESHGenName() );
864
865   TCollection_AsciiString aScript;
866   if( isMultiFile )
867     aScript += "def RebuildData(theStudy):";
868   aScript += "\n\t";
869   aScript += helper + "aFilterManager = " + aSMESHGen + ".CreateFilterManager()\n\t";
870   aScript += helper + "aMeasurements = " + aSMESHGen + ".CreateMeasurements()\n\t";
871   if ( isPublished )
872     aScript += aSMESHGen + " = smeshBuilder.New(theStudy)";
873   else
874     aScript += aSMESHGen + " = smeshBuilder.New(None)";
875
876   // import python files corresponding to plugins
877   set<string> moduleNameSet;
878   map<string, GenericHypothesisCreator_i*>::iterator hyp_creator = myHypCreatorMap.begin();
879   for ( ; hyp_creator != myHypCreatorMap.end(); ++hyp_creator ) {
880     string moduleName = hyp_creator->second->GetModuleName();
881     bool newModule = moduleNameSet.insert( moduleName ).second;
882     if ( newModule )
883       aScript += helper + "\n\t" + "from salome." + (char*) moduleName.c_str() + " import " + (char*) moduleName.c_str() +"Builder";
884   }
885
886   // Dump trace of restored study
887   if (theSavedTrace.Length() > 0) {
888     // For the convertion of IDL API calls -> smeshBuilder.py API, "smesh" standing for SMESH_Gen
889     // was replaces with "smeshgen" (==TPythonDump::SMESHGenName()).
890     // Change "smesh" -> "smeshgen" in the trace saved before passage to smeshBuilder.py API
891     bool isNewVersion =
892       theSavedTrace.Location( anOldGen + ".", 1, theSavedTrace.Length() );
893     if ( !isNewVersion ) {
894       TCollection_AsciiString aSavedTrace( theSavedTrace );
895       TCollection_AsciiString aSmeshCall ( "smesh." ), gen( "gen" );
896       int beg, end = aSavedTrace.Length(), from = 1;
897       while ( from < end && ( beg = aSavedTrace.Location( aSmeshCall, from, end ))) {
898         char charBefore = ( beg == 1 ) ? ' ' : aSavedTrace.Value( beg - 1 );
899         if ( isspace( charBefore ) || charBefore == '=' ) { // "smesh." is not a part of a long word
900           aSavedTrace.Insert( beg + aSmeshCall.Length() - 1, gen );// "smesh" -> "smeshgen"
901           end += gen.Length();
902         }
903         from = beg + aSmeshCall.Length();
904       }
905       aScript += helper + "\n" + aSavedTrace;
906     }
907     else
908       // append a saved trace to the script
909       aScript += helper + "\n" + theSavedTrace;
910   }
911
912   // Dump trace of API methods calls
913   TCollection_AsciiString aNewLines = GetNewPythonLines(aStudyID);
914   if (aNewLines.Length() > 0) {
915     aScript += helper + "\n" + aNewLines;
916   }
917
918   // Convert IDL API calls into smeshBuilder.py API.
919   // Some objects are wrapped with python classes and
920   // Resource_DataMapOfAsciiStringAsciiString holds methods returning wrapped objects
921   Resource_DataMapOfAsciiStringAsciiString anEntry2AccessorMethod;
922   std::set< TCollection_AsciiString >      aRemovedObjIDs;
923   if ( !getenv("NO_2smeshpy_conversion"))
924     aScript = SMESH_2smeshpy::ConvertScript( aScript, anEntry2AccessorMethod,
925                                              theObjectNames, aRemovedObjIDs,
926                                              theStudy, isHistoricalDump );
927
928   // Replace characters used instead of quote marks to quote notebook variables
929   {
930     int pos = 1;
931     while (( pos = aScript.Location( 1, SMESH::TVar::Quote(), pos, aScript.Length() )))
932       aScript.SetValue( pos, '"' );
933   }
934
935   // Find entries to be replaced by names
936   Handle(TColStd_HSequenceOfInteger) aSeq = FindEntries(aScript);
937   Standard_Integer aLen = aSeq->Length();
938
939   if (aLen == 0 && isMultiFile)
940     return aScript;
941
942   // Replace entries by the names
943   GEOM::GEOM_Gen_ptr geom = GetGeomEngine();
944   TColStd_SequenceOfAsciiString seqRemoved;
945   Resource_DataMapOfAsciiStringAsciiString mapRemoved;
946   Standard_Integer objectCounter = 0, aStart = 1, aScriptLength = aScript.Length();
947   TCollection_AsciiString anUpdatedScript, anEntry, aName, aBaseName("smeshObj_");
948
949   // Collect names of GEOM objects to exclude same names of SMESH objects
950   GEOM::string_array_var aGeomNames = geom->GetAllDumpNames();
951   int ign = 0, nbgn = aGeomNames->length();
952   for (; ign < nbgn; ign++) {
953     aName = aGeomNames[ign];
954     theObjectNames.Bind(aName, "1");
955   }
956
957   bool importGeom = false;
958   for (Standard_Integer i = 1; i <= aLen; i += 2) {
959     anUpdatedScript += aScript.SubString(aStart, aSeq->Value(i) - 1);
960     anEntry = aScript.SubString(aSeq->Value(i), aSeq->Value(i + 1));
961     // is a GEOM object?
962     aName = geom->GetDumpName( anEntry.ToCString() );
963     if (aName.IsEmpty()) {
964       // is a SMESH object
965       if (theObjectNames.IsBound(anEntry)) {
966         // The Object is in Study
967         aName = theObjectNames.Find(anEntry);
968         // check validity of aName
969         bool isValidName = fixPythonName( aName );
970         if (theObjectNames.IsBound(aName) && anEntry != theObjectNames(aName)) {
971           // diff objects have same name - make a new name by appending a digit
972           TCollection_AsciiString aName2;
973           Standard_Integer i = 0;
974           do {
975             aName2 = aName + "_" + ++i;
976           } while (theObjectNames.IsBound(aName2) && anEntry != theObjectNames(aName2));
977           aName = aName2;
978           isValidName = false;
979         }
980         if ( !isValidName )
981           theObjectNames(anEntry) = aName;
982
983       } else {
984         // Removed Object
985         do {
986           aName = aBaseName + (++objectCounter);
987         } while (theObjectNames.IsBound(aName));
988         seqRemoved.Append(aName);
989         mapRemoved.Bind(anEntry, "1");
990         theObjectNames.Bind(anEntry, aName);
991       }
992       theObjectNames.Bind(aName, anEntry); // to detect same name of diff objects
993     }
994     else
995     {
996       importGeom = true;
997     }
998     anUpdatedScript += aName;
999     aStart = aSeq->Value(i + 1) + 1;
1000   }
1001
1002   // set initial part of aSript
1003   TCollection_AsciiString initPart = "import ";
1004   if ( isMultiFile )
1005     initPart += helper + "salome, ";
1006   initPart += " SMESH, SALOMEDS\n";
1007   initPart += "from salome.smesh import smeshBuilder\n";
1008   if ( importGeom && isMultiFile )
1009   {
1010     initPart += ("\n## import GEOM dump file ## \n"
1011                  "import string, os, sys, re\n"
1012                  "sys.path.insert( 0, os.path.dirname(__file__) )\n"
1013                  "exec(\"from \"+re.sub(\"SMESH$\",\"GEOM\",__name__)+\" import *\")\n");
1014   }
1015   anUpdatedScript.Insert ( 1, initPart );
1016
1017   // add final part of aScript
1018   if (aLen && aSeq->Value(aLen) < aScriptLength)
1019     anUpdatedScript += aScript.SubString(aSeq->Value(aLen) + 1, aScriptLength);
1020
1021   // Remove removed objects
1022   if ( seqRemoved.Length() > 0 ) {
1023     anUpdatedScript += "\n\t## some objects were removed";
1024     anUpdatedScript += "\n\taStudyBuilder = theStudy.NewBuilder()";
1025   }
1026   for (int ir = 1; ir <= seqRemoved.Length(); ir++) {
1027     if ( aRemovedObjIDs.count( seqRemoved.Value(ir) )) continue;
1028     anUpdatedScript += "\n\tSO = theStudy.FindObjectIOR(theStudy.ConvertObjectToIOR(";
1029     anUpdatedScript += seqRemoved.Value(ir);
1030     // for object wrapped by class of smeshBuilder.py
1031     anEntry = theObjectNames( seqRemoved.Value(ir) );
1032     if ( anEntry2AccessorMethod.IsBound( anEntry ) )
1033       anUpdatedScript += helper + "." + anEntry2AccessorMethod( anEntry );
1034     anUpdatedScript += "))\n\tif SO is not None: aStudyBuilder.RemoveObjectWithChildren(SO)";
1035   }
1036
1037   // Set object names
1038   anUpdatedScript += "\n\t## set object names";
1039 //   anUpdatedScript += "\n\t\tsmeshgui = salome.ImportComponentGUI(\"SMESH\")";
1040 //   anUpdatedScript += "\n\t\tsmeshgui.Init(theStudy._get_StudyId())";
1041 //   anUpdatedScript += "\n";
1042
1043   TCollection_AsciiString aGUIName;
1044   Resource_DataMapOfAsciiStringAsciiString mapEntries;
1045   for (Standard_Integer i = 1; i <= aLen; i += 2)
1046   {
1047     anEntry = aScript.SubString(aSeq->Value(i), aSeq->Value(i + 1));
1048     aName   = geom->GetDumpName( anEntry.ToCString() );
1049     if (aName.IsEmpty() && // Not a GEOM object
1050         theNames.IsBound(anEntry) &&
1051         !aRemovedObjIDs.count(anEntry) && // a command creating anEntry was erased
1052         !mapEntries.IsBound(anEntry) && // Not yet processed
1053         !mapRemoved.IsBound(anEntry)) // Was not removed
1054     {
1055       aName    = theObjectNames.Find(anEntry);
1056       aGUIName = theNames.Find(anEntry);
1057       mapEntries.Bind(anEntry, aName);
1058       anUpdatedScript += helper + "\n\t" + aSMESHGen + ".SetName(" + aName;
1059       if ( anEntry2AccessorMethod.IsBound( anEntry ) )
1060         anUpdatedScript += helper + "." + anEntry2AccessorMethod( anEntry );
1061       anUpdatedScript += helper + ", '" + aGUIName + "')";
1062     }
1063   }
1064
1065   // Issue 0021249: removed (a similar block is dumped by SALOMEDSImpl_Study)
1066   //anUpdatedScript += "\n\tif salome.sg.hasDesktop():";
1067   //anUpdatedScript += "\n\t\tsalome.sg.updateObjBrowser(0)";
1068
1069   // -----------------------------------------------------------------
1070   // store visual properties of displayed objects
1071   // -----------------------------------------------------------------
1072
1073   if (isPublished)
1074   {
1075     //Output the script that sets up the visual parameters.
1076     CORBA::String_var compDataType = ComponentDataType();
1077     char* script = theStudy->GetDefaultScript( compDataType.in(), "\t");
1078     if (script && strlen(script) > 0) {
1079       anUpdatedScript += "\n\n\t### Store presentation parameters of displayed objects\n";
1080       anUpdatedScript += script;
1081       CORBA::string_free(script);
1082     }
1083   }
1084
1085   if( isMultiFile )
1086     anUpdatedScript += "\n\tpass";
1087   anUpdatedScript += "\n";
1088
1089   if( !isMultiFile ) // remove unnecessary tabulation
1090     RemoveTabulation( anUpdatedScript );
1091
1092   // -----------------------------------------------------------------
1093   // put string literals describing patterns into separate functions
1094   // -----------------------------------------------------------------
1095
1096   TCollection_AsciiString aLongString, aFunctionType;
1097   int where = 1;
1098   set< string > functionNameSet;
1099   while ( SMESH::TPythonDump::CutoutLongString( anUpdatedScript, where, aLongString, aFunctionType ))
1100   {
1101     // make a python string literal
1102     aLongString.Prepend(":\n\treturn '''\n");
1103     aLongString += "\n\t'''\n\tpass\n";
1104
1105     TCollection_AsciiString functionName;
1106
1107     // check if the function returning this literal is already defined
1108     int posAlready = anUpdatedScript.Location( aLongString, where, anUpdatedScript.Length() );
1109     if ( posAlready ) // already defined
1110     {
1111       // find the function name
1112       int functBeg = posAlready;
1113       char* script = (char*) anUpdatedScript.ToCString() + posAlready - 1; // look at ":" after "def fuction()"
1114       while ( *script != ' ' ) {
1115         script--;
1116         functBeg--;
1117       }
1118       functBeg++; // do not take ' '
1119       posAlready--; // do not take ':'
1120       functionName = anUpdatedScript.SubString( functBeg, posAlready );
1121     }
1122     else // not defined yet
1123     {
1124       // find a unique function name
1125       fixPythonName( aFunctionType );
1126       Standard_Integer nb = 0;
1127       do functionName = aFunctionType + "_" + ( nb++ ) + "()";
1128       while ( !functionNameSet.insert( functionName.ToCString() ).second );
1129
1130       // define function
1131       TCollection_AsciiString funDef = helper + "def " + functionName + aLongString;
1132       if ( isMultiFile )
1133       {
1134         anUpdatedScript += helper + "\n\n" + funDef;
1135       }
1136       else
1137       {
1138         funDef += "\n\n";
1139         anUpdatedScript.Insert( 1, funDef);
1140         where += funDef.Length();
1141       }
1142     }
1143     anUpdatedScript.InsertBefore( where, functionName ); // call function
1144   }
1145
1146   aValidScript = true;
1147
1148   return anUpdatedScript;
1149 }
1150
1151 //=============================================================================
1152 /*!
1153  *  GetNewPythonLines
1154  */
1155 //=============================================================================
1156 TCollection_AsciiString SMESH_Gen_i::GetNewPythonLines (int theStudyID)
1157 {
1158   TCollection_AsciiString aScript;
1159
1160   // Dump trace of API methods calls
1161   if (myPythonScripts.find(theStudyID) != myPythonScripts.end()) {
1162     Handle(TColStd_HSequenceOfAsciiString) aPythonScript = myPythonScripts[theStudyID];
1163     Standard_Integer istr, aLen = aPythonScript->Length();
1164     for (istr = 1; istr <= aLen; istr++) {
1165       aScript += "\n\t";
1166       aScript += aPythonScript->Value(istr);
1167     }
1168     aScript += "\n";
1169   }
1170
1171   return aScript;
1172 }
1173
1174 //=============================================================================
1175 /*!
1176  *  CleanPythonTrace
1177  */
1178 //=============================================================================
1179 void SMESH_Gen_i::CleanPythonTrace (int theStudyID)
1180 {
1181   TCollection_AsciiString aScript;
1182
1183   // Clean trace of API methods calls
1184   if (myPythonScripts.find(theStudyID) != myPythonScripts.end()) {
1185     myPythonScripts[theStudyID]->Clear();
1186   }
1187 }