if executing a file, add the file's directory to the path to so that other files...
[plcapi.git] / plcsh
1 #!/usr/bin/python
2 #
3 # Interactive shell for testing PLCAPI
4 #
5 # Mark Huang <mlhuang@cs.princeton.edu>
6 # Copyright (C) 2005 The Trustees of Princeton University
7 #
8 # $Id$
9 #
10
11 import os
12 import sys
13 from socket import gethostname
14 from optparse import OptionParser
15 from getpass import getpass
16 from traceback import print_exc
17
18 sys.path.append(os.path.dirname(os.path.realpath(sys.argv[0])))
19 from PLC.Shell import Shell
20
21 parser = OptionParser(add_help_option = False)
22 parser.add_option("-f", "--config", help = "PLC configuration file")
23 parser.add_option("-h", "--url", help = "API URL")
24 parser.add_option("-c", "--cacert", help = "API SSL certificate")
25 parser.add_option("-k", "--insecure", help = "Do not check SSL certificate")
26 parser.add_option("-m", "--method", help = "API authentication method")
27 parser.add_option("-s", "--session", help = "API session key")
28 parser.add_option("-u", "--user", help = "API user name")
29 parser.add_option("-p", "--password", help = "API password")
30 parser.add_option("-r", "--role", help = "API role")
31 parser.add_option("-x", "--xmlrpc", action = "store_true", default = False, help = "Use XML-RPC interface")
32 parser.add_option("--help", action = "help", help = "show this help message and exit")
33 (options, args) = parser.parse_args()
34
35 # If user is specified but password is not
36 if options.user is not None and options.password is None:
37     try:
38         options.password = getpass()
39     except (EOFError, KeyboardInterrupt):
40         print
41         sys.exit(0)
42
43 # Initialize a single global instance (scripts may re-initialize
44 # this instance and/or create additional instances).
45 try:
46     shell = Shell(globals = globals(),
47                   config = options.config,
48                   url = options.url, xmlrpc = options.xmlrpc, cacert = options.cacert,
49                   method = options.method, role = options.role,
50                   user = options.user, password = options.password,
51                   session = options.session)
52     # Register a few more globals for backward compatibility
53     auth = shell.auth
54     api = shell.api
55     config = shell.config
56 except Exception, err:
57     print "Error:", err
58     print
59     parser.print_help()
60     sys.exit(1)
61
62 # If called by a script 
63 if len(sys.argv) > 1 and os.path.exists(sys.argv[1]):
64     # Pop us off the argument stack
65     sys.argv.pop(0)
66     script = sys.argv[0]
67     # Add of script to sys.path 
68     path = os.path.dirname(os.path.abspath(script))
69     sys.path.append(path)
70     from pprint import pprint
71     pprint(sys.path)                    
72     execfile(sys.argv[0])
73
74 # Otherwise, run an interactive shell environment
75 else:
76     if shell.server is None:
77         print "PlanetLab Central Direct API Access"
78         prompt = ""
79     elif shell.auth['AuthMethod'] == "anonymous":
80         prompt = "[anonymous]"
81         print "Connected anonymously"
82     elif shell.auth['AuthMethod'] == "session":
83         # XXX No way to tell node and user sessions apart from the
84         # client point of view.
85         prompt = "[%s]" % gethostname()
86         print "%s connected using session authentication" % gethostname()
87     else:
88         prompt = "[%s]" % shell.auth['Username']
89         print "%s connected using %s authentication" % \
90               (shell.auth['Username'], shell.auth['AuthMethod'])
91
92     # Readline and tab completion support
93     import atexit
94     import readline
95     import rlcompleter
96
97     print 'Type "system.listMethods()" or "help(method)" for more information.'
98     # Load command history
99     history_path = os.path.join(os.environ["HOME"], ".plcapi_history")
100     try:
101         file(history_path, 'a').close()
102         readline.read_history_file(history_path)
103         atexit.register(readline.write_history_file, history_path)
104     except IOError:
105         pass
106
107     # Enable tab completion
108     readline.parse_and_bind("tab: complete")
109
110     try:
111         while True:
112             command = ""
113             while True:
114                 # Get line
115                 try:
116                     if command == "":
117                         sep = ">>> "
118                     else:
119                         sep = "... "
120                     line = raw_input(prompt + sep)
121                 # Ctrl-C
122                 except KeyboardInterrupt:
123                     command = ""
124                     print
125                     break
126
127                 # Build up multi-line command
128                 command += line
129
130                 # Blank line or first line does not end in :
131                 if line == "" or (command == line and line[-1] != ':'):
132                     break
133
134                 command += os.linesep
135
136             # Blank line
137             if command == "":
138                 continue
139             # Quit
140             elif command in ["q", "quit", "exit"]:
141                 break
142
143             try:
144                 try:
145                     # Try evaluating as an expression and printing the result
146                     result = eval(command)
147                     if result is not None:
148                         print result
149                 except SyntaxError:
150                     # Fall back to executing as a statement
151                     exec command
152             except Exception, err:
153                 print_exc()
154
155     except EOFError:
156         print
157         pass