blob: 488c3599fffedf227aeb349779c0229f7994fea8 [file] [log] [blame]
adminbae64d82013-08-01 10:50:15 -07001#!/usr/bin/env python
2'''
3Created on 20-Dec-2012
Jeremy Songsterae01bba2016-07-11 15:39:17 -07004Modified 2016 by ON.Lab
Jon Hall5f15fef2015-07-17 14:22:14 -07005
Jeremy Songsterae01bba2016-07-11 15:39:17 -07006Please refer questions to either the onos test mailing list at <onos-test@onosproject.org>,
7the System Testing Plans and Results wiki page at <https://wiki.onosproject.org/x/voMg>,
8or the System Testing Guide page at <https://wiki.onosproject.org/x/WYQg>
adminbae64d82013-08-01 10:50:15 -07009
10 TestON is free software: you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation, either version 2 of the License, or
13 (at your option) any later version.
14
15 TestON is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
Jon Hall4ba53f02015-07-29 13:07:41 -070021 along with TestON. If not, see <http://www.gnu.org/licenses/>.
adminbae64d82013-08-01 10:50:15 -070022
23
24'''
25
26
27"""
28cli will provide the CLI shell for teston framework.
29
30A simple command-line interface for TestON.
31
32The TestON CLI provides a simple console which
33makes it easy to launch the test. For example, the command run will execute the test.
34
35teston> run test DpctlTest
36Several useful commands are provided.
37"""
38
39from subprocess import call
40from cmd import Cmd
41from os import isatty
42import sys
43import re
44import os
45import time
46import threading
47import __builtin__
48import pprint
49dump = pprint.PrettyPrinter(indent=4)
50__builtin__.testthread = False
51introduction = "TestON is the testing framework \nDeveloped by Paxterra Solutions (www.paxterrasolutions.com)"
Jon Hall0bde9ba2015-03-19 11:32:57 -070052__builtin__.COLORS = False
adminbae64d82013-08-01 10:50:15 -070053
Jon Hall1dd5a0a2015-07-08 10:49:26 -070054path = re.sub( "/bin$", "", sys.path[0] )
55sys.path.insert( 1, path )
Jon Hall0bde9ba2015-03-19 11:32:57 -070056from core.teston import *
adminbae64d82013-08-01 10:50:15 -070057
58class CLI( threading.Thread,Cmd,object ):
59 "command-line interface to execute the test."
60
61 prompt = 'teston> '
62
63 def __init__( self, teston, stdin=sys.stdin ):
64 self.teston = teston
Jon Hall0bde9ba2015-03-19 11:32:57 -070065
adminbae64d82013-08-01 10:50:15 -070066 self._mainevent = threading.Event()
67 threading.Thread.__init__(self)
68 self.main_stop = False
69 self.locals = { 'test': teston }
70 self.stdin = stdin
71 Cmd.__init__( self )
72 self.pause = False
73 self.stop = False
74 __builtin__.cli = self
75
76 def emptyline( self ):
77 "Don't repeat last command when you hit return."
78 pass
79
80 helpStr = (
81 " teston help"
82 )
83
84 def do_help( self, line ):
85 "Describe available CLI commands."
86 Cmd.do_help( self, line )
87 if line is '':
88 output( self.helpStr )
89 def do_run(self,args):
90 '''
91 run command will execute the test with following optional command line arguments
92 logdir <directory to store logs in>
93 testcases <list of testcases separated by comma or range of testcases separated by hypen>
94 mail <mail-id or list of mail-ids seperated by comma>
95 example 1, to execute the examples specified in the ~/examples diretory.
96 '''
Jon Hall1306a562015-09-04 11:21:24 -070097 try:
98 args = args.split()
99 options = {}
100 options = self.parseArgs(args,options)
101 options = dictToObj(options)
102 if not testthread:
103 test = TestThread(options)
104 test.start()
105 while test.isAlive():
106 test.join(1)
107 else:
108 print main.TEST+ " test execution paused, please resume that before executing to another test"
109 except KeyboardInterrupt, SystemExit:
110 print "Interrupt called, Exiting."
111 test._Thread__stop()
112 main.cleanup()
113 main.exit()
Jon Hall4ba53f02015-07-29 13:07:41 -0700114
adminbae64d82013-08-01 10:50:15 -0700115 def do_resume(self, line):
116 '''
117 resume command will continue the execution of paused test.
118 teston>resume
119 [2013-01-07 23:03:44.640723] [PoxTest] [STEP] 1.1: Checking the host reachability using pingHost
120 2013-01-07 23:03:44,858 - PoxTest - INFO - Expected Prompt Found
121 ....
122 '''
123 if testthread:
124 testthread.play()
125 else :
126 print "There is no test to resume"
Jon Hall4ba53f02015-07-29 13:07:41 -0700127
adminbae64d82013-08-01 10:50:15 -0700128 def do_nextstep(self,line):
129 '''
Jon Hall4ba53f02015-07-29 13:07:41 -0700130 nextstep will execute the next-step of the paused test and
adminbae64d82013-08-01 10:50:15 -0700131 it will pause the test after finishing of step.
Jon Hall4ba53f02015-07-29 13:07:41 -0700132
adminbae64d82013-08-01 10:50:15 -0700133 teston> nextstep
134 Will pause the test's execution, after completion of this step.....
Jon Hall4ba53f02015-07-29 13:07:41 -0700135
adminbae64d82013-08-01 10:50:15 -0700136 teston> [2013-01-07 21:24:26.286601] [PoxTest] [STEP] 1.8: Checking the host reachability using pingHost
137 2013-01-07 21:24:26,455 - PoxTest - INFO - Expected Prompt Found
138 .....
139 teston>
Jon Hall4ba53f02015-07-29 13:07:41 -0700140
adminbae64d82013-08-01 10:50:15 -0700141 '''
142 if testthread:
143 main.log.info("Executing the nextstep, Will pause test execution, after completion of the step")
144 testthread.play()
145 time.sleep(.1)
146 testthread.pause()
147 else:
148 print "There is no paused test "
Jon Hall4ba53f02015-07-29 13:07:41 -0700149
adminbae64d82013-08-01 10:50:15 -0700150 def do_dumpvar(self,line):
151 '''
152 dumpvar will print all the test data in raw format.
Jon Hall4ba53f02015-07-29 13:07:41 -0700153 usgae :
adminbae64d82013-08-01 10:50:15 -0700154 teston>dumpvar main
155 Here 'main' will be the test object.
Jon Hall4ba53f02015-07-29 13:07:41 -0700156
157 teston>dumpvar params
adminbae64d82013-08-01 10:50:15 -0700158 here 'params' will be the parameters specified in the params file.
Jon Hall4ba53f02015-07-29 13:07:41 -0700159
adminbae64d82013-08-01 10:50:15 -0700160 teston>dumpvar topology
161 here 'topology' will be topology specification of the test specified in topo file.
162 '''
163 if testthread:
164 if line == "main":
165 dump.pprint(vars(main))
166 else :
167 try :
168 dump.pprint(vars(main)[line])
Jon Hall1306a562015-09-04 11:21:24 -0700169 except KeyError as e:
adminbae64d82013-08-01 10:50:15 -0700170 print e
171 else :
172 print "There is no paused test "
Jon Hall4ba53f02015-07-29 13:07:41 -0700173
adminbae64d82013-08-01 10:50:15 -0700174 def do_currentcase(self,line):
175 '''
176 currentcase will return the current case in the test execution.
Jon Hall4ba53f02015-07-29 13:07:41 -0700177
adminbae64d82013-08-01 10:50:15 -0700178 teston>currentcase
179 Currently executing test case is: 2
Jon Hall4ba53f02015-07-29 13:07:41 -0700180
adminbae64d82013-08-01 10:50:15 -0700181 '''
182 if testthread:
183 print "Currently executing test case is: "+str(main.CurrentTestCaseNumber)
184 else :
185 print "There is no paused test "
Jon Hall4ba53f02015-07-29 13:07:41 -0700186
187
adminbae64d82013-08-01 10:50:15 -0700188 def do_currentstep(self,line):
189 '''
190 currentstep will return the current step in the test execution.
Jon Hall4ba53f02015-07-29 13:07:41 -0700191
adminbae64d82013-08-01 10:50:15 -0700192 teston>currentstep
193 Currently executing test step is: 2.3
194 '''
195 if testthread:
196 print "Currently executing test step is: "+str(main.CurrentTestCaseNumber)+'.'+str(main.stepCount)
197 else :
198 print "There is no paused test "
Jon Hall4ba53f02015-07-29 13:07:41 -0700199
200
adminbae64d82013-08-01 10:50:15 -0700201 def do_stop(self,line):
202 '''
203 Will stop the paused test, if any !
204 '''
205 if testthread:
206 testthread.stop()
Jon Hall4ba53f02015-07-29 13:07:41 -0700207
adminbae64d82013-08-01 10:50:15 -0700208 return 'exited by user command'
Jon Hall4ba53f02015-07-29 13:07:41 -0700209
adminbae64d82013-08-01 10:50:15 -0700210 def do_gettest(self,line):
211 '''
212 gettest will return the test name which is under execution or recently executed.
Jon Hall4ba53f02015-07-29 13:07:41 -0700213
adminbae64d82013-08-01 10:50:15 -0700214 Test under execution:
Jon Hall4ba53f02015-07-29 13:07:41 -0700215 teston>gettest
adminbae64d82013-08-01 10:50:15 -0700216 Currently executing Test is: PoxTest
Jon Hall4ba53f02015-07-29 13:07:41 -0700217
adminbae64d82013-08-01 10:50:15 -0700218 Test recently executed:
219 Recently executed test is: MininetTest
220 '''
221 try :
222 if testthread :
223 print "Currently executing Test is: "+main.TEST
224 else :
225 print "Recently executed test is: "+main.TEST
Jon Hall4ba53f02015-07-29 13:07:41 -0700226
adminbae64d82013-08-01 10:50:15 -0700227 except NameError:
228 print "There is no previously executed Test"
Jon Hall4ba53f02015-07-29 13:07:41 -0700229
adminbae64d82013-08-01 10:50:15 -0700230 def do_showlog(self,line):
231 '''
232 showlog will show the test's Log
233 teston>showlog
234 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
235 .....
236 teston>showlog
237 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
238 .....
239 '''
240 try :
241 if testthread :
242 print "Currently executing Test's log is: "+main.LogFileName
Jon Hall4ba53f02015-07-29 13:07:41 -0700243
adminbae64d82013-08-01 10:50:15 -0700244 else :
245 print "Last executed test's log is : "+main.LogFileName
Jon Hall4ba53f02015-07-29 13:07:41 -0700246
adminbae64d82013-08-01 10:50:15 -0700247 logFile = main.LogFileName
248 logFileHandler = open(logFile, 'r')
249 for msg in logFileHandler.readlines() :
250 print msg,
Jon Hall4ba53f02015-07-29 13:07:41 -0700251
adminbae64d82013-08-01 10:50:15 -0700252 logFileHandler.close()
Jon Hall4ba53f02015-07-29 13:07:41 -0700253
adminbae64d82013-08-01 10:50:15 -0700254 except NameError:
255 print "There is no previously executed Test"
Jon Hall4ba53f02015-07-29 13:07:41 -0700256
257
258
adminbae64d82013-08-01 10:50:15 -0700259 def parseArgs(self,args,options):
260 '''
261 This will parse the command line arguments.
262 '''
263 options = self.initOptions(options)
264 try :
265 for index, option in enumerate(args):
266 if index > 0 :
Hari Krishna03f530e2015-07-10 17:28:27 -0700267 if re.match("logdir|mail|example|testdir|testcases|onoscell", option, flags = 0):
adminbae64d82013-08-01 10:50:15 -0700268 index = index+1
269 options[option] = args[index]
270 options = self.testcasesInRange(index,option,args,options)
YPZhang1c89e762016-06-29 10:43:58 -0700271 elif re.match("--params", option, flags=0):
272 # check if there is a params
273 index = index + 1
274 options['params'].append(args[index])
adminbae64d82013-08-01 10:50:15 -0700275 else :
276 options['testname'] = option
Jon Hall1306a562015-09-04 11:21:24 -0700277 except IndexError as e:
adminbae64d82013-08-01 10:50:15 -0700278 print e
Jon Hall4ba53f02015-07-29 13:07:41 -0700279
adminbae64d82013-08-01 10:50:15 -0700280 return options
Jon Hall4ba53f02015-07-29 13:07:41 -0700281
adminbae64d82013-08-01 10:50:15 -0700282 def initOptions(self,options):
283 '''
284 This will initialize the commandline options.
285 '''
286 options['logdir'] = None
287 options['mail'] = None
288 options['example'] = None
289 options['testdir'] = None
290 options['testcases'] = None
Hari Krishna03f530e2015-07-10 17:28:27 -0700291 options['onoscell'] = None
YPZhang1c89e762016-06-29 10:43:58 -0700292 # init params as a empty list
293 options['params'] = []
Jon Hall4ba53f02015-07-29 13:07:41 -0700294 return options
295
adminbae64d82013-08-01 10:50:15 -0700296 def testcasesInRange(self,index,option,args,options):
297 '''
298 This method will handle testcases list,specified in range [1-10].
299 '''
300 if re.match("testcases",option,1):
301 testcases = []
302 args[index] = re.sub("\[|\]","",args[index],0)
303 m = re.match("(\d+)\-(\d+)",args[index],flags=0)
304 if m:
305 start_case = eval(m.group(1))
306 end_case = eval(m.group(2))
307 if (start_case <= end_case):
308 i = start_case
309 while i <= end_case:
310 testcases.append(i)
Jon Hall4ba53f02015-07-29 13:07:41 -0700311 i= i+1
adminbae64d82013-08-01 10:50:15 -0700312 else :
313 print "Please specify testcases properly like 1-5"
314 else :
315 options[option] = args[index]
316 return options
317 options[option] = str(testcases)
Jon Hall4ba53f02015-07-29 13:07:41 -0700318
adminbae64d82013-08-01 10:50:15 -0700319 return options
Jon Hall4ba53f02015-07-29 13:07:41 -0700320
adminbae64d82013-08-01 10:50:15 -0700321 def cmdloop(self, intro=introduction):
322 print introduction
323 while True:
324 try:
325 super(CLI, self).cmdloop(intro="")
326 self.postloop()
327 except KeyboardInterrupt:
Jon Hall1306a562015-09-04 11:21:24 -0700328 if testthread:
329 testthread.pause()
330 else:
331 print "KeyboardInterrupt, Exiting."
332 sys.exit()
adminbae64d82013-08-01 10:50:15 -0700333
334 def do_echo( self, line ):
335 '''
336 Echoing of given input.
337 '''
338 output(line)
339
340 def do_sh( self, line ):
341 '''
342 Run an external shell command
343 sh pwd
344 sh ifconfig etc.
345 '''
346 call( line, shell=True )
347
348
349 def do_py( self, line ):
350 '''
351 Evaluate a Python expression.
Jon Hall4ba53f02015-07-29 13:07:41 -0700352
adminbae64d82013-08-01 10:50:15 -0700353 py main.log.info("Sample Log Information")
354 2013-01-07 12:07:26,804 - PoxTest - INFO - Sample Log Information
Jon Hall4ba53f02015-07-29 13:07:41 -0700355
adminbae64d82013-08-01 10:50:15 -0700356 '''
357 try:
358 exec( line )
Jon Hall1306a562015-09-04 11:21:24 -0700359 except Exception as e:
adminbae64d82013-08-01 10:50:15 -0700360 output( str( e ) + '\n' )
Jon Hall4ba53f02015-07-29 13:07:41 -0700361
adminbae64d82013-08-01 10:50:15 -0700362 def do_interpret(self,line):
363 '''
364 interpret will translate the single line openspeak statement to equivalent python script.
Jon Hall4ba53f02015-07-29 13:07:41 -0700365
adminbae64d82013-08-01 10:50:15 -0700366 teston> interpret ASSERT result EQUALS main.TRUE ONPASS "Ping executed successfully" ONFAIL "Ping failed"
367 utilities.assert_equals(expect=main.TRUE,actual=result,onpass="Ping executed successfully",onfail="Ping failed")
Jon Hall4ba53f02015-07-29 13:07:41 -0700368
adminbae64d82013-08-01 10:50:15 -0700369 '''
370 from core import openspeak
371 ospk = openspeak.OpenSpeak()
372 try :
373 translated_code = ospk.interpret(text=line)
374 print translated_code
Jon Hall1306a562015-09-04 11:21:24 -0700375 except AttributeError as e:
adminbae64d82013-08-01 10:50:15 -0700376 print 'Dynamic params are not allowed in single statement translations'
Jon Hall4ba53f02015-07-29 13:07:41 -0700377
adminbae64d82013-08-01 10:50:15 -0700378 def do_do (self,line):
379 '''
380 Do will translate and execute the openspeak statement for the paused test.
381 do <OpenSpeak statement>
382 '''
383 if testthread:
384 from core import openspeak
385 ospk = openspeak.OpenSpeak()
386 try :
387 translated_code = ospk.interpret(text=line)
388 eval(translated_code)
Jon Hall1306a562015-09-04 11:21:24 -0700389 except ( AttributeError, SyntaxError ) as e:
390 print 'Dynamic params are not allowed in single statement translations:'
391 print e
adminbae64d82013-08-01 10:50:15 -0700392 else :
393 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 -0700394
adminbae64d82013-08-01 10:50:15 -0700395 def do_compile(self,line):
396 '''
397 compile will translate the openspeak (.ospk) file into TestON test script (python).
Jon Hall4ba53f02015-07-29 13:07:41 -0700398 It will receive the openspeak file path as input and will generate
399 equivalent test-script file in the same directory.
400
adminbae64d82013-08-01 10:50:15 -0700401 usage:
402 -----
403 teston>compile /home/openflow/TestON/PoxTest.ospk
Jon Hall4ba53f02015-07-29 13:07:41 -0700404
adminbae64d82013-08-01 10:50:15 -0700405 Auto-generated test-script file is /home/openflow/TestON/PoxTest.py
406 '''
407 from core import openspeak
Jon Hall4ba53f02015-07-29 13:07:41 -0700408 openspeak = openspeak.OpenSpeak()
adminbae64d82013-08-01 10:50:15 -0700409 openspeakfile = line
410 if os.path.exists(openspeakfile) :
411 openspeak.compiler(openspeakfile=openspeakfile,writetofile=1)
412 print "Auto-generated test-script file is "+ re.sub("ospk","py",openspeakfile,0)
413 else:
414 print 'There is no such file : '+line
415
416 def do_exit( self, _line ):
417 "Exit"
418 if testthread:
419 testthread.stop()
Jon Hall4ba53f02015-07-29 13:07:41 -0700420
adminbae64d82013-08-01 10:50:15 -0700421 sys.exit()
422
423 return 'exited by user command'
424
425 def do_quit( self, line ):
426 "Exit"
427 return self.do_exit( line )
428
429 def do_EOF( self, line ):
430 "Exit"
431 output( '\n' )
432 return self.do_exit( line )
433
434 def isatty( self ):
435 "Is our standard input a tty?"
436 return isatty( self.stdin.fileno() )
437
438 def do_source( self, line ):
439 '''
440 Read shell commands from an input file and execute them sequentially.
441 cmdsource.txt :
Jon Hall4ba53f02015-07-29 13:07:41 -0700442
adminbae64d82013-08-01 10:50:15 -0700443 "pwd
444 ls "
Jon Hall4ba53f02015-07-29 13:07:41 -0700445
adminbae64d82013-08-01 10:50:15 -0700446 teston>source /home/openflow/cmdsource.txt
447 /home/openflow/TestON/bin/
448 cli.py __init__.py
Jon Hall4ba53f02015-07-29 13:07:41 -0700449
adminbae64d82013-08-01 10:50:15 -0700450 '''
Jon Hall4ba53f02015-07-29 13:07:41 -0700451
adminbae64d82013-08-01 10:50:15 -0700452 args = line.split()
453 if len(args) != 1:
454 error( 'usage: source <file>\n' )
455 return
456 try:
457 self.inputFile = open( args[ 0 ] )
458 while True:
459 line = self.inputFile.readline()
460 if len( line ) > 0:
461 call( line, shell=True )
462 else:
463 break
464 except IOError:
465 error( 'error reading file %s\n' % args[ 0 ] )
Jon Hall4ba53f02015-07-29 13:07:41 -0700466
adminbae64d82013-08-01 10:50:15 -0700467 def do_time( self, line ):
468 "Measure time taken for any command in TestON."
469 start = time.time()
470 self.onecmd(line)
471 elapsed = time.time() - start
472 self.stdout.write("*** Elapsed time: %0.6f secs\n" % elapsed)
473
474 def default( self, line ):
475 """Called on an input line when the command prefix is not recognized."""
476 first, args, line = self.parseline( line )
477 if not args:
478 return
479 if args and len(args) > 0 and args[ -1 ] == '\n':
480 args = args[ :-1 ]
481 rest = args.split( ' ' )
482
483 error( '*** Unknown command: %s\n' % first )
484
adminbae64d82013-08-01 10:50:15 -0700485class TestThread(threading.Thread):
486 '''
487 TestThread class will handle the test execution and will communicate with the thread in the do_run.
488 '''
489 def __init__(self,options):
490 self._stopevent = threading.Event()
491 threading.Thread.__init__(self)
492 self.is_stop = False
493 self.options = options
494 __builtin__.testthread = self
495
496 def run(self):
497 '''
498 Will execute the test.
499 '''
500 while not self.is_stop :
501 if not self._stopevent.isSet():
502 self.test_on = TestON(self.options)
503 try :
504 if self.test_on.init_result:
505 result = self.test_on.run()
506 if not self.is_stop :
507 result = self.test_on.cleanup()
508 self.is_stop = True
Jon Hall1306a562015-09-04 11:21:24 -0700509 except KeyboardInterrupt:
510 print "Recevied Interrupt, cleaning-up the logs and drivers before exiting"
adminbae64d82013-08-01 10:50:15 -0700511 result = self.test_on.cleanup()
512 self.is_stop = True
513
Jon Hall4ba53f02015-07-29 13:07:41 -0700514 __builtin__.testthread = False
adminbae64d82013-08-01 10:50:15 -0700515
516 def pause(self):
517 '''
518 Will pause the test.
519 '''
Jon Hall1306a562015-09-04 11:21:24 -0700520 if not cli.pause:
521 print "Will pause the test's execution, after completion of this step.....\n\n\n\n"
522 cli.pause = True
523 self._stopevent.set()
524 elif cli.pause and self.is_stop:
525 print "KeyboardInterrupt, Exiting."
526 self.test_on.exit()
527 else:
528 print "Recevied Interrupt, cleaning-up the logs and drivers before exiting"
529 result = self.test_on.cleanup()
530 self.is_stop = True
adminbae64d82013-08-01 10:50:15 -0700531
532 def play(self):
533 '''
534 Will resume the paused test.
535 '''
536 self._stopevent.clear()
537 cli.pause = False
Jon Hall4ba53f02015-07-29 13:07:41 -0700538
adminbae64d82013-08-01 10:50:15 -0700539 def stop(self):
540 '''
541 Will stop the test execution.
542 '''
Jon Hall4ba53f02015-07-29 13:07:41 -0700543
adminbae64d82013-08-01 10:50:15 -0700544 print "Stopping the test"
545 self.is_stop = True
546 cli.stop = True
547 __builtin__.testthread = False
Jon Hall4ba53f02015-07-29 13:07:41 -0700548
adminbae64d82013-08-01 10:50:15 -0700549def output(msg):
550 '''
551 Simply, print the message in console
552 '''
553 print msg
554
555def error(msg):
556 '''
557 print the error message.
558 '''
559 print msg
560
561def dictToObj(dictionary):
562 '''
563 This will facilitates the converting of the dictionary to the object.
564 This method will help to send options as object format to the test.
565 '''
566 if isinstance(dictionary, list):
567 dictionary = [dictToObj(x) for x in dictionary]
568 if not isinstance(dictionary, dict):
569 return dictionary
570 class Convert(object):
571 pass
572 obj = Convert()
573 for k in dictionary:
574 obj.__dict__[k] = dictToObj(dictionary[k])
575 return obj
576
577
578if __name__ == '__main__':
579 if len(sys.argv) > 1:
Jon Hall0bde9ba2015-03-19 11:32:57 -0700580 __builtin__.COLORS = True
adminbae64d82013-08-01 10:50:15 -0700581 CLI("test").onecmd(' '.join(sys.argv[1:]))
582 else:
Jon Hall0bde9ba2015-03-19 11:32:57 -0700583 __builtin__.COLORS = False
adminbae64d82013-08-01 10:50:15 -0700584 CLI("test").cmdloop()