Setting tag plcapi-7.0-0
[plcapi.git] / plcsh
1 #!/usr/bin/env python3
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
9 import os
10 import sys
11 from socket import gethostname
12 from optparse import OptionParser
13 from getpass import getpass
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 usage="""Usage: %prog [options]
20    runs an interactive shell
21 Usage: %prog [options] script script-arguments
22 Usage: %prog script [plcsh-options --] script arguments
23    run a script"""
24
25 parser = OptionParser(usage=usage,add_help_option = False)
26 parser.add_option("-f", "--config", help = "PLC configuration file")
27 parser.add_option("-h", "--url", help = "API URL")
28 parser.add_option("-c", "--cacert", help = "API SSL certificate")
29 parser.add_option("-k", "--insecure", help = "Do not check SSL certificate")
30 parser.add_option("-m", "--method", help = "API authentication method")
31 parser.add_option("-s", "--session", help = "API session key")
32 parser.add_option("-u", "--user", help = "API user name")
33 parser.add_option("-p", "--password", help = "API password")
34 parser.add_option("-r", "--role", help = "API role")
35 parser.add_option("-x", "--xmlrpc", action = "store_true",
36                   default = False, help = "Use XML-RPC interface")
37 # pass this to the invoked shell if any
38 parser.add_option("--help", action = "store_true", dest="help", default=False,
39                   help = "show this help message and exit")
40 (options, args) = parser.parse_args()
41
42 if not args and options.help:
43     parser.print_help()
44     sys.exit(1)
45
46 # If user is specified but password is not
47 if options.user is not None and options.password is None:
48     try:
49         options.password = getpass()
50     except (EOFError, KeyboardInterrupt):
51         print()
52         sys.exit(0)
53
54 # Initialize a single global instance (scripts may re-initialize
55 # this instance and/or create additional instances).
56 try:
57     shell = Shell(globals = globals(),
58                   config = options.config,
59                   url = options.url, xmlrpc = options.xmlrpc, cacert = options.cacert,
60                   method = options.method, role = options.role,
61                   user = options.user, password = options.password,
62                   session = options.session)
63     # Register a few more globals for backward compatibility
64     auth = shell.auth
65     api = shell.api
66     config = shell.config
67 except Exception as err:
68     print("Error:", err)
69     print()
70     parser.print_help()
71     sys.exit(1)
72
73 # If called by a script
74 if args:
75     if not os.path.exists(args[0]):
76         print('File %s not found'%args[0])
77         parser.print_help()
78         sys.exit(1)
79     else:
80         # re-append --help if provided
81         if options.help:
82             args.append('--help')
83         # use args as sys.argv for the next shell, so our own options get removed for the next script
84         sys.argv = args
85         script = sys.argv[0]
86         # Add of script to sys.path
87         path = os.path.dirname(os.path.abspath(script))
88         sys.path.append(path)
89         with open(script) as feed:
90             exec(feed.read())
91
92 # Otherwise, run an interactive shell environment
93 else:
94     if shell.server is None:
95         print("PlanetLab Central Direct API Access")
96         prompt = ""
97     elif shell.auth['AuthMethod'] == "anonymous":
98         prompt = "[anonymous]"
99         print("Connected anonymously")
100     elif shell.auth['AuthMethod'] == "session":
101         # XXX No way to tell node and user sessions apart from the
102         # client point of view.
103         prompt = "[%s]" % gethostname()
104         print("%s connected using session authentication" % gethostname())
105     else:
106         prompt = "[%s]" % shell.auth['Username']
107         print("%s connected using %s authentication" % \
108               (shell.auth['Username'], shell.auth['AuthMethod']))
109
110     # Readline and tab completion support
111     import atexit
112     import readline
113     import rlcompleter
114
115     print('Type "system.listMethods()" or "help(method)" for more information.')
116     # Load command history
117     history_path = os.path.join(os.environ["HOME"], ".plcapi_history")
118     try:
119         # check directory: pretend to open
120         with open(history_path, 'a') as check:
121             pass
122         readline.read_history_file(history_path)
123         atexit.register(readline.write_history_file, history_path)
124     except IOError:
125         pass
126
127     # Enable tab completion
128     readline.parse_and_bind("tab: complete")
129
130     try:
131         while True:
132             command = ""
133             while True:
134                 # Get line
135                 try:
136                     if command == "":
137                         sep = ">>> "
138                     else:
139                         sep = "... "
140                     line = input(prompt + sep)
141                 # Ctrl-C
142                 except KeyboardInterrupt:
143                     command = ""
144                     print()
145                     break
146
147                 # Build up multi-line command
148                 command += line
149
150                 # Blank line or first line does not end in :
151                 if line == "" or (command == line and line[-1] != ':'):
152                     break
153
154                 command += os.linesep
155
156             # Blank line
157             if command == "":
158                 continue
159             # Quit
160             elif command in ["q", "quit", "exit"]:
161                 break
162
163             try:
164                 try:
165                     # Try evaluating as an expression and printing the result
166                     result = eval(command)
167                     if result is not None:
168                         print(result)
169                 except SyntaxError:
170                     # Fall back to executing as a statement
171                     exec(command)
172             except Exception as err:
173                 print_exc()
174
175     except EOFError:
176         print()
177         pass