blob: f49bfca4e12c78534745fe0e286b4eee50a71d6e [file] [log] [blame]
adminbae64d82013-08-01 10:50:15 -07001#!/usr/bin/env python
2'''
3Created on 20-Dec-2012
Jon Hall5f15fef2015-07-17 14:22:14 -07004
adminbae64d82013-08-01 10:50:15 -07005@author: Anil Kumar (anilkumar.s@paxterrasolutions.com)
6
7
8
9 TestON is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 2 of the License, or
12 (at your option) any later version.
13
14 TestON is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
Jon Hall4ba53f02015-07-29 13:07:41 -070020 along with TestON. If not, see <http://www.gnu.org/licenses/>.
adminbae64d82013-08-01 10:50:15 -070021
22
23'''
24
25
26"""
27cli will provide the CLI shell for teston framework.
28
29A simple command-line interface for TestON.
30
31The TestON CLI provides a simple console which
32makes it easy to launch the test. For example, the command run will execute the test.
33
34teston> run test DpctlTest
35Several useful commands are provided.
36"""
37
38from subprocess import call
39from cmd import Cmd
40from os import isatty
41import sys
42import re
43import os
44import time
45import threading
46import __builtin__
47import pprint
48dump = pprint.PrettyPrinter(indent=4)
49__builtin__.testthread = False
50introduction = "TestON is the testing framework \nDeveloped by Paxterra Solutions (www.paxterrasolutions.com)"
Jon Hall0bde9ba2015-03-19 11:32:57 -070051__builtin__.COLORS = False
adminbae64d82013-08-01 10:50:15 -070052
Jon Hall1dd5a0a2015-07-08 10:49:26 -070053path = re.sub( "/bin$", "", sys.path[0] )
54sys.path.insert( 1, path )
Jon Hall0bde9ba2015-03-19 11:32:57 -070055from core.teston import *
adminbae64d82013-08-01 10:50:15 -070056
57class CLI( threading.Thread,Cmd,object ):
58 "command-line interface to execute the test."
59
60 prompt = 'teston> '
61
62 def __init__( self, teston, stdin=sys.stdin ):
63 self.teston = teston
Jon Hall0bde9ba2015-03-19 11:32:57 -070064
adminbae64d82013-08-01 10:50:15 -070065 self._mainevent = threading.Event()
66 threading.Thread.__init__(self)
67 self.main_stop = False
68 self.locals = { 'test': teston }
69 self.stdin = stdin
70 Cmd.__init__( self )
71 self.pause = False
72 self.stop = False
73 __builtin__.cli = self
74
75 def emptyline( self ):
76 "Don't repeat last command when you hit return."
77 pass
78
79 helpStr = (
80 " teston help"
81 )
82
83 def do_help( self, line ):
84 "Describe available CLI commands."
85 Cmd.do_help( self, line )
86 if line is '':
87 output( self.helpStr )
88 def do_run(self,args):
89 '''
90 run command will execute the test with following optional command line arguments
91 logdir <directory to store logs in>
92 testcases <list of testcases separated by comma or range of testcases separated by hypen>
93 mail <mail-id or list of mail-ids seperated by comma>
94 example 1, to execute the examples specified in the ~/examples diretory.
95 '''
Jon Hall1306a562015-09-04 11:21:24 -070096 try:
97 args = args.split()
98 options = {}
99 options = self.parseArgs(args,options)
100 options = dictToObj(options)
101 if not testthread:
102 test = TestThread(options)
103 test.start()
104 while test.isAlive():
105 test.join(1)
106 else:
107 print main.TEST+ " test execution paused, please resume that before executing to another test"
108 except KeyboardInterrupt, SystemExit:
109 print "Interrupt called, Exiting."
110 test._Thread__stop()
111 main.cleanup()
112 main.exit()
Jon Hall4ba53f02015-07-29 13:07:41 -0700113
adminbae64d82013-08-01 10:50:15 -0700114 def do_resume(self, line):
115 '''
116 resume command will continue the execution of paused test.
117 teston>resume
118 [2013-01-07 23:03:44.640723] [PoxTest] [STEP] 1.1: Checking the host reachability using pingHost
119 2013-01-07 23:03:44,858 - PoxTest - INFO - Expected Prompt Found
120 ....
121 '''
122 if testthread:
123 testthread.play()
124 else :
125 print "There is no test to resume"
Jon Hall4ba53f02015-07-29 13:07:41 -0700126
adminbae64d82013-08-01 10:50:15 -0700127 def do_nextstep(self,line):
128 '''
Jon Hall4ba53f02015-07-29 13:07:41 -0700129 nextstep will execute the next-step of the paused test and
adminbae64d82013-08-01 10:50:15 -0700130 it will pause the test after finishing of step.
Jon Hall4ba53f02015-07-29 13:07:41 -0700131
adminbae64d82013-08-01 10:50:15 -0700132 teston> nextstep
133 Will pause the test's execution, after completion of this step.....
Jon Hall4ba53f02015-07-29 13:07:41 -0700134
adminbae64d82013-08-01 10:50:15 -0700135 teston> [2013-01-07 21:24:26.286601] [PoxTest] [STEP] 1.8: Checking the host reachability using pingHost
136 2013-01-07 21:24:26,455 - PoxTest - INFO - Expected Prompt Found
137 .....
138 teston>
Jon Hall4ba53f02015-07-29 13:07:41 -0700139
adminbae64d82013-08-01 10:50:15 -0700140 '''
141 if testthread:
142 main.log.info("Executing the nextstep, Will pause test execution, after completion of the step")
143 testthread.play()
144 time.sleep(.1)
145 testthread.pause()
146 else:
147 print "There is no paused test "
Jon Hall4ba53f02015-07-29 13:07:41 -0700148
adminbae64d82013-08-01 10:50:15 -0700149 def do_dumpvar(self,line):
150 '''
151 dumpvar will print all the test data in raw format.
Jon Hall4ba53f02015-07-29 13:07:41 -0700152 usgae :
adminbae64d82013-08-01 10:50:15 -0700153 teston>dumpvar main
154 Here 'main' will be the test object.
Jon Hall4ba53f02015-07-29 13:07:41 -0700155
156 teston>dumpvar params
adminbae64d82013-08-01 10:50:15 -0700157 here 'params' will be the parameters specified in the params file.
Jon Hall4ba53f02015-07-29 13:07:41 -0700158
adminbae64d82013-08-01 10:50:15 -0700159 teston>dumpvar topology
160 here 'topology' will be topology specification of the test specified in topo file.
161 '''
162 if testthread:
163 if line == "main":
164 dump.pprint(vars(main))
165 else :
166 try :
167 dump.pprint(vars(main)[line])
Jon Hall1306a562015-09-04 11:21:24 -0700168 except KeyError as e:
adminbae64d82013-08-01 10:50:15 -0700169 print e
170 else :
171 print "There is no paused test "
Jon Hall4ba53f02015-07-29 13:07:41 -0700172
adminbae64d82013-08-01 10:50:15 -0700173 def do_currentcase(self,line):
174 '''
175 currentcase will return the current case in the test execution.
Jon Hall4ba53f02015-07-29 13:07:41 -0700176
adminbae64d82013-08-01 10:50:15 -0700177 teston>currentcase
178 Currently executing test case is: 2
Jon Hall4ba53f02015-07-29 13:07:41 -0700179
adminbae64d82013-08-01 10:50:15 -0700180 '''
181 if testthread:
182 print "Currently executing test case is: "+str(main.CurrentTestCaseNumber)
183 else :
184 print "There is no paused test "
Jon Hall4ba53f02015-07-29 13:07:41 -0700185
186
adminbae64d82013-08-01 10:50:15 -0700187 def do_currentstep(self,line):
188 '''
189 currentstep will return the current step in the test execution.
Jon Hall4ba53f02015-07-29 13:07:41 -0700190
adminbae64d82013-08-01 10:50:15 -0700191 teston>currentstep
192 Currently executing test step is: 2.3
193 '''
194 if testthread:
195 print "Currently executing test step is: "+str(main.CurrentTestCaseNumber)+'.'+str(main.stepCount)
196 else :
197 print "There is no paused test "
Jon Hall4ba53f02015-07-29 13:07:41 -0700198
199
adminbae64d82013-08-01 10:50:15 -0700200 def do_stop(self,line):
201 '''
202 Will stop the paused test, if any !
203 '''
204 if testthread:
205 testthread.stop()
Jon Hall4ba53f02015-07-29 13:07:41 -0700206
adminbae64d82013-08-01 10:50:15 -0700207 return 'exited by user command'
Jon Hall4ba53f02015-07-29 13:07:41 -0700208
adminbae64d82013-08-01 10:50:15 -0700209 def do_gettest(self,line):
210 '''
211 gettest will return the test name which is under execution or recently executed.
Jon Hall4ba53f02015-07-29 13:07:41 -0700212
adminbae64d82013-08-01 10:50:15 -0700213 Test under execution:
Jon Hall4ba53f02015-07-29 13:07:41 -0700214 teston>gettest
adminbae64d82013-08-01 10:50:15 -0700215 Currently executing Test is: PoxTest
Jon Hall4ba53f02015-07-29 13:07:41 -0700216
adminbae64d82013-08-01 10:50:15 -0700217 Test recently executed:
218 Recently executed test is: MininetTest
219 '''
220 try :
221 if testthread :
222 print "Currently executing Test is: "+main.TEST
223 else :
224 print "Recently executed test is: "+main.TEST
Jon Hall4ba53f02015-07-29 13:07:41 -0700225
adminbae64d82013-08-01 10:50:15 -0700226 except NameError:
227 print "There is no previously executed Test"
Jon Hall4ba53f02015-07-29 13:07:41 -0700228
adminbae64d82013-08-01 10:50:15 -0700229 def do_showlog(self,line):
230 '''
231 showlog will show the test's Log
232 teston>showlog
233 Last executed test's log is : //home/openflow/TestON/logs/PoxTest_07_Jan_2013_21_42_11/PoxTest_07_Jan_2013_21_42_11.log
234 .....
235 teston>showlog
236 Currently executing Test's log is: /home/openflow/TestON/logs/PoxTest_07_Jan_2013_21_46_58/PoxTest_07_Jan_2013_21_46_58.log
237 .....
238 '''
239 try :
240 if testthread :
241 print "Currently executing Test's log is: "+main.LogFileName
Jon Hall4ba53f02015-07-29 13:07:41 -0700242
adminbae64d82013-08-01 10:50:15 -0700243 else :
244 print "Last executed test's log is : "+main.LogFileName
Jon Hall4ba53f02015-07-29 13:07:41 -0700245
adminbae64d82013-08-01 10:50:15 -0700246 logFile = main.LogFileName
247 logFileHandler = open(logFile, 'r')
248 for msg in logFileHandler.readlines() :
249 print msg,
Jon Hall4ba53f02015-07-29 13:07:41 -0700250
adminbae64d82013-08-01 10:50:15 -0700251 logFileHandler.close()
Jon Hall4ba53f02015-07-29 13:07:41 -0700252
adminbae64d82013-08-01 10:50:15 -0700253 except NameError:
254 print "There is no previously executed Test"
Jon Hall4ba53f02015-07-29 13:07:41 -0700255
256
257
adminbae64d82013-08-01 10:50:15 -0700258 def parseArgs(self,args,options):
259 '''
260 This will parse the command line arguments.
261 '''
262 options = self.initOptions(options)
263 try :
YPZhang16f6e562016-07-12 15:50:31 -0700264 index = 0
265 while index < len( args ):
266 option = args[index]
adminbae64d82013-08-01 10:50:15 -0700267 if index > 0 :
YPZhang16f6e562016-07-12 15:50:31 -0700268 if re.match("--params", option, flags=0):
YPZhang1c89e762016-06-29 10:43:58 -0700269 # check if there is a params
YPZhang16f6e562016-07-12 15:50:31 -0700270 options['params'].append(args[index+1])
271 elif re.match("logdir|mail|example|testdir|testcases|onoscell", option, flags = 0):
272 options[option] = args[index+1]
273 options = self.testcasesInRange(index+1,option,args,options)
274 index += 2
adminbae64d82013-08-01 10:50:15 -0700275 else :
276 options['testname'] = option
YPZhang16f6e562016-07-12 15:50:31 -0700277 index += 1
Jon Hall1306a562015-09-04 11:21:24 -0700278 except IndexError as e:
YPZhang16f6e562016-07-12 15:50:31 -0700279 print (e)
280 main.cleanup()
281 main.exit()
Jon Hall4ba53f02015-07-29 13:07:41 -0700282
adminbae64d82013-08-01 10:50:15 -0700283 return options
Jon Hall4ba53f02015-07-29 13:07:41 -0700284
adminbae64d82013-08-01 10:50:15 -0700285 def initOptions(self,options):
286 '''
287 This will initialize the commandline options.
288 '''
289 options['logdir'] = None
290 options['mail'] = None
291 options['example'] = None
292 options['testdir'] = None
293 options['testcases'] = None
Hari Krishna03f530e2015-07-10 17:28:27 -0700294 options['onoscell'] = None
YPZhang1c89e762016-06-29 10:43:58 -0700295 # init params as a empty list
296 options['params'] = []
Jon Hall4ba53f02015-07-29 13:07:41 -0700297 return options
298
adminbae64d82013-08-01 10:50:15 -0700299 def testcasesInRange(self,index,option,args,options):
300 '''
301 This method will handle testcases list,specified in range [1-10].
302 '''
303 if re.match("testcases",option,1):
304 testcases = []
305 args[index] = re.sub("\[|\]","",args[index],0)
306 m = re.match("(\d+)\-(\d+)",args[index],flags=0)
307 if m:
308 start_case = eval(m.group(1))
309 end_case = eval(m.group(2))
310 if (start_case <= end_case):
311 i = start_case
312 while i <= end_case:
313 testcases.append(i)
Jon Hall4ba53f02015-07-29 13:07:41 -0700314 i= i+1
adminbae64d82013-08-01 10:50:15 -0700315 else :
316 print "Please specify testcases properly like 1-5"
317 else :
318 options[option] = args[index]
319 return options
320 options[option] = str(testcases)
Jon Hall4ba53f02015-07-29 13:07:41 -0700321
adminbae64d82013-08-01 10:50:15 -0700322 return options
Jon Hall4ba53f02015-07-29 13:07:41 -0700323
adminbae64d82013-08-01 10:50:15 -0700324 def cmdloop(self, intro=introduction):
325 print introduction
326 while True:
327 try:
328 super(CLI, self).cmdloop(intro="")
329 self.postloop()
330 except KeyboardInterrupt:
Jon Hall1306a562015-09-04 11:21:24 -0700331 if testthread:
332 testthread.pause()
333 else:
334 print "KeyboardInterrupt, Exiting."
335 sys.exit()
adminbae64d82013-08-01 10:50:15 -0700336
337 def do_echo( self, line ):
338 '''
339 Echoing of given input.
340 '''
341 output(line)
342
343 def do_sh( self, line ):
344 '''
345 Run an external shell command
346 sh pwd
347 sh ifconfig etc.
348 '''
349 call( line, shell=True )
350
351
352 def do_py( self, line ):
353 '''
354 Evaluate a Python expression.
Jon Hall4ba53f02015-07-29 13:07:41 -0700355
adminbae64d82013-08-01 10:50:15 -0700356 py main.log.info("Sample Log Information")
357 2013-01-07 12:07:26,804 - PoxTest - INFO - Sample Log Information
Jon Hall4ba53f02015-07-29 13:07:41 -0700358
adminbae64d82013-08-01 10:50:15 -0700359 '''
360 try:
361 exec( line )
Jon Hall1306a562015-09-04 11:21:24 -0700362 except Exception as e:
adminbae64d82013-08-01 10:50:15 -0700363 output( str( e ) + '\n' )
Jon Hall4ba53f02015-07-29 13:07:41 -0700364
adminbae64d82013-08-01 10:50:15 -0700365 def do_interpret(self,line):
366 '''
367 interpret will translate the single line openspeak statement to equivalent python script.
Jon Hall4ba53f02015-07-29 13:07:41 -0700368
adminbae64d82013-08-01 10:50:15 -0700369 teston> interpret ASSERT result EQUALS main.TRUE ONPASS "Ping executed successfully" ONFAIL "Ping failed"
370 utilities.assert_equals(expect=main.TRUE,actual=result,onpass="Ping executed successfully",onfail="Ping failed")
Jon Hall4ba53f02015-07-29 13:07:41 -0700371
adminbae64d82013-08-01 10:50:15 -0700372 '''
373 from core import openspeak
374 ospk = openspeak.OpenSpeak()
375 try :
376 translated_code = ospk.interpret(text=line)
377 print translated_code
Jon Hall1306a562015-09-04 11:21:24 -0700378 except AttributeError as e:
adminbae64d82013-08-01 10:50:15 -0700379 print 'Dynamic params are not allowed in single statement translations'
Jon Hall4ba53f02015-07-29 13:07:41 -0700380
adminbae64d82013-08-01 10:50:15 -0700381 def do_do (self,line):
382 '''
383 Do will translate and execute the openspeak statement for the paused test.
384 do <OpenSpeak statement>
385 '''
386 if testthread:
387 from core import openspeak
388 ospk = openspeak.OpenSpeak()
389 try :
390 translated_code = ospk.interpret(text=line)
391 eval(translated_code)
Jon Hall1306a562015-09-04 11:21:24 -0700392 except ( AttributeError, SyntaxError ) as e:
393 print 'Dynamic params are not allowed in single statement translations:'
394 print e
adminbae64d82013-08-01 10:50:15 -0700395 else :
396 print "Do will translate and execute the openspeak statement for the paused test.\nPlease use interpret to translate the OpenSpeak statement."
Jon Hall4ba53f02015-07-29 13:07:41 -0700397
adminbae64d82013-08-01 10:50:15 -0700398 def do_compile(self,line):
399 '''
400 compile will translate the openspeak (.ospk) file into TestON test script (python).
Jon Hall4ba53f02015-07-29 13:07:41 -0700401 It will receive the openspeak file path as input and will generate
402 equivalent test-script file in the same directory.
403
adminbae64d82013-08-01 10:50:15 -0700404 usage:
405 -----
406 teston>compile /home/openflow/TestON/PoxTest.ospk
Jon Hall4ba53f02015-07-29 13:07:41 -0700407
adminbae64d82013-08-01 10:50:15 -0700408 Auto-generated test-script file is /home/openflow/TestON/PoxTest.py
409 '''
410 from core import openspeak
Jon Hall4ba53f02015-07-29 13:07:41 -0700411 openspeak = openspeak.OpenSpeak()
adminbae64d82013-08-01 10:50:15 -0700412 openspeakfile = line
413 if os.path.exists(openspeakfile) :
414 openspeak.compiler(openspeakfile=openspeakfile,writetofile=1)
415 print "Auto-generated test-script file is "+ re.sub("ospk","py",openspeakfile,0)
416 else:
417 print 'There is no such file : '+line
418
419 def do_exit( self, _line ):
420 "Exit"
421 if testthread:
422 testthread.stop()
Jon Hall4ba53f02015-07-29 13:07:41 -0700423
adminbae64d82013-08-01 10:50:15 -0700424 sys.exit()
425
426 return 'exited by user command'
427
428 def do_quit( self, line ):
429 "Exit"
430 return self.do_exit( line )
431
432 def do_EOF( self, line ):
433 "Exit"
434 output( '\n' )
435 return self.do_exit( line )
436
437 def isatty( self ):
438 "Is our standard input a tty?"
439 return isatty( self.stdin.fileno() )
440
441 def do_source( self, line ):
442 '''
443 Read shell commands from an input file and execute them sequentially.
444 cmdsource.txt :
Jon Hall4ba53f02015-07-29 13:07:41 -0700445
adminbae64d82013-08-01 10:50:15 -0700446 "pwd
447 ls "
Jon Hall4ba53f02015-07-29 13:07:41 -0700448
adminbae64d82013-08-01 10:50:15 -0700449 teston>source /home/openflow/cmdsource.txt
450 /home/openflow/TestON/bin/
451 cli.py __init__.py
Jon Hall4ba53f02015-07-29 13:07:41 -0700452
adminbae64d82013-08-01 10:50:15 -0700453 '''
Jon Hall4ba53f02015-07-29 13:07:41 -0700454
adminbae64d82013-08-01 10:50:15 -0700455 args = line.split()
456 if len(args) != 1:
457 error( 'usage: source <file>\n' )
458 return
459 try:
460 self.inputFile = open( args[ 0 ] )
461 while True:
462 line = self.inputFile.readline()
463 if len( line ) > 0:
464 call( line, shell=True )
465 else:
466 break
467 except IOError:
468 error( 'error reading file %s\n' % args[ 0 ] )
Jon Hall4ba53f02015-07-29 13:07:41 -0700469
adminbae64d82013-08-01 10:50:15 -0700470 def do_time( self, line ):
471 "Measure time taken for any command in TestON."
472 start = time.time()
473 self.onecmd(line)
474 elapsed = time.time() - start
475 self.stdout.write("*** Elapsed time: %0.6f secs\n" % elapsed)
476
477 def default( self, line ):
478 """Called on an input line when the command prefix is not recognized."""
479 first, args, line = self.parseline( line )
480 if not args:
481 return
482 if args and len(args) > 0 and args[ -1 ] == '\n':
483 args = args[ :-1 ]
484 rest = args.split( ' ' )
485
486 error( '*** Unknown command: %s\n' % first )
487
adminbae64d82013-08-01 10:50:15 -0700488class TestThread(threading.Thread):
489 '''
490 TestThread class will handle the test execution and will communicate with the thread in the do_run.
491 '''
492 def __init__(self,options):
493 self._stopevent = threading.Event()
494 threading.Thread.__init__(self)
495 self.is_stop = False
496 self.options = options
497 __builtin__.testthread = self
498
499 def run(self):
500 '''
501 Will execute the test.
502 '''
503 while not self.is_stop :
504 if not self._stopevent.isSet():
505 self.test_on = TestON(self.options)
506 try :
507 if self.test_on.init_result:
508 result = self.test_on.run()
509 if not self.is_stop :
510 result = self.test_on.cleanup()
511 self.is_stop = True
Jon Hall1306a562015-09-04 11:21:24 -0700512 except KeyboardInterrupt:
513 print "Recevied Interrupt, cleaning-up the logs and drivers before exiting"
adminbae64d82013-08-01 10:50:15 -0700514 result = self.test_on.cleanup()
515 self.is_stop = True
516
Jon Hall4ba53f02015-07-29 13:07:41 -0700517 __builtin__.testthread = False
adminbae64d82013-08-01 10:50:15 -0700518
519 def pause(self):
520 '''
521 Will pause the test.
522 '''
Jon Hall1306a562015-09-04 11:21:24 -0700523 if not cli.pause:
524 print "Will pause the test's execution, after completion of this step.....\n\n\n\n"
525 cli.pause = True
526 self._stopevent.set()
527 elif cli.pause and self.is_stop:
528 print "KeyboardInterrupt, Exiting."
529 self.test_on.exit()
530 else:
531 print "Recevied Interrupt, cleaning-up the logs and drivers before exiting"
532 result = self.test_on.cleanup()
533 self.is_stop = True
adminbae64d82013-08-01 10:50:15 -0700534
535 def play(self):
536 '''
537 Will resume the paused test.
538 '''
539 self._stopevent.clear()
540 cli.pause = False
Jon Hall4ba53f02015-07-29 13:07:41 -0700541
adminbae64d82013-08-01 10:50:15 -0700542 def stop(self):
543 '''
544 Will stop the test execution.
545 '''
Jon Hall4ba53f02015-07-29 13:07:41 -0700546
adminbae64d82013-08-01 10:50:15 -0700547 print "Stopping the test"
548 self.is_stop = True
549 cli.stop = True
550 __builtin__.testthread = False
Jon Hall4ba53f02015-07-29 13:07:41 -0700551
adminbae64d82013-08-01 10:50:15 -0700552def output(msg):
553 '''
554 Simply, print the message in console
555 '''
556 print msg
557
558def error(msg):
559 '''
560 print the error message.
561 '''
562 print msg
563
564def dictToObj(dictionary):
565 '''
566 This will facilitates the converting of the dictionary to the object.
567 This method will help to send options as object format to the test.
568 '''
569 if isinstance(dictionary, list):
570 dictionary = [dictToObj(x) for x in dictionary]
571 if not isinstance(dictionary, dict):
572 return dictionary
573 class Convert(object):
574 pass
575 obj = Convert()
576 for k in dictionary:
577 obj.__dict__[k] = dictToObj(dictionary[k])
578 return obj
579
580
581if __name__ == '__main__':
582 if len(sys.argv) > 1:
Jon Hall0bde9ba2015-03-19 11:32:57 -0700583 __builtin__.COLORS = True
adminbae64d82013-08-01 10:50:15 -0700584 CLI("test").onecmd(' '.join(sys.argv[1:]))
585 else:
Jon Hall0bde9ba2015-03-19 11:32:57 -0700586 __builtin__.COLORS = False
adminbae64d82013-08-01 10:50:15 -0700587 CLI("test").cmdloop()