]> SALOME platform Git repositories - modules/kernel.git/blob - src/KERNEL_PY/__init__.py
Salome HOME
Create FactoryServer Container servant into the current process
[modules/kernel.git] / src / KERNEL_PY / __init__.py
1 #  -*- coding: iso-8859-1 -*-
2 # Copyright (C) 2007-2021  CEA/DEN, EDF R&D, OPEN CASCADE
3 #
4 # Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
5 # CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
6 #
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.
11 #
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.
16 #
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
20 #
21 # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
22 #
23
24 #  File   : salome.py renamed as __init__.py for python packaging (gboulant)
25 #  Author : Paul RASCLE, EDF
26 #  Module : SALOME
27 #
28 """ 
29 Module salome gives access to Salome resources.
30
31 variables:
32
33   - salome.orb             : CORBA
34   - salome.naming_service  : instance of naming Service class
35       - methods:
36           - Resolve(name)  : find a CORBA object (ior) by its pathname
37           - Register(name) : register a CORBA object under a pathname
38
39   - salome.lcc             : instance of lifeCycleCORBA class
40       - methods:
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
45
46   - salome.sg              : salome object to communicate with the graphical user interface (if any)
47       - methods:
48          - updateObjBrowser():
49
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
56
57          - Display(*Entry):
58          - DisplayOnly(Entry):
59          - Erase(Entry):
60          - DisplayAll():
61          - EraseAll():
62
63          - IDToObject(Entry):    returns CORBA reference from entry
64
65   - salome.myStudyName     : active Study Name
66   - salome.myStudy         : the active Study itself (CORBA ior)
67       - methods : defined in SALOMEDS.idl
68
69 """
70 ## @package salome
71 # Module salome gives access to Salome resources.
72 #
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)
79
80 #
81 # ==========================================================================
82 #
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).
86 #
87 ROOT_PYTHONPACKAGE_NAME="salome"
88 #
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
95 # of the type:
96 #
97 # <MODULE_ROOT_DIR>/lib/pythonX.Y/site-packages/salome/<ROOT_PYTHONPACKAGE_NAME>
98 #
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.
101 #
102 import os, sys
103 from salome_utils import verbose
104
105 MATCH_ENDING_PATTERN="site-packages" + os.path.sep + "salome"
106
107 def extend_path(pname):
108     for dir in sys.path:
109         if not isinstance(dir, str) or not os.path.isdir(dir) or not dir.endswith(MATCH_ENDING_PATTERN):
110             continue
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)
117
118 extend_path(ROOT_PYTHONPACKAGE_NAME)
119 # ==========================================================================
120 #
121
122 from salome_kernel import *
123 from salome_study import *
124 from salome_iapp import *
125 import salome_study
126
127 #
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.
131
132 import sys
133 flags = None
134 if not flags:
135     try:
136         # dl module can be unavailable
137         import dl
138         flags = dl.RTLD_NOW | dl.RTLD_GLOBAL
139     except Exception:
140         pass
141     pass
142 if not flags:
143     try:
144         # DLFCN module can be unavailable
145         import DLFCN
146         flags = DLFCN.RTLD_NOW | DLFCN.RTLD_GLOBAL
147     except Exception:
148         pass
149     pass
150 if not flags:
151     try:
152         # ctypes module can be unavailable
153         import ctypes
154         flags = ctypes.RTLD_GLOBAL
155     except Exception:
156         pass
157     pass
158
159 # Disable -> bug with scipy, seems very dangerous to do that
160 #if flags:
161 #    sys.setdlopenflags(flags)
162 #    pass
163
164 orb, lcc, naming_service, cm, sg, esm, dsm, modulcat = None,None,None,None,None,None,None,None
165 myStudy, myStudyName = None,None
166
167 salome_initial=True
168
169 __EMB_SERVANT_ENV_VAR_NAME = "SALOME_EMB_SERVANT"
170
171 def standalone():
172     import os
173     os.environ[__EMB_SERVANT_ENV_VAR_NAME] = "1"
174     import KernelBasis
175     KernelBasis.setSSLMode(True)
176
177 def salome_init(path=None, embedded=False):
178     import os
179     import KernelBasis
180     if __EMB_SERVANT_ENV_VAR_NAME in os.environ:
181         KernelBasis.setSSLMode(True)
182     #
183     if KernelBasis.getSSLMode():
184         if KernelBasis.getIOROfEmbeddedNS() == "":
185             salome_init_without_session(path, embedded)
186         else:
187             salome_init_without_session_attached(path, embedded)
188     else:
189         salome_init_with_session(path, embedded)
190
191 class StandAloneLifecyle:
192     def __init__(self, containerManager, resourcesManager):
193         self._cm = containerManager
194         self._rm = resourcesManager
195
196     def FindOrLoadComponent(self,contName,moduleName):
197         global orb
198         import importlib
199         builder_name = moduleName + "_SalomeSessionless"
200         moduleObj = importlib.import_module(builder_name)
201         result, orb = moduleObj.buildInstance(orb)
202         return result
203         #raise RuntimeError("Undealed situation cont = {} module = {}".format(contName,moduleName))
204
205     def getContainerManager(self):
206       return self._cm
207
208     def getResourcesManager(self):
209       return self._rm
210
211 def salome_init_without_session_common(path=None, embedded=False):
212     from ORBConfigFile import writeORBConfigFileSSL
213     OMNIORB_USER_PATH = "OMNIORB_USER_PATH"
214     def RemoveOmniorbConfigFile():
215         import os
216         if "OMNIORB_CONFIG" in os.environ:
217             fileToRemove = os.environ["OMNIORB_CONFIG"]
218             if os.path.exists(fileToRemove):
219                 os.unlink(fileToRemove)
220
221     if OMNIORB_USER_PATH in os.environ:
222         import atexit
223         writeORBConfigFileSSL(os.environ[OMNIORB_USER_PATH],kwargs={"with_pid":True})
224         atexit.register(RemoveOmniorbConfigFile)
225
226     global lcc,naming_service,myStudy,orb,modulcat,sg
227     import KernelBasis
228     KernelBasis.setSSLMode(True)
229     import KernelDS
230     myStudy = KernelDS.myStudy()
231     import CORBA
232     orb=CORBA.ORB_init([''])
233     import KernelModuleCatalog
234     import SALOME_ModuleCatalog
235     from salome_kernel import list_of_catalogs_regarding_environement
236     modulcat = KernelModuleCatalog.myModuleCatalog( list_of_catalogs_regarding_environement() )
237     #
238     poa = orb.resolve_initial_references("RootPOA")
239     poaManager = poa._get_the_POAManager()
240     poaManager.activate()
241     #
242     sg = salome_iapp_init(embedded)
243     salome_study_init_without_session(path)
244     #
245     from NamingService import NamingService
246     naming_service = NamingService()
247
248 def salome_init_without_session(path=None, embedded=False):
249     salome_init_without_session_common(path,embedded)
250     global lcc,cm,dsm,esm
251     import KernelLauncher
252     cm = KernelLauncher.myContainerManager()
253     lcc = StandAloneLifecyle(cm, KernelLauncher.myResourcesManager())
254     # create a FactoryServer Container servant
255     import KernelContainer
256     KernelContainer.myContainer()
257     # activate poaManager to accept co-localized CORBA calls.
258     from KernelSDS import GetDSMInstance
259     import sys
260     if hasattr(sys, 'argv'):
261       argv = sys.argv
262     else:
263       argv = ['']
264     dsm = GetDSMInstance(argv)
265     # esm inherits from SALOME_CPythonHelper singleton already initialized by GetDSMInstance
266     # esm inherits also from SALOME_ResourcesManager creation/initialization (concerning SingleThreadPOA POA) when KernelLauncher.GetContainerManager() has been called
267     esm = KernelLauncher.GetExternalServer()
268     
269 def salome_init_without_session_attached(path=None, embedded=False):
270     """
271     Configuration SSL inside a python interpretor launched in the SALOME_Container_No_NS_Serv.
272     In this configuration, 
273     """
274     salome_init_without_session_common(path,embedded)
275     global lcc,cm,dsm,esm
276     import CORBA
277     orb=CORBA.ORB_init([''])
278     import Engines
279     import KernelBasis
280     nsAbroad = orb.string_to_object( KernelBasis.getIOROfEmbeddedNS() )
281     import SALOME
282     CM_NAME_IN_NS = "/ContainerManager"
283     cm = orb.string_to_object( nsAbroad.Resolve(CM_NAME_IN_NS).decode() )
284     naming_service.Register(cm,CM_NAME_IN_NS)
285     RM_NAME_IN_NS = "/ResourcesManager"
286     rm = orb.string_to_object( nsAbroad.Resolve(RM_NAME_IN_NS).decode() )
287     naming_service.Register(rm,RM_NAME_IN_NS)
288     #
289     DSM_NAME_IN_NS = "/DataServerManager"
290     lcc = StandAloneLifecyle(cm,rm)
291     dsm = orb.string_to_object( nsAbroad.Resolve(DSM_NAME_IN_NS).decode() )
292     naming_service.Register(dsm,DSM_NAME_IN_NS)
293     #
294     ESM_NAME_IN_NS = "/ExternalServers"
295     esm = orb.string_to_object( nsAbroad.Resolve(ESM_NAME_IN_NS).decode() )
296     naming_service.Register(esm,ESM_NAME_IN_NS)
297
298 def salome_init_with_session(path=None, embedded=False):
299     """
300     Performs only once SALOME general purpose initialisation for scripts.
301     Provides:
302     orb             reference to CORBA
303     lcc             a LifeCycleCorba instance
304     naming_service  a naming service instance
305     cm              reference to the container manager
306     esm             reference to external server manager
307     dsm             reference to shared dataserver manager
308     modulcat        reference to modulecatalog instance
309     sg              access to SALOME GUI (when linked with IAPP GUI)
310     myStudy         active study itself (CORBA reference)
311     myStudyName     active study name
312     """
313     global salome_initial
314     global orb, lcc, naming_service, cm, esm, dsm, modulcat
315     global sg
316     global myStudy, myStudyName
317     import KernelBasis
318     KernelBasis.setSSLMode(False)
319     try:
320         if salome_initial:
321             salome_initial=False
322             sg = salome_iapp_init(embedded)
323             orb, lcc, naming_service, cm, esm, dsm, modulcat = salome_kernel_init()
324             myStudy, myStudyName = salome_study_init(path)
325             pass
326         pass
327     except RuntimeError as inst:
328         # wait a little to avoid trace mix
329         import time
330         time.sleep(0.2)
331         x = inst
332         print("salome.salome_init():", x)
333         print("""
334         ============================================
335         May be there is no running SALOME session
336         salome.salome_init() is intended to be used
337         within an already running session
338         ============================================
339         """)
340         raise
341     
342 def salome_close():
343     global salome_initial, myStudy, myStudyName
344     try:
345         # study can be clear either from GUI or directly with salome.myStudy.Clear()
346         myStudy.Clear()
347     except Exception:
348         pass
349     salome_initial=True
350     salome_iapp_close()
351     salome_study_close()
352     myStudy, myStudyName = None, None
353     import KernelBasis
354     if KernelBasis.getSSLMode() and not KernelBasis.getGUIMode():
355         import KernelDS
356         KernelDS.KillGlobalSessionInstance()
357         import KernelSDS
358         KernelSDS.KillCPythonHelper()
359     pass
360
361 def salome_NS():
362     import CORBA
363     import CosNaming
364     orb = CORBA.ORB_init()
365     ns0 = orb.resolve_initial_references("NameService")
366     return ns0._narrow(CosNaming.NamingContext)
367
368 def salome_walk_on_containers(ns,root):
369     import CosNaming
370     it = ns.list(0)[1]
371     if not it:
372         return
373     cont = True
374     while cont:
375         cont,obj = it.next_one()
376         if cont:
377             if obj.binding_name[0].kind == "object":
378                 import Engines
379                 corbaObj = ns.resolve(obj.binding_name)
380                 if isinstance(corbaObj,Engines._objref_Container):
381                     yield corbaObj,(root,obj.binding_name[0].id)
382             else:
383                 father = ns.resolve([obj.binding_name[0]])
384                 for elt,elt2 in salome_walk_on_containers(father,root+[obj.binding_name[0].id]):
385                     yield elt,elt2
386             pass
387         pass
388     pass
389
390 def salome_shutdown_containers_with_session():
391     salome_init()
392     ns=salome_NS()
393     li = [elt for elt in salome_walk_on_containers(ns,[""])]
394     print("Number of containers in NS : {}".format(len(li)))
395     for cont,(root,cont_name) in li:
396         try:
397             cont.Shutdown()
398         except Exception:
399             pass
400         ref_in_ns = "/".join(root+[cont_name])
401         naming_service.Destroy_Name(ref_in_ns)
402     print("Number of containers in NS after clean : {}".format( len( list(salome_walk_on_containers(ns,[""])) )))
403     
404 def salome_shutdown_containers_without_session():
405     containersEntries = [elt for elt in naming_service.repr() if "/Containers/" == elt[:12]]
406     for containerEntry in containersEntries:
407         cont = naming_service.Resolve(containerEntry)
408         try:
409             cont.Shutdown()
410         except:
411             pass
412
413 def salome_shutdown_containers():
414     import KernelBasis
415     if KernelBasis.getSSLMode():
416         salome_shutdown_containers_without_session()
417     else:
418         salome_shutdown_containers_with_session()
419
420 class SessionContextManager:
421     def __enter__(self):
422         standalone()
423         salome_init()
424     def __exit__(self, type, value, traceback):
425         salome_close()
426
427 #to expose all objects to pydoc
428 __all__=dir()