[Pytest-commit] commit/pytest: 5 new changesets

commits-noreply at bitbucket.org commits-noreply at bitbucket.org
Wed Dec 11 11:34:10 CET 2013


5 new commits in pytest:

https://bitbucket.org/hpk42/pytest/commits/0a824a82b71d/
Changeset:   0a824a82b71d
User:        flub
Date:        2013-11-22 13:27:34
Summary:     Correct comment
Affected #:  1 file

diff -r 4951204afadcc1070e0d478c7ba4e8bdd29cd8fd -r 0a824a82b71ddc93965f84fd0835a4d651607611 _pytest/assertion/rewrite.py
--- a/_pytest/assertion/rewrite.py
+++ b/_pytest/assertion/rewrite.py
@@ -655,7 +655,7 @@
             res_expr = ast.Compare(left_res, [op], [next_res])
             self.statements.append(ast.Assign([store_names[i]], res_expr))
             left_res, left_expl = next_res, next_expl
-        # Use py.code._reprcompare if that's available.
+        # Use pytest.assertion.util._reprcompare if that's available.
         expl_call = self.helper("call_reprcompare",
                                 ast.Tuple(syms, ast.Load()),
                                 ast.Tuple(load_names, ast.Load()),


https://bitbucket.org/hpk42/pytest/commits/1106c3f79880/
Changeset:   1106c3f79880
User:        flub
Date:        2013-11-22 13:28:59
Summary:     Ensure the long descriptions and formatting preserve unicode correctly

This is the first stage towards fixing issue319, at least
py.io.saferepr and py.code.ExceptionInfo need to be addressed as well.
Affected #:  2 files

diff -r 0a824a82b71ddc93965f84fd0835a4d651607611 -r 1106c3f79880b30e6a8ddfff56a4d8ecca5ff40b _pytest/assertion/__init__.py
--- a/_pytest/assertion/__init__.py
+++ b/_pytest/assertion/__init__.py
@@ -78,10 +78,13 @@
 
         for new_expl in hook_result:
             if new_expl:
-                # Don't include pageloads of data unless we are very verbose (-vv)
-                if len(''.join(new_expl[1:])) > 80*8 and item.config.option.verbose < 2:
-                    new_expl[1:] = ['Detailed information truncated, use "-vv" to see']
-                res = '\n~'.join(new_expl)
+                # Don't include pageloads of data unless we are very
+                # verbose (-vv)
+                if (len(py.builtin._totext('').join(new_expl[1:])) > 80*8
+                        and item.config.option.verbose < 2):
+                    new_expl[1:] = [py.builtin._totext(
+                        'Detailed information truncated, use "-vv" to see')]
+                res = py.builtin._totext('\n~').join(new_expl)
                 if item.config.getvalue("assertmode") == "rewrite":
                     # The result will be fed back a python % formatting
                     # operation, which will fail if there are extraneous

diff -r 0a824a82b71ddc93965f84fd0835a4d651607611 -r 1106c3f79880b30e6a8ddfff56a4d8ecca5ff40b _pytest/assertion/util.py
--- a/_pytest/assertion/util.py
+++ b/_pytest/assertion/util.py
@@ -11,6 +11,7 @@
 
 
 BuiltinAssertionError = py.builtin.builtins.AssertionError
+u = py.builtin._totext
 
 # The _reprcompare attribute on the util module is used by the new assertion
 # interpretation code and assertion rewriter to detect this plugin was
@@ -29,7 +30,18 @@
     for when one explanation needs to span multiple lines, e.g. when
     displaying diffs.
     """
-    # simplify 'assert False where False = ...'
+    explanation = _collapse_false(explanation)
+    lines = _split_explanation(explanation)
+    result = _format_lines(lines)
+    return u('\n').join(result)
+
+
+def _collapse_false(explanation):
+    """Collapse expansions of False
+
+    So this strips out any "assert False\n{where False = ...\n}"
+    blocks.
+    """
     where = 0
     while True:
         start = where = explanation.find("False\n{False = ", where)
@@ -51,28 +63,48 @@
             explanation = (explanation[:start] + explanation[start+15:end-1] +
                            explanation[end+1:])
             where -= 17
-    raw_lines = (explanation or '').split('\n')
-    # escape newlines not followed by {, } and ~
+    return explanation
+
+
+def _split_explanation(explanation):
+    """Return a list of individual lines in the explanation
+
+    This will return a list of lines split on '\n{', '\n}' and '\n~'.
+    Any other newlines will be escaped and appear in the line as the
+    literal '\n' characters.
+    """
+    raw_lines = (explanation or u('')).split('\n')
     lines = [raw_lines[0]]
     for l in raw_lines[1:]:
         if l.startswith('{') or l.startswith('}') or l.startswith('~'):
             lines.append(l)
         else:
             lines[-1] += '\\n' + l
+    return lines
 
+
+def _format_lines(lines):
+    """Format the individual lines
+
+    This will replace the '{', '}' and '~' characters of our mini
+    formatting language with the proper 'where ...', 'and ...' and ' +
+    ...' text, taking care of indentation along the way.
+
+    Return a list of formatted lines.
+    """
     result = lines[:1]
     stack = [0]
     stackcnt = [0]
     for line in lines[1:]:
         if line.startswith('{'):
             if stackcnt[-1]:
-                s = 'and   '
+                s = u('and   ')
             else:
-                s = 'where '
+                s = u('where ')
             stack.append(len(result))
             stackcnt[-1] += 1
             stackcnt.append(0)
-            result.append(' +' + '  '*(len(stack)-1) + s + line[1:])
+            result.append(u(' +') + u('  ')*(len(stack)-1) + s + line[1:])
         elif line.startswith('}'):
             assert line.startswith('}')
             stack.pop()
@@ -80,9 +112,9 @@
             result[stack[-1]] += line[1:]
         else:
             assert line.startswith('~')
-            result.append('  '*len(stack) + line[1:])
+            result.append(u('  ')*len(stack) + line[1:])
     assert len(stack) == 1
-    return '\n'.join(result)
+    return result
 
 
 # Provide basestring in python3
@@ -95,9 +127,9 @@
 def assertrepr_compare(config, op, left, right):
     """Return specialised explanations for some operators/operands"""
     width = 80 - 15 - len(op) - 2  # 15 chars indentation, 1 space around op
-    left_repr = py.io.saferepr(left, maxsize=int(width/2))
+    left_repr = py.io.saferepr(left, maxsize=int(width/2)) # XXX mangles unicode
     right_repr = py.io.saferepr(right, maxsize=width-len(left_repr))
-    summary = '%s %s %s' % (left_repr, op, right_repr)
+    summary = u('%s %s %s') % (left_repr, op, right_repr)
 
     issequence = lambda x: (isinstance(x, (list, tuple, Sequence))
                             and not isinstance(x, basestring))
@@ -120,13 +152,12 @@
         elif op == 'not in':
             if istext(left) and istext(right):
                 explanation = _notin_text(left, right, verbose)
-    except py.builtin._sysex:
-        raise
-    except:
+    except Exception:
         excinfo = py.code.ExceptionInfo()
         explanation = [
-            '(pytest_assertion plugin: representation of details failed.  '
-            'Probably an object has a faulty __repr__.)', str(excinfo)]
+            u('(pytest_assertion plugin: representation of details failed.  '
+              'Probably an object has a faulty __repr__.)'),
+            u(excinfo)]
 
     if not explanation:
         return None
@@ -148,8 +179,8 @@
                 break
         if i > 42:
             i -= 10                 # Provide some context
-            explanation = ['Skipping %s identical leading '
-                           'characters in diff, use -v to show' % i]
+            explanation = [u('Skipping %s identical leading '
+                             'characters in diff, use -v to show') % i]
             left = left[i:]
             right = right[i:]
         if len(left) == len(right):
@@ -158,8 +189,8 @@
                     break
             if i > 42:
                 i -= 10     # Provide some context
-                explanation += ['Skipping %s identical trailing '
-                                'characters in diff, use -v to show' % i]
+                explanation += [u('Skipping %s identical trailing '
+                                  'characters in diff, use -v to show') % i]
                 left = left[:-i]
                 right = right[:-i]
     explanation += [line.strip('\n')
@@ -172,16 +203,15 @@
     explanation = []
     for i in range(min(len(left), len(right))):
         if left[i] != right[i]:
-            explanation += ['At index %s diff: %r != %r' %
-                            (i, left[i], right[i])]
+            explanation += [u('At index %s diff: %r != %r')
+                            % (i, left[i], right[i])]
             break
     if len(left) > len(right):
-        explanation += [
-            'Left contains more items, first extra item: %s' %
-            py.io.saferepr(left[len(right)],)]
+        explanation += [u('Left contains more items, first extra item: %s')
+                        % py.io.saferepr(left[len(right)],)]
     elif len(left) < len(right):
         explanation += [
-            'Right contains more items, first extra item: %s' %
+            u('Right contains more items, first extra item: %s') %
             py.io.saferepr(right[len(left)],)]
     return explanation  # + _diff_text(py.std.pprint.pformat(left),
                         #             py.std.pprint.pformat(right))
@@ -192,11 +222,11 @@
     diff_left = left - right
     diff_right = right - left
     if diff_left:
-        explanation.append('Extra items in the left set:')
+        explanation.append(u('Extra items in the left set:'))
         for item in diff_left:
             explanation.append(py.io.saferepr(item))
     if diff_right:
-        explanation.append('Extra items in the right set:')
+        explanation.append(u('Extra items in the right set:'))
         for item in diff_right:
             explanation.append(py.io.saferepr(item))
     return explanation
@@ -207,25 +237,25 @@
     common = set(left).intersection(set(right))
     same = dict((k, left[k]) for k in common if left[k] == right[k])
     if same and not verbose:
-        explanation += ['Omitting %s identical items, use -v to show' %
+        explanation += [u('Omitting %s identical items, use -v to show') %
                         len(same)]
     elif same:
-        explanation += ['Common items:']
+        explanation += [u('Common items:')]
         explanation += py.std.pprint.pformat(same).splitlines()
     diff = set(k for k in common if left[k] != right[k])
     if diff:
-        explanation += ['Differing items:']
+        explanation += [u('Differing items:')]
         for k in diff:
             explanation += [py.io.saferepr({k: left[k]}) + ' != ' +
                             py.io.saferepr({k: right[k]})]
     extra_left = set(left) - set(right)
     if extra_left:
-        explanation.append('Left contains more items:')
+        explanation.append(u('Left contains more items:'))
         explanation.extend(py.std.pprint.pformat(
             dict((k, left[k]) for k in extra_left)).splitlines())
     extra_right = set(right) - set(left)
     if extra_right:
-        explanation.append('Right contains more items:')
+        explanation.append(u('Right contains more items:'))
         explanation.extend(py.std.pprint.pformat(
             dict((k, right[k]) for k in extra_right)).splitlines())
     return explanation
@@ -237,14 +267,14 @@
     tail = text[index+len(term):]
     correct_text = head + tail
     diff = _diff_text(correct_text, text, verbose)
-    newdiff = ['%s is contained here:' % py.io.saferepr(term, maxsize=42)]
+    newdiff = [u('%s is contained here:') % py.io.saferepr(term, maxsize=42)]
     for line in diff:
-        if line.startswith('Skipping'):
+        if line.startswith(u('Skipping')):
             continue
-        if line.startswith('- '):
+        if line.startswith(u('- ')):
             continue
-        if line.startswith('+ '):
-            newdiff.append('  ' + line[2:])
+        if line.startswith(u('+ ')):
+            newdiff.append(u('  ') + line[2:])
         else:
             newdiff.append(line)
     return newdiff


https://bitbucket.org/hpk42/pytest/commits/eebaac396f1f/
Changeset:   eebaac396f1f
User:        flub
Date:        2013-11-24 18:45:48
Summary:     Respect unicode in AssertionError argument

This is related to issue319
Affected #:  1 file

diff -r 1106c3f79880b30e6a8ddfff56a4d8ecca5ff40b -r eebaac396f1f9c769268c89ea615afec16abcb62 _pytest/assertion/reinterpret.py
--- a/_pytest/assertion/reinterpret.py
+++ b/_pytest/assertion/reinterpret.py
@@ -2,17 +2,17 @@
 import py
 from _pytest.assertion.util import BuiltinAssertionError
 
+
 class AssertionError(BuiltinAssertionError):
     def __init__(self, *args):
         BuiltinAssertionError.__init__(self, *args)
         if args:
             try:
-                self.msg = str(args[0])
-            except py.builtin._sysex:
-                raise
-            except:
-                self.msg = "<[broken __repr__] %s at %0xd>" %(
-                    args[0].__class__, id(args[0]))
+                self.msg = py.builtin._totext(args[0])
+            except Exception:
+                self.msg = py.builtin._totext(
+                    "<[broken __repr__] %s at %0xd> %s"
+                    % (args[0].__class__, id(args[0])))
         else:
             f = py.code.Frame(sys._getframe(1))
             try:


https://bitbucket.org/hpk42/pytest/commits/e98bfdcae5ea/
Changeset:   e98bfdcae5ea
User:        flub
Date:        2013-11-29 01:29:14
Summary:     Add test for unicode assertion descriptions

Also clean up a few debugging leftovers.
Affected #:  3 files

diff -r eebaac396f1f9c769268c89ea615afec16abcb62 -r e98bfdcae5ea7b6ffe1c47fd99c8d686d6581e08 _pytest/assertion/reinterpret.py
--- a/_pytest/assertion/reinterpret.py
+++ b/_pytest/assertion/reinterpret.py
@@ -11,7 +11,7 @@
                 self.msg = py.builtin._totext(args[0])
             except Exception:
                 self.msg = py.builtin._totext(
-                    "<[broken __repr__] %s at %0xd> %s"
+                    "<[broken __repr__] %s at %0xd>"
                     % (args[0].__class__, id(args[0])))
         else:
             f = py.code.Frame(sys._getframe(1))

diff -r eebaac396f1f9c769268c89ea615afec16abcb62 -r e98bfdcae5ea7b6ffe1c47fd99c8d686d6581e08 _pytest/assertion/util.py
--- a/_pytest/assertion/util.py
+++ b/_pytest/assertion/util.py
@@ -127,7 +127,7 @@
 def assertrepr_compare(config, op, left, right):
     """Return specialised explanations for some operators/operands"""
     width = 80 - 15 - len(op) - 2  # 15 chars indentation, 1 space around op
-    left_repr = py.io.saferepr(left, maxsize=int(width/2)) # XXX mangles unicode
+    left_repr = py.io.saferepr(left, maxsize=int(width/2))
     right_repr = py.io.saferepr(right, maxsize=width-len(left_repr))
     summary = u('%s %s %s') % (left_repr, op, right_repr)
 

diff -r eebaac396f1f9c769268c89ea615afec16abcb62 -r e98bfdcae5ea7b6ffe1c47fd99c8d686d6581e08 testing/test_assertion.py
--- a/testing/test_assertion.py
+++ b/testing/test_assertion.py
@@ -1,3 +1,4 @@
+# -*- coding: utf-8 -*-
 import sys
 
 import py, pytest
@@ -176,6 +177,15 @@
         expl = ' '.join(callequal('foo', 'bar'))
         assert 'raised in repr()' not in expl
 
+    def test_unicode(self):
+        left = py.builtin._totext('£€', 'utf-8')
+        right = py.builtin._totext('£', 'utf-8')
+        expl = callequal(left, right)
+        assert expl[0] == py.builtin._totext("'£€' == '£'", 'utf-8')
+        assert expl[1] == py.builtin._totext('- £€', 'utf-8')
+        assert expl[2] == py.builtin._totext('+ £', 'utf-8')
+
+
 def test_python25_compile_issue257(testdir):
     testdir.makepyfile("""
         def test_rewritten():


https://bitbucket.org/hpk42/pytest/commits/3d74d1564b1b/
Changeset:   3d74d1564b1b
User:        hpk42
Date:        2013-12-11 11:28:06
Summary:     add changelog: fix issue319 - correctly show unicode in assertion errors.  Many
thanks to Floris Bruynooghe for the complete PR.  Also means
we depend on py>=1.4.19 now.
Affected #:  8 files

diff -r 6bc51574e761e06bae5975cb51914a679bd4f60e -r 3d74d1564b1bda43484a129dea8f9442b3a18f11 CHANGELOG
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -13,6 +13,10 @@
 - PR90: add --color=yes|no|auto option to force terminal coloring 
   mode ("auto" is default).  Thanks Marc Abramowitz.
 
+- fix issue319 - correctly show unicode in assertion errors.  Many
+  thanks to Floris Bruynooghe for the complete PR.  Also means
+  we depend on py>=1.4.19 now.
+
 - fix issue396 - correctly sort and finalize class-scoped parametrized 
   tests independently from number of methods on the class.  
 

diff -r 6bc51574e761e06bae5975cb51914a679bd4f60e -r 3d74d1564b1bda43484a129dea8f9442b3a18f11 _pytest/__init__.py
--- a/_pytest/__init__.py
+++ b/_pytest/__init__.py
@@ -1,2 +1,2 @@
 #
-__version__ = '2.4.3.dev2'
+__version__ = '2.5.0.dev1'

diff -r 6bc51574e761e06bae5975cb51914a679bd4f60e -r 3d74d1564b1bda43484a129dea8f9442b3a18f11 _pytest/assertion/__init__.py
--- a/_pytest/assertion/__init__.py
+++ b/_pytest/assertion/__init__.py
@@ -78,10 +78,13 @@
 
         for new_expl in hook_result:
             if new_expl:
-                # Don't include pageloads of data unless we are very verbose (-vv)
-                if len(''.join(new_expl[1:])) > 80*8 and item.config.option.verbose < 2:
-                    new_expl[1:] = ['Detailed information truncated, use "-vv" to see']
-                res = '\n~'.join(new_expl)
+                # Don't include pageloads of data unless we are very
+                # verbose (-vv)
+                if (len(py.builtin._totext('').join(new_expl[1:])) > 80*8
+                        and item.config.option.verbose < 2):
+                    new_expl[1:] = [py.builtin._totext(
+                        'Detailed information truncated, use "-vv" to see')]
+                res = py.builtin._totext('\n~').join(new_expl)
                 if item.config.getvalue("assertmode") == "rewrite":
                     # The result will be fed back a python % formatting
                     # operation, which will fail if there are extraneous

diff -r 6bc51574e761e06bae5975cb51914a679bd4f60e -r 3d74d1564b1bda43484a129dea8f9442b3a18f11 _pytest/assertion/reinterpret.py
--- a/_pytest/assertion/reinterpret.py
+++ b/_pytest/assertion/reinterpret.py
@@ -2,17 +2,17 @@
 import py
 from _pytest.assertion.util import BuiltinAssertionError
 
+
 class AssertionError(BuiltinAssertionError):
     def __init__(self, *args):
         BuiltinAssertionError.__init__(self, *args)
         if args:
             try:
-                self.msg = str(args[0])
-            except py.builtin._sysex:
-                raise
-            except:
-                self.msg = "<[broken __repr__] %s at %0xd>" %(
-                    args[0].__class__, id(args[0]))
+                self.msg = py.builtin._totext(args[0])
+            except Exception:
+                self.msg = py.builtin._totext(
+                    "<[broken __repr__] %s at %0xd>"
+                    % (args[0].__class__, id(args[0])))
         else:
             f = py.code.Frame(sys._getframe(1))
             try:

diff -r 6bc51574e761e06bae5975cb51914a679bd4f60e -r 3d74d1564b1bda43484a129dea8f9442b3a18f11 _pytest/assertion/rewrite.py
--- a/_pytest/assertion/rewrite.py
+++ b/_pytest/assertion/rewrite.py
@@ -655,7 +655,7 @@
             res_expr = ast.Compare(left_res, [op], [next_res])
             self.statements.append(ast.Assign([store_names[i]], res_expr))
             left_res, left_expl = next_res, next_expl
-        # Use py.code._reprcompare if that's available.
+        # Use pytest.assertion.util._reprcompare if that's available.
         expl_call = self.helper("call_reprcompare",
                                 ast.Tuple(syms, ast.Load()),
                                 ast.Tuple(load_names, ast.Load()),

diff -r 6bc51574e761e06bae5975cb51914a679bd4f60e -r 3d74d1564b1bda43484a129dea8f9442b3a18f11 _pytest/assertion/util.py
--- a/_pytest/assertion/util.py
+++ b/_pytest/assertion/util.py
@@ -11,6 +11,7 @@
 
 
 BuiltinAssertionError = py.builtin.builtins.AssertionError
+u = py.builtin._totext
 
 # The _reprcompare attribute on the util module is used by the new assertion
 # interpretation code and assertion rewriter to detect this plugin was
@@ -29,7 +30,18 @@
     for when one explanation needs to span multiple lines, e.g. when
     displaying diffs.
     """
-    # simplify 'assert False where False = ...'
+    explanation = _collapse_false(explanation)
+    lines = _split_explanation(explanation)
+    result = _format_lines(lines)
+    return u('\n').join(result)
+
+
+def _collapse_false(explanation):
+    """Collapse expansions of False
+
+    So this strips out any "assert False\n{where False = ...\n}"
+    blocks.
+    """
     where = 0
     while True:
         start = where = explanation.find("False\n{False = ", where)
@@ -51,28 +63,48 @@
             explanation = (explanation[:start] + explanation[start+15:end-1] +
                            explanation[end+1:])
             where -= 17
-    raw_lines = (explanation or '').split('\n')
-    # escape newlines not followed by {, } and ~
+    return explanation
+
+
+def _split_explanation(explanation):
+    """Return a list of individual lines in the explanation
+
+    This will return a list of lines split on '\n{', '\n}' and '\n~'.
+    Any other newlines will be escaped and appear in the line as the
+    literal '\n' characters.
+    """
+    raw_lines = (explanation or u('')).split('\n')
     lines = [raw_lines[0]]
     for l in raw_lines[1:]:
         if l.startswith('{') or l.startswith('}') or l.startswith('~'):
             lines.append(l)
         else:
             lines[-1] += '\\n' + l
+    return lines
 
+
+def _format_lines(lines):
+    """Format the individual lines
+
+    This will replace the '{', '}' and '~' characters of our mini
+    formatting language with the proper 'where ...', 'and ...' and ' +
+    ...' text, taking care of indentation along the way.
+
+    Return a list of formatted lines.
+    """
     result = lines[:1]
     stack = [0]
     stackcnt = [0]
     for line in lines[1:]:
         if line.startswith('{'):
             if stackcnt[-1]:
-                s = 'and   '
+                s = u('and   ')
             else:
-                s = 'where '
+                s = u('where ')
             stack.append(len(result))
             stackcnt[-1] += 1
             stackcnt.append(0)
-            result.append(' +' + '  '*(len(stack)-1) + s + line[1:])
+            result.append(u(' +') + u('  ')*(len(stack)-1) + s + line[1:])
         elif line.startswith('}'):
             assert line.startswith('}')
             stack.pop()
@@ -80,9 +112,9 @@
             result[stack[-1]] += line[1:]
         else:
             assert line.startswith('~')
-            result.append('  '*len(stack) + line[1:])
+            result.append(u('  ')*len(stack) + line[1:])
     assert len(stack) == 1
-    return '\n'.join(result)
+    return result
 
 
 # Provide basestring in python3
@@ -97,7 +129,7 @@
     width = 80 - 15 - len(op) - 2  # 15 chars indentation, 1 space around op
     left_repr = py.io.saferepr(left, maxsize=int(width/2))
     right_repr = py.io.saferepr(right, maxsize=width-len(left_repr))
-    summary = '%s %s %s' % (left_repr, op, right_repr)
+    summary = u('%s %s %s') % (left_repr, op, right_repr)
 
     issequence = lambda x: (isinstance(x, (list, tuple, Sequence))
                             and not isinstance(x, basestring))
@@ -120,13 +152,12 @@
         elif op == 'not in':
             if istext(left) and istext(right):
                 explanation = _notin_text(left, right, verbose)
-    except py.builtin._sysex:
-        raise
-    except:
+    except Exception:
         excinfo = py.code.ExceptionInfo()
         explanation = [
-            '(pytest_assertion plugin: representation of details failed.  '
-            'Probably an object has a faulty __repr__.)', str(excinfo)]
+            u('(pytest_assertion plugin: representation of details failed.  '
+              'Probably an object has a faulty __repr__.)'),
+            u(excinfo)]
 
     if not explanation:
         return None
@@ -148,8 +179,8 @@
                 break
         if i > 42:
             i -= 10                 # Provide some context
-            explanation = ['Skipping %s identical leading '
-                           'characters in diff, use -v to show' % i]
+            explanation = [u('Skipping %s identical leading '
+                             'characters in diff, use -v to show') % i]
             left = left[i:]
             right = right[i:]
         if len(left) == len(right):
@@ -158,8 +189,8 @@
                     break
             if i > 42:
                 i -= 10     # Provide some context
-                explanation += ['Skipping %s identical trailing '
-                                'characters in diff, use -v to show' % i]
+                explanation += [u('Skipping %s identical trailing '
+                                  'characters in diff, use -v to show') % i]
                 left = left[:-i]
                 right = right[:-i]
     explanation += [line.strip('\n')
@@ -172,16 +203,15 @@
     explanation = []
     for i in range(min(len(left), len(right))):
         if left[i] != right[i]:
-            explanation += ['At index %s diff: %r != %r' %
-                            (i, left[i], right[i])]
+            explanation += [u('At index %s diff: %r != %r')
+                            % (i, left[i], right[i])]
             break
     if len(left) > len(right):
-        explanation += [
-            'Left contains more items, first extra item: %s' %
-            py.io.saferepr(left[len(right)],)]
+        explanation += [u('Left contains more items, first extra item: %s')
+                        % py.io.saferepr(left[len(right)],)]
     elif len(left) < len(right):
         explanation += [
-            'Right contains more items, first extra item: %s' %
+            u('Right contains more items, first extra item: %s') %
             py.io.saferepr(right[len(left)],)]
     return explanation  # + _diff_text(py.std.pprint.pformat(left),
                         #             py.std.pprint.pformat(right))
@@ -192,11 +222,11 @@
     diff_left = left - right
     diff_right = right - left
     if diff_left:
-        explanation.append('Extra items in the left set:')
+        explanation.append(u('Extra items in the left set:'))
         for item in diff_left:
             explanation.append(py.io.saferepr(item))
     if diff_right:
-        explanation.append('Extra items in the right set:')
+        explanation.append(u('Extra items in the right set:'))
         for item in diff_right:
             explanation.append(py.io.saferepr(item))
     return explanation
@@ -207,25 +237,25 @@
     common = set(left).intersection(set(right))
     same = dict((k, left[k]) for k in common if left[k] == right[k])
     if same and not verbose:
-        explanation += ['Omitting %s identical items, use -v to show' %
+        explanation += [u('Omitting %s identical items, use -v to show') %
                         len(same)]
     elif same:
-        explanation += ['Common items:']
+        explanation += [u('Common items:')]
         explanation += py.std.pprint.pformat(same).splitlines()
     diff = set(k for k in common if left[k] != right[k])
     if diff:
-        explanation += ['Differing items:']
+        explanation += [u('Differing items:')]
         for k in diff:
             explanation += [py.io.saferepr({k: left[k]}) + ' != ' +
                             py.io.saferepr({k: right[k]})]
     extra_left = set(left) - set(right)
     if extra_left:
-        explanation.append('Left contains more items:')
+        explanation.append(u('Left contains more items:'))
         explanation.extend(py.std.pprint.pformat(
             dict((k, left[k]) for k in extra_left)).splitlines())
     extra_right = set(right) - set(left)
     if extra_right:
-        explanation.append('Right contains more items:')
+        explanation.append(u('Right contains more items:'))
         explanation.extend(py.std.pprint.pformat(
             dict((k, right[k]) for k in extra_right)).splitlines())
     return explanation
@@ -237,14 +267,14 @@
     tail = text[index+len(term):]
     correct_text = head + tail
     diff = _diff_text(correct_text, text, verbose)
-    newdiff = ['%s is contained here:' % py.io.saferepr(term, maxsize=42)]
+    newdiff = [u('%s is contained here:') % py.io.saferepr(term, maxsize=42)]
     for line in diff:
-        if line.startswith('Skipping'):
+        if line.startswith(u('Skipping')):
             continue
-        if line.startswith('- '):
+        if line.startswith(u('- ')):
             continue
-        if line.startswith('+ '):
-            newdiff.append('  ' + line[2:])
+        if line.startswith(u('+ ')):
+            newdiff.append(u('  ') + line[2:])
         else:
             newdiff.append(line)
     return newdiff

diff -r 6bc51574e761e06bae5975cb51914a679bd4f60e -r 3d74d1564b1bda43484a129dea8f9442b3a18f11 setup.py
--- a/setup.py
+++ b/setup.py
@@ -17,7 +17,7 @@
 
 long_description = open("README.rst").read()
 def main():
-    install_requires = ["py>=1.4.17"]
+    install_requires = ["py>=1.4.19"]
     if sys.version_info < (2,7):
         install_requires.append("argparse")
     if sys.platform == "win32":
@@ -27,7 +27,7 @@
         name='pytest',
         description='py.test: simple powerful testing with Python',
         long_description = long_description,
-        version='2.4.3.dev2',
+        version='2.5.0.dev1',
         url='http://pytest.org',
         license='MIT license',
         platforms=['unix', 'linux', 'osx', 'cygwin', 'win32'],

diff -r 6bc51574e761e06bae5975cb51914a679bd4f60e -r 3d74d1564b1bda43484a129dea8f9442b3a18f11 testing/test_assertion.py
--- a/testing/test_assertion.py
+++ b/testing/test_assertion.py
@@ -1,3 +1,4 @@
+# -*- coding: utf-8 -*-
 import sys
 
 import py, pytest
@@ -176,6 +177,15 @@
         expl = ' '.join(callequal('foo', 'bar'))
         assert 'raised in repr()' not in expl
 
+    def test_unicode(self):
+        left = py.builtin._totext('£€', 'utf-8')
+        right = py.builtin._totext('£', 'utf-8')
+        expl = callequal(left, right)
+        assert expl[0] == py.builtin._totext("'£€' == '£'", 'utf-8')
+        assert expl[1] == py.builtin._totext('- £€', 'utf-8')
+        assert expl[2] == py.builtin._totext('+ £', 'utf-8')
+
+
 def test_python25_compile_issue257(testdir):
     testdir.makepyfile("""
         def test_rewritten():

Repository URL: https://bitbucket.org/hpk42/pytest/

--

This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.


More information about the pytest-commit mailing list