[PATCH 0/3] Preliminary refactoring for Python 3.xx compat

View: New views
4 Messages — Rating Filter:   Alert me  

[PATCH 0/3] Preliminary refactoring for Python 3.xx compat

by R. Tyler Ballance :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

I started experimenting with Python 3.1 this weekend, primarily
looking at how much work will be needed to get Cheetah running on
Python 3 while maintaining 2.xx compat.

The unfortunate fact of the matter is that it will likely be
impossible to run the same codebase on both Python 2.xx (our
bread and butter) and Python 3.xx (the promised land).

I plan on creating a "future" branch for Python 3.xx work,
the idea being Cheetah 2.4.xx will still be where primary
development work will be done, and features will be "forward-
ported" to the future branch for Cheetah 3000.

Currently, I am undertaking a general refactoring of as much of
the codebase in a 2.xx/3.xx compatible fashion such that the
ultimate code fork will be minor and maintainable.

This patch series prunes some stale code (VerifyType, unittest_local)
as well as refactors some of the types abuse Cheetah currently
does.

I am also planning to make an API incompatibility change for
Template.compile(), breaking it out into Template.compile_file() and
Template.compile_str(), that change is not covered in this series.


Comments and review welcome

Cheers


R. Tyler Ballance (3):
  Refactor raw print statements in accordance with 2to3
  Refactor usage of the "types" module out, per 2to3 -f types
  Refactor CheetahWrapper tests to locate my local
    cheetah/cheetah-compile in my PATH

 SetupConfig.py                       |    2 +-
 SetupTools.py                        |   24 +-
 buildandrun                          |   66 +++
 cheetah/CheetahWrapper.py            |    8 +-
 cheetah/DummyTransaction.py          |    2 +-
 cheetah/Filters.py                   |   24 +-
 cheetah/ImportManager.py             |    4 +-
 cheetah/NameMapper.py                |   14 +-
 cheetah/Parser.py                    |   15 +-
 cheetah/SettingsManager.py           |    8 +-
 cheetah/Template.py                  |    2 +-
 cheetah/TemplateCmdLineIface.py      |    8 +-
 cheetah/Templates/_SkeletonPage.py   |   10 +-
 cheetah/Tests/CheetahWrapper.py      |   31 +-
 cheetah/Tests/Filters.py             |    2 +-
 cheetah/Tests/Misc.py                |   20 +
 cheetah/Tests/Performance.py         |    8 +-
 cheetah/Tests/Regressions.py         |    2 +-
 cheetah/Tests/SyntaxAndOutput.py     |    4 +-
 cheetah/Tests/Template.py            |    4 +-
 cheetah/Tests/Test.py                |    2 +
 cheetah/Tests/VerifyType.py          |  158 ------
 cheetah/Tests/unittest_local_copy.py |  978 ----------------------------------
 cheetah/Tests/xmlrunner.py           |    4 +-
 cheetah/Tools/MondoReport.py         |    9 +-
 cheetah/Tools/SiteHierarchy.py       |   10 +-
 cheetah/Utils/Misc.py                |   22 +-
 cheetah/Utils/VerifyType.py          |   83 ---
 cheetah/Utils/memcache.py            |   50 +-
 cheetah/Utils/statprof.py            |   16 +-
 cheetah/Version.py                   |   10 +-
 cheetah/c/_verifytype.c              |  107 ----
 32 files changed, 225 insertions(+), 1482 deletions(-)
 create mode 100755 buildandrun
 create mode 100644 cheetah/Tests/Misc.py
 delete mode 100644 cheetah/Tests/VerifyType.py
 delete mode 100755 cheetah/Tests/unittest_local_copy.py
 delete mode 100644 cheetah/Utils/VerifyType.py
 delete mode 100644 cheetah/c/_verifytype.c


------------------------------------------------------------------------------
Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day
trial. Simplify your report design, integration and deployment - and focus on
what you do best, core application coding. Discover what's new with
Crystal Reports now.  http://p.sf.net/sfu/bobj-july
_______________________________________________
Cheetahtemplate-discuss mailing list
Cheetahtemplate-discuss@...
https://lists.sourceforge.net/lists/listinfo/cheetahtemplate-discuss

[PATCH 1/3] Refactor raw print statements in accordance with 2to3

by R. Tyler Ballance :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Removed prints in a couple places entirely, some of this
code should likely use the `logging` module instead
---
 SetupConfig.py                       |    2 +-
 SetupTools.py                        |   12 +++++-----
 cheetah/CheetahWrapper.py            |    8 +++---
 cheetah/Filters.py                   |   24 ++++++++++----------
 cheetah/ImportManager.py             |    4 +-
 cheetah/NameMapper.py                |   14 ++++++------
 cheetah/Parser.py                    |   15 ++++--------
 cheetah/Template.py                  |    2 +-
 cheetah/TemplateCmdLineIface.py      |    8 +++---
 cheetah/Templates/_SkeletonPage.py   |    2 +-
 cheetah/Tests/CheetahWrapper.py      |    4 +-
 cheetah/Tests/Filters.py             |    2 +-
 cheetah/Tests/Performance.py         |    8 +++---
 cheetah/Tests/Regressions.py         |    2 +-
 cheetah/Tests/SyntaxAndOutput.py     |    2 +-
 cheetah/Tests/Template.py            |    4 +-
 cheetah/Tests/unittest_local_copy.py |    4 +-
 cheetah/Tests/xmlrunner.py           |    4 +-
 cheetah/Tools/SiteHierarchy.py       |   10 ++++----
 cheetah/Utils/memcache.py            |   39 +++++++++++++++------------------
 cheetah/Utils/statprof.py            |   16 +++++++-------
 cheetah/Version.py                   |   10 ++++----
 22 files changed, 94 insertions(+), 102 deletions(-)

diff --git a/SetupConfig.py b/SetupConfig.py
index c95001d..85539e9 100644
--- a/SetupConfig.py
+++ b/SetupConfig.py
@@ -71,7 +71,7 @@ if not os.getenv('CHEETAH_INSTALL_WITHOUT_SETUPTOOLS'):
                 ]
         }
     except ImportError:
-        print 'Not using setuptools, so we cannot install the Markdown dependency'
+        print('Not using setuptools, so we cannot install the Markdown dependency')
 
 
 description = "Cheetah is a template engine and code generation tool."
diff --git a/SetupTools.py b/SetupTools.py
index d08eef2..096ee40 100644
--- a/SetupTools.py
+++ b/SetupTools.py
@@ -158,14 +158,14 @@ def run_setup(configurations):
     try:
         apply(setup, (), kws)
     except BuildFailed, x:
-        print "One or more C extensions failed to build."
-        print "Details: %s" % x
-        print "Retrying without C extensions enabled."
+        print("One or more C extensions failed to build.")
+        print("Details: %s" % x)
+        print("Retrying without C extensions enabled.")
 
         del kws['ext_modules']
         apply(setup, (), kws)
 
-        print "One or more C extensions failed to build."
-        print "Performance enhancements will not be available."
-        print "Pure Python installation succeeded."
+        print("One or more C extensions failed to build.")
+        print("Performance enhancements will not be available.")
+        print("Pure Python installation succeeded.")
 
diff --git a/cheetah/CheetahWrapper.py b/cheetah/CheetahWrapper.py
index 3b1f991..d01f46a 100644
--- a/cheetah/CheetahWrapper.py
+++ b/cheetah/CheetahWrapper.py
@@ -195,14 +195,14 @@ Files are %s""", args, pprint.pformat(vars(opts)), files)
 
 
         if opts.print_settings:
-            print
-            print '>> Available Cheetah compiler settings:'
+            print()
+            print('>> Available Cheetah compiler settings:')
             from Cheetah.Compiler import _DEFAULT_COMPILER_SETTINGS
             listing = _DEFAULT_COMPILER_SETTINGS
             listing.sort(key=lambda l: l[0][0].lower())
 
             for l in listing:
-                print '\t%s (default: "%s")\t%s' % l
+                print('\t%s (default: "%s")\t%s' % l)
             sys.exit(0)
 
         #cleanup trailing path separators
@@ -266,7 +266,7 @@ you do have write permission to and re-run the tests.""")
         runner.run(unittest.TestSuite(Test.suites))
         
     def version(self):
-        print Version
+        print(Version)
 
     # If you add a command, also add it to the 'meths' variable in main().
     
diff --git a/cheetah/Filters.py b/cheetah/Filters.py
index d452439..39ac9ec 100644
--- a/cheetah/Filters.py
+++ b/cheetah/Filters.py
@@ -65,9 +65,9 @@ class Markdown(EncodeUnicode):
         try:
             import markdown
         except ImportError:
-            print '>>> Exception raised importing the "markdown" module'
-            print '>>> Are you sure you have the ElementTree module installed?'
-            print '          http://effbot.org/downloads/#elementtree'
+            print('>>> Exception raised importing the "markdown" module')
+            print('>>> Are you sure you have the ElementTree module installed?')
+            print('          http://effbot.org/downloads/#elementtree')
             raise
 
         encoded = super(Markdown, self).filter(value, **kwargs)
@@ -97,8 +97,8 @@ class CodeHighlighter(EncodeUnicode):
             from pygments import lexers
             from pygments import formatters
         except ImportError, ex:
-            print '<%s> - Failed to import pygments! (%s)' % (self.__class__.__name__, ex)
-            print '-- You may need to install it from: http://pygments.org'
+            print('<%s> - Failed to import pygments! (%s)' % (self.__class__.__name__, ex))
+            print('-- You may need to install it from: http://pygments.org')
             return encoded
 
         lexer = None
@@ -196,15 +196,15 @@ class StripSqueeze(Filter):
 def test():
     s1 = "abc <=> &"
     s2 = "   asdf  \n\t  1  2    3\n"
-    print "WebSafe INPUT:", `s1`
-    print "      WebSafe:", `WebSafe().filter(s1)`
+    print("WebSafe INPUT:", `s1`)
+    print("      WebSafe:", `WebSafe().filter(s1)`)
     
-    print
-    print " Strip INPUT:", `s2`
-    print "       Strip:", `Strip().filter(s2)`
-    print "StripSqueeze:", `StripSqueeze().filter(s2)`
+    print()
+    print(" Strip INPUT:", `s2`)
+    print("       Strip:", `Strip().filter(s2)`)
+    print("StripSqueeze:", `StripSqueeze().filter(s2)`)
 
-    print "Unicode:", `EncodeUnicode().filter(u'aoeu12345\u1234')`
+    print("Unicode:", `EncodeUnicode().filter(u'aoeu12345\u1234')`)
     
 if __name__ == "__main__":  
     test()
diff --git a/cheetah/ImportManager.py b/cheetah/ImportManager.py
index 743360e..667898f 100755
--- a/cheetah/ImportManager.py
+++ b/cheetah/ImportManager.py
@@ -223,8 +223,8 @@ class DirOwner(Owner):
                     co = compile(open(py[0], 'r').read()+'\n', py[0], 'exec')
                     break
                 except SyntaxError, e:
-                    print "Invalid syntax in %s" % py[0]
-                    print e.args
+                    print("Invalid syntax in %s" % py[0])
+                    print(e.args)
                     raise
             elif pyc:
                 stuff = open(pyc[0], 'rb').read()
diff --git a/cheetah/NameMapper.py b/cheetah/NameMapper.py
index 3a6322e..c70db38 100644
--- a/cheetah/NameMapper.py
+++ b/cheetah/NameMapper.py
@@ -364,13 +364,13 @@ def example():
         }
     b = 'this is local b'
 
