2 # -*- coding: iso-8859-1 -*-
3 # Copyright (C) 2007-2023 CEA, EDF, OPEN CASCADE
5 # Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
6 # CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
8 # This library is free software; you can redistribute it and/or
9 # modify it under the terms of the GNU Lesser General Public
10 # License as published by the Free Software Foundation; either
11 # version 2.1 of the License, or (at your option) any later version.
13 # This library is distributed in the hope that it will be useful,
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 # Lesser General Public License for more details.
18 # You should have received a copy of the GNU Lesser General Public
19 # License along with this library; if not, write to the Free Software
20 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
26 # \brief Module that provides services to launch SALOME
29 import sys, os, string, glob, time, pickle, re
31 from server import process_id, Server
34 from salomeContextUtils import ScriptAndArgsObjectEncoder
38 ## Setting formatter in setVerbose() was commented because adding of handler
39 ## breaks using of root logger in other modules and cause many double lines in logs.
40 #FORMAT = '%(levelname)s : %(asctime)s : [%(filename)s:%(funcName)s:%(lineno)s] : %(message)s'
41 #logging.basicConfig(format=FORMAT)
42 logger = logging.getLogger()
44 class ColoredFormatter(logging.Formatter):
45 BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE = range(30,38)
46 COLORS = { 'WARNING': YELLOW, 'INFO': WHITE, 'DEBUG': BLUE, 'CRITICAL': YELLOW, 'ERROR': RED }
47 def __init__(self, *args, **kwargs):
48 logging.Formatter.__init__(self, *args, **kwargs)
49 def format(self, record):
51 COLOR_SEQ = "\033[1;%dm"
53 frame = inspect.currentframe()
56 record.levelname = COLOR_SEQ % ColoredFormatter.COLORS[record.levelname] + record.levelname + RESET_SEQ
57 record.msg = "{} ( callsite is {} of file \"{}\" at line {} )".format(record.msg, frame.f_code.co_name,inspect.getsourcefile(frame),inspect.getlineno(frame) )
58 return logging.Formatter.format(self, record)
60 class BackTraceFormatter(logging.Formatter):
61 def __init__(self, *args, **kwargs):
62 logging.Formatter.__init__(self, *args, **kwargs)
63 def format(self, record):
65 frame = inspect.currentframe()
66 # go upward of the stack to catch the effective callsite. Not very steady....
67 # should be replaced by an analysis of frame.f_code
70 record.msg = "{} ( callsite is {} of file \"{}\" at line {} )".format(record.msg, frame.f_code.co_name,inspect.getsourcefile(frame),inspect.getlineno(frame) )
71 return logging.Formatter.format(self, record)
73 def setVerbose(verbose):
74 from packaging import version
75 current_version = version.parse("{}.{}".format(sys.version_info.major,sys.version_info.minor))
76 version_ref = version.parse("3.5.0")
79 if current_version >= version_ref:
80 formatter = BackTraceFormatter('%(levelname)s : %(asctime)s : %(message)s ',style='%')
82 formatter = logging.Formatter('%(levelname)s : %(asctime)s : %(message)s ',style='%')
83 formatter.default_time_format = '%H:%M:%S'
84 formatter.default_msec_format = "%s.%03d"
85 stream_handler = logging.StreamHandler()
86 stream_handler.setFormatter(formatter)
87 logger.addHandler(stream_handler)
89 verbose_map = { "0": logging.WARNING, "1": logging.INFO, "2": logging.DEBUG}
90 if verbose in verbose_map:
91 logger.setLevel(verbose_map[verbose])
93 # -----------------------------------------------------------------------------
95 # Class definitions to launch CORBA Servers
98 class InterpServer(Server):
99 def __init__(self,args):
101 if sys.platform == "win32":
102 self.CMD=['cmd', '/c', 'start cmd.exe', '/K', 'python']
103 elif sys.platform == "darwin":
104 env_ld_library_path=['env', 'DYLD_LIBRARY_PATH=' + os.getenv("LD_LIBRARY_PATH")]
105 self.CMD=['xterm', '-e'] + env_ld_library_path + ['python']
107 env_ld_library_path=['env', 'LD_LIBRARY_PATH=' + os.getenv("LD_LIBRARY_PATH")]
108 self.CMD=['xterm', '-e'] + env_ld_library_path + ['python']
113 print("INTERPSERVER::command = ", command)
115 pid = subprocess.Popen(command).pid
116 process_id[pid]=self.CMD
121 def get_cata_path(list_modules,modules_root_dir):
122 """Build a list of catalog paths (cata_path) to initialize the ModuleCatalog server
127 for module in list_modules:
128 if module in modules_root_dir:
129 module_root_dir=modules_root_dir[module]
130 module_cata=module+"Catalog.xml"
131 cata_file=os.path.join(module_root_dir, "share",setenv.salome_subdir, "resources",module.lower(), module_cata)
133 if os.path.exists(cata_file):
134 cata_path.append(cata_file)
135 modules_cata[module]=cata_file
137 cata_file=os.path.join(module_root_dir, "share",setenv.salome_subdir, "resources", module_cata)
138 if os.path.exists(cata_file):
139 cata_path.append(cata_file)
140 modules_cata[module]=cata_file
142 for path in os.getenv("SALOME_CATALOGS_PATH","").split(os.pathsep):
143 if os.path.exists(path):
144 for cata_file in glob.glob(os.path.join(path,"*Catalog.xml")):
145 module_name= os.path.basename(cata_file)[:-11]
146 if module_name not in modules_cata:
147 cata_path.append(cata_file)
148 modules_cata[module_name]=cata_file
152 class CatalogServer(Server):
153 def __init__(self,args):
156 self.SCMD1=['SALOME_ModuleCatalog_Server']
157 if 'launcher' in self.args:
158 pos = args['launcher'].find(":")
160 self.SCMD1+=['-ORBInitRef']
161 machine = args['launcher'][0:pos]
162 port = args['launcher'][pos+1:]
163 self.SCMD1+=["NameService=corbaname::" + machine + ":" + port]
164 self.SCMD1+=['-common']
166 home_dir=os.path.expanduser("~")
167 if home_dir is not None:
168 self.SCMD2=['-personal',os.path.join(home_dir,'Salome', 'resources', 'CatalogModulePersonnel.xml')]
170 def setpath(self,modules_list,modules_root_dir):
171 list_modules = modules_list[:]
172 list_modules.reverse()
173 if self.args["gui"] :
174 list_modules = ["KERNEL", "GUI"] + list_modules
176 list_modules = ["KERNEL"] + list_modules
178 cata_path=get_cata_path(list_modules,modules_root_dir)
180 self.CMD=self.SCMD1 + ['"' + '"::"'.join(cata_path) + '"'] + self.SCMD2
184 class SalomeDSServer(Server):
185 def __init__(self,args):
188 self.CMD=['SALOMEDS_Server']
189 if 'launcher' in self.args:
190 pos = args['launcher'].find(":")
192 self.CMD+=['-ORBInitRef']
193 machine = args['launcher'][0:pos]
194 port = args['launcher'][pos+1:]
195 self.CMD+=["NameService=corbaname::" + machine + ":" + port]
199 class ConnectionManagerServer(Server):
200 def __init__(self,args):
203 self.CMD=['SALOME_ConnectionManagerServer']
204 if 'launcher' in self.args:
205 pos = args['launcher'].find(":")
207 self.CMD+=['-ORBInitRef']
208 machine = args['launcher'][0:pos]
209 port = args['launcher'][pos+1:]
210 self.CMD+=["NameService=corbaname::" + machine + ":" + port]
215 class RegistryServer(Server):
216 def __init__(self,args):
219 self.CMD=['SALOME_Registry_Server', '--salome_session','theSession']
220 if 'launcher' in self.args:
221 pos = args['launcher'].find(":")
223 self.CMD+=['-ORBInitRef']
224 machine = args['launcher'][0:pos]
225 port = args['launcher'][pos+1:]
226 self.CMD+=["NameService=corbaname::" + machine + ":" + port]
230 class ContainerCPPServer(Server):
231 def __init__(self,args,with_gui=False):
234 self.CMD=['SALOME_Container']
235 if 'launcher' in self.args:
236 pos = args['launcher'].find(":")
238 self.CMD+=['-ORBInitRef']
239 machine = args['launcher'][0:pos]
240 port = args['launcher'][pos+1:]
241 self.CMD+=["NameService=corbaname::" + machine + ":" + port]
242 self.CMD+=['FactoryServer']
243 if not with_gui and self.args["valgrind_session"]:
245 val = os.getenv("VALGRIND_OPTIONS")
249 self.CMD = l + self.CMD
254 class LoggerServer(Server):
255 def __init__(self,args):
258 from salome_utils import generateFileName, getLogDir
259 logfile = generateFileName( getLogDir(),
265 print("===========================================================")
266 print("Logger server: put log to the file:")
268 print("===========================================================")
269 self.CMD=['SALOME_Logger_Server', logfile]
271 pass # end of LoggerServer class
276 class CommonSessionServer(Server):
277 def __init__(self,args,modules_list,modules_root_dir):
278 self.args = args.copy()
279 # Bug 11512 (Problems with runSalome --xterm on Mandrake and Debian Sarge)
280 #self.args['xterm']=0
283 self.SCMD1=[self.getSessionServerExe()]
284 if "SQUISH_PREFIX" in os.environ:
285 if platform.system() == "Windows" :
286 self.SCMD1 = [os.path.join(os.getenv("SQUISH_PREFIX"), "bin", "dllpreload.exe"),os.path.join(os.getenv("SQUISH_SALOME_PATH"), "W64", "GUI", "bin", "salome", self.SCMD1[0])]
288 os.environ["LD_LIBRARY_PATH"] = os.environ["SQUISH_PREFIX"] + "/lib:" + os.environ["LD_LIBRARY_PATH"]
290 if 'launcher' in self.args:
291 pos = args['launcher'].find(":")
293 self.SCMD1+=['-ORBInitRef']
294 machine = args['launcher'][0:pos]
295 port = args['launcher'][pos+1:]
296 self.SCMD1+=["NameService=corbaname::" + machine + ":" + port]
297 if 'registry' in self.args['embedded']:
298 self.SCMD1+=['--with','Registry',
299 '(','--salome_session','theSession',')']
300 if 'moduleCatalog' in self.args['embedded']:
301 self.SCMD1+=['--with','ModuleCatalog','(','-common']
302 home_dir=os.path.expanduser("~")
303 if home_dir is not None:
304 self.SCMD2+=['-personal',os.path.join(home_dir,'Salome','resources','CatalogModulePersonnel.xml')]
306 if 'study' in self.args['embedded']:
307 self.SCMD2+=['--with','SALOMEDS','(',')']
308 if 'cppContainer' in self.args['embedded']:
309 self.SCMD2+=['--with','Container','(','FactoryServer',')']
310 if 'SalomeAppEngine' in self.args['embedded']:
311 self.SCMD2+=['--with','SalomeAppEngine','(',')']
313 if 'cppContainer' in self.args['standalone'] or 'cppContainer' in self.args['embedded']:
315 if 'pyContainer' in self.args['standalone'] or 'pyContainer' in self.args['embedded']:
316 raise Exception('Python containers no longer supported')
318 session_gui = self.args.get('session_gui', True)
320 self.SCMD2+=['--hide-desktop']
322 if not self.args['splash']:
323 self.SCMD2+=['--hide-splash']
325 if self.args['study_hdf'] is not None:
326 self.SCMD2+=['--study-hdf=%s'%self.args['study_hdf']]
329 if 'pyscript' in self.args and len(self.args['pyscript']) > 0:
330 msg = json.dumps(self.args['pyscript'], cls=ScriptAndArgsObjectEncoder)
331 self.SCMD2+=['--pyscript=%s'%(msg)]
334 if self.args['gui_log_file'] is not None:
335 self.SCMD2+=['--gui-log-file=%s'%self.args['gui_log_file']]
339 if self.args['noexcepthandler']:
340 self.SCMD2+=['--no-exception-handler']
341 if 'user_config' in self.args:
342 self.SCMD2+=['--resources=%s'%self.args['user_config']]
343 if 'modules' in self.args:
345 #keep only modules with GUI
346 for m in modules_list:
347 if m not in modules_root_dir:
348 list_modules.insert(0,m)
350 fr1 = os.path.join(modules_root_dir[m],"share","salome","resources",m.lower(),"SalomeApp.xml")
351 fr2 = os.path.join(modules_root_dir[m],"share","salome","resources","SalomeApp.xml")
352 if os.path.exists(fr1) or os.path.exists(fr2):
353 list_modules.insert(0,m)
354 list_modules.reverse()
355 self.SCMD2+=['--modules (%s)' % ":".join(list_modules)]
357 if 'language' in self.args:
358 self.SCMD2+=['--language=%s' % self.args['language']]
359 os_handle, iorfakens = tempfile.mkstemp()
360 self.iorfakens = iorfakens
362 self.SCMD2+=["--iorfakens={}".format(iorfakens)]
366 def getSessionServerExe(self):
369 def setpath(self,modules_list,modules_root_dir):
370 list_modules = modules_list[:]
371 list_modules.reverse()
372 if self.args["gui"] :
373 list_modules = ["KERNEL", "GUI"] + list_modules
375 list_modules = ["KERNEL"] + list_modules
377 cata_path=get_cata_path(list_modules,modules_root_dir)
379 if ("gui" in self.args) & ('moduleCatalog' in self.args['embedded']):
380 #Use '::' instead ":" because drive path with "D:\" is invalid on windows platform
381 self.CMD=self.SCMD1 + ['"' + '"::"'.join(cata_path) + '"'] + self.SCMD2
383 self.CMD=self.SCMD1 + self.SCMD2
384 if 'test' in self.args:
385 self.CMD+=['-test'] + self.args['test']
386 elif 'play' in self.args:
387 self.CMD+=['-play'] + self.args['play']
389 if self.args["gdb_session"] or self.args["ddd_session"]:
390 f = open(".gdbinit4salome", "w")
392 args = " ".join(self.CMD[1:])
393 args = args.replace("(", "\(")
394 args = args.replace(")", "\)")
398 if self.args["ddd_session"]:
399 self.CMD = ["ddd", "--command=.gdbinit4salome", self.CMD[0]]
400 elif self.args["gdb_session"]:
401 self.CMD = ["xterm", "-e", "gdb", "--command=.gdbinit4salome", self.CMD[0]]
405 if self.args["valgrind_session"]:
407 val = os.getenv("VALGRIND_OPTIONS")
411 self.CMD = l + self.CMD
414 class SessionServer(CommonSessionServer):
415 def __init__(self,args,modules_list,modules_root_dir):
416 super().__init__(args,modules_list,modules_root_dir)
418 KernelBasis.setSSLMode(False)
420 def getSessionServerExe(self):
421 return "SALOME_Session_Server"
424 class LauncherServer(Server):
425 def __init__(self,args):
428 self.SCMD1=['SALOME_LauncherServer']
431 if 'registry' in self.args['embedded']:
432 self.SCMD1+=['--with','Registry',
433 '(','--salome_session','theSession',')']
434 if 'moduleCatalog' in self.args['embedded']:
435 self.SCMD1+=['--with','ModuleCatalog','(','-common']
436 home_dir=os.path.expanduser("~")
437 if home_dir is not None:
438 self.SCMD2=['-personal',os.path.join(home_dir,'Salome','resources','CatalogModulePersonnel.xml')]
440 if 'study' in self.args['embedded']:
441 self.SCMD2+=['--with','SALOMEDS','(',')']
442 if 'cppContainer' in self.args['embedded']:
443 self.SCMD2+=['--with','Container','(','FactoryServer',')']
445 def setpath(self,modules_list,modules_root_dir):
446 list_modules = modules_list[:]
447 list_modules.reverse()
448 if self.args["gui"] :
449 list_modules = ["KERNEL", "GUI"] + list_modules
451 list_modules = ["KERNEL"] + list_modules
453 cata_path=get_cata_path(list_modules,modules_root_dir)
455 if ("gui" in self.args) & ('moduleCatalog' in self.args['embedded']):
456 #Use '::' instead ":" because drive path with "D:\" is invalid on windows platform
457 self.CMD=self.SCMD1 + ['"' + '"::"'.join(cata_path) + '"'] + self.SCMD2
459 self.CMD=self.SCMD1 + self.SCMD2