comparison cmd2/cmd2.py @ 104:bd91925d813c

having a hard time capturing stdout
author catherine@dellzilla
date Fri, 24 Oct 2008 13:29:22 -0400
parents e4daf715fc31
children 130340609e19
comparison
equal deleted inserted replaced
103:e4daf715fc31 104:bd91925d813c
20 20
21 CHANGES: 21 CHANGES:
22 As of 0.3.0, options should be specified as `optparse` options. See README.txt. 22 As of 0.3.0, options should be specified as `optparse` options. See README.txt.
23 flagReader.py options are still supported for backward compatibility 23 flagReader.py options are still supported for backward compatibility
24 """ 24 """
25 import cmd, re, os, sys, optparse, subprocess, tempfile, pyparsing, doctest 25 import cmd, re, os, sys, optparse, subprocess, tempfile, pyparsing, doctest, unittest
26 from optparse import make_option 26 from optparse import make_option
27 __version__ = '0.3.7' 27 __version__ = '0.3.7'
28 28
29 class OptionParser(optparse.OptionParser): 29 class OptionParser(optparse.OptionParser):
30 def exit(self, status=0, msg=None): 30 def exit(self, status=0, msg=None):
674 setattr(self, attrib, getattr(self.obj, attrib)) 674 setattr(self, attrib, getattr(self.obj, attrib))
675 def restore(self): 675 def restore(self):
676 for attrib in self.attribs: 676 for attrib in self.attribs:
677 setattr(self.obj, attrib, getattr(self, attrib)) 677 setattr(self.obj, attrib, getattr(self, attrib))
678 678
679 class Borg(object):
680 '''All instances of any Borg subclass will share state.
681 from Python Cookbook, 2nd Ed., recipe 6.16'''
682 _shared_state = {}
683 def __new__(cls, *a, **k):
684 obj = object.__new__(cls, *a, **k)
685 obj.__dict__ = cls._shared_state
686 return obj
687
688 class OutputTrap(Borg):
689 '''Instantiate an OutputTrap to divert/capture ALL stdout output. For use in unit testing.
690 Call `tearDown()` to return to normal output.'''
691 old_stdout = sys.stdout
692 def __init__(self):
693 #self.old_stdout = sys.stdout
694 self.trap = tempfile.TemporaryFile()
695 sys.stdout = self.trap
696 def dump(self):
697 'Reads trapped stdout output.'
698 self.trap.seek(0)
699 result = self.trap.read()
700 self.trap.close()
701 self.trap = tempfile.TemporaryFile()
702 sys.stdout = self.trap
703 return result
704 def tearDown(self):
705 sys.stdout = self.old_stdout
706
707 class TranscriptReader(object):
708 def __init__(self, cmdapp, filename='test_cmd2.txt'):
709 self.cmdapp = cmdapp
710 try:
711 tfile = open(filename)
712 self.transcript = tfile.read()
713 tfile.close()
714 except IOError:
715 self.transcript = ''
716 self.bookmark = 0
717 def refreshCommandFinder(self):
718 prompt = pyparsing.Suppress(pyparsing.lineStart + self.cmdapp.prompt)
719 continuationPrompt = pyparsing.Suppress(pyparsing.lineStart + self.cmdapp.continuationPrompt)
720 self.cmdtxtPattern = (prompt + pyparsing.restOfLine + pyparsing.ZeroOrMore(
721 pyparsing.lineEnd + continuationPrompt + pyparsing.restOfLine))("command")
722 def inputGenerator(self):
723 while True:
724 self.refreshCommandFinder()
725 (thiscmd, startpos, endpos) = self.cmdtxtPattern.scanString(self.transcript[self.bookmark:], maxMatches=1).next()
726 lineNum = self.transcript.count('\n', 0, self.bookmark+startpos) + 2
727 self.bookmark += endpos
728 yield (''.join(thiscmd.command), lineNum)
729 def nextExpected(self):
730 self.refreshCommandFinder()
731 try:
732 (thiscmd, startpos, endpos) = self.cmdtxtPattern.scanString(self.transcript[self.bookmark:], maxMatches=1).next()
733 result = self.transcript[self.bookmark:self.bookmark+startpos]
734 self.bookmark += startpos
735 return result
736 except StopIteration:
737 return self.transcript[self.bookmark:]
738
739 class Cmd2TestCase(unittest.TestCase):
740 '''Subclass this, setting CmdApp and transcriptFileName, to make a unittest.TestCase class
741 that will execute the commands in transcriptFileName and expect the results shown.'''
742 # problem: this (raw) case gets called by unittest.main - we don't want it to be. hmm
743 CmdApp = None
744 transcriptFileName = ''
745 def setUp(self):
746 if self.CmdApp:
747 self.cmdapp = self.CmdApp()
748 self.outputTrap = OutputTrap()
749 self.transcriptReader = TranscriptReader(self.cmdapp, self.transcriptFileName)
750 def testall(self):
751 if self.CmdApp:
752 for (cmdInput, lineNum) in self.transcriptReader.inputGenerator():
753 self.cmdapp.onecmd(cmdInput)
754 result = self.outputTrap.dump()
755 expected = self.transcriptReader.nextExpected()
756 self.assertEqual(result.strip(), expected.strip(),
757 '\nFile %s, line %d\nCommand was:\n%s\nExpected:\n%s\nGot:\n%s\n' %
758 (self.transcriptFileName, lineNum, cmdInput, expected, result))
759 def tearDown(self):
760 if self.CmdApp:
761 self.outputTrap.tearDown()
762
679 if __name__ == '__main__': 763 if __name__ == '__main__':
680 doctest.testmod() 764 doctest.testmod()