1 # -*- coding: iso-8859-1 -*-
2 # Copyright (C) 2007-2024 CEA, EDF, OPEN CASCADE
4 # Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
5 # CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
7 # This library is free software; you can redistribute it and/or
8 # modify it under the terms of the GNU Lesser General Public
9 # License as published by the Free Software Foundation; either
10 # version 2.1 of the License, or (at your option) any later version.
12 # This library is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 # Lesser General Public License for more details.
17 # You should have received a copy of the GNU Lesser General Public
18 # License along with this library; if not, write to the Free Software
19 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
24 # File : salome.py renamed as __init__.py for python packaging (gboulant)
25 # Author : Paul RASCLE, EDF
29 Module salome gives access to Salome resources.
34 - salome.naming_service : instance of naming Service class
36 - Resolve(name) : find a CORBA object (ior) by its pathname
37 - Register(name) : register a CORBA object under a pathname
39 - salome.lcc : instance of lifeCycleCORBA class
41 - FindOrLoadComponent(server,name) :
42 obtain an Engine (CORBA object)
43 or launch the Engine if not found,
44 with a Server name and an Engine name
46 - salome.sg : salome object to communicate with the graphical user interface (if any)
50 - SelectedCount(): returns number of selected objects
51 - getSelected(i): returns entry of selected object number i
52 - getAllSelected(): returns list of entry of selected objects
53 - AddIObject(Entry): select an existing Interactive object
54 - RemoveIObject(Entry): remove object from selection
55 - ClearIObjects(): clear selection
63 - IDToObject(Entry): returns CORBA reference from entry
65 - salome.myStudyName : active Study Name
66 - salome.myStudy : the active Study itself (CORBA ior)
67 - methods : defined in SALOMEDS.idl
71 # Module salome gives access to Salome resources.
73 # \param salome.orb : CORBA orb object
74 # \param salome.naming_service : instance of naming Service class (SALOME_NamingServicePy::SALOME_NamingServicePy_i)
75 # \param salome.lcc : instance of lifeCycleCORBA class (SALOME_LifeCycleCORBA)
76 # \param salome.sg : Salome object to communicate with the graphical user interface, if running (see interface in salome_iapp::SalomeOutsideGUI)
77 # \param salome.myStudyName : active Study Name
78 # \param salome.myStudy : the active Study (interface SALOMEDS::Study)
81 # ==========================================================================
83 # The function extend_path is used here to aggregate in a single
84 # virtual python package all the python sub-packages embedded in each
85 # SALOME modules (python "namespace" pattern).
87 ROOT_PYTHONPACKAGE_NAME="salome"
89 # This root package name is expected to be found as a directory in
90 # some paths of the sys.path variable, especially the paths
91 # <MODULE_ROOT_DIR>/lib/pythonX.Y/site-packages/salome where are
92 # installed the python files. These paths are theorically appended by
93 # the SALOME main runner and should be in the sys.path at this point
94 # of the application. The extend_path is looking then for directories
97 # <MODULE_ROOT_DIR>/lib/pythonX.Y/site-packages/salome/<ROOT_PYTHONPACKAGE_NAME>
99 # And append them to the sys.path. These directories are supposed to
100 # be the pieces to be aggregated as a single virtual python package.
103 from salome_utils import verbose
105 MATCH_ENDING_PATTERN="site-packages" + os.path.sep + "salome"
107 def extend_path(pname):
109 if not isinstance(dir, str) or not os.path.isdir(dir) or not dir.endswith(MATCH_ENDING_PATTERN):
111 subdir = os.path.join(dir, pname)
112 # XXX This may still add duplicate entries to path on
113 # case-insensitive filesystems
114 if os.path.isdir(subdir) and subdir not in __path__:
115 if verbose(): print("INFO - The directory %s is appended to sys.path" % subdir)
116 __path__.append(subdir)
118 extend_path(ROOT_PYTHONPACKAGE_NAME)
119 # ==========================================================================
122 from salome_kernel import *
123 from salome_study import *
124 from salome_iapp import *
128 # The next block is workaround for the problem of shared symbols loading for the extension modules (e.g. SWIG-generated)
129 # that causes RTTI unavailable in some cases. To solve this problem, sys.setdlopenflags() function is used.
130 # Depending on the Python version and platform, the dlopen flags can be defined in the dl, DLFUN or ctypes module.
136 # dl module can be unavailable
138 flags = dl.RTLD_NOW | dl.RTLD_GLOBAL
144 # DLFCN module can be unavailable
146 flags = DLFCN.RTLD_NOW | DLFCN.RTLD_GLOBAL
152 # ctypes module can be unavailable
154 flags = ctypes.RTLD_GLOBAL
159 # Disable -> bug with scipy, seems very dangerous to do that
161 # sys.setdlopenflags(flags)
164 orb, lcc, naming_service, cm, sg, esm, dsm, logm, modulcat, rm = None,None,None,None,None,None,None,None,None,None
165 myStudy, myStudyName = None,None
174 KernelBasis.setSSLMode(False)
176 def salome_init(path=None, embedded=False, iorfakensfile=None, forced=False):
178 Initialize SALOME client process (that can also be server).
179 3 modes of initialization exists:
180 - SSL mode (see salome_init_without_session)
181 - SSL mode attached in the context of python execution inside SALOME_Container_No_NS_Serv server (typically YACS)
182 - Classical mode (see salome_init_with_session)
183 :param iorfakensfile: filename inside which IOR of fake NS will be written
184 :param forced: tell if the multi-initialization protection mecanism of salome_init must be skiped of not
185 (typically in the context where a path to a study is given whereas a previous initialisation without it was done)
188 if lcc is not None:# multi-initialization protection mecanism is based on lcc global var
190 PATH_TO_STUDY_FILE_TO_INITIATE = "PATH_TO_STUDY_FILE_TO_INITIATE"
192 if KernelBasis.getSSLMode():
193 if KernelBasis.getIOROfEmbeddedNS() == "":
195 # make runSalome.py -t study.hdf toto.py
196 if path is None and PATH_TO_STUDY_FILE_TO_INITIATE in os.environ:
197 path = os.environ[PATH_TO_STUDY_FILE_TO_INITIATE]
198 salome_init_without_session(path, embedded, iorfakensfile)
200 salome_init_without_session_attached(path, embedded)
202 salome_init_with_session(path, embedded)
204 def salome_init_without_session_common(path=None, embedded=False):
205 from ORBConfigFile import writeORBConfigFileSSL
206 OMNIORB_USER_PATH = "OMNIORB_USER_PATH"
207 def RemoveOmniorbConfigFile():
209 if "OMNIORB_CONFIG" in os.environ:
210 fileToRemove = os.environ["OMNIORB_CONFIG"]
211 if os.path.exists(fileToRemove):
212 os.unlink(fileToRemove)
214 if OMNIORB_USER_PATH in os.environ:
216 writeORBConfigFileSSL(os.environ[OMNIORB_USER_PATH],kwargs={"with_pid":True})
217 atexit.register(RemoveOmniorbConfigFile)
219 global lcc,naming_service,myStudy,myStudyName,orb,modulcat,sg
221 KernelBasis.setSSLMode(True)
223 myStudy = KernelDS.myStudy()
225 orb=CORBA.ORB_init([''])
226 import KernelModuleCatalog
227 import SALOME_ModuleCatalog
228 from salome_kernel import list_of_catalogs_regarding_environement
229 modulcat = KernelModuleCatalog.myModuleCatalog( list_of_catalogs_regarding_environement() )
231 poa = orb.resolve_initial_references("RootPOA")
232 poaManager = poa._get_the_POAManager()
233 poaManager.activate()
235 sg = salome_iapp_init(embedded)
236 salome_study_init_without_session(path)
238 from NamingService import NamingService
239 naming_service = NamingService()
240 myStudyName = myStudy.Name
242 def salome_init_without_session(path=None, embedded=False, iorfakensfile=None):
244 Force creation of all servants needed by SALOME session in the current process.
245 A Fake NamingService is created storing reference of all servants in the current process.
247 salome_init_without_session_common(path,embedded)
248 global lcc,cm,dsm,esm,rm,logm
249 import KernelLauncher
250 cm = KernelLauncher.myContainerManager()
251 type(cm).SetOverrideEnvForContainersSimple = ContainerManagerSetOverrideEnvForContainersSimple
252 rm = KernelLauncher.myResourcesManager()
253 from LifeCycleCORBA import LifeCycleCORBASSL
254 lcc = LifeCycleCORBASSL()
255 # create a FactoryServer Container servant
256 import KernelContainer
257 KernelContainer.myContainer()
258 # activate poaManager to accept co-localized CORBA calls.
259 from KernelSDS import GetDSMInstance
261 if hasattr(sys, 'argv'):
265 dsm = GetDSMInstance(argv)
266 # esm inherits from SALOME_CPythonHelper singleton already initialized by GetDSMInstance
267 # esm inherits also from SALOME_ResourcesManager creation/initialization (concerning SingleThreadPOA POA) when KernelLauncher.GetContainerManager() has been called
268 esm = KernelLauncher.GetExternalServer()
270 logm = KernelLauncher.myLogManager()
271 type(logm).NaiveFetch = LogManagerNaiveFetch
272 type(logm).Fetch = LogManagerFetch
273 type(logm).DumpInFile = LogManagerDumpInFile
274 type(logm).LaunchMonitoringDumpFile = LogManagerLaunchMonitoringDumpFile
275 type(logm).FinalFetchBeforeDying = LogManagerFinalFetchBeforeDying
276 type(logm).GetLatestMonitoringDumpFile = LogManagerGetLatestMonitoringDumpFile
277 type(logm).DumpIORInFile = LogManagerDumpIORInFile
280 naming_service.Register(KernelLogger.myLogger(),"/Logger")
282 from NamingService import NamingService
283 if iorfakensfile is not None:
284 with open(iorfakensfile,"w") as iorfakensf:
285 iorfakensf.write(NamingService.IOROfNS())
287 CM_NAME_IN_NS = "/ContainerManager"
288 RM_NAME_IN_NS = "/ResourcesManager"
289 DSM_NAME_IN_NS = "/DataServerManager"
290 ESM_NAME_IN_NS = "/ExternalServers"
291 LOGM_NAME_IN_NS = "/LogManager"
293 def salome_init_without_session_attached(path=None, embedded=False):
295 Configuration SSL inside a python interpretor launched in the SALOME_Container_No_NS_Serv.
296 In this configuration, a local FakeNamingService is created and remote objects are stored in it.
297 lcc is pointing to the FakeNamingService above.
299 salome_init_without_session_common(path,embedded)
300 global lcc,cm,dsm,esm,rm,logm
302 orb=CORBA.ORB_init([''])
305 nsAbroad = orb.string_to_object( KernelBasis.getIOROfEmbeddedNS() )
307 cm = orb.string_to_object( nsAbroad.Resolve(CM_NAME_IN_NS).decode() )
308 type(cm).SetOverrideEnvForContainersSimple = ContainerManagerSetOverrideEnvForContainersSimple
309 naming_service.Register(cm,CM_NAME_IN_NS)
310 rm = orb.string_to_object( nsAbroad.Resolve(RM_NAME_IN_NS).decode() )
311 naming_service.Register(rm,RM_NAME_IN_NS)
313 from LifeCycleCORBA import LifeCycleCORBASSL
314 lcc = LifeCycleCORBASSL()
315 dsm = orb.string_to_object( nsAbroad.Resolve(DSM_NAME_IN_NS).decode() )
316 naming_service.Register(dsm,DSM_NAME_IN_NS)
318 esm = orb.string_to_object( nsAbroad.Resolve(ESM_NAME_IN_NS).decode() )
319 naming_service.Register(esm,ESM_NAME_IN_NS)
321 logm = orb.string_to_object( nsAbroad.Resolve(LOGM_NAME_IN_NS).decode() )
322 naming_service.Register(logm,LOGM_NAME_IN_NS)
324 def salome_init_with_session(path=None, embedded=False):
326 Performs only once SALOME general purpose initialisation for scripts.
328 orb reference to CORBA
329 lcc a LifeCycleCorba instance
330 naming_service a naming service instance
331 cm reference to the container manager
332 esm reference to external server manager
333 dsm reference to shared dataserver manager
334 modulcat reference to modulecatalog instance
335 sg access to SALOME GUI (when linked with IAPP GUI)
336 myStudy active study itself (CORBA reference)
337 myStudyName active study name
339 global salome_initial
340 global orb, lcc, naming_service, cm, esm, dsm, modulcat
342 global myStudy, myStudyName
344 KernelBasis.setSSLMode(False)
348 sg = salome_iapp_init(embedded)
349 orb, lcc, naming_service, cm, esm, dsm, modulcat = salome_kernel_init()
350 myStudy, myStudyName = salome_study_init(path)
353 except RuntimeError as inst:
354 # wait a little to avoid trace mix
358 print("salome.salome_init_with_session():", x)
360 ============================================
361 May be there is no running SALOME session
362 salome.salome_init() is intended to be used
363 within an already running session
364 ============================================
369 global salome_initial, myStudy, myStudyName, lcc
371 # study can be clear either from GUI or directly with salome.myStudy.Clear()
378 myStudy, myStudyName = None, None
379 lcc = None # to salome_init to rebuild all in case of salome_init after salome_close
381 if KernelBasis.getSSLMode() and not KernelBasis.getGUIMode():
383 KernelDS.KillGlobalSessionInstance()
385 KernelSDS.KillCPythonHelper()
391 orb = CORBA.ORB_init()
392 ns0 = orb.resolve_initial_references("NameService")
393 return ns0._narrow(CosNaming.NamingContext)
395 def salome_walk_on_containers(ns,root):
402 cont,obj = it.next_one()
404 if obj.binding_name[0].kind == "object":
406 corbaObj = ns.resolve(obj.binding_name)
407 if isinstance(corbaObj,Engines._objref_Container):
408 yield corbaObj,(root,obj.binding_name[0].id)
410 father = ns.resolve([obj.binding_name[0]])
411 for elt,elt2 in salome_walk_on_containers(father,root+[obj.binding_name[0].id]):
417 def salome_shutdown_containers_with_session():
420 li = [elt for elt in salome_walk_on_containers(ns,[""])]
421 print("Number of containers in NS : {}".format(len(li)))
422 for cont,(root,cont_name) in li:
427 ref_in_ns = "/".join(root+[cont_name])
428 naming_service.Destroy_Name(ref_in_ns)
429 print("Number of containers in NS after clean : {}".format( len( list(salome_walk_on_containers(ns,[""])) )))
431 def retrieve_containers_in_ns():
432 return [elt for elt in naming_service.repr() if "/Containers/" == elt[:12]]
434 def get_all_containers():
435 containersEntries = retrieve_containers_in_ns()
436 return [naming_service.Resolve(containerEntry) for containerEntry in containersEntries]
438 def salome_shutdown_containers_without_session():
439 for cont in get_all_containers():
445 def salome_shutdown_containers():
447 if KernelBasis.getSSLMode():
448 salome_shutdown_containers_without_session()
450 salome_shutdown_containers_with_session()
452 class SessionContextManager:
456 def __exit__(self, type, value, traceback):
459 def ContainerManagerSetOverrideEnvForContainersSimple(self,env):
460 envEff = [ Engines.KeyValPairString(key=k,val=v) for k,v in env ]
461 return self.SetOverrideEnvForContainers( envEff )
463 def LogManagerNaiveFetch(self):
465 Fetch data from server with multiple CORBA invokations.
467 import SALOME_ContainerHelper
468 return [SALOME_ContainerHelper.ContainerLogInfoClt(elt) for elt in self.listOfContainerLogs()]
470 def LogManagerFetch(self,clearMemory = False):
472 Fetch data from server in one shot mode.
474 from SALOME_ContainerHelper import unserializeLogManager
475 return unserializeLogManager( self.getAllStruct(clearMemory) )
477 def LogManagerDumpInFile(self,fileName,clearMemory = False):
478 with open(fileName,"wb") as f:
479 f.write( self.getAllStruct( clearMemory ) )
482 class LogManagerLaunchMonitoringFileCtxMgr:
483 def __init__(self, intervalInMs, outFileName):
484 self._interval_in_ms = intervalInMs
485 self._out_filename = outFileName
486 self._monitoring_params = None
489 self._monitoring_params = salome.logm.LaunchMonitoringDumpFile(self._interval_in_ms, self._out_filename)
490 return self._monitoring_params
491 def __exit__(self,exctype, exc, tb):
494 SALOME_PyNode.StopMonitoring( self._monitoring_params )
495 salome.logm.GetLatestMonitoringDumpFile()
498 def LogManagerLaunchMonitoringDumpFile(self, intervalInMs, outFileName):
500 This method loops indefinitely every intervalInMs milliseconds to dump the singleton
501 content of perf log stored in salome.logm.
502 This method runs in a dedicated subprocess that can be killed at any time.
503 So subprocess code must deal with.
505 See also LogManagerGetLatestMonitoringDumpFile
508 ior = orb.object_to_string( logm )
510 outFileName2 = os.path.abspath( os.path.expanduser(outFileName) )
515 # outFileNameSave stores the content of outFileName during phase of dumping
516 with tempfile.NamedTemporaryFile(prefix=os.path.basename(outFileName2),dir=os.path.dirname(outFileName2)) as f:
517 outFileNameSave = f.name
518 with tempfile.NamedTemporaryFile(prefix="htopmain_",suffix=".py") as f:
520 with open(tempPyFile,"w") as f:
521 f.write("""import Engines
526 orb=CORBA.ORB_init([''], CORBA.ORB_ID)
527 logm = orb.string_to_object("{ior}")
528 outFileName = "{outFileName}"
529 outFileNameSave = "{outFileNameSave}"
530 logm.setFileNamePairOfLogger(outFileName, outFileNameSave )
533 if os.path.exists( outFileName ):
534 shutil.copy(outFileName,outFileNameSave)
535 logm.versionB_IsTheLatestValidVersion()
536 salome.LogManagerDumpInFile(logm,outFileName)
537 logm.versionA_IsTheLatestValidVersion()
538 time.sleep( {intervalInMs} / 1000.0 )
539 """.format( **locals()))
540 logging.debug( "File for monitoring dump file : {}".format(tempPyFile) )
541 pyFileName = SALOME_PyNode.FileDeleter( tempPyFile )
542 pid = KernelBasis.LaunchMonitoring( tempPyFile )
543 return SALOME_PyNode.MonitoringInfo(pyFileName,intervalInMs,None,pid)
545 def LogManagerDumpIORInFile(self, iorFileName):
547 with open(iorFileName,"w") as f:
548 f.write( orb.object_to_string( logm ) )
550 def LogManagerLoadFromFile(fileName):
551 from SALOME_ContainerHelper import unserializeLogManager
552 with open(fileName,"rb") as f:
554 return unserializeLogManager( data )
556 def LogManagerLoadFromIORFile( iorFile ):
558 def LoadAndWrite(logm,tempFileName):
560 logm.putStructInFileAtomic( False, tempFileName )
561 tempFileAuto = SALOME_PyNode.FileDeleter( tempFileName )
562 ret = LogManagerLoadFromFile( tempFileAuto.filename )
564 with open(iorFile,"r") as f:
568 salome_init_without_session()
569 logm = orb.string_to_object( ior )
570 with tempfile.NamedTemporaryFile(dir=os.path.expanduser("~")) as f:
571 tempFileName = f.name
572 return LoadAndWrite( logm, tempFileName )
574 def LogManagerFinalFetchBeforeDying(self):
576 a,b = self.getFileNamePairOfLogger()
580 def LogManagerGetLatestMonitoringDumpFile(self):
583 a,b = self.getFileNamePairOfLogger()
588 lastVersion = self.getLastVersionOfFileNameLogger()
590 logging.debug("LogManagerGetLatestMonitoringDumpFile SITUATION A")
591 if os.path.exists( b ):
593 self.FinalFetchBeforeDying()
596 logging.debug("LogManagerGetLatestMonitoringDumpFile SITUATION B")
597 if os.path.exists( b ):
599 self.FinalFetchBeforeDying()
601 logging.warning("in LogManagerGetLatestMonitoringDumpFile an unexpected situation araises.")
604 #to expose all objects to pydoc