Salome HOME
Merge multi-study removal branch.
[modules/kernel.git] / bin / runConsole.py
1 #  -*- coding: iso-8859-1 -*-
2 # Copyright (C) 2007-2017  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 from optparse import OptionParser
25 import os
26 import sys
27 import user
28 import pickle
29
30 # Use to display newlines (\n) in epilog
31 class MyParser(OptionParser):
32   def format_epilog(self, formatter):
33     return self.epilog
34 #
35
36 def __parse_args(args):
37   if args is None:
38     args = []
39
40   usage = "Usage: salome connect [-p port] [ -c command | script | - ]"
41   epilog  = """
42 Connects a Python console to a local SALOME instance.\n
43 If port is given, try to connect to corresponding instance.
44 If port is not given, or does not correspond to a running instance,
45 ask user to select a port from list of available SALOME instances.\n
46
47 The -c option can be used to specify the command to execute in the interpreter.
48 A script can also be used.
49 For example:
50        salome connect -p 2810 -c 'print "Hello"'
51        salome connect -p 2810 hello.py
52 """
53   parser = MyParser(usage=usage, epilog=epilog)
54   parser.add_option("-p", metavar="<port>", default=0,
55                     action="store", type="string", dest="port",
56                     help="The port to connect to."
57                     )
58   parser.add_option('-c', dest="command", default=None,
59                     help="The command to execute in the interpreter."
60                     )
61   try:
62     (options, args) = parser.parse_args(args)
63   except Exception, e:
64     print e
65     return
66
67   return options, args
68 #
69
70 def __show_running_instances(list_of_instances):
71   print '-'*10
72   print "Running instances:"
73   for i in range(len(list_of_instances)):
74     host, port, _ = list_of_instances[i]
75     print "   [%d] %s:%s"%(i+1, host, port)
76   print '-'*10
77 #
78
79 def __choose_in(choices):
80   __show_running_instances(choices)
81   rep = raw_input("Please enter the number of instance to use (0 to cancel): ")
82   if rep == '0':
83     return None, None, None
84   elif rep in [str(i) for i in range(1, len(choices)+1)]:
85     return choices[int(rep)-1]
86   else:
87     print "*** Invalid number! ***"
88     return __choose_in(choices)
89 #
90
91 def __get_running_session(requested_port=None, lastInstanceByDefault=False):
92   import glob
93   import salome_utils
94   from ORBConfigFile import readORBConfigFile
95
96   omniorbUserPath = os.getenv("OMNIORB_USER_PATH")
97   files = glob.glob(os.path.join(omniorbUserPath,".omniORB_"+salome_utils.getUserName()+"_*[!last].cfg"))
98   available_connexions = []
99   for filename in files:
100     host, port = readORBConfigFile(filename)
101     available_connexions.append((host, port, filename))
102
103   host, port, filename = None, None, None
104   if requested_port:
105     print "Search for running instance on port %s..."%requested_port
106     found = [(h,p,f) for h,p,f in available_connexions if int(p) == int(requested_port)]
107     if not found:
108       print "   ...no running instance found"
109     elif len(found) == 1:
110       host, port, filename = found[0]
111       print "   ...found unique instance: %s:%s"%(host,port)
112     else:
113       print "   ...multiple instances found ; please choose one in the following:"
114       host, port, filename = __choose_in(found)
115   else: # no requested port
116     if not available_connexions:
117       print "No running instance found"
118     elif len(available_connexions) == 1:
119       host, port, filename = available_connexions[0]
120       print "Found unique instance: %s:%s"%(host,port)
121     else:
122       print "Multiple instances found ; please choose one in the following:"
123       host, port, filename = __choose_in(available_connexions)
124       pass
125
126   if port:
127     print "Selected instance: %s:%s"%(host, port)
128   else:
129     print "Cancel."
130
131   return host, port, filename
132 #
133
134 import CORBA
135 import CosNaming
136 import orbmodule
137
138 class client(orbmodule.client):
139   def initNS(self,args):
140     # Obtain a reference to the root naming context
141     obj = self.orb.resolve_initial_references("NameService")
142     try:
143       self.rootContext = obj._narrow(CosNaming.NamingContext)
144       return
145     except (CORBA.TRANSIENT,CORBA.OBJECT_NOT_EXIST,CORBA.COMM_FAILURE):
146       print "It's not a valid naming service"
147       self.rootContext = None
148       sys.stdout.flush()
149       raise
150 #
151
152 def start_client():
153   try:
154     clt = client()
155   except Exception:
156     import traceback
157     traceback.print_exc()
158     sys.exit(1)
159   #
160
161   session_server = clt.Resolve('/Kernel/Session')
162   if session_server:
163     session = clt.waitNS("/Kernel/Session")
164   catalog = clt.waitNS("/Kernel/ModulCatalog")
165   study = clt.waitNS("/Study")
166
167   import salome
168   salome.salome_init()
169   from salome import lcc
170   print "--> now connected to SALOME"
171 #
172
173 def _prompt(environment=None, commands=None, message="Connecting to SALOME"):
174   if environment is None:
175     environment = globals().copy()
176     environment.update(locals())
177   if commands is None:
178     commands = []
179
180   import code
181   import rlcompleter
182   import readline
183   readline.set_completer(rlcompleter.Completer(environment).complete)
184   readline.parse_and_bind("tab: complete")
185   # calling this with globals ensures we can see the environment
186   print message
187   shell = code.InteractiveConsole(environment)
188   for cmd in commands:
189     print "Execute command:", cmd
190     shell.push(cmd)
191     pass
192   shell.interact()
193 #
194
195 def connect(args=None, env=None):
196   if env is not None:
197     os.environ = env
198   options, args = __parse_args(args)
199   host, port, filename = __get_running_session(options.port)
200   if not port:
201     return 0
202
203   cmd = [
204     "os.environ['OMNIORB_CONFIG'] = '%s'"%filename,
205     "start_client()"
206     ]
207   if options.command:
208     cmd.append(options.command)
209   if args: # unprocessed: may be scripts
210     for arg in args:
211       cmd.append("execfile('%s')"%os.path.abspath(os.path.expanduser(arg)))
212
213   if port:
214     import subprocess
215     absoluteAppliPath = os.getenv('ABSOLUTE_APPLI_PATH','')
216     env_copy = os.environ.copy()
217     proc = subprocess.Popen(['python', os.path.join(absoluteAppliPath,"bin","salome","runConsole.py"), pickle.dumps(cmd)], shell=False, close_fds=True, env=env_copy)
218     return proc.communicate()
219 #
220
221 if __name__ == "__main__":
222   if len(sys.argv) == 2:
223     cmd = pickle.loads(sys.argv[1])
224     sys.argv = []
225     _prompt(commands=cmd)
226   else:
227     print "runConsole.py: incorrect usage!"
228 #