Initial checkin of new API implementation
[plcapi.git] / Shell.py
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: plcsh,v 1.3 2006/01/09 19:57:24 mlhuang Exp $
9 #
10
11 import os, sys
12 import traceback
13 import getopt
14 import pydoc
15
16 from PLC.API import PLCAPI
17 from PLC.Method import Method
18
19 # Defaults
20 config = "/etc/planetlab/plc_config"
21
22 def usage():
23     print "Usage: %s [OPTION]..." % sys.argv[0]
24     print "Options:"
25     print "     -f, --config=FILE       PLC configuration file (default: %s)" % config
26     print "     -h, --help              This message"
27     sys.exit(1)
28
29 # Get options
30 try:
31     (opts, argv) = getopt.getopt(sys.argv[1:], "f:h", ["config=", "help"])
32 except getopt.GetoptError, err:
33     print "Error: " + err.msg
34     usage()
35
36 for (opt, optval) in opts:
37     if opt == "-f" or opt == "--config":
38         config = optval
39     elif opt == "-h" or opt == "--help":
40         usage()
41
42 api = PLCAPI(config)
43
44 class Dummy:
45     """
46     Dummy class to support tab completion of API methods with dots in
47     their names (e.g., system.listMethods).
48     """
49     pass
50         
51 # Define all methods in the global namespace to support tab completion
52 for method in api.methods:
53     paths = method.split(".")
54     if len(paths) > 1:
55         first = paths.pop(0)
56         if first not in globals():
57             globals()[first] = Dummy()
58         obj = globals()[first]
59         for path in paths:
60             if not hasattr(obj, path):
61                 if path == paths[-1]:
62                     setattr(obj, path, api.callable(method))
63                 else:
64                     setattr(obj, path, Dummy())
65             obj = getattr(obj, path)
66     else:
67         globals()[method] = api.callable(method)
68
69 pyhelp = help
70 def help(thing):
71     """
72     Override builtin help() function to support calling help(method).
73     """
74
75     if isinstance(thing, Method):
76         return pydoc.pager(thing.help())
77     else:
78         return pyhelp(thing)
79
80 # If a file is specified
81 if argv:
82     execfile(argv[0])
83     sys.exit(0)
84
85 # Otherwise, create an interactive shell environment
86
87 print "PlanetLab Central Direct API Access"
88 prompt = ""
89 print 'Type "system.listMethods()" or "help(method)" for more information.'
90
91 # Readline and tab completion support
92 import atexit
93 import readline
94 import rlcompleter
95
96 # Load command history
97 history_path = os.path.join(os.environ["HOME"], ".plcapi_history")
98 try:
99     file(history_path, 'a').close()
100     readline.read_history_file(history_path)
101     atexit.register(readline.write_history_file, history_path)
102 except IOError:
103     pass
104
105 # Enable tab completion
106 readline.parse_and_bind("tab: complete")
107
108 try:
109     while True:
110         command = ""
111         while True:
112             # Get line
113             try:
114                 if command == "":
115                     sep = ">>> "
116                 else:
117                     sep = "... "
118                 line = raw_input(prompt + sep)
119             # Ctrl-C
120             except KeyboardInterrupt:
121                 command = ""
122                 print
123                 break
124
125             # Build up multi-line command
126             command += line
127
128             # Blank line or first line does not end in :
129             if line == "" or (command == line and line[-1] != ':'):
130                 break
131
132             command += os.linesep
133
134         # Blank line
135         if command == "":
136             continue
137         # Quit
138         elif command in ["q", "quit", "exit"]:
139             break
140
141         try:
142             try:
143                 # Try evaluating as an expression and printing the result
144                 result = eval(command)
145                 if result is not None:
146                     print result
147             except:
148                 # Fall back to executing as a statement
149                 exec command
150         except Exception, err:
151             traceback.print_exc()
152
153 except EOFError:
154     print
155     pass