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