4 srfsh.py - provides a basic shell for issuing OpenSRF requests
10 - runs <count> opensrf.math requests and reports the average time
12 request <service> <method> [<param1>, <param2>, ...]
13 - performs an opensrf request
16 - sets an environment variable
18 Environment variables:
19 SRFSH_OUTPUT = pretty - print pretty JSON and key/value pairs for network objects
20 = raw - print formatted JSON
22 SRFSH_LOCALE = <locale> - request responses to be returned in locale <locale> if available
25 import os, sys, time, readline, atexit, re
32 # -------------------------------------------------------------------
34 # -------------------------------------------------------------------
39 #line = raw_input("srfsh% ")
40 line = raw_input("\033[01;32msrfsh\033[01;34m% \033[00m")
43 if str.lower(line) == 'exit' or str.lower(line) == 'quit':
45 parts = str.split(line)
49 if command == 'request':
54 if command == 'math_bench':
56 handle_math_bench(parts)
73 except KeyboardInterrupt:
81 # -------------------------------------------------------------------
82 # Set env variables to control behavior
83 # -------------------------------------------------------------------
84 def handle_set(parts):
86 pattern = re.compile('(.*)=(.*)').match(cmd)
87 key = pattern.group(1)
88 val = pattern.group(2)
90 print "%s = %s" % (key, val)
92 def handle_get(parts):
94 print get_var(parts[0])
99 # -------------------------------------------------------------------
101 # -------------------------------------------------------------------
105 # -------------------------------------------------------------------
106 # performs an opensrf request
107 # -------------------------------------------------------------------
108 def handle_request(parts):
109 service = parts.pop(0)
110 method = parts.pop(0)
111 locale = __get_locale()
112 jstr = '[%s]' % "".join(parts)
116 params = osrf.json.to_object(jstr)
118 print "Error parsing JSON: %s" % jstr
121 ses = osrf.ses.ClientSession(service, locale=locale)
125 req = ses.request2(method, tuple(params))
129 resp = req.recv(timeout=120)
130 osrf.log.log_internal("Looping through receive request")
133 total = time.time() - start
135 otp = get_var('SRFSH_OUTPUT')
137 print "\n" + osrf.json.debug_net_object(resp.content())
139 print osrf.json.pprint(osrf.json.to_json(resp.content()))
145 print "Total request time: %f" % total
149 def handle_math_bench(parts):
151 count = int(parts.pop(0))
152 ses = osrf.ses.ClientSession('opensrf.math')
155 for cnt in range(100):
157 sys.stdout.write('.')
159 sys.stdout.write( str( cnt / 10 ) )
163 for cnt in range(count):
165 starttime = time.time()
166 req = ses.request('add', 1, 2)
167 resp = req.recv(timeout=2)
168 endtime = time.time()
170 if resp.content() == 3:
171 sys.stdout.write("+")
173 times.append( endtime - starttime )
175 print "What happened? %s" % str(resp.content())
178 if not ( (cnt + 1) % 100):
179 print ' [%d]' % (cnt + 1)
185 print "\naverage time %f" % (total / len(times))
190 # -------------------------------------------------------------------
191 # Defines the tab-completion handling and sets up the readline history
192 # -------------------------------------------------------------------
193 def setup_readline():
194 class SrfshCompleter(object):
195 def __init__(self, words):
199 def complete(self, prefix, index):
200 if prefix != self.prefix:
201 # find all words that start with this prefix
202 self.matching_words = [
203 w for w in self.words if w.startswith(prefix)
207 return self.matching_words[index]
211 words = 'request', 'help', 'exit', 'quit', 'opensrf.settings', 'opensrf.math', 'set'
212 completer = SrfshCompleter(words)
213 readline.parse_and_bind("tab: complete")
214 readline.set_completer(completer.complete)
216 histfile = os.path.join(get_var('HOME'), ".srfsh_history")
218 readline.read_history_file(histfile)
221 atexit.register(readline.write_history_file, histfile)
224 file = os.path.join(get_var('HOME'), ".srfsh.xml")
225 print_green("Connecting to opensrf...")
226 osrf.system.connect(file, 'srfsh')
230 # Load the user defined external plugins
231 # XXX Make this a real module interface, with tab-complete words, commands, etc.
233 plugins = osrf.conf.get('plugins')
236 # XXX standard srfsh.xml does not yet define <plugins> element
237 print_red("No plugins defined in /srfsh/plugins/plugin\n")
240 plugins = osrf.conf.get('plugins.plugin')
241 if not isinstance(plugins, list):
244 for module in plugins:
245 name = module['module']
246 init = module['init']
247 print_green("Loading module %s..." % name)
250 string = 'from %s import %s\n%s()' % (name, init, init)
255 sys.stderr.write("\nError importing plugin %s, with init symbol %s: \n%s\n" % (name, init, e))
258 if not get_var('SRFSH_OUTPUT'):
259 set_var('SRFSH_OUTPUT', 'pretty')
261 # XXX Do we need to differ between LANG and LC_MESSAGES?
262 if not get_var('SRFSH_LOCALE'):
263 set_var('SRFSH_LOCALE', get_var('LC_ALL'))
265 def set_var(key, val):
266 os.environ[key] = val
270 return os.environ[key]
276 Return the defined locale for this srfsh session.
278 A locale in OpenSRF is currently defined as a [a-z]{2}-[A-Z]{2} pattern.
279 This function munges the LC_ALL setting to conform to that pattern; for
280 example, trimming en_CA.UTF-8 to en-CA.
283 >>> srfsh.set_var('SRFSH_LOCALE', 'zz-ZZ')
284 >>> print __get_locale()
286 >>> srfsh.set_var('SRFSH_LOCALE', 'en_CA.UTF-8')
287 >>> print __get_locale()
291 env_locale = get_var('SRFSH_LOCALE')
292 pattern = re.compile(r'^\s*([a-z]+)[^a-zA-Z]([A-Z]+)').search(env_locale)
293 lang = pattern.group(1)
294 region = pattern.group(2)
295 locale = "%s-%s" % (lang, region)
298 def print_green(string):
299 sys.stdout.write("\033[01;32m")
300 sys.stdout.write(string)
301 sys.stdout.write("\033[00m")
304 def print_red(string):
305 sys.stdout.write("\033[01;31m")
306 sys.stdout.write(string)
307 sys.stdout.write("\033[00m")
311 if __name__ == '__main__':