-    print valueForKey(a.dic,'subDict')
-    print valueForName(a, 'dic.item')
-    print valueForName(vars(), 'b')
-    print valueForName(__builtins__, 'dir')()
-    print valueForName(vars(), 'a.classVar')
-    print valueForName(vars(), 'a.dic.func', executeCallables=True)
-    print valueForName(vars(), 'a.method2.item1', executeCallables=True)
+    print(valueForKey(a.dic,'subDict'))
+    print(valueForName(a, 'dic.item'))
+    print(valueForName(vars(), 'b'))
+    print(valueForName(__builtins__, 'dir')())
+    print(valueForName(vars(), 'a.classVar'))
+    print(valueForName(vars(), 'a.dic.func', executeCallables=True))
+    print(valueForName(vars(), 'a.method2.item1', executeCallables=True))
 
 if __name__ == '__main__':
     example()
diff --git a/cheetah/Parser.py b/cheetah/Parser.py
index 7436e9c..4a8515d 100644
--- a/cheetah/Parser.py
+++ b/cheetah/Parser.py
@@ -1224,7 +1224,6 @@ class _LowLevelParser(SourceReader):
                 startPosIdx = 3
             else:
                 startPosIdx = 1
-            #print 'CHEETAH STRING', nextToken, theStr, startPosIdx
             self.setPos(beforeTokenPos+startPosIdx+1)
             outputExprs = []
             strConst = ''
@@ -1240,8 +1239,6 @@ class _LowLevelParser(SourceReader):
             self.setPos(endPos)
             if strConst:
                 outputExprs.append(repr(strConst))
-            #if not self.atEnd() and self.matches('.join('):
-            #    print 'DEBUG***'
             token = "''.join(["+','.join(outputExprs)+"])"
         return token
 
@@ -1854,13 +1851,11 @@ class _HighLevelParser(_LowLevelParser):
         try:
             self._compiler.setCompilerSetting(settingName, valueExpr)
         except:
-            out = sys.stderr
-            print >> out, 'An error occurred while processing the following #compiler directive.'
-            print >> out, '-'*80
-            print >> out, self[startPos:endPos]
-            print >> out, '-'*80
-            print >> out, 'Please check the syntax of these settings.'
-            print >> out, 'A full Python exception traceback follows.'
+            sys.stderr.write('An error occurred while processing the following #compiler directive.\n')
+            sys.stderr.write('----------------------------------------------------------------------\n')
+            sys.stderr.write('%s\n' % self[startPos:endPos])
+            sys.stderr.write('----------------------------------------------------------------------\n')
+            sys.stderr.write('Please check the syntax of these settings.\n\n')
             raise
 
 
diff --git a/cheetah/Template.py b/cheetah/Template.py
index ec92208..ab63074 100644
--- a/cheetah/Template.py
+++ b/cheetah/Template.py
@@ -1837,7 +1837,7 @@ class Template(Servlet):
         # 'dic = super(ThisClass, self).webInput(names, namesMulti, ...)'
         # and then the code below.
         if debug:
-           print "<PRE>\n" + pprint.pformat(dic) + "\n</PRE>\n\n"
+           print("<PRE>\n" + pprint.pformat(dic) + "\n</PRE>\n\n")
         self.searchList().insert(0, dic)
         return dic
 
diff --git a/cheetah/TemplateCmdLineIface.py b/cheetah/TemplateCmdLineIface.py
index 16a90cf..6690b6d 100644
--- a/cheetah/TemplateCmdLineIface.py
+++ b/cheetah/TemplateCmdLineIface.py
@@ -41,7 +41,7 @@ class CmdLineIface:
         """The main program controller."""
         
         self._processCmdLineArgs()
-        print self._template
+        print(self._template)
         
     def _processCmdLineArgs(self):
         try:
@@ -53,13 +53,13 @@ class CmdLineIface:
 
         except getopt.GetoptError, v:
             # print help information and exit:
-            print v
-            print self.usage()
+            print(v)
+            print(self.usage())
             sys.exit(2)
         
         for o, a in self._opts:
             if o in ('-h','--help'):
-                print self.usage()
+                print(self.usage())
                 sys.exit()
             if o == '--env':
                 self._template.searchList().insert(0, os.environ)
diff --git a/cheetah/Templates/_SkeletonPage.py b/cheetah/Templates/_SkeletonPage.py
index fe01ebf..95a59a7 100644
--- a/cheetah/Templates/_SkeletonPage.py
+++ b/cheetah/Templates/_SkeletonPage.py
@@ -88,7 +88,7 @@ class _SkeletonPage(Template):
             if not self._stylesheets.has_key(identifier):
                 warning = '# the identifier ' + identifier + \
                           'was in stylesheetsOrder, but not in stylesheets'
-                print warning
+                print(warning)
                 stylesheetTagsTxt += warning
                 continue
                     
diff --git a/cheetah/Tests/CheetahWrapper.py b/cheetah/Tests/CheetahWrapper.py
index e152e68..809be40 100644
--- a/cheetah/Tests/CheetahWrapper.py
+++ b/cheetah/Tests/CheetahWrapper.py
@@ -52,7 +52,7 @@ class CFBase(unittest.TestCase):
 
     def inform(self, message):
         if self.verbose:
-            print message
+            print(message)
 
     def setUp(self):
         """Create the top-level directories, subdirectories and .tmpl
@@ -520,7 +520,7 @@ def listTests(cheetahWrapperFile):
             break
         m = rx.search(lin)
         if m:
-            print m.group(1)
+            print(m.group(1))
     f.close()
 
 def main():
diff --git a/cheetah/Tests/Filters.py b/cheetah/Tests/Filters.py
index bf35440..9b3c7c2 100644
--- a/cheetah/Tests/Filters.py
+++ b/cheetah/Tests/Filters.py
@@ -31,7 +31,7 @@ Header
             assert template == expected
         except Exception, ex:
             if ex.__class__.__name__ == 'MarkdownException' and majorVer == 2 and minorVer < 5:
-                print '>>> NOTE: Support for the Markdown filter will be broken for you. Markdown says: %s' % ex
+                print('>>> NOTE: Support for the Markdown filter will be broken for you. Markdown says: %s' % ex)
                 return
             raise
 
diff --git a/cheetah/Tests/Performance.py b/cheetah/Tests/Performance.py
index 8101e85..fc74367 100644
--- a/cheetah/Tests/Performance.py
+++ b/cheetah/Tests/Performance.py
@@ -57,8 +57,8 @@ def perftest(max_num_pystones, current_pystone=None):
                     pystone_total_time = total_time / pystone_rate
                 global DEBUG
                 if DEBUG:
-                    print 'The test "%s" took: %s pystones' % (function.func_name,
-                        pystone_total_time)
+                    print('The test "%s" took: %s pystones' % (function.func_name,
+                        pystone_total_time))
                 else:
                     if pystone_total_time > (max_num_pystones + TOLERANCE):
                         raise DurationError((('Test too long (%.2f Ps, '
@@ -98,8 +98,8 @@ class PerformanceTest(unittest.TestCase):
         self.prof.stop()
         self.prof.close()
         if self.display:
-            print '>>> %s (%d iterations) ' % (self.__class__.__name__,
-                    self.iterations)
+            print('>>> %s (%d iterations) ' % (self.__class__.__name__,
+                    self.iterations))
             stats = hotshot.stats.load('%s.prof' % self.__class__.__name__)
             #stats.strip_dirs()
             stats.sort_stats('time', 'calls')
diff --git a/cheetah/Tests/Regressions.py b/cheetah/Tests/Regressions.py
index 4d50348..67a736a 100644
--- a/cheetah/Tests/Regressions.py
+++ b/cheetah/Tests/Regressions.py
@@ -29,7 +29,7 @@ class GetAttrTest(unittest.TestCase):
     def test_ValidException(self):
         o = CustomGetAttrClass()
         try:
-            print o.attr
+            print(o.attr)
         except GetAttrException, e:
             # expected
             return
diff --git a/cheetah/Tests/SyntaxAndOutput.py b/cheetah/Tests/SyntaxAndOutput.py
index 72721bc..6bd6963 100644
--- a/cheetah/Tests/SyntaxAndOutput.py
+++ b/cheetah/Tests/SyntaxAndOutput.py
@@ -171,7 +171,7 @@ Template output mismatch:
                 )
             moduleCode = templateObj._CHEETAH_generatedModuleCode
         if self.DEBUGLEV >= 1:
-            print moduleCode
+            print(moduleCode)
         try:
             output = templateObj.respond() # rather than __str__, because of unicode
             assert output==expectedOutput, self._outputMismatchReport(output, expectedOutput)
diff --git a/cheetah/Tests/Template.py b/cheetah/Tests/Template.py
index 144ae6f..7edbdb9 100644
--- a/cheetah/Tests/Template.py
+++ b/cheetah/Tests/Template.py
@@ -293,7 +293,7 @@ class TryExceptImportTest(TemplateTest):
 class ClassMethodSupport(TemplateTest):
     def test_BasicDecorator(self):
         if sys.version_info[0] == 2 and sys.version_info[1] == 3:
-                print 'This version of Python doesn\'t support decorators, skipping tests'
+                print('This version of Python doesn\'t support decorators, skipping tests')
                 return
         template = '''
             #@classmethod
@@ -311,7 +311,7 @@ class ClassMethodSupport(TemplateTest):
 class StaticMethodSupport(TemplateTest):
     def test_BasicDecorator(self):
         if sys.version_info[0] == 2 and sys.version_info[1] == 3:
-                print 'This version of Python doesn\'t support decorators, skipping tests'
+                print('This version of Python doesn\'t support decorators, skipping tests')
                 return
         template = '''
             #@staticmethod
diff --git a/cheetah/Tests/unittest_local_copy.py b/cheetah/Tests/unittest_local_copy.py
index a5f5499..11d2d2c 100755
--- a/cheetah/Tests/unittest_local_copy.py
+++ b/cheetah/Tests/unittest_local_copy.py
@@ -917,8 +917,8 @@ Examples:
         self.runTests()
 
     def usageExit(self, msg=None):
-        if msg: print msg
-        print self.USAGE % self.__dict__
+        if msg: print(msg)
+        print(self.USAGE % self.__dict__)
         sys.exit(2)
 
     def parseArgs(self, argv):
diff --git a/cheetah/Tests/xmlrunner.py b/cheetah/Tests/xmlrunner.py
index dc49c56..bc9f6ab 100644
--- a/cheetah/Tests/xmlrunner.py
+++ b/cheetah/Tests/xmlrunner.py
@@ -313,7 +313,7 @@ class XMLTestRunnerTest(unittest.TestCase):
         """
         class TestTest(unittest.TestCase):
             def test_foo(self):
-                print "Test"
+                print("Test")
         self._try_test_run(TestTest, """<testsuite errors="0" failures="0" name="unittest.TestSuite" tests="1" time="0.000">
   <testcase classname="__main__.TestTest" name="test_foo" time="0.000"></testcase>
   <system-out><![CDATA[Test
@@ -329,7 +329,7 @@ class XMLTestRunnerTest(unittest.TestCase):
         """
         class TestTest(unittest.TestCase):
             def test_foo(self):
-                print >>sys.stderr, "Test"
+                print("Test", file=sys.stderr)
         self._try_test_run(TestTest, """<testsuite errors="0" failures="0" name="unittest.TestSuite" tests="1" time="0.000">
   <testcase classname="__main__.TestTest" name="test_foo" time="0.000"></testcase>
   <system-out><![CDATA[]]></system-out>
diff --git a/cheetah/Tools/SiteHierarchy.py b/cheetah/Tools/SiteHierarchy.py
index 06da56f..6cae0bc 100644
--- a/cheetah/Tools/SiteHierarchy.py
+++ b/cheetah/Tools/SiteHierarchy.py
@@ -173,10 +173,10 @@ if __name__ == '__main__':
     ]
 
  for url in ['/', '/services', '/services/products/widget', '/contact']:
- print '<p>', '='*50
- print '<br> %s: <br>\n' % url
+ print('<p>', '='*50)
+ print('<br> %s: <br>\n' % url)
  n = Hierarchy(hierarchy, url, menuCSSClass='menu', crumbCSSClass='crumb',
       prefix='/here')
- print n.menuList()
- print '<p>', '-'*50
- print n.crumbs()
+ print(n.menuList())
+ print('<p>', '-'*50)
+ print(n.crumbs())
diff --git a/cheetah/Utils/memcache.py b/cheetah/Utils/memcache.py
index ee9678d..029f621 100644
--- a/cheetah/Utils/memcache.py
+++ b/cheetah/Utils/memcache.py
@@ -177,7 +177,6 @@ class Client:
         for i in range(Client._SERVER_RETRIES):
             server = self.buckets[serverhash % len(self.buckets)]
             if server.connect():
-                #print "(using server %s)" % server,
                 return server, key
             serverhash = hash(str(serverhash) + str(i))
         return None, None
@@ -555,10 +554,9 @@ def _doctest():
     return doctest.testmod(memcache, globs=globs)
 
 if __name__ == "__main__":
-    print "Testing docstrings..."
+    print("Testing docstrings...")
     _doctest()
-    print "Running tests:"
-    print
+    print("Running tests:")
     #servers = ["127.0.0.1:11211", "127.0.0.1:11212"]
     servers = ["127.0.0.1:11211"]
     mc = Client(servers, debug=1)
@@ -568,14 +566,14 @@ if __name__ == "__main__":
             return "%s (%s)" % (val, type(val))
         return "%s" % val
     def test_setget(key, val):
-        print "Testing set/get {'%s': %s} ..." % (to_s(key), to_s(val)),
+        print("Testing set/get {'%s': %s} ..." % (to_s(key), to_s(val)))
         mc.set(key, val)
         newval = mc.get(key)
         if newval == val:
-            print "OK"
+            print("OK")
             return 1
         else:
-            print "FAIL"
+            print("FAIL")
             return 0
 
     class FooStruct:
@@ -591,34 +589,33 @@ if __name__ == "__main__":
     test_setget("a_string", "some random string")
     test_setget("an_integer", 42)
     if test_setget("long", long(1<<30)):
-        print "Testing delete ...",
+        print("Testing delete ...")
         if mc.delete("long"):
-            print "OK"
+            print("OK")
         else:
-            print "FAIL"
-    print "Testing get_multi ...",
-    print mc.get_multi(["a_string", "an_integer"])
+            print("FAIL")
+    print("Testing get_multi ...")
+    print(mc.get_multi(["a_string", "an_integer"]))
 
-    print "Testing get(unknown value) ...",
-    print to_s(mc.get("unknown_value"))
+    print("Testing get(unknown value) ...")
+    print(to_s(mc.get("unknown_value")))
 
     f = FooStruct()
     test_setget("foostruct", f)
 
-    print "Testing incr ...",
+    print("Testing incr ...")
     x = mc.incr("an_integer", 1)
     if x == 43:
-        print "OK"
+        print("OK")
     else:
-        print "FAIL"
+        print("FAIL")
 
-    print "Testing decr ...",
+    print("Testing decr ...")
     x = mc.decr("an_integer", 1)
     if x == 42:
-        print "OK"
+        print("OK")
     else:
-        print "FAIL"
-
+        print("FAIL")
 
 
 # vim: ts=4 sw=4 et :
diff --git a/cheetah/Utils/statprof.py b/cheetah/Utils/statprof.py
index 55638eb..d6d64d6 100644
--- a/cheetah/Utils/statprof.py
+++ b/cheetah/Utils/statprof.py
@@ -277,15 +277,15 @@ class CallStats(object):
         self.cum_secs_per_call = None
 
     def display(self):
-        print '%6.2f %9.2f %9.2f  %s' % (self.pcnt_time_in_proc,
+        print('%6.2f %9.2f %9.2f  %s' % (self.pcnt_time_in_proc,
                                          self.cum_secs_in_proc,
                                          self.self_secs_in_proc,
-                                         self.name)
+                                         self.name))
 
 
 def display():
     if state.sample_count == 0:
-        print 'No samples recorded.'
+        print('No samples recorded.')
         return
 
     l = [CallStats(x) for x in call_data.itervalues()]
@@ -293,12 +293,12 @@ def display():
     l.sort(reverse=True)
     l = [x[2] for x in l]
 
-    print '%5.5s %10.10s   %7.7s  %-8.8s' % ('%  ', 'cumulative', 'self', '')
-    print '%5.5s  %9.9s  %8.8s  %-8.8s' % ("time", "seconds", "seconds", "name")
+    print('%5.5s %10.10s   %7.7s  %-8.8s' % ('%  ', 'cumulative', 'self', ''))
+    print('%5.5s  %9.9s  %8.8s  %-8.8s' % ("time", "seconds", "seconds", "name"))
 
     for x in l:
         x.display()
 
-    print '---'
-    print 'Sample count: %d' % state.sample_count
-    print 'Total time: %f seconds' % state.accumulated_time
+    print('---')
+    print('Sample count: %d' % state.sample_count)
+    print('Total time: %f seconds' % state.accumulated_time)
diff --git a/cheetah/Version.py b/cheetah/Version.py
index 7fdf82f..9cc2e91 100644
--- a/cheetah/Version.py
+++ b/cheetah/Version.py
@@ -32,11 +32,11 @@ def convertVersionStringToTuple(s):
 
 if __name__ == '__main__':
     c = convertVersionStringToTuple
-    print c('2.0a1')
-    print c('2.0b1')
-    print c('2.0rc1')
-    print c('2.0')
-    print c('2.0.2')
+    print(c('2.0a1'))
+    print(c('2.0b1'))
+    print(c('2.0rc1'))
+    print(c('2.0'))
+    print(c('2.0.2'))
 
 
     assert c('0.9.19b1') < c('0.9.19')
--
1.6.4.2


------------------------------------------------------------------------------
Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day
trial. Simplify your report design, integration and deployment - and focus on
what you do best, core application coding. Discover what's new with
Crystal Reports now.  http://p.sf.net/sfu/bobj-july
_______________________________________________
Cheetahtemplate-discuss mailing list
Cheetahtemplate-discuss@...
https://lists.sourceforge.net/lists/listinfo/cheetahtemplate-discuss

[PATCH 2/3] Refactor usage of the "types" module out, per 2to3 -f types

by R. Tyler Ballance :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Left out cheetah/Template.py which will need to be refactored
a bit more aggressively, particularly in Template.compile()
---
 SetupTools.py                        |   12 +-
 cheetah/DummyTransaction.py          |    2 +-
 cheetah/SettingsManager.py           |    8 +-
 cheetah/Templates/_SkeletonPage.py   |    8 +-
 cheetah/Tests/Misc.py                |   20 +
 cheetah/Tests/SyntaxAndOutput.py     |    2 +-
 cheetah/Tests/Test.py                |    2 +
 cheetah/Tests/VerifyType.py          |  158 ------
 cheetah/Tests/unittest_local_copy.py |  978 ----------------------------------
 cheetah/Tools/MondoReport.py         |    9 +-
 cheetah/Utils/Misc.py                |   22 +-
 cheetah/Utils/VerifyType.py          |   83 ---
 cheetah/Utils/memcache.py            |   11 +-
 cheetah/c/_verifytype.c              |  107 ----
 14 files changed, 45 insertions(+), 1377 deletions(-)
 create mode 100644 cheetah/Tests/Misc.py
 delete mode 100644 cheetah/Tests/VerifyType.py
 delete mode 100755 cheetah/Tests/unittest_local_copy.py
 delete mode 100644 cheetah/Utils/VerifyType.py
 delete mode 100644 cheetah/c/_verifytype.c

diff --git a/SetupTools.py b/SetupTools.py
index 096ee40..0f5377d 100644
--- a/SetupTools.py
+++ b/SetupTools.py
@@ -77,8 +77,8 @@ class mod_install_data(install_data):
         data_files = self.get_inputs()
         
         for entry in data_files:
-            if type(entry) != types.StringType:
-                raise ValueError, 'The entries in "data_files" must be strings'
+            if isinstance(entry, basestring):
+                raise ValueError('The entries in "data_files" must be strings')
             
             entry = string.join(string.split(entry, '/'), os.sep)
             # entry is a filename or glob pattern
@@ -137,13 +137,7 @@ def run_setup(configurations):
     for configuration in configurations:
         kws.update(vars(configuration))
     for name, value in kws.items():
-        if name[:1] == '_' or \
-           type(value) not in (types.StringType,
-                               types.ListType,
-                               types.TupleType,
-                               types.DictType,
-                               types.IntType,
-                               ):
+        if name[:1] == '_' or not isinstance(value, (basestring, list, tuple, dict, int)):
             del kws[name]
 
     # Add setup extensions
diff --git a/cheetah/DummyTransaction.py b/cheetah/DummyTransaction.py
index f84ade4..72f8662 100644
--- a/cheetah/DummyTransaction.py
+++ b/cheetah/DummyTransaction.py
@@ -92,7 +92,7 @@ class TransformerResponse(DummyResponse):
         output = super(TransformerResponse, self).getvalue(**kwargs)
         if self._filter:
             _filter = self._filter
-            if isinstance(_filter, types.TypeType):
+            if isinstance(_filter, type):
                 _filter = _filter()
             return _filter.filter(output)
         return output
diff --git a/cheetah/SettingsManager.py b/cheetah/SettingsManager.py
index dfb396b..07c88a1 100644
--- a/cheetah/SettingsManager.py
+++ b/cheetah/SettingsManager.py
@@ -34,10 +34,8 @@ def mergeNestedDictionaries(dict1, dict2, copy=False, deepcopy=False):
     elif deepcopy:
         dict1 = copyModule.deepcopy(dict1)
         
-    for key,val in dict2.items():
-        if dict1.has_key(key) and type(val) == types.DictType and \
-           type(dict1[key]) == types.DictType:
-            
+    for key,val in dict2.iteritems():
+        if dict1.has_key(key) and isinstance(val, dict) and isinstance(dict1[key], dict):
             dict1[key] = mergeNestedDictionaries(dict1[key], val)
         else:
             dict1[key] = val
@@ -96,7 +94,7 @@ class _SettingsCollector(object):
         """
         S = {}
         attrs = vars(mod)
-        for k, v in attrs.items():
+        for k, v in attrs.iteritems():
             if (ignoreUnderscored and k.startswith('_')):
                 continue
             else:
diff --git a/cheetah/Templates/_SkeletonPage.py b/cheetah/Templates/_SkeletonPage.py
index 95a59a7..afb54b2 100644
--- a/cheetah/Templates/_SkeletonPage.py
+++ b/cheetah/Templates/_SkeletonPage.py
@@ -115,8 +115,8 @@ class _SkeletonPage(Template):
         SRC filename rather than a code string."""
         
         javascriptTagsTxt = []
-        for key, details in self._javascriptTags.items():
-            if type(details) not in (types.ListType, types.TupleType):
+        for key, details in self._javascriptTags.iteritems():
+            if not isinstance(details, (list, tuple)):
                 details = ['',details]
                 
             javascriptTagsTxt += ['<script language="JavaScript', str(details[0]),
@@ -124,8 +124,8 @@ class _SkeletonPage(Template):
                                   str(details[0]), '\n//--></script>\n']
 
 
-        for key, details in self._javascriptLibs.items():
-            if type(details) not in (types.ListType, types.TupleType):
+        for key, details in self._javascriptLibs.iteritems():
+            if not isinstance(details, (list, tuple)):
                 details = ['',details]
 
             javascriptTagsTxt += ['<script language="JavaScript', str(details[0]),
diff --git a/cheetah/Tests/Misc.py b/cheetah/Tests/Misc.py
new file mode 100644
index 0000000..9ea66f0
--- /dev/null
+++ b/cheetah/Tests/Misc.py
@@ -0,0 +1,20 @@
+#!/usr/bin/env python
+
+import unittest
+
+from Cheetah import SettingsManager
+
+
+class SettingsManagerTests(unittest.TestCase):
+    def test_mergeDictionaries(self):
+        left = {'foo' : 'bar', 'abc' : {'a' : 1, 'b' : 2, 'c' : (3,)}}
+        right = {'xyz' : (10, 9)}
+        expect = {'xyz': (10, 9), 'foo': 'bar', 'abc': {'a': 1, 'c': (3,), 'b': 2}}
+
+        result = SettingsManager.mergeNestedDictionaries(left, right)
+        self.assertEquals(result, expect)
+
+
+if __name__ == '__main__':
+    unittest.main()
+
diff --git a/cheetah/Tests/SyntaxAndOutput.py b/cheetah/Tests/SyntaxAndOutput.py
index 6bd6963..0702ded 100644
--- a/cheetah/Tests/SyntaxAndOutput.py
+++ b/cheetah/Tests/SyntaxAndOutput.py
@@ -3199,7 +3199,7 @@ else:
     
 
 def install_eols():
-    klasses = [v for v in globals().values() if isinstance(v, (types.ClassType, types.TypeType)) and issubclass(v, unittest.TestCase)]
+    klasses = [v for v in globals().values() if isinstance(v, type) and issubclass(v, unittest.TestCase)]
     for klass in klasses:
         name = klass.__name__        
         if hasattr(klass,'convertEOLs') and klass.convertEOLs:
diff --git a/cheetah/Tests/Test.py b/cheetah/Tests/Test.py
index 13b0171..872de8e 100755
--- a/cheetah/Tests/Test.py
+++ b/cheetah/Tests/Test.py
@@ -15,6 +15,7 @@ import unittest
 
 import SyntaxAndOutput
 import NameMapper
+import Misc
 import Filters
 import Template
 import Cheps
@@ -32,6 +33,7 @@ suites = [
    #unittest.findTestCases(Cheps),
    unittest.findTestCases(Regressions),
    unittest.findTestCases(Unicode),
+   unittest.findTestCases(Misc),
 ]
 
 if not sys.platform.startswith('java'):
diff --git a/cheetah/Tests/VerifyType.py b/cheetah/Tests/VerifyType.py
deleted file mode 100644
index a581d70..0000000
--- a/cheetah/Tests/VerifyType.py
+++ /dev/null
@@ -1,158 +0,0 @@
-#!/usr/bin/env python
-import unittest
-
-from Cheetah.Utils import VerifyType
-from Cheetah import _verifytype
-
-class VerifyType_Test(unittest.TestCase):
-    def test_Verified(self):
-        arg = 'foo'
-        legalTypes = [str, unicode]
-        try:
-            rc = VerifyType.VerifyType(arg, 'arg', legalTypes, 'string')
-            assert rc
-        except TypeError:
-            self.fail('Should not have raised a TypeError here')
-
-        try:
-            rc = _verifytype.verifyType(arg, 'arg', legalTypes, 'string')
-            assert rc
-        except TypeError:
-            self.fail('Should not have raised a TypeError here')
-
-    def test_Unverified(self):
-        arg = 'foo'
-        legalTypes = [list, dict]
-        self.failUnlessRaises(TypeError, VerifyType.VerifyType, arg,
-                    'arg', legalTypes, 'list or dict')
-        self.failUnlessRaises(TypeError, _verifytype.verifyType, arg,
-                    'arg', legalTypes, 'list or dict')
-
-    def test_IncorrectNumberOfArgs(self):
-        arg = 'foo'
-        legalTypes = [str, unicode]
-
-        self.failUnlessRaises(TypeError,  VerifyType.VerifyType)
-        self.failUnlessRaises(TypeError, _verifytype.verifyType)
-
-        self.failUnlessRaises(TypeError,  VerifyType.VerifyType, arg)
-        self.failUnlessRaises(TypeError, _verifytype.verifyType, arg)
-
-        self.failUnlessRaises(TypeError,  VerifyType.VerifyType, arg,
-                    'arg')
-        self.failUnlessRaises(TypeError, _verifytype.verifyType, arg,
-                    'arg')
-
-        self.failUnlessRaises(TypeError,  VerifyType.VerifyType, arg,
-                    'arg', legalTypes)
-        self.failUnlessRaises(TypeError, _verifytype.verifyType, arg,
-                    'arg', legalTypes)
-
-        self.failUnlessRaises(TypeError,  VerifyType.VerifyType, arg,
-                    'arg', legalTypes, 'string', 'errmsgExtra', 'one more')
-        self.failUnlessRaises(TypeError, _verifytype.verifyType, arg,
-                    'arg', legalTypes, 'string', 'errmsgExtra', 'one more')
-
-    def test_LegalTypesNotIterable(self):
-        arg = 'foo'
-        legalTypes = 1
-
-        self.failUnlessRaises(TypeError,  VerifyType.VerifyType, arg,
-                    'arg', legalTypes, 'string')
-        self.failUnlessRaises(TypeError, _verifytype.verifyType, arg,
-                    'arg', legalTypes, 'string')
-
-class FakeClass(dict):
-    pass
-
-class VerifyTypeClass_Test(unittest.TestCase):
-    def test_VerifiedClass(self):
-        arg = FakeClass
-        legalTypes = [type]
-        try:
-            rc = VerifyType.VerifyTypeClass(arg, 'arg', legalTypes, '', dict)
-            assert rc
-        except TypeError:
-            self.fail('Should not have raised a TypeError here')
-
-        try:
-            rc = _verifytype.verifyTypeClass(arg, 'arg', legalTypes, 'foo', dict)
-            assert rc
-        except TypeError:
-            self.fail('Should not have raised a TypeError here')
-
-    def test_UnverifiedClass(self):
-        arg = FakeClass
-        legalTypes = [type]
-        self.failUnlessRaises(TypeError,  VerifyType.VerifyTypeClass, arg,
-                    legalTypes, 'subclass of list', list)
-        self.failUnlessRaises(TypeError, _verifytype.verifyTypeClass, arg,
-                    legalTypes, 'subclass of list', list)
-
-    def test_Verified(self):
-        arg = 'foo'
-        legalTypes = [str, unicode]
-        try:
-            rc = VerifyType.VerifyTypeClass(arg, 'arg', legalTypes, 'string', int)
-            assert rc
-        except TypeError:
-            self.fail('Should not have raised a TypeError here')
-
-        try:
-            rc = _verifytype.verifyTypeClass(arg, 'arg', legalTypes, 'string', int)
-            assert rc
-        except TypeError:
-            self.fail('Should not have raised a TypeError here')
-
-    def test_Unverified(self):
-        arg = 'foo'
-        legalTypes = [list, dict]
-        self.failUnlessRaises(TypeError,  VerifyType.VerifyTypeClass, arg,
-                    'arg', legalTypes, 'list or dict', int)
-        self.failUnlessRaises(TypeError, _verifytype.verifyTypeClass, arg,
-                    'arg', legalTypes, 'list or dict', int)
-
-    def test_IncorrectNumberOfArgs(self):
-        arg = 'foo'
-        legalTypes = [str, unicode]
-
-        self.failUnlessRaises(TypeError,  VerifyType.VerifyTypeClass)
-        self.failUnlessRaises(TypeError, _verifytype.verifyTypeClass)
-
-        self.failUnlessRaises(TypeError,  VerifyType.VerifyTypeClass, arg)
-        self.failUnlessRaises(TypeError, _verifytype.verifyTypeClass, arg)
-
-        self.failUnlessRaises(TypeError,  VerifyType.VerifyTypeClass, arg,
-                    'arg')
-        self.failUnlessRaises(TypeError, _verifytype.verifyTypeClass, arg,
-                    'arg')
-
-        self.failUnlessRaises(TypeError,  VerifyType.VerifyTypeClass, arg,
-                    'arg', legalTypes)
-        self.failUnlessRaises(TypeError, _verifytype.verifyTypeClass, arg,
-                    'arg', legalTypes)
-
-        self.failUnlessRaises(TypeError,  VerifyType.VerifyTypeClass, arg,
-                    'arg', legalTypes, 'string')
-        self.failUnlessRaises(TypeError, _verifytype.verifyTypeClass, arg,
-                    'arg', legalTypes, 'string')
-
-        self.failUnlessRaises(TypeError,  VerifyType.VerifyTypeClass, arg,
-                    'arg', legalTypes, 'string', int, 'errmsgExtra', 'one more')
-        self.failUnlessRaises(TypeError, _verifytype.verifyTypeClass, arg,
-                    'arg', legalTypes, 'string', int, 'errmsgExtra', 'one more')
-
-    def test_LegalTypesNotIterable(self):
-        arg = 'foo'
-        legalTypes = 1
-
-        self.failUnlessRaises(TypeError,  VerifyType.VerifyTypeClass, arg,
-                    'arg', legalTypes, 'string', int)
-        self.failUnlessRaises(TypeError, _verifytype.verifyTypeClass, arg,
-                    'arg', legalTypes, 'string', int)
-
-
-
-
-if __name__ == '__main__':
-    unittest.main()
diff --git a/cheetah/Tests/unittest_local_copy.py b/cheetah/Tests/unittest_local_copy.py
deleted file mode 100755
index 11d2d2c..0000000
--- a/cheetah/Tests/unittest_local_copy.py
+++ /dev/null
@@ -1,978 +0,0 @@
-#!/usr/bin/env python
-""" This is a hacked version of PyUnit that extends its reporting capabilities
-with optional meta data on the test cases.  It also makes it possible to
-separate the standard and error output streams in TextTestRunner.
-
-It's a hack rather than a set of subclasses because a) Steve had used double
-underscore private attributes for some things I needed access to, and b) the
-changes affected so many classes that it was easier just to hack it.
-
-The changes are in the following places:
-TestCase:
-   - minor refactoring of  __init__ and __call__ internals
-   - added some attributes and methods for storing and retrieving meta data
-
-_TextTestResult
-   - refactored the stream handling
-   - incorporated all the output code from TextTestRunner
-   - made the output of FAIL and ERROR information more flexible and
-     incorporated the new meta data from TestCase
-   - added a flag called 'explain' to __init__ that controls whether the new '
-     explanation'   meta data from TestCase is printed along with tracebacks
-  
-TextTestRunner
-   - delegated all output to _TextTestResult
-   - added 'err' and 'explain' to the __init__ signature to match the changes
-     in _TextTestResult
-  
-TestProgram
-   - added -e and --explain as flags on the command line
-
--- Tavis Rudd <tavis@...> (Sept 28th, 2001)
-
-- _TestTextResult.printErrorList(): print blank line after each traceback
-
--- Mike Orr <mso@...> (Nov 11, 2002)
-
-TestCase methods copied from unittest in Python 2.3:
-  - .assertAlmostEqual(first, second, places=7, msg=None): to N decimal places.
-  - .failIfAlmostEqual(first, second, places=7, msg=None)
-
--- Mike Orr (Jan 5, 2004)
-
-
-Below is the original docstring for unittest.
----------------------------------------------------------------------------
-Python unit testing framework, based on Erich Gamma's JUnit and Kent Beck's
-Smalltalk testing framework.
-
-This module contains the core framework classes that form the basis of
-specific test cases and suites (TestCase, TestSuite etc.), and also a
-text-based utility class for running the tests and reporting the results
-(TextTestRunner).
-
-Simple usage:
-
-    import unittest
-
-    class IntegerArithmenticTestCase(unittest.TestCase):
-        def testAdd(self):  ## test method names begin 'test*'
-            self.assertEquals((1 + 2), 3)
-            self.assertEquals(0 + 1, 1)
-        def testMultiply(self);
-            self.assertEquals((0 * 10), 0)
-            self.assertEquals((5 * 8), 40)
-
-    if __name__ == '__main__':
-        unittest.main()
-
-Further information is available in the bundled documentation, and from
-
-  http://pyunit.sourceforge.net/
-
-Copyright (c) 1999, 2000, 2001 Steve Purcell
-This module is free software, and you may redistribute it and/or modify
-it under the same terms as Python itself, so long as this copyright message
-and disclaimer are retained in their original form.
-
-IN NO EVENT SHALL THE AUTHOR BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
-SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF
-THIS CODE, EVEN IF THE AUTHOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
-DAMAGE.
-
-THE AUTHOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-PARTICULAR PURPOSE.  THE CODE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS,
-AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
-SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
-"""
-
-__author__ = "Steve Purcell"
-__email__ = "stephen_purcell at yahoo dot com"
-__revision__ = "$Revision: 1.11 $"[11:-2]
-
-
-##################################################
-## DEPENDENCIES ##
-
-import os
-import re
-import string
-import sys
-import time
-import traceback
-import types
-import pprint
-
-##################################################
-## CONSTANTS & GLOBALS
-
-try:
-    True,False
-except NameError:
-    True, False = (1==1),(1==0)
-
-##############################################################################
-# Test framework core
-##############################################################################
-
-
-class TestResult:
-    """Holder for test result information.
-
-    Test results are automatically managed by the TestCase and TestSuite
-    classes, and do not need to be explicitly manipulated by writers of tests.
-
-    Each instance holds the total number of tests run, and collections of
-    failures and errors that occurred among those test runs. The collections
-    contain tuples of (testcase, exceptioninfo), where exceptioninfo is a
-    tuple of values as returned by sys.exc_info().
-    """
-    def __init__(self):
-        self.failures = []
-        self.errors = []
-        self.testsRun = 0
-        self.shouldStop = 0
-
-    def startTest(self, test):
-        "Called when the given test is about to be run"
-        self.testsRun = self.testsRun + 1
-
-    def stopTest(self, test):
-        "Called when the given test has been run"
-        pass
-
-    def addError(self, test, err):
-        "Called when an error has occurred"
-        self.errors.append((test, err))
-
-    def addFailure(self, test, err):
-        "Called when a failure has occurred"
-        self.failures.append((test, err))
-
-    def addSuccess(self, test):
-        "Called when a test has completed successfully"
-        pass
-
-    def wasSuccessful(self):
-        "Tells whether or not this result was a success"
-        return len(self.failures) == len(self.errors) == 0
-
-    def stop(self):
-        "Indicates that the tests should be aborted"
-        self.shouldStop = 1
-
-    def __repr__(self):
-        return "<%s run=%i errors=%i failures=%i>" % \
-               (self.__class__, self.testsRun, len(self.errors),
-                len(self.failures))
-        
-class TestCase:
-    """A class whose instances are single test cases.
-
-    By default, the test code itself should be placed in a method named
-    'runTest'.
-
-    If the fixture may be used for many test cases, create as
-    many test methods as are needed. When instantiating such a TestCase
-    subclass, specify in the constructor arguments the name of the test method
-    that the instance is to execute.
-
-    Test authors should subclass TestCase for their own tests. Construction
-    and deconstruction of the test's environment ('fixture') can be
-    implemented by overriding the 'setUp' and 'tearDown' methods respectively.
-
-    If it is necessary to override the __init__ method, the base class
-    __init__ method must always be called. It is important that subclasses
-    should not change the signature of their __init__ method, since instances
-    of the classes are instantiated automatically by parts of the framework
-    in order to be run.
-    """
-
-    # This attribute determines which exception will be raised when
-    # the instance's assertion methods fail; test methods raising this
-    # exception will be deemed to have 'failed' rather than 'errored'
-
-    failureException = AssertionError
-
-    # the name of the fixture.  Used for displaying meta data about the test
-    name = None
-    
-    def __init__(self, methodName='runTest'):
-        """Create an instance of the class that will use the named test
-        method when executed. Raises a ValueError if the instance does
-        not have a method with the specified name.
-        """
-        self._testMethodName = methodName
-        self._setupTestMethod()
-        self._setupMetaData()
-
-    def _setupTestMethod(self):
-        try:
-            self._testMethod = getattr(self, self._testMethodName)
-        except AttributeError:
-            raise ValueError, "no such test method in %s: %s" % \
-                  (self.__class__, self._testMethodName)
-        
-    ## meta data methods
-        
-    def _setupMetaData(self):
-        """Setup the default meta data for the test case:
-
-        - id: self.__class__.__name__ + testMethodName OR self.name + testMethodName
-        - description: 1st line of Class docstring + 1st line of method docstring
-        - explanation: rest of Class docstring + rest of method docstring
-        
-        """
-
-        
-        testDoc = self._testMethod.__doc__ or '\n'
-        testDocLines = testDoc.splitlines()
-        
-        testDescription = testDocLines[0].strip()
-        if len(testDocLines) > 1:
-            testExplanation = '\n'.join(
-                [ln.strip() for ln in testDocLines[1:]]
-                ).strip()
-        else:
-            testExplanation = ''
-            
-        fixtureDoc = self.__doc__ or '\n'
-        fixtureDocLines = fixtureDoc.splitlines()
-        fixtureDescription = fixtureDocLines[0].strip()
-        if len(fixtureDocLines) > 1:
-            fixtureExplanation = '\n'.join(
-                [ln.strip() for ln in fixtureDocLines[1:]]
-                ).strip()
-        else:
-            fixtureExplanation = ''
-        
-        if not self.name:
-            self.name = self.__class__
-        self._id = "%s.%s" % (self.name, self._testMethodName)
-        
-        if not fixtureDescription:
-            self._description = testDescription
-        else:
-            self._description = fixtureDescription + ', ' + testDescription
-
-        if not fixtureExplanation:
-            self._explanation = testExplanation
-        else:
-            self._explanation = ['Fixture Explanation:',
-                                 '--------------------',
-                                 fixtureExplanation,
-                                 '',
-                                 'Test Explanation:',
-                                 '-----------------',
-                                 testExplanation
-                                 ]
-            self._explanation = '\n'.join(self._explanation)
-
-    def id(self):
-        return self._id
-
-    def setId(self, id):
-        self._id = id
-
-    def describe(self):
-        """Returns a one-line description of the test, or None if no
-        description has been provided.
-
-        The default implementation of this method returns the first line of
-        the specified test method's docstring.
-        """
-        return self._description
-
-    shortDescription = describe
-    
-    def setDescription(self, descr):
-        self._description = descr
-    
-    def explain(self):
-        return self._explanation
-
-    def setExplanation(self, expln):
-        self._explanation = expln
-
-    ## core methods
-
-    def setUp(self):
-        "Hook method for setting up the test fixture before exercising it."
-        pass
-    
-    def run(self, result=None):
-        return self(result)
-        
-    def tearDown(self):
-        "Hook method for deconstructing the test fixture after testing it."
-        pass
-
-    def debug(self):
-        """Run the test without collecting errors in a TestResult"""
-        self.setUp()
-        self._testMethod()
-        self.tearDown()
-
-    ## internal methods
-
-    def defaultTestResult(self):
-        return TestResult()
-    
-    def __call__(self, result=None):
-        if result is None:
-            result = self.defaultTestResult()
-        
-        result.startTest(self)
-        try:
-            try:
-                self.setUp()
-            except:
-                result.addError(self, self.__exc_info())
-                return
-            
-            ok = 0
-            try:
-                self._testMethod()
-                ok = 1
-            except self.failureException, e:
-                result.addFailure(self, self.__exc_info())
-            except:
-                result.addError(self, self.__exc_info())
-            try:
-                self.tearDown()
-            except:
-                result.addError(self, self.__exc_info())
-                ok = 0
-            if ok:
-                result.addSuccess(self)
-        finally:
-            result.stopTest(self)
-            
-        return result
-        
-    def countTestCases(self):
-        return 1
-      
-    def __str__(self):
-        return "%s (%s)" % (self._testMethodName, self.__class__)
-
-    def __repr__(self):
-        return "<%s testMethod=%s>" % \
-               (self.__class__, self._testMethodName)
-
-    def __exc_info(self):
-        """Return a version of sys.exc_info() with the traceback frame
-           minimised; usually the top level of the traceback frame is not
-           needed.
-        """
-        exctype, excvalue, tb = sys.exc_info()
-        if sys.platform[:4] == 'java': ## tracebacks look different in Jython
-            return (exctype, excvalue, tb)
-        newtb = tb.tb_next
-        if newtb is None:
-            return (exctype, excvalue, tb)
-        return (exctype, excvalue, newtb)
-
-    ## methods for use by the test cases
-
-    def fail(self, msg=None):
-        """Fail immediately, with the given message."""
-        raise self.failureException, msg
-
-    def failIf(self, expr, msg=None):
-        "Fail the test if the expression is true."
-        if expr: raise self.failureException, msg
-
-    def failUnless(self, expr, msg=None):
-        """Fail the test unless the expression is true."""
-        if not expr: raise self.failureException, msg
-
-    def failUnlessRaises(self, excClass, callableObj, *args, **kwargs):
-        """Fail unless an exception of class excClass is thrown
-           by callableObj when invoked with arguments args and keyword
-           arguments kwargs. If a different type of exception is
-           thrown, it will not be caught, and the test case will be
-           deemed to have suffered an error, exactly as for an
-           unexpected exception.
-        """
-        try:
-            apply(callableObj, args, kwargs)
-        except excClass:
-            return
-        else:
-            if hasattr(excClass,'__name__'): excName = excClass.__name__
-            else: excName = str(excClass)
-            raise self.failureException, excName
-
-    def failUnlessEqual(self, first, second, msg=None):
-        """Fail if the two objects are unequal as determined by the '!='
-           operator.
-        """
-        if first != second:
-            raise self.failureException, (msg or '%s != %s' % (first, second))
-
-    def failIfEqual(self, first, second, msg=None):
-        """Fail if the two objects are equal as determined by the '=='
-           operator.
-        """
-        if first == second:
-            raise self.failureException, (msg or '%s == %s' % (first, second))
-
-    def failUnlessAlmostEqual(self, first, second, places=7, msg=None):
-        """Fail if the two objects are unequal as determined by their
-           difference rounded to the given number of decimal places
-           (default 7) and comparing to zero.
-
-           Note that decimal places (from zero) is usually not the same
-           as significant digits (measured from the most signficant digit).
-        """
-        if round(second-first, places) != 0:
-            raise self.failureException, \
-                  (msg or '%s != %s within %s places' % (`first`, `second`, `places` ))
-
-    def failIfAlmostEqual(self, first, second, places=7, msg=None):
-        """Fail if the two objects are equal as determined by their
-           difference rounded to the given number of decimal places
-           (default 7) and comparing to zero.
-
-           Note that decimal places (from zero) is usually not the same
-           as significant digits (measured from the most signficant digit).
-        """
-        if round(second-first, places) == 0:
-            raise self.failureException, \
-                  (msg or '%s == %s within %s places' % (`first`, `second`, `places`))
-
-    ## aliases
-
-    assertEqual = assertEquals = failUnlessEqual
-
-    assertNotEqual = assertNotEquals = failIfEqual
-
-    assertAlmostEqual = assertAlmostEquals = failUnlessAlmostEqual
-
-    assertNotAlmostEqual = assertNotAlmostEquals = failIfAlmostEqual
-
-    assertRaises = failUnlessRaises
-
-    assert_ = failUnless
-
-
-class FunctionTestCase(TestCase):
-    """A test case that wraps a test function.
-
-    This is useful for slipping pre-existing test functions into the
-    PyUnit framework. Optionally, set-up and tidy-up functions can be
-    supplied. As with TestCase, the tidy-up ('tearDown') function will
-    always be called if the set-up ('setUp') function ran successfully.
-    """
-
-    def __init__(self, testFunc, setUp=None, tearDown=None,
-                 description=None):
-        TestCase.__init__(self)
-        self.__setUpFunc = setUp
-        self.__tearDownFunc = tearDown
-        self.__testFunc = testFunc
-        self.__description = description
-
-    def setUp(self):
-        if self.__setUpFunc is not None:
-            self.__setUpFunc()
-
-    def tearDown(self):
-        if self.__tearDownFunc is not None:
-            self.__tearDownFunc()
-
-    def runTest(self):
-        self.__testFunc()
-
-    def id(self):
-        return self.__testFunc.__name__
-
-    def __str__(self):
-        return "%s (%s)" % (self.__class__, self.__testFunc.__name__)
-
-    def __repr__(self):
-        return "<%s testFunc=%s>" % (self.__class__, self.__testFunc)
-
-
-    def describe(self):
-        if self.__description is not None: return self.__description
-        doc = self.__testFunc.__doc__
-        return doc and string.strip(string.split(doc, "\n")[0]) or None
-    
-    ## aliases
-    shortDescription = describe
-
-class TestSuite:
-    """A test suite is a composite test consisting of a number of TestCases.
-
-    For use, create an instance of TestSuite, then add test case instances.
-    When all tests have been added, the suite can be passed to a test
-    runner, such as TextTestRunner. It will run the individual test cases
-    in the order in which they were added, aggregating the results. When
-    subclassing, do not forget to call the base class constructor.
-    """
-    def __init__(self, tests=(), suiteName=None):
-        self._tests = []
-        self._testMap = {}
-        self.suiteName = suiteName
-        self.addTests(tests)
-
-    def __repr__(self):
-        return "<%s tests=%s>" % (self.__class__, pprint.pformat(self._tests))
-
-    __str__ = __repr__
-
-    def countTestCases(self):
-        cases = 0
-        for test in self._tests:
-            cases = cases + test.countTestCases()
-        return cases
-
-    def addTest(self, test):
-        self._tests.append(test)
-        if isinstance(test, TestSuite) and test.suiteName:
-            name = test.suiteName
-        elif isinstance(test, TestCase):
-            #print test, test._testMethodName
-            name = test._testMethodName
-        else:
-            name = test.__class__.__name__
-        self._testMap[name] = test
-        
-    def addTests(self, tests):
-        for test in tests:
-            self.addTest(test)
-
-    def getTestForName(self, name):
-        return self._testMap[name]
-
-    def run(self, result):
-        return self(result)
-
-    def __call__(self, result):
-        for test in self._tests:
-            if result.shouldStop:
-                break
-            test(result)
-        return result
-
-    def debug(self):
-        """Run the tests without collecting errors in a TestResult"""
-        for test in self._tests: test.debug()
-
-
-##############################################################################
-# Text UI
-##############################################################################
-
-class StreamWrapper:
-    def __init__(self, out=sys.stdout, err=sys.stderr):
-        self._streamOut = out
-        self._streamErr = err
-
-    def write(self, txt):
-        self._streamOut.write(txt)
-        self._streamOut.flush()
-    
-    def writeln(self, *lines):
-        for line in lines:
-            self.write(line + '\n')
-        if not lines:
-            self.write('\n')
-
-    def writeErr(self, txt):
-        self._streamErr.write(txt)
-    
-    def writelnErr(self, *lines):
-        for line in lines:
-            self.writeErr(line + '\n')
-        if not lines:
-            self.writeErr('\n')
-
-
-class _TextTestResult(TestResult, StreamWrapper):
-    _separatorWidth = 70
-    _sep1 = '='
-    _sep2 = '-'
-    _errorSep1 = '*'
-    _errorSep2 = '-'
-    _errorSep3 = ''
-    
-    def __init__(self,
-                 stream=sys.stdout,
-                 errStream=sys.stderr,
-                 verbosity=1,
-                 explain=False):
-        
-        TestResult.__init__(self)
-        StreamWrapper.__init__(self, out=stream, err=errStream)        
-
-        self._verbosity = verbosity
-        self._showAll = verbosity > 1
-        self._dots = (verbosity == 1)
-        self._explain = explain
-
-    ## startup and shutdown methods
-        
-    def beginTests(self):
-        self._startTime = time.time()
-
-    def endTests(self):
-        self._stopTime = time.time()
-        self._timeTaken = float(self._stopTime - self._startTime)
-
-    def stop(self):
-        self.shouldStop = 1
-        
-    ## methods called for each test
-        
-    def startTest(self, test):
-        TestResult.startTest(self, test)
-        if self._showAll:
-            self.write("%s (%s)" %( test.id(), test.describe() ) )
-            self.write(" ... ")
-
-    def addSuccess(self, test):
-        TestResult.addSuccess(self, test)
-        if self._showAll:
-            self.writeln("ok")
-        elif self._dots:
-            self.write('.')
-
-    def addError(self, test, err):
-        TestResult.addError(self, test, err)
-        if self._showAll:
-            self.writeln("ERROR")
-        elif self._dots:
-            self.write('E')
-        if err[0] is KeyboardInterrupt:
-            self.stop()
-
-    def addFailure(self, test, err):
-        TestResult.addFailure(self, test, err)
-        if self._showAll:
-            self.writeln("FAIL")
-        elif self._dots:
-            self.write('F')
-
-    ## display methods
-
-    def summarize(self):
-        self.printErrors()
-        self.writeSep2()
-        run = self.testsRun
-        self.writeln("Ran %d test%s in %.3fs" %
-                            (run, run == 1 and "" or "s", self._timeTaken))
-        self.writeln()
-        if not self.wasSuccessful():
-            self.writeErr("FAILED (")
-            failed, errored = map(len, (self.failures, self.errors))
-            if failed:
-                self.writeErr("failures=%d" % failed)
-            if errored:
-                if failed: self.writeErr(", ")
-                self.writeErr("errors=%d" % errored)
-            self.writelnErr(")")
-        else:
-            self.writelnErr("OK")
-
-    def writeSep1(self):
-        self.writeln(self._sep1 * self._separatorWidth)
-
-    def writeSep2(self):
-        self.writeln(self._sep2 * self._separatorWidth)
-
-    def writeErrSep1(self):
-        self.writeln(self._errorSep1 * self._separatorWidth)
-
-    def writeErrSep2(self):
-        self.writeln(self._errorSep2 * self._separatorWidth)
-
-    def printErrors(self):
-        if self._dots or self._showAll:
-            self.writeln()
-        self.printErrorList('ERROR', self.errors)
-        self.printErrorList('FAIL', self.failures)
-
-    def printErrorList(self, flavour, errors):
-        for test, err in errors:
-            self.writeErrSep1()
-            self.writelnErr("%s %s (%s)" % (flavour, test.id(), test.describe() ))
-            if self._explain:
-                expln = test.explain()
-                if expln:
-                    self.writeErrSep2()
-                    self.writeErr( expln )
-                    self.writelnErr()
-
-            self.writeErrSep2()
-            for line in apply(traceback.format_exception, err):
-                for l in line.split("\n")[:-1]:
-                    self.writelnErr(l)
-            self.writelnErr("")
-
-class TextTestRunner:
-    def __init__(self,
-                 stream=sys.stdout,
-                 errStream=sys.stderr,
-                 verbosity=1,
-                 explain=False):
-
-        self._out = stream
-        self._err = errStream
-        self._verbosity = verbosity
-        self._explain = explain
-        
-    ## main methods
-
-    def run(self, test):
-        result = self._makeResult()
-        result.beginTests()
-        test( result )
-        result.endTests()      
-        result.summarize()
-        
-        return result
-    
-    ## internal methods
-
-    def _makeResult(self):
-        return _TextTestResult(stream=self._out,
-                               errStream=self._err,
-                               verbosity=self._verbosity,
-                               explain=self._explain,
-                               )
-
-##############################################################################
-# Locating and loading tests
-##############################################################################
-
-class TestLoader:
-    """This class is responsible for loading tests according to various
-    criteria and returning them wrapped in a Test
-    """
-    testMethodPrefix = 'test'
-    sortTestMethodsUsing = cmp
-    suiteClass = TestSuite
-
-    def loadTestsFromTestCase(self, testCaseClass):
-        """Return a suite of all tests cases contained in testCaseClass"""
-        return self.suiteClass(tests=map(testCaseClass,
-                                         self.getTestCaseNames(testCaseClass)),
-                               suiteName=testCaseClass.__name__)
-
-    def loadTestsFromModule(self, module):
-        """Return a suite of all tests cases contained in the given module"""
-        tests = []
-        for name in dir(module):
-            obj = getattr(module, name)
-            if type(obj) == types.ClassType and issubclass(obj, TestCase):
-                tests.append(self.loadTestsFromTestCase(obj))
-        return self.suiteClass(tests)
-
-    def loadTestsFromName(self, name, module=None):
-        """Return a suite of all tests cases given a string specifier.
-
-        The name may resolve either to a module, a test case class, a
-        test method within a test case class, or a callable object which
-        returns a TestCase or TestSuite instance.
-
-        The method optionally resolves the names relative to a given module.
-        """
-        parts = string.split(name, '.')
-        if module is None:
-            if not parts:
-                raise ValueError, "incomplete test name: %s" % name
-            else:
-                parts_copy = parts[:]
-                while parts_copy:
-                    try:
-                        module = __import__(string.join(parts_copy,'.'))
-                        break
-                    except ImportError:
-                        del parts_copy[-1]
-                        if not parts_copy: raise
-                parts = parts[1:]
-        obj = module
-        for part in parts:
-            if isinstance(obj, TestSuite):
-                obj = obj.getTestForName(part)
-            else:
-                obj = getattr(obj, part)
-
-        if type(obj) == types.ModuleType:
-            return self.loadTestsFromModule(obj)
-        elif type(obj) == types.ClassType and issubclass(obj, TestCase):
-            return self.loadTestsFromTestCase(obj)
-        elif type(obj) == types.UnboundMethodType:
-            return obj.im_class(obj.__name__)
-        elif isinstance(obj, TestSuite):
-            return obj
-        elif isinstance(obj, TestCase):
-            return obj
-        elif callable(obj):
-            test = obj()
-            if not isinstance(test, TestCase) and \
-               not isinstance(test, TestSuite):
-                raise ValueError, \
-                      "calling %s returned %s, not a test" %(obj,test)
-            return test
-        else:
-            raise ValueError, "don't know how to make test from: %s" % obj
-
-    def loadTestsFromNames(self, names, module=None):
-        """Return a suite of all tests cases found using the given sequence
-        of string specifiers. See 'loadTestsFromName()'.
-        """
-        suites = []
-        for name in names:
-            suites.append(self.loadTestsFromName(name, module))
-        return self.suiteClass(suites)
-
-    def getTestCaseNames(self, testCaseClass):
-        """Return a sorted sequence of method names found within testCaseClass.
-        """
-        testFnNames = [fn for fn in dir(testCaseClass) if fn.startswith(self.testMethodPrefix)]
-        if hasattr(testCaseClass, 'runTest'):
-            testFnNames.append('runTest')
-        for baseclass in testCaseClass.__bases__:
-            for testFnName in self.getTestCaseNames(baseclass):
-                if testFnName not in testFnNames:  # handle overridden methods
-                    testFnNames.append(testFnName)
-        if self.sortTestMethodsUsing:
-            testFnNames.sort(self.sortTestMethodsUsing)
-        return testFnNames
-
-
-
-defaultTestLoader = TestLoader()
-
-
-##############################################################################
-# Patches for old functions: these functions should be considered obsolete
-##############################################################################
-
-def _makeLoader(prefix, sortUsing, suiteClass=None):
-    loader = TestLoader()
-    loader.sortTestMethodsUsing = sortUsing
-    loader.testMethodPrefix = prefix
-    if suiteClass: loader.suiteClass = suiteClass
-    return loader
-
-def getTestCaseNames(testCaseClass, prefix, sortUsing=cmp):
-    return _makeLoader(prefix, sortUsing).getTestCaseNames(testCaseClass)
-
-def makeSuite(testCaseClass, prefix='test', sortUsing=cmp, suiteClass=TestSuite):
-    return _makeLoader(prefix, sortUsing, suiteClass).loadTestsFromTestCase(testCaseClass)
-
-def findTestCases(module, prefix='test', sortUsing=cmp, suiteClass=TestSuite):
-    return _makeLoader(prefix, sortUsing, suiteClass).loadTestsFromModule(module)
-
-##############################################################################
-# Facilities for running tests from the command line
-##############################################################################
-
-class TestProgram:
-    """A command-line program that runs a set of tests; this is primarily
-       for making test modules conveniently executable.
-    """
-    USAGE = """\
-Usage: %(progName)s [options] [test] [...]
-
-Options:
-  -h, --help       Show this message
-  -v, --verbose    Verbose output
-  -q, --quiet      Minimal output
-  -e, --expain     Output extra test details if there is a failure or error
-  
-Examples:
-  %(progName)s                               - run default set of tests
-  %(progName)s MyTestSuite                   - run suite 'MyTestSuite'
-  %(progName)s MyTestSuite.MyTestCase        - run suite 'MyTestSuite'
-  %(progName)s MyTestCase.testSomething      - run MyTestCase.testSomething
-  %(progName)s MyTestCase                    - run all 'test*' test methods
-                                               in MyTestCase
-"""
-    def __init__(self, module='__main__', defaultTest=None,
-                 argv=None, testRunner=None, testLoader=defaultTestLoader,
-                 testSuite=None):
-        if type(module) == type(''):
-            self.module = __import__(module)
-            for part in string.split(module,'.')[1:]:
-                self.module = getattr(self.module, part)
-        else:
-            self.module = module
-        if argv is None:
-            argv = sys.argv
-        self.test = testSuite
-        self.verbosity = 1
-        self.explain = 0
-        self.defaultTest = defaultTest
-        self.testRunner = testRunner
-        self.testLoader = testLoader
-        self.progName = os.path.basename(argv[0])
-        self.parseArgs(argv)
-        self.runTests()
-
-    def usageExit(self, msg=None):
-        if msg: print(msg)
-        print(self.USAGE % self.__dict__)
-        sys.exit(2)
-
-    def parseArgs(self, argv):
-        import getopt
-        try:
-            options, args = getopt.getopt(argv[1:], 'hHvqer',
-                                  ['help','verbose','quiet','explain', 'raise'])
-            for opt, value in options:
-                if opt in ('-h','-H','--help'):
-                    self.usageExit()
-                if opt in ('-q','--quiet'):
-                    self.verbosity = 0
-                if opt in ('-v','--verbose'):
-                    self.verbosity = 2
-                if opt in ('-e','--explain'):
-                    self.explain = True
-            if len(args) == 0 and self.defaultTest is None and self.test is None:
-                self.test = self.testLoader.loadTestsFromModule(self.module)
-                return
-            if len(args) > 0:
-                self.testNames = args
-            else:
-                self.testNames = (self.defaultTest,)
-            self.createTests()
-        except getopt.error, msg:
-            self.usageExit(msg)
-
-    def createTests(self):
-        if self.test == None:
-            self.test = self.testLoader.loadTestsFromNames(self.testNames,
-                                                           self.module)
-
-    def runTests(self):
-        if self.testRunner is None:
-            self.testRunner = TextTestRunner(verbosity=self.verbosity,
-                                             explain=self.explain)
-        result = self.testRunner.run(self.test)
-        self._cleanupAfterRunningTests()
-        sys.exit(not result.wasSuccessful())
-
-    def _cleanupAfterRunningTests(self):
-        """A hook method that is called immediately prior to calling
-        sys.exit(not result.wasSuccessful()) in self.runTests().
-        """
-        pass
-
-main = TestProgram
-
-
-##############################################################################
-# Executing this module from the command line
-##############################################################################
-
-if __name__ == "__main__":
-    main(module=None)
-
-# vim: shiftwidth=4 tabstop=4 expandtab
diff --git a/cheetah/Tools/MondoReport.py b/cheetah/Tools/MondoReport.py
index d0fada2..e8d34a4 100644
--- a/cheetah/Tools/MondoReport.py
+++ b/cheetah/Tools/MondoReport.py
@@ -12,7 +12,7 @@ next.query.
 
 How about Report: .page(), .all(), .summary()?  Or PageBreaker.
 """
-import operator, types
+import operator
 try:
     from Cheetah.NameMapper import valueForKey as lookup_func
 except ImportError:
@@ -22,18 +22,13 @@ except ImportError:
         else:
             return obj[name] # Raises KeyError.
 
-########## CONSTANTS ##############################
-
-True, False = (1==1), (1==0)
-numericTypes = types.IntType, types.LongType, types.FloatType
-
 ########## PUBLIC GENERIC FUNCTIONS ##############################
 
 class NegativeError(ValueError):
     pass
 
 def isNumeric(v):
-    return type(v) in numericTypes
+    return isinstance(v, (int, float))
 
 def isNonNegative(v):
     ret = isNumeric(v)
diff --git a/cheetah/Utils/Misc.py b/cheetah/Utils/Misc.py
index 6ff5bb2..81949d1 100644
--- a/cheetah/Utils/Misc.py
+++ b/cheetah/Utils/Misc.py
@@ -1,20 +1,8 @@
-# $Id: Misc.py,v 1.8 2005/11/02 22:26:08 tavis_rudd Exp $
-"""Miscellaneous functions/objects used by Cheetah but also useful standalone.
-
-Meta-Data
-================================================================================
-Author: Mike Orr <iron@...>
-License: This software is released for unlimited distribution under the
-         terms of the MIT license.  See the LICENSE file.
-Version: $Revision: 1.8 $
-Start Date: 2001/11/07
-Last Revision Date: $Date: 2005/11/02 22:26:08 $
+#!/usr/bin/env python
+"""
+    Miscellaneous functions/objects used by Cheetah but also useful standalone.
 """
-__author__ = "Mike Orr <iron@...>"
-__revision__ = "$Revision: 1.8 $"[11:-2]
-
 import os          # Used in mkdirsWithPyInitFile.
-import types       # Used in useOrRaise.
 import sys         # Used in die.
 
 ##################################################
@@ -29,7 +17,7 @@ def useOrRaise(thing, errmsg=''):
 
     Called by: Cheetah.Servlet.cgiImport()
     """
-    if type(thing) == types.ClassType and issubclass(thing, Exception):
+    if isinstance(thing, type) and issubclass(thing, Exception):
         raise thing(errmsg)
     return thing
 
@@ -76,6 +64,4 @@ def mkdirsWithPyInitFiles(path):
         f = open(init, 'w') # Open and close to produce empty file.
         f.close()
 
-
-
 # vim: shiftwidth=4 tabstop=4 expandtab
diff --git a/cheetah/Utils/VerifyType.py b/cheetah/Utils/VerifyType.py
deleted file mode 100644
index 11a435d..0000000
--- a/cheetah/Utils/VerifyType.py
+++ /dev/null
@@ -1,83 +0,0 @@
-# $Id: VerifyType.py,v 1.4 2005/11/02 22:26:08 tavis_rudd Exp $
-"""Functions to verify an argument's type
-
-Meta-Data
-================================================================================
-Author: Mike Orr <iron@...>
-License: This software is released for unlimited distribution under the
-         terms of the MIT license.  See the LICENSE file.
-Version: $Revision: 1.4 $
-Start Date: 2001/11/07
-Last Revision Date: $Date: 2005/11/02 22:26:08 $
-"""
-__author__ = "Mike Orr <iron@...>"
-__revision__ = "$Revision: 1.4 $"[11:-2]
-
-##################################################
-## DEPENDENCIES
-
-import types       # Used in VerifyTypeClass.
-
-##################################################
-## PRIVATE FUNCTIONS
-
-def _errmsg(argname, ltd, errmsgExtra=''):
-    """Construct an error message.
-
-    argname, string, the argument name.
-    ltd, string, description of the legal types.
-    errmsgExtra, string, text to append to error mssage.
-    Returns: string, the error message.
-    """
-    if errmsgExtra:
-        errmsgExtra = '\n' + errmsgExtra
-    return "arg '%s' must be %s%s" % (argname, ltd, errmsgExtra)
-
-
-##################################################
-## TYPE VERIFICATION FUNCTIONS
-
-def VerifyType(arg, argname, legalTypes, ltd, errmsgExtra=''):
-    """Verify the type of an argument.
-    
-    arg, any, the argument.
-    argname, string, name of the argument.
-    legalTypes, list of type objects, the allowed types.
-    ltd, string, description of legal types (for error message).
-    errmsgExtra, string, text to append to error message.
-    Returns: None.
-    Exceptions: TypeError if 'arg' is the wrong type.
-    """
-    if type(arg) not in legalTypes:
-        m = _errmsg(argname, ltd, errmsgExtra)
-        raise TypeError(m)
-    return True
-
-
-def VerifyTypeClass(arg, argname, legalTypes, ltd, klass, errmsgExtra=''):
-    """Same, but if it's a class, verify it's a subclass of the right class.
-
-    arg, any, the argument.
-    argname, string, name of the argument.
-    legalTypes, list of type objects, the allowed types.
-    ltd, string, description of legal types (for error message).
-    klass, class, the parent class.
-    errmsgExtra, string, text to append to the error message.
-    Returns: None.
-    Exceptions: TypeError if 'arg' is the wrong type.
-    """
-    VerifyType(arg, argname, legalTypes, ltd, errmsgExtra)
-    # If no exception, the arg is a legal type.
-    if type(arg) == types.ClassType and not issubclass(arg, klass):
-        # Must test for "is class type" to avoid TypeError from issubclass().
-        m = _errmsg(argname, ltd, errmsgExtra)
-        raise TypeError(m)
-    return True
-
-# @@MO: Commented until we determine whether it's useful.
-#def VerifyClass(arg, argname, klass, ltd):
-#    """Same, but allow *only* a subclass of the right class.
-#    """
-#    VerifyTypeClass(arg, argname, [types.ClassType], ltd, klass)
-
-# vim: shiftwidth=4 tabstop=4 expandtab
diff --git a/cheetah/Utils/memcache.py b/cheetah/Utils/memcache.py
index 029f621..c535303 100644
--- a/cheetah/Utils/memcache.py
+++ b/cheetah/Utils/memcache.py
@@ -45,7 +45,6 @@ More detailed documentation is available in the L{Client} class.
 import sys
 import socket
 import time
-import types
 try:
     import cPickle as pickle
 except ImportError:
@@ -168,7 +167,7 @@ class Client:
                 self.buckets.append(server)
 
     def _get_server(self, key):
-        if type(key) == types.TupleType:
+        if isinstance(key, tuple):
             serverhash = key[0]
             key = key[1]
         else:
@@ -301,7 +300,7 @@ class Client:
         self._statlog(cmd)
 
         flags = 0
-        if isinstance(val, types.StringTypes):
+        if isinstance(val, str):
             pass
         elif isinstance(val, int):
             flags |= Client._FLAG_INTEGER
@@ -343,7 +342,7 @@ class Client:
             value = self._recv_value(server, flags, rlen)
             server.expect("END")
         except (_Error, socket.error), msg:
-            if type(msg) is types.TupleType:
+            if isinstance(msg, tuple):
                 msg = msg[1]
             server.mark_dead(msg)
             return None
@@ -451,7 +450,7 @@ class _Host:
     _DEAD_RETRY = 30  # number of seconds before retrying a dead server.
 
     def __init__(self, host, debugfunc=None):
-        if isinstance(host, types.TupleType):
+        if isinstance(host, tuple):
             host = host[0]
             self.weight = host[1]
         else:
@@ -562,7 +561,7 @@ if __name__ == "__main__":
     mc = Client(servers, debug=1)
 
     def to_s(val):
-        if not isinstance(val, types.StringTypes):
+        if not isinstance(val, str):
             return "%s (%s)" % (val, type(val))
         return "%s" % val
     def test_setget(key, val):
diff --git a/cheetah/c/_verifytype.c b/cheetah/c/_verifytype.c
deleted file mode 100644
index 6dadf22..0000000
--- a/cheetah/c/_verifytype.c
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * C-version of the src/Utils/VerifyType.py module.
- *
- * (c) 2009, R. Tyler Ballance <tyler@...>
- */
-#include <Python.h>
-#if __STDC_VERSION__ >= 199901L
-#include <stdbool.h>
-#else
-typedef enum { false, true } bool;
-#endif
-
-#include "Cheetah.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-static PyObject *_errorMessage(char *arg, char *legalTypes, char *extra)
-{
-    return PyString_FromFormat("Argument '%s' must be %s\n", arg, legalTypes);
-}
-
-static PyObject *py_verifytype(PyObject *self, PyObject *args, PyObject *kwargs)
-{
-    PyObject *argument, *legalTypes;
-    char *arg_string, *types_string, *extra;
-    PyObject *iterator, *item;
-    bool rc = false;
-    char *kwlist[] = {"argument", "argument_name", "legalType",
-                "types_string", "errmsgExtra", NULL};
-
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OsOs|s", kwlist, &argument,
-                &arg_string, &legalTypes, &types_string, &extra))
-        return NULL;
-
-    iterator = PyObject_GetIter(legalTypes);
-    if (iterator == NULL) {
-        return NULL;
-    }
-
-    while (item = PyIter_Next(iterator)) {
-        if ((PyObject *)argument->ob_type == item) {
-            rc = true;
-            Py_DECREF(item);
-            break;
-        }
-        Py_DECREF(item);
-    }
-    Py_DECREF(iterator);
-
-    if (rc)
-        Py_RETURN_TRUE;
-
-    PyErr_SetObject(PyExc_TypeError, _errorMessage(arg_string,
-            types_string, extra));
-    return NULL;
-}
-
-static PyObject *py_verifytypeclass(PyObject *self, PyObject *args, PyObject *kwargs)
-{
-    PyObject *argument, *legalTypes, *klass;
-    PyObject *verifyTypeArgs, *v;
-    char *arg_string, *types_string, *extra;
-    bool rc = false;
-
-    char *kwlist[] = {"argument", "argument_name", "legalTypes",
-           "types_string", "klass", "errmsgExtra", NULL};
-
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OsOsO|s", kwlist, &argument,
-                &arg_string, &legalTypes, &types_string, &klass, &extra))
-        return NULL;
-
-    verifyTypeArgs = Py_BuildValue("OsOs", argument, arg_string, legalTypes,
-            types_string);
-    v = py_verifytype(self, verifyTypeArgs, NULL);
-
-    if (v == NULL)
-        return NULL;
-    Py_DECREF(v);
-
-    if (PyClass_Check(argument) && (!PyClass_IsSubclass(argument, klass)) ) {
-        PyErr_SetObject(PyExc_TypeError, _errorMessage(arg_string,
-                types_string, extra));
-        return NULL;
-    }
-    Py_RETURN_TRUE;
-}
-
-static const char _verifytypedoc[] = "\
-\n\
-";
-static struct PyMethodDef _verifytype_methods[] = {
-    {"verifyType", (PyCFunction)py_verifytype, METH_VARARGS | METH_KEYWORDS, NULL},
-    {"verifyTypeClass", (PyCFunction)py_verifytypeclass, METH_VARARGS | METH_KEYWORDS, NULL},
-    {NULL}
-};
-
-PyMODINIT_FUNC init_verifytype()
-{
-    PyObject *module = Py_InitModule3("_verifytype", _verifytype_methods,
-            _verifytypedoc);
-}
-
-#ifdef __cplusplus
-}
-#endif
--
1.6.4.2


------------------------------------------------------------------------------
Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day
trial. Simplify your report design, integration and deployment - and focus on
what you do best, core application coding. Discover what's new with
Crystal Reports now.  http://p.sf.net/sfu/bobj-july
_______________________________________________
Cheetahtemplate-discuss mailing list
Cheetahtemplate-discuss@...
https://lists.sourceforge.net/lists/listinfo/cheetahtemplate-discuss

[PATCH 3/3] Refactor CheetahWrapper tests to locate my local cheetah/cheetah-compile in my PATH

by R. Tyler Ballance :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Adding the "buildandrun" shortcut script so to easily rerun the
full test suite locally; usage: ./buildandrun cheetah/Tests/Test.py
---
 buildandrun                     |   66 +++++++++++++++++++++++++++++++++++++++
 cheetah/Tests/CheetahWrapper.py |   27 +++++++++++++---
 2 files changed, 88 insertions(+), 5 deletions(-)
 create mode 100755 buildandrun

diff --git a/buildandrun b/buildandrun
new file mode 100755
index 0000000..d3b4e42
--- /dev/null
+++ b/buildandrun
@@ -0,0 +1,66 @@
+#!/usr/bin/env python
+
+import logging
+import os
+import os.path
+import subprocess
+import sys
+
+from optparse import OptionParser
+
+if os.getenv('DEBUG'):
+    logging.basicConfig(level=logging.DEBUG)
+
+def recursiverm(d):
+    for root, dirs, files in os.walk(d):
+        for f in files:
+            f = root + os.path.sep + f
+            logging.debug('Removing file: %s' % f)
+            os.unlink(f)
+
+def main():
+    op = OptionParser()
+    op.add_option('-c', '--clean', dest='clean', action='store_true',
+            help='Remove the contents of the build directory')
+    opts, args = op.parse_args()
+    if not args:
+        print('Specify a test script')
+        return
+
+
+    if opts.clean:
+        logging.debug('Removing build/')
+        recursiverm('build')
+
+    logging.debug('Building Cheetah')
+    rc = subprocess.call(('python', 'setup.py', 'build'))
+
+    if rc:
+        logging.debug('Build failed!')
+        return
+
+    logging.debug('Adjusting PATH and PYTHONPATH')
+    cwd = os.getcwd()
+
+    libdir = None
+    scriptdir = None
+
+    for sub in os.listdir('build'):
+        if sub.startswith('scripts'):
+            scriptdir = os.path.sep.join((cwd, 'build', sub))
+        if sub.startswith('lib'):
+            libdir = os.path.sep.join((cwd, 'build', sub))
+
+    newpath = '%s:%s' % (scriptdir, os.getenv('PATH'))
+    logging.debug('Setting PATH to: %s' % newpath)
+    os.putenv('PATH', newpath)
+    logging.debug('Setting PYTHONPATH to: %s' % libdir)
+    os.putenv('PYTHONPATH', libdir)
+
+    rc = subprocess.call( ['python',] + args )
+
+
+
+if __name__ == '__main__':
+    main()
+
diff --git a/cheetah/Tests/CheetahWrapper.py b/cheetah/Tests/CheetahWrapper.py
index 809be40..e44edef 100644
--- a/cheetah/Tests/CheetahWrapper.py
+++ b/cheetah/Tests/CheetahWrapper.py
@@ -12,6 +12,8 @@ Besides unittest usage, recognizes the following command-line options:
         Show the output of each subcommand.  (Normally suppressed.)
 '''
 import os
+import os.path
+import pdb
 import re                                     # Used by listTests.
 import shutil
 import sys
@@ -24,10 +26,13 @@ from Cheetah.CheetahWrapper import CheetahWrapper  # Used by NoBackup.
 try:
     from subprocess import Popen, PIPE, STDOUT
     class Popen4(Popen):
-        def __init__(self, cmd, bufsize=-1):
-            super(Popen4, self).__init__(cmd, bufsize=bufsize,
-                                         shell=True, close_fds=True,
-                                         stdin=PIPE, stdout=PIPE, stderr=STDOUT)
+        def __init__(self, cmd, bufsize=-1, shell=True, close_fds=True,
+                        stdin=PIPE, stdout=PIPE, stderr=STDOUT, **kwargs):
+
+            super(Popen4, self).__init__(cmd, bufsize=bufsize, shell=shell,
+                            close_fds=close_fds, stdin=stdin, stdout=stdout,
+                            stderr=stderr, **kwargs)
+
             self.tochild = self.stdin
             self.fromchild = self.stdout
             self.childerr = self.stderr
@@ -152,6 +157,17 @@ Found %(result)r"""
         msg = "backup file exists in spite of --nobackup: %s" % path
         self.failIf(exists, msg)
 
+    def locate_command(self, cmd):
+        paths = os.getenv('PATH')
+        if not paths:
+            return cmd
+        parts = cmd.split(' ')
+        paths = paths.split(':')
+        for p in paths:
+            p = p + os.path.sep + parts[0]
+            if os.path.isfile(p):
+                return ' '.join([p] + parts[1:])
+        return ' '.join(parts)
 
     def assertWin32Subprocess(self, cmd):
         _in, _out = os.popen4(cmd)
@@ -163,7 +179,8 @@ Found %(result)r"""
         return rc, output
 
     def assertPosixSubprocess(self, cmd):
-        process = Popen4(cmd)
+        cmd = self.locate_command(cmd)
+        process = Popen4(cmd, env=os.environ)
         process.tochild.close()
         output = process.fromchild.read()
         status = process.wait()
--
1.6.4.2


------------------------------------------------------------------------------
Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day
trial. Simplify your report design, integration and deployment - and focus on
what you do best, core application coding. Discover what's new with
Crystal Reports now.  http://p.sf.net/sfu/bobj-july
_______________________________________________
Cheetahtemplate-discuss mailing list
Cheetahtemplate-discuss@...
https://lists.sourceforge.net/lists/listinfo/cheetahtemplate-discuss