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 guilogfile = self.args['gui_log_file']
336 if os.path.exists(guilogfile) and os.path.isfile(guilogfile):
338 os.remove(guilogfile)
340 print("Error: cannot remove existing log file", guilogfile)
342 if guilogfile is not None:
343 self.SCMD2+=['--gui-log-file=%s'%guilogfile]
347 if self.args['noexcepthandler']:
348 self.SCMD2+=['--no-exception-handler']
349 if 'user_config' in self.args:
350 self.SCMD2+=['--resources=%s'%self.args['user_config']]
351 if 'modules' in self.args:
353 #keep only modules with GUI
354 for m in modules_list:
355 if m not in modules_root_dir:
356 list_modules.insert(0,m)
358 fr1 = os.path.join(modules_root_dir[m],"share","salome","resources",m.lower(),"SalomeApp.xml")
359 fr2 = os.path.join(modules_root_dir[m],"share","salome","resources","SalomeApp.xml")
360 if os.path.exists(fr1) or os.path.exists(fr2):
361 list_modules.insert(0,m)
362 list_modules.reverse()
363 self.SCMD2+=['--modules (%s)' % ":".join(list_modules)]
365 if 'language' in self.args:
366 self.SCMD2+=['--language=%s' % self.args['language']]
367 os_handle, iorfakens = tempfile.mkstemp()
368 self.iorfakens = iorfakens
370 self.SCMD2+=["--iorfakens={}".format(iorfakens)]
374 def getSessionServerExe(self):
377 def setpath(self,modules_list,modules_root_dir):
378 list_modules = modules_list[:]
379 list_modules.reverse()
380 if self.args["gui"] :
381 list_modules = ["KERNEL", "GUI"] + list_modules
383 list_modules = ["KERNEL"] + list_modules
385 cata_path=get_cata_path(list_modules,modules_root_dir)
387 if ("gui" in self.args) & ('moduleCatalog' in self.args['embedded']):
388 #Use '::' instead ":" because drive path with "D:\" is invalid on windows platform
389 self.CMD=self.SCMD1 + ['"' + '"::"'.join(cata_path) + '"'] + self.SCMD2
391 self.CMD=self.SCMD1 + self.SCMD2
392 if 'test' in self.args:
393 self.CMD+=['-test'] + self.args['test']
394 elif 'play' in self.args:
395 self.CMD+=['-play'] + self.args['play']
397 if self.args["gdb_session"] or self.args["ddd_session"]:
398 f = open(".gdbinit4salome", "w")
400 args = " ".join(self.CMD[1:])
401 args = args.replace("(", "\(")
402 args = args.replace(")", "\)")
406 if self.args["ddd_session"]:
407 self.CMD = ["ddd", "--command=.gdbinit4salome", self.CMD[0]]
408 elif self.args["gdb_session"]:
409 self.CMD = ["xterm", "-e", "gdb", "--command=.gdbinit4salome", self.CMD[0]]
413 if self.args["valgrind_session"]:
415 val = os.getenv("VALGRIND_OPTIONS")
419 self.CMD = l + self.CMD
422 class SessionServer(CommonSessionServer):
423 def __init__(self,args,modules_list,modules_root_dir):
424 super().__init__(args,modules_list,modules_root_dir)
426 KernelBasis.setSSLMode(False)
428 def getSessionServerExe(self):
429 return "SALOME_Session_Server"
432 class LauncherServer(Server):
433 def __init__(self,args):
436 self.SCMD1=['SALOME_LauncherServer']
439 if 'registry' in self.args['embedded']:
440 self.SCMD1+=['--with','Registry',
441 '(','--salome_session','theSession',')']
442 if 'moduleCatalog' in self.args['embedded']:
443 self.SCMD1+=['--with','ModuleCatalog','(','-common']
444 home_dir=os.path.expanduser("~")
445 if home_dir is not None:
446 self.SCMD2=['-personal',os.path.join(home_dir,'Salome','resources','CatalogModulePersonnel.xml')]
448 if 'study' in self.args['embedded']:
449 self.SCMD2+=['--with','SALOMEDS','(',')']
450 if 'cppContainer' in self.args['embedded']:
451 self.SCMD2+=['--with','Container','(','FactoryServer',')']
453 def setpath(self,modules_list,modules_root_dir):
454 list_modules = modules_list[:]
455 list_modules.reverse()
456 if self.args["gui"] :
457 list_modules = ["KERNEL", "GUI"] + list_modules
459 list_modules = ["KERNEL"] + list_modules
461 cata_path=get_cata_path(list_modules,modules_root_dir)
463 if ("gui" in self.args) & ('moduleCatalog' in self.args['embedded']):
464 #Use '::' instead ":" because drive path with "D:\" is invalid on windows platform
465 self.CMD=self.SCMD1 + ['"' + '"::"'.join(cata_path) + '"'] + self.SCMD2
467 self.CMD=self.SCMD1 + self.SCMD2