- separate out command-line parsing/interpreter from PLC.Shell
[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: Shell.py,v 1.1 2007/01/08 18:10:30 mlhuang Exp $
9 #
10
11 import os
12 import sys
13 from optparse import OptionParser
14 from traceback import print_exc
15
16 sys.path.append(os.path.dirname(os.path.realpath(sys.argv[0])))
17 from PLC.Shell import Shell
18
19 parser = OptionParser(add_help_option = False)
20 parser.add_option("-f", "--config", help = "PLC configuration file")
21 parser.add_option("-h", "--url", help = "API URL")
22 parser.add_option("-c", "--cacert", help = "API SSL certificate")
23 parser.add_option("-m", "--method", help = "API authentication method")
24 parser.add_option("-u", "--user", help = "API user name")
25 parser.add_option("-p", "--password", help = "API password")
26 parser.add_option("-r", "--role", help = "API role")
27 parser.add_option("-x", "--xmlrpc", action = "store_true", default = False, help = "Use XML-RPC interface")
28 parser.add_option("--help", action = "help", help = "show this help message and exit")
29 (options, args) = parser.parse_args()
30
31 # If user is specified but password is not
32 if options.user is not None and options.password is None:
33     try:
34         options.password = getpass.getpass()
35     except (EOFError, KeyboardInterrupt):
36         print
37         sys.exit(0)
38
39 # Initialize a single global instance (scripts may re-initialize
40 # this instance and/or create additional instances).
41 try:
42     shell = Shell(globals = globals(),
43                   config = options.config,
44                   url = options.url, xmlrpc = options.xmlrpc, cacert = options.cacert,
45                   method = options.method, role = options.role,
46                   user = options.user, password = options.password)
47 except Exception, err:
48     print "Error:", err
49     print
50     parser.print_help()
51     sys.exit(1)
52
53 # If called by a script
54 if len(sys.argv) > 1 and os.path.exists(sys.argv[1]):
55     # Pop us off the argument stack
56     sys.argv.pop(0)
57     execfile(sys.argv[0])
58
59 # Otherwise, run an interactive shell environment
60 else:
61     if shell.server is None:
62         print "PlanetLab Central Direct API Access"
63         prompt = ""
64     elif shell.auth['AuthMethod'] == "anonymous":
65         prompt = "[anonymous]"
66         print "Connected anonymously"
67     else:
68         prompt = "[%s]" % shell.auth['Username']
69         print "%s connected using %s authentication" % \
70               (shell.auth['Username'], shell.auth['AuthMethod'])
71
72     # Readline and tab completion support
73     import atexit
74     import readline
75     import rlcompleter
76
77     print 'Type "system.listMethods()" or "help(method)" for more information.'
78     # Load command history
79     history_path = os.path.join(os.environ["HOME"], ".plcapi_history")
80     try:
81         file(history_path, 'a').close()
82         readline.read_history_file(history_path)
83         atexit.register(readline.write_history_file, history_path)
84     except IOError:
85         pass
86
87     # Enable tab completion
88     readline.parse_and_bind("tab: complete")
89
90     try:
91         while True:
92             command = ""
93             while True:
94                 # Get line
95                 try:
96                     if command == "":
97                         sep = ">>> "
98                     else:
99                         sep = "... "
100                     line = raw_input(prompt + sep)
101                 # Ctrl-C
102                 except KeyboardInterrupt:
103                     command = ""
104                     print
105                     break
106
107                 # Build up multi-line command
108                 command += line
109
110                 # Blank line or first line does not end in :
111                 if line == "" or (command == line and line[-1] != ':'):
112                     break
113
114                 command += os.linesep
115
116             # Blank line
117             if command == "":
118                 continue
119             # Quit
120             elif command in ["q", "quit", "exit"]:
121                 break
122
123             try:
124                 try:
125                     # Try evaluating as an expression and printing the result
126                     result = eval(command)
127                     if result is not None:
128                         print result
129                 except SyntaxError:
130                     # Fall back to executing as a statement
131                     exec command
132             except Exception, err:
133                 print_exc()
134
135     except EOFError:
136         print
137         pass