← Back to team overview

testtools-dev team mailing list archive

[Merge] lp:~gz/testtools/python_3_for_0.9.10 into lp:testtools

 

Martin [gz] has proposed merging lp:~gz/testtools/python_3_for_0.9.10 into lp:testtools.

Requested reviews:
  testtools developers (testtools-dev)

For more details, see:
https://code.launchpad.net/~gz/testtools/python_3_for_0.9.10/+merge/58602

Make testtools suite pass on Python 3 again, as bug 688729 holds new complaint about StringIO.

The usual set of issues:
* Is print a statement or a function, even in doctests (I like bad-style brackets here, to make people think)
* No more iteritems (used dict.items instead, MatchesStructure shouldn't have giant dicts)
* Superfluous "is not true"[1] in some assertions (use TestCase.fail not TestCase.assertTrue)
* Low-level IO and tempfile and binary confusion (papered over, there's some bogus code here)
* StringIO moved and changed (use testtools.compat)
* Relative import is bad (absolutise)
* Syntax change to except clause (ugly sys.exc_info workaround)


[1]: <http://hg.python.org/cpython/file/4bd68b1f8702/Lib/unittest/case.py#l519>
-- 
https://code.launchpad.net/~gz/testtools/python_3_for_0.9.10/+merge/58602
Your team testtools developers is requested to review the proposed merge of lp:~gz/testtools/python_3_for_0.9.10 into lp:testtools.
=== modified file 'testtools/matchers.py'
--- testtools/matchers.py	2011-04-12 13:53:14 +0000
+++ testtools/matchers.py	2011-04-20 23:57:25 +0000
@@ -578,7 +578,7 @@
 
     >>> MatchesListwise([Equals(1)]).match([1])
     >>> MatchesListwise([Equals(1), Equals(2)]).match([1, 2])
-    >>> print MatchesListwise([Equals(1), Equals(2)]).match([2, 1]).describe()
+    >>> print (MatchesListwise([Equals(1), Equals(2)]).match([2, 1]).describe())
     Differences: [
     1 != 2
     2 != 1
@@ -628,7 +628,7 @@
 
     def update(self, **kws):
         new_kws = self.kws.copy()
-        for attr, matcher in kws.iteritems():
+        for attr, matcher in kws.items():
             if matcher is None:
                 new_kws.pop(attr, None)
             else:
@@ -637,14 +637,14 @@
 
     def __str__(self):
         kws = []
-        for attr, matcher in sorted(self.kws.iteritems()):
+        for attr, matcher in sorted(self.kws.items()):
             kws.append("%s=%s" % (attr, matcher))
         return "%s(%s)" % (self.__class__.__name__, ', '.join(kws))
 
     def match(self, value):
         matchers = []
         values = []
-        for attr, matcher in sorted(self.kws.iteritems()):
+        for attr, matcher in sorted(self.kws.items()):
             matchers.append(Annotate(attr, matcher))
             values.append(getattr(value, attr))
         return MatchesListwise(matchers).match(values)

=== modified file 'testtools/testcase.py'
--- testtools/testcase.py	2011-04-01 13:45:45 +0000
+++ testtools/testcase.py	2011-04-20 23:57:25 +0000
@@ -279,8 +279,8 @@
 
     def assertIn(self, needle, haystack):
         """Assert that needle is in haystack."""
-        self.assertTrue(
-            needle in haystack, '%r not in %r' % (needle, haystack))
+        if needle not in haystack:
+            self.fail('%r not in %r' % (needle, haystack))
 
     def assertIs(self, expected, observed, message=''):
         """Assert that 'expected' is 'observed'.
@@ -291,28 +291,27 @@
         """
         if message:
             message = ': ' + message
-        self.assertTrue(
-            expected is observed,
-            '%r is not %r%s' % (expected, observed, message))
+        if expected is not observed:
+            self.fail('%r is not %r%s' % (expected, observed, message))
 
     def assertIsNot(self, expected, observed, message=''):
         """Assert that 'expected' is not 'observed'."""
         if message:
             message = ': ' + message
-        self.assertTrue(
-            expected is not observed,
-            '%r is %r%s' % (expected, observed, message))
+        if expected is observed:
+            self.fail('%r is %r%s' % (expected, observed, message))
 
     def assertNotIn(self, needle, haystack):
         """Assert that needle is not in haystack."""
-        self.assertTrue(
-            needle not in haystack, '%r in %r' % (needle, haystack))
+        if needle in haystack:
+            self.fail('%r in %r' % (needle, haystack))
 
     def assertIsInstance(self, obj, klass, msg=None):
         if msg is None:
             msg = '%r is not an instance of %s' % (
                 obj, self._formatTypes(klass))
-        self.assertTrue(isinstance(obj, klass), msg)
+        if not isinstance(obj, klass):
+            self.fail(msg)
 
     def assertRaises(self, excClass, callableObj, *args, **kwargs):
         """Fail unless an exception of class excClass is thrown

=== modified file 'testtools/tests/test_content.py'
--- testtools/tests/test_content.py	2011-02-19 08:54:14 +0000
+++ testtools/tests/test_content.py	2011-04-20 23:57:25 +0000
@@ -90,11 +90,12 @@
     def test_from_file(self):
         fd, path = tempfile.mkstemp()
         self.addCleanup(os.remove, path)
-        os.write(fd, 'some data')
+        os.write(fd, _b('some data'))
         os.close(fd)
         content = content_from_file(path, UTF8_TEXT, chunk_size=2)
         self.assertThat(
-            list(content.iter_bytes()), Equals(['so', 'me', ' d', 'at', 'a']))
+            list(content.iter_bytes()),
+            Equals([_b('so'), _b('me'), _b(' d'), _b('at'), _b('a')]))
 
     def test_from_nonexistent_file(self):
         directory = tempfile.mkdtemp()
@@ -108,12 +109,12 @@
 
     def test_from_file_eager_loading(self):
         fd, path = tempfile.mkstemp()
-        os.write(fd, 'some data')
+        os.write(fd, _b('some data'))
         os.close(fd)
         content = content_from_file(path, UTF8_TEXT, buffer_now=True)
         os.remove(path)
         self.assertThat(
-            _b('').join(content.iter_bytes()), Equals('some data'))
+            ''.join(content.iter_text()), Equals('some data'))
 
     def test_from_stream(self):
         data = StringIO('some data')
@@ -129,13 +130,13 @@
     def test_from_stream_eager_loading(self):
         fd, path = tempfile.mkstemp()
         self.addCleanup(os.remove, path)
-        os.write(fd, 'some data')
+        os.write(fd, _b('some data'))
         stream = open(path, 'rb')
         content = content_from_stream(stream, UTF8_TEXT, buffer_now=True)
-        os.write(fd, 'more data')
+        os.write(fd, _b('more data'))
         os.close(fd)
         self.assertThat(
-            _b('').join(content.iter_bytes()), Equals('some data'))
+            ''.join(content.iter_text()), Equals('some data'))
 
     def test_from_text(self):
         data = _u("some data")
@@ -162,9 +163,12 @@
 class TestAttachFile(TestCase):
 
     def make_file(self, data):
+        # GZ 2011-04-21: This helper could be useful for methods above trying
+        #                to use mkstemp, but should handle write failures and
+        #                always close the fd. There must be a better way.
         fd, path = tempfile.mkstemp()
         self.addCleanup(os.remove, path)
-        os.write(fd, data)
+        os.write(fd, _b(data))
         os.close(fd)
         return path
 
@@ -202,7 +206,7 @@
         content_file = open(path, 'w')
         content_file.write('new data')
         content_file.close()
-        self.assertEqual(''.join(content.iter_bytes()), 'new data')
+        self.assertEqual(''.join(content.iter_text()), 'new data')
 
     def test_eager_read_by_default(self):
         class SomeTest(TestCase):
@@ -215,7 +219,7 @@
         content_file = open(path, 'w')
         content_file.write('new data')
         content_file.close()
-        self.assertEqual(''.join(content.iter_bytes()), 'some data')
+        self.assertEqual(''.join(content.iter_text()), 'some data')
 
 
 def test_suite():

=== modified file 'testtools/tests/test_matchers.py'
--- testtools/tests/test_matchers.py	2011-04-14 10:31:30 +0000
+++ testtools/tests/test_matchers.py	2011-04-20 23:57:25 +0000
@@ -4,13 +4,15 @@
 
 import doctest
 import re
-import StringIO
 import sys
 
 from testtools import (
     Matcher, # check that Matcher is exposed at the top level for docs.
     TestCase,
     )
+from testtools.compat import (
+    StringIO,
+    )
 from testtools.matchers import (
     AfterPreproccessing,
     Annotate,
@@ -490,7 +492,7 @@
     t = p.get_doctest(
         obj.__doc__, sys.modules[obj.__module__].__dict__, name, '', 0)
     r = doctest.DocTestRunner()
-    output = StringIO.StringIO()
+    output = StringIO()
     r.run(t, out=output.write)
     return r.failures, output.getvalue()
 

=== modified file 'testtools/tests/test_testtools.py'
--- testtools/tests/test_testtools.py	2011-04-01 13:45:45 +0000
+++ testtools/tests/test_testtools.py	2011-04-20 23:57:25 +0000
@@ -37,7 +37,7 @@
 except SyntaxError:
     pass
 else:
-    from test_with_with import *
+    from testtools.tests.test_with_with import *
 
 
 class TestPlaceHolder(TestCase):

=== modified file 'testtools/tests/test_with_with.py'
--- testtools/tests/test_with_with.py	2011-01-22 17:56:00 +0000
+++ testtools/tests/test_with_with.py	2011-04-20 23:57:25 +0000
@@ -2,6 +2,8 @@
 
 from __future__ import with_statement
 
+import sys
+
 from testtools import (
     ExpectedException,
     TestCase,
@@ -18,7 +20,8 @@
         try:
             with ExpectedException(ValueError, 'tes.'):
                 raise ValueError('mismatch')
-        except AssertionError, e:
+        except AssertionError:
+            e = sys.exc_info()[1]
             self.assertEqual('"mismatch" does not match "tes.".', str(e))
         else:
             self.fail('AssertionError not raised.')
@@ -27,7 +30,8 @@
         try:
             with ExpectedException(TypeError, 'tes.'):
                 raise ValueError('mismatch')
-        except ValueError, e:
+        except ValueError:
+            e = sys.exc_info()[1]
             self.assertEqual('mismatch', str(e))
         else:
             self.fail('ValueError not raised.')
@@ -36,7 +40,8 @@
         try:
             with ExpectedException(TypeError, 'tes.'):
                 pass
-        except AssertionError, e:
+        except AssertionError:
+            e = sys.exc_info()[1]
             self.assertEqual('TypeError not raised.', str(e))
         else:
             self.fail('AssertionError not raised.')


Follow ups