Skip to content

Commit a5dd73f

Browse files
committed
Use a simple +- ASCII string in the string representation of pytest.approx In Python 2
Fix pytest-dev#2111
1 parent 5365f7c commit a5dd73f

File tree

3 files changed

+45
-22
lines changed

3 files changed

+45
-22
lines changed

CHANGELOG.rst

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,11 @@
1515
* Provide ``:ref:`` targets for ``recwarn.rst`` so we can use intersphinx referencing.
1616
Thanks to `@dupuy`_ for the report and `@lwm`_ for the PR.
1717

18+
* In Python 2, use a simple ``+-`` ASCII string in the string representation of ``pytest.approx`` (for example ``"4 +- 4.0e-06"``)
19+
because it is brittle to handle that in different contexts and representations internally in pytest
20+
which can result in bugs such as `#2111`_. In Python 3, the representation still uses ``±`` (for example ``4 ± 4.0e-06``).
21+
Thanks `@kerrick-lyft`_ for the report and `@nicoddemus`_ for the PR.
22+
1823
* Using ``item.Function``, ``item.Module``, etc., is now issuing deprecation warnings, prefer
1924
``pytest.Function``, ``pytest.Module``, etc., instead (`#2034`_).
2025
Thanks `@nmundar`_ for the PR.
@@ -42,25 +47,27 @@
4247

4348
*
4449

45-
.. _@mbukatov: https://github.com/mbukatov
46-
.. _@dupuy: https://bitbucket.org/dupuy/
47-
.. _@d-b-w: https://bitbucket.org/d-b-w/
48-
.. _@lwm: https://github.com/lwm
4950
.. _@adler-j: https://github.com/adler-j
51+
.. _@d-b-w: https://bitbucket.org/d-b-w/
5052
.. _@DuncanBetts: https://github.com/DuncanBetts
53+
.. _@dupuy: https://bitbucket.org/dupuy/
54+
.. _@kerrick-lyft: https://github.com/kerrick-lyft
55+
.. _@lwm: https://github.com/lwm
56+
.. _@mbukatov: https://github.com/mbukatov
5157
.. _@nedbat: https://github.com/nedbat
5258
.. _@nmundar: https://github.com/nmundar
5359

54-
.. _#2089: https://github.com/pytest-dev/pytest/issues/2089
55-
.. _#478: https://github.com/pytest-dev/pytest/issues/478
56-
.. _#687: https://github.com/pytest-dev/pytest/issues/687
5760
.. _#2016: https://github.com/pytest-dev/pytest/issues/2016
5861
.. _#2034: https://github.com/pytest-dev/pytest/issues/2034
5962
.. _#2038: https://github.com/pytest-dev/pytest/issues/2038
6063
.. _#2078: https://github.com/pytest-dev/pytest/issues/2078
6164
.. _#2082: https://github.com/pytest-dev/pytest/issues/2082
65+
.. _#2089: https://github.com/pytest-dev/pytest/issues/2089
6266
.. _#2103: https://github.com/pytest-dev/pytest/issues/2103
6367
.. _#2105: https://github.com/pytest-dev/pytest/issues/2105
68+
.. _#2111: https://github.com/pytest-dev/pytest/issues/2111
69+
.. _#478: https://github.com/pytest-dev/pytest/issues/478
70+
.. _#687: https://github.com/pytest-dev/pytest/issues/687
6471

6572

6673
3.0.4

_pytest/python.py

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1434,16 +1434,10 @@ def __repr__(self):
14341434
except ValueError:
14351435
vetted_tolerance = '???'
14361436

1437-
plus_minus = u'{0} \u00b1 {1}'.format(self.expected, vetted_tolerance)
1438-
1439-
# In python2, __repr__() must return a string (i.e. not a unicode
1440-
# object). In python3, __repr__() must return a unicode object
1441-
# (although now strings are unicode objects and bytes are what
1442-
# strings were).
14431437
if sys.version_info[0] == 2:
1444-
return plus_minus.encode('utf-8')
1438+
return '{0} +- {1}'.format(self.expected, vetted_tolerance)
14451439
else:
1446-
return plus_minus
1440+
return u'{0} \u00b1 {1}'.format(self.expected, vetted_tolerance)
14471441

14481442
def __eq__(self, actual):
14491443
# Short-circuit exact equality.

testing/python/approx.py

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# encoding: utf-8
2-
2+
import sys
33
import pytest
44
import doctest
55

@@ -9,6 +9,7 @@
99
from fractions import Fraction
1010
inf, nan = float('inf'), float('nan')
1111

12+
1213
class MyDocTestRunner(doctest.DocTestRunner):
1314

1415
def __init__(self):
@@ -23,12 +24,13 @@ class TestApprox:
2324

2425
def test_repr_string(self):
2526
# Just make sure the Unicode handling doesn't raise any exceptions.
26-
print(approx(1.0))
27-
print(approx([1.0, 2.0, 3.0]))
28-
print(approx(inf))
29-
print(approx(1.0, rel=nan))
30-
print(approx(1.0, rel=inf))
31-
print(approx(1.0j, rel=inf))
27+
plus_minus = u'\u00b1' if sys.version_info[0] > 2 else u'+-'
28+
assert repr(approx(1.0)) == '1.0 {pm} 1.0e-06'.format(pm=plus_minus)
29+
assert repr(approx([1.0, 2.0])) == '1.0 {pm} 1.0e-06, 2.0 {pm} 2.0e-06'.format(pm=plus_minus)
30+
assert repr(approx(inf)) == 'inf'
31+
assert repr(approx(1.0, rel=nan)) == '1.0 {pm} ???'.format(pm=plus_minus)
32+
assert repr(approx(1.0, rel=inf)) == '1.0 {pm} inf'.format(pm=plus_minus)
33+
assert repr(approx(1.0j, rel=inf)) == '1j'
3234

3335
def test_operator_overloading(self):
3436
assert 1 == approx(1, rel=1e-6, abs=1e-12)
@@ -285,3 +287,23 @@ def test_doctests(self):
285287
runner = MyDocTestRunner()
286288
runner.run(test)
287289

290+
def test_unicode_plus_minus(self, testdir):
291+
"""
292+
Comparing approx instances inside lists should not produce an error in the detailed diff.
293+
Integration test for issue #2111.
294+
"""
295+
testdir.makepyfile("""
296+
import pytest
297+
def test_foo():
298+
assert [3] == [pytest.approx(4)]
299+
""")
300+
expected = '4.0e-06'
301+
# for some reason in Python 2.6 it is not displaying the tolerance representation correctly
302+
if sys.version_info[:2] == (2, 6):
303+
expected = '???'
304+
result = testdir.runpytest()
305+
result.stdout.fnmatch_lines([
306+
'*At index 0 diff: 3 != 4 * {0}'.format(expected),
307+
'=* 1 failed in *=',
308+
])
309+

0 commit comments

Comments
 (0)