"Fossies" - the Fresh Open Source Software Archive

Member "cheetah3-3.2.6.post2/Cheetah/Tests/CheetahWrapper.py" (20 Apr 2021, 19735 Bytes) of package /linux/www/cheetah3-3.2.6.post2.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Python source code syntax highlighting (style: standard) with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file. For more information about "CheetahWrapper.py" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 3-3.2.2_vs_3-3.2.3.

    1 #!/usr/bin/env python
    2 '''
    3 Tests for the 'cheetah' command.
    4 
    5 Besides unittest usage, recognizes the following command-line options:
    6     --list CheetahWrapper.py
    7         List all scenarios that are tested.  The argument is the path
    8         of this script.
    9      --nodelete
   10         Don't delete scratch directory at end.
   11      --output
   12         Show the output of each subcommand.  (Normally suppressed.)
   13 '''
   14 
   15 import os
   16 import os.path
   17 import re                                     # Used by listTests.
   18 import shutil
   19 import sys
   20 import tempfile
   21 import unittest
   22 
   23 from optparse import OptionParser
   24 from Cheetah.CheetahWrapper import CheetahWrapper  # Used by NoBackup.
   25 
   26 try:
   27     from subprocess import Popen, PIPE, STDOUT
   28 
   29     class Popen4(Popen):
   30         def __init__(self, cmd, bufsize=-1, shell=True, close_fds=True,
   31                      stdin=PIPE, stdout=PIPE, stderr=STDOUT, **kwargs):
   32 
   33             super(Popen4, self).__init__(
   34                 cmd, bufsize=bufsize, shell=shell, close_fds=close_fds,
   35                 stdin=stdin, stdout=stdout, stderr=stderr, **kwargs)
   36 
   37             self.tochild = self.stdin
   38             self.fromchild = self.stdout
   39             self.childerr = self.stderr
   40 except ImportError:
   41     from popen2 import Popen4
   42 
   43 DELETE = True  # True to clean up after ourselves, False for debugging.
   44 OUTPUT = False  # Normally False, True for debugging.
   45 
   46 BACKUP_SUFFIX = CheetahWrapper.BACKUP_SUFFIX
   47 
   48 
   49 def warn(msg):
   50     sys.stderr.write(msg + '\n')
   51 
   52 
   53 class CFBase(unittest.TestCase):
   54     """Base class for "cheetah compile" and "cheetah fill" unit tests.
   55     """
   56     srcDir = ''  # Nonblank to create source directory.
   57     subdirs = ('child', 'child/grandkid')  # Delete in reverse order.
   58     srcFiles = ('a.tmpl', 'child/a.tmpl', 'child/grandkid/a.tmpl')
   59     expectError = False  # Used by --list option.
   60 
   61     def inform(self, message):
   62         if self.verbose:
   63             print(message)
   64 
   65     def setUp(self):
   66         """Create the top-level directories, subdirectories and .tmpl
   67            files.
   68         """
   69         self.cmd = self.locate_cheetah('cheetah')
   70         cwd = os.getcwd()
   71         if not os.environ.get('PYTHONPATH'):
   72             os.environ['PYTHONPATH'] = cwd
   73         else:
   74             pythonPath = os.environ['PYTHONPATH']
   75             if (pythonPath != cwd) and \
   76                     not pythonPath.endswith(':%s' % cwd):
   77                 os.environ['PYTHONPATH'] = '%s:%s' % (pythonPath, cwd)
   78         # Step 1: Create the scratch directory and chdir into it.
   79         self.scratchDir = scratchDir = tempfile.mkdtemp()
   80         self.origCwd = os.getcwd()
   81         os.chdir(scratchDir)
   82         if self.srcDir:
   83             os.mkdir(self.srcDir)
   84         # Step 2: Create source subdirectories.
   85         for dir in self.subdirs:
   86             os.mkdir(dir)
   87         # Step 3: Create the .tmpl files, each in its proper directory.
   88         for fil in self.srcFiles:
   89             f = open(fil, 'w')
   90             f.write("Hello, world!\n")
   91             f.close()
   92 
   93     def tearDown(self):
   94         os.chdir(self.origCwd)
   95         if DELETE:
   96             shutil.rmtree(self.scratchDir, True)  # Ignore errors.
   97             if os.path.exists(self.scratchDir):
   98                 warn("Warning: unable to delete scratch directory %s")
   99         else:
  100             warn("Warning: not deleting scratch directory %s"
  101                  % self.scratchDir)
  102 
  103     def _checkDestFileHelper(self, path, expected,
  104                              allowSurroundingText, errmsg):
  105         """Low-level helper to check a destination file.
  106 
  107            in : path, string, the destination path.
  108                 expected, string, the expected contents.
  109                 allowSurroundingtext, bool, allow the result to contain
  110                   additional text around the 'expected' substring?
  111                 errmsg, string, the error message.  It may contain the
  112                   following "%"-operator keys: path, expected, result.
  113            out: None
  114         """
  115         path = os.path.abspath(path)
  116         exists = os.path.exists(path)
  117         msg = "destination file missing: %s" % path
  118         self.assertTrue(exists, msg)
  119         f = open(path, 'r')
  120         result = f.read()
  121         f.close()
  122         if allowSurroundingText:
  123             success = result.find(expected) != -1
  124         else:
  125             success = result == expected
  126         msg = errmsg % locals()
  127         self.assertTrue(success, msg)
  128 
  129     def checkCompile(self, path):
  130         # Raw string to prevent "\n" from being converted to a newline.
  131         # expected = R"write('Hello, world!\n')"
  132         expected = "Hello, world!"  # might output a u'' string
  133         errmsg = """\
  134 destination file %(path)s doesn't contain expected substring:
  135 %(expected)r"""
  136         self._checkDestFileHelper(path, expected, True, errmsg)
  137 
  138     def checkFill(self, path):
  139         expected = "Hello, world!\n"
  140         errmsg = """\
  141 destination file %(path)s contains wrong result.
  142 Expected %(expected)r
  143 Found %(result)r"""
  144         self._checkDestFileHelper(path, expected, False, errmsg)
  145 
  146     def checkSubdirPyInit(self, path):
  147         """Verify a destination subdirectory exists and contains an
  148            __init__.py file.
  149         """
  150         exists = os.path.exists(path)
  151         msg = "destination subdirectory %s misssing" % path
  152         self.assertTrue(exists, msg)
  153         initPath = os.path.join(path, "__init__.py")
  154         exists = os.path.exists(initPath)
  155         msg = "destination init file missing: %s" % initPath
  156         self.assertTrue(exists, msg)
  157 
  158     def checkNoBackup(self, path):
  159         """Verify 'path' does not exist.  (To check --nobackup.)
  160         """
  161         exists = os.path.exists(path)
  162         msg = "backup file exists in spite of --nobackup: %s" % path
  163         self.assertFalse(exists, msg)
  164 
  165     def locate_cheetah(self, cmd):
  166         paths = os.getenv('PATH')
  167         if not paths:
  168             return cmd
  169         paths = paths.split(':')
  170         for p in paths:
  171             p = os.path.join(p, cmd)
  172             p = os.path.abspath(p)
  173             if os.path.isfile(p):
  174                 return p
  175         return cmd
  176 
  177     def assertWin32Subprocess(self, cmd):
  178         try:
  179             from subprocess import Popen, PIPE, STDOUT
  180         except ImportError:
  181             _in, _out = os.popen4(cmd)
  182             _in.close()
  183             output = _out.read()
  184             status = _out.close()
  185             if status is None:
  186                 status = 0
  187         else:
  188             process = Popen(cmd, shell=True,
  189                             stdin=PIPE, stdout=PIPE, stderr=STDOUT)
  190             process.stdin.close()
  191             output = process.stdout.read()
  192             status = process.wait()
  193             process.stdout.close()
  194         return status, output
  195 
  196     def assertPosixSubprocess(self, cmd):
  197         cmd = cmd.replace('cheetah', self.cmd)
  198         process = Popen4(cmd, env=os.environ)
  199         process.tochild.close()
  200         output = process.fromchild.read()
  201         status = process.wait()
  202         process.fromchild.close()
  203         return status, output
  204 
  205     def assertSubprocess(self, cmd, nonzero=False):
  206         status, output = None, None
  207         if sys.platform == 'win32':
  208             status, output = self.assertWin32Subprocess(cmd)
  209         else:
  210             status, output = self.assertPosixSubprocess(cmd)
  211 
  212         if not nonzero:
  213             self.assertEqual(status, 0, '''Subprocess exited with a non-zero status (%d)
  214                             %s''' % (status, output))
  215         else:
  216             self.assertNotEqual(status, 0, '''Subprocess exited with a zero status (%d)
  217                             %s''' % (status, output))
  218         return output
  219 
  220     def go(self, cmd, expectedStatus=0, expectedOutputSubstring=None):
  221         """Run a "cheetah compile" or "cheetah fill" subcommand.
  222 
  223            in : cmd, string, the command to run.
  224                 expectedStatus, int, subcommand's expected output status.
  225                   0 if the subcommand is expected to succeed, 1-255 otherwise.
  226                 expectedOutputSubstring, string, substring which much appear
  227                   in the standard output or standard error.  None to skip this
  228                   test.
  229            out: None.
  230         """
  231         output = self.assertSubprocess(cmd)
  232         if expectedOutputSubstring is not None:
  233             msg = "substring %r not found in subcommand output: %s" % \
  234                 (expectedOutputSubstring, cmd)
  235             substringTest = output.find(expectedOutputSubstring) != -1
  236             self.assertTrue(substringTest, msg)
  237 
  238 
  239 class CFIdirBase(CFBase):
  240     """Subclass for tests with --idir.
  241     """
  242     srcDir = 'SRC'
  243     subdirs = ('SRC/child', 'SRC/child/grandkid')  # Delete in reverse order.
  244     srcFiles = ('SRC/a.tmpl', 'SRC/child/a.tmpl', 'SRC/child/grandkid/a.tmpl')
  245 
  246 
  247 ##################################################
  248 # TEST CASE CLASSES
  249 
  250 
  251 class OneFile(CFBase):
  252     def testCompile(self):
  253         self.go("cheetah compile a.tmpl")
  254         self.checkCompile("a.py")
  255 
  256     def testFill(self):
  257         self.go("cheetah fill a.tmpl")
  258         self.checkFill("a.html")
  259 
  260     def testText(self):
  261         self.go("cheetah fill --oext txt a.tmpl")
  262         self.checkFill("a.txt")
  263 
  264 
  265 class OneFileNoExtension(CFBase):
  266     def testCompile(self):
  267         self.go("cheetah compile a")
  268         self.checkCompile("a.py")
  269 
  270     def testFill(self):
  271         self.go("cheetah fill a")
  272         self.checkFill("a.html")
  273 
  274     def testText(self):
  275         self.go("cheetah fill --oext txt a")
  276         self.checkFill("a.txt")
  277 
  278 
  279 class SplatTmpl(CFBase):
  280     def testCompile(self):
  281         self.go("cheetah compile *.tmpl")
  282         self.checkCompile("a.py")
  283 
  284     def testFill(self):
  285         self.go("cheetah fill *.tmpl")
  286         self.checkFill("a.html")
  287 
  288     def testText(self):
  289         self.go("cheetah fill --oext txt *.tmpl")
  290         self.checkFill("a.txt")
  291 
  292 
  293 class ThreeFilesWithSubdirectories(CFBase):
  294     def testCompile(self):
  295         self.go("cheetah compile a.tmpl child/a.tmpl child/grandkid/a.tmpl")
  296         self.checkCompile("a.py")
  297         self.checkCompile("child/a.py")
  298         self.checkCompile("child/grandkid/a.py")
  299 
  300     def testFill(self):
  301         self.go("cheetah fill a.tmpl child/a.tmpl child/grandkid/a.tmpl")
  302         self.checkFill("a.html")
  303         self.checkFill("child/a.html")
  304         self.checkFill("child/grandkid/a.html")
  305 
  306     def testText(self):
  307         self.go("cheetah fill --oext txt "
  308                 "a.tmpl child/a.tmpl child/grandkid/a.tmpl")
  309         self.checkFill("a.txt")
  310         self.checkFill("child/a.txt")
  311         self.checkFill("child/grandkid/a.txt")
  312 
  313 
  314 class ThreeFilesWithSubdirectoriesNoExtension(CFBase):
  315     def testCompile(self):
  316         self.go("cheetah compile a child/a child/grandkid/a")
  317         self.checkCompile("a.py")
  318         self.checkCompile("child/a.py")
  319         self.checkCompile("child/grandkid/a.py")
  320 
  321     def testFill(self):
  322         self.go("cheetah fill a child/a child/grandkid/a")
  323         self.checkFill("a.html")
  324         self.checkFill("child/a.html")
  325         self.checkFill("child/grandkid/a.html")
  326 
  327     def testText(self):
  328         self.go("cheetah fill --oext txt a child/a child/grandkid/a")
  329         self.checkFill("a.txt")
  330         self.checkFill("child/a.txt")
  331         self.checkFill("child/grandkid/a.txt")
  332 
  333 
  334 class SplatTmplWithSubdirectories(CFBase):
  335     def testCompile(self):
  336         self.go("cheetah compile *.tmpl child/*.tmpl child/grandkid/*.tmpl")
  337         self.checkCompile("a.py")
  338         self.checkCompile("child/a.py")
  339         self.checkCompile("child/grandkid/a.py")
  340 
  341     def testFill(self):
  342         self.go("cheetah fill *.tmpl child/*.tmpl child/grandkid/*.tmpl")
  343         self.checkFill("a.html")
  344         self.checkFill("child/a.html")
  345         self.checkFill("child/grandkid/a.html")
  346 
  347     def testText(self):
  348         self.go("cheetah fill --oext txt "
  349                 "*.tmpl child/*.tmpl child/grandkid/*.tmpl")
  350         self.checkFill("a.txt")
  351         self.checkFill("child/a.txt")
  352         self.checkFill("child/grandkid/a.txt")
  353 
  354 
  355 class OneFileWithOdir(CFBase):
  356     def testCompile(self):
  357         self.go("cheetah compile --odir DEST a.tmpl")
  358         self.checkSubdirPyInit("DEST")
  359         self.checkCompile("DEST/a.py")
  360 
  361     def testFill(self):
  362         self.go("cheetah fill --odir DEST a.tmpl")
  363         self.checkFill("DEST/a.html")
  364 
  365     def testText(self):
  366         self.go("cheetah fill --odir DEST --oext txt a.tmpl")
  367         self.checkFill("DEST/a.txt")
  368 
  369 
  370 class VarietyWithOdir(CFBase):
  371     def testCompile(self):
  372         self.go("cheetah compile --odir DEST "
  373                 "a.tmpl child/a child/grandkid/*.tmpl")
  374         self.checkSubdirPyInit("DEST")
  375         self.checkSubdirPyInit("DEST/child")
  376         self.checkSubdirPyInit("DEST/child/grandkid")
  377         self.checkCompile("DEST/a.py")
  378         self.checkCompile("DEST/child/a.py")
  379         self.checkCompile("DEST/child/grandkid/a.py")
  380 
  381     def testFill(self):
  382         self.go("cheetah fill --odir DEST "
  383                 "a.tmpl child/a child/grandkid/*.tmpl")
  384         self.checkFill("DEST/a.html")
  385         self.checkFill("DEST/child/a.html")
  386         self.checkFill("DEST/child/grandkid/a.html")
  387 
  388     def testText(self):
  389         self.go("cheetah fill --odir DEST --oext txt "
  390                 "a.tmpl child/a child/grandkid/*.tmpl")
  391         self.checkFill("DEST/a.txt")
  392         self.checkFill("DEST/child/a.txt")
  393         self.checkFill("DEST/child/grandkid/a.txt")
  394 
  395 
  396 class RecurseExplicit(CFBase):
  397     def testCompile(self):
  398         self.go("cheetah compile -R child")
  399         self.checkCompile("child/a.py")
  400         self.checkCompile("child/grandkid/a.py")
  401 
  402     def testFill(self):
  403         self.go("cheetah fill -R child")
  404         self.checkFill("child/a.html")
  405         self.checkFill("child/grandkid/a.html")
  406 
  407     def testText(self):
  408         self.go("cheetah fill -R --oext txt child")
  409         self.checkFill("child/a.txt")
  410         self.checkFill("child/grandkid/a.txt")
  411 
  412 
  413 class RecurseImplicit(CFBase):
  414     def testCompile(self):
  415         self.go("cheetah compile -R")
  416         self.checkCompile("child/a.py")
  417         self.checkCompile("child/grandkid/a.py")
  418 
  419     def testFill(self):
  420         self.go("cheetah fill -R")
  421         self.checkFill("a.html")
  422         self.checkFill("child/a.html")
  423         self.checkFill("child/grandkid/a.html")
  424 
  425     def testText(self):
  426         self.go("cheetah fill -R --oext txt")
  427         self.checkFill("a.txt")
  428         self.checkFill("child/a.txt")
  429         self.checkFill("child/grandkid/a.txt")
  430 
  431 
  432 class RecurseExplicitWIthOdir(CFBase):
  433     def testCompile(self):
  434         self.go("cheetah compile -R --odir DEST child")
  435         self.checkSubdirPyInit("DEST/child")
  436         self.checkSubdirPyInit("DEST/child/grandkid")
  437         self.checkCompile("DEST/child/a.py")
  438         self.checkCompile("DEST/child/grandkid/a.py")
  439 
  440     def testFill(self):
  441         self.go("cheetah fill -R --odir DEST child")
  442         self.checkFill("DEST/child/a.html")
  443         self.checkFill("DEST/child/grandkid/a.html")
  444 
  445     def testText(self):
  446         self.go("cheetah fill -R --odir DEST --oext txt child")
  447         self.checkFill("DEST/child/a.txt")
  448         self.checkFill("DEST/child/grandkid/a.txt")
  449 
  450 
  451 class Flat(CFBase):
  452     def testCompile(self):
  453         self.go("cheetah compile --flat child/a.tmpl")
  454         self.checkCompile("a.py")
  455 
  456     def testFill(self):
  457         self.go("cheetah fill --flat child/a.tmpl")
  458         self.checkFill("a.html")
  459 
  460     def testText(self):
  461         self.go("cheetah fill --flat --oext txt child/a.tmpl")
  462         self.checkFill("a.txt")
  463 
  464 
  465 class FlatRecurseCollision(CFBase):
  466     expectError = True
  467 
  468     def testCompile(self):
  469         self.assertSubprocess("cheetah compile -R --flat", nonzero=True)
  470 
  471     def testFill(self):
  472         self.assertSubprocess("cheetah fill -R --flat", nonzero=True)
  473 
  474     def testText(self):
  475         self.assertSubprocess("cheetah fill -R --flat", nonzero=True)
  476 
  477 
  478 class IdirRecurse(CFIdirBase):
  479     def testCompile(self):
  480         self.go("cheetah compile -R --idir SRC child")
  481         self.checkSubdirPyInit("child")
  482         self.checkSubdirPyInit("child/grandkid")
  483         self.checkCompile("child/a.py")
  484         self.checkCompile("child/grandkid/a.py")
  485 
  486     def testFill(self):
  487         self.go("cheetah fill -R --idir SRC child")
  488         self.checkFill("child/a.html")
  489         self.checkFill("child/grandkid/a.html")
  490 
  491     def testText(self):
  492         self.go("cheetah fill -R --idir SRC --oext txt child")
  493         self.checkFill("child/a.txt")
  494         self.checkFill("child/grandkid/a.txt")
  495 
  496 
  497 class IdirOdirRecurse(CFIdirBase):
  498     def testCompile(self):
  499         self.go("cheetah compile -R --idir SRC --odir DEST child")
  500         self.checkSubdirPyInit("DEST/child")
  501         self.checkSubdirPyInit("DEST/child/grandkid")
  502         self.checkCompile("DEST/child/a.py")
  503         self.checkCompile("DEST/child/grandkid/a.py")
  504 
  505     def testFill(self):
  506         self.go("cheetah fill -R --idir SRC --odir DEST child")
  507         self.checkFill("DEST/child/a.html")
  508         self.checkFill("DEST/child/grandkid/a.html")
  509 
  510     def testText(self):
  511         self.go("cheetah fill -R --idir SRC --odir DEST --oext txt child")
  512         self.checkFill("DEST/child/a.txt")
  513         self.checkFill("DEST/child/grandkid/a.txt")
  514 
  515 
  516 class IdirFlatRecurseCollision(CFIdirBase):
  517     expectError = True
  518 
  519     def testCompile(self):
  520         self.assertSubprocess(
  521             "cheetah compile -R --flat --idir SRC", nonzero=True)
  522 
  523     def testFill(self):
  524         self.assertSubprocess(
  525             "cheetah fill -R --flat --idir SRC", nonzero=True)
  526 
  527     def testText(self):
  528         self.assertSubprocess(
  529             "cheetah fill -R --flat --idir SRC --oext txt", nonzero=True)
  530 
  531 
  532 class NoBackup(CFBase):
  533     """Run the command twice each time and verify a backup file is
  534        *not* created.
  535     """
  536     def testCompile(self):
  537         self.go("cheetah compile --nobackup a.tmpl")
  538         self.go("cheetah compile --nobackup a.tmpl")
  539         self.checkNoBackup("a.py" + BACKUP_SUFFIX)
  540 
  541     def testFill(self):
  542         self.go("cheetah fill --nobackup a.tmpl")
  543         self.go("cheetah fill --nobackup a.tmpl")
  544         self.checkNoBackup("a.html" + BACKUP_SUFFIX)
  545 
  546     def testText(self):
  547         self.go("cheetah fill --nobackup --oext txt a.tmpl")
  548         self.go("cheetah fill --nobackup --oext txt a.tmpl")
  549         self.checkNoBackup("a.txt" + BACKUP_SUFFIX)
  550 
  551 
  552 def listTests(cheetahWrapperFile):
  553     """cheetahWrapperFile, string, path of this script.
  554 
  555        XXX TODO: don't print test where expectError is true.
  556     """
  557     rx = re.compile(R'self\.go\("(.*?)"\)')
  558     f = open(cheetahWrapperFile)
  559     while True:
  560         lin = f.readline()
  561         if not lin:
  562             break
  563         m = rx.search(lin)
  564         if m:
  565             print(m.group(1))
  566     f.close()
  567 
  568 
  569 def main():
  570     global DELETE, OUTPUT
  571     parser = OptionParser()
  572     parser.add_option("--list", action="store", dest="listTests")
  573     parser.add_option("--nodelete", action="store_true")
  574     parser.add_option("--output", action="store_true")
  575     # The following options are passed to unittest.
  576     parser.add_option("-e", "--explain", action="store_true")
  577     parser.add_option("-v", "--verbose", action="store_true")
  578     parser.add_option("-q", "--quiet", action="store_true")
  579     opts, files = parser.parse_args()
  580     if opts.nodelete:
  581         DELETE = False
  582     if opts.output:
  583         OUTPUT = True
  584     if opts.listTests:
  585         listTests(opts.listTests)
  586     else:
  587         # Eliminate script-specific command-line arguments to prevent
  588         # errors in unittest.
  589         del sys.argv[1:]
  590         for opt in ("explain", "verbose", "quiet"):
  591             if getattr(opts, opt):
  592                 sys.argv.append("--" + opt)
  593         sys.argv.extend(files)
  594         unittest.main()
  595 
  596 
  597 if __name__ == '__main__':
  598     main()