Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix UnicodeEncodeError when string comparison with unicode has failed. #1870

Merged
merged 2 commits into from
Aug 26, 2016

Conversation

AiOO
Copy link
Contributor

@AiOO AiOO commented Aug 25, 2016

Thanks for submitting a PR, your contribution is really appreciated!

Here's a quick checklist that should be present in PRs:

  • [v] Target: for bug or doc fixes, target master; for new features, target features;
  • [v] Make sure to include one or more tests for your change;
  • [v] Add yourself to AUTHORS;
  • [v] Add a new entry to CHANGELOG.rst
    • Choose any open position to avoid merge conflicts with other PRs.
    • Add a link to the issue you are fixing (if any) using RST syntax.
    • The pytest team likes to have people to acknowledged in the CHANGELOG, so please add a thank note to yourself ("Thanks @user for the PR") and a link to your GitHub profile. It may sound weird thanking yourself, but otherwise a maintainer would have to do it manually before or after merging instead of just using GitHub's merge button. This makes it easier on the maintainers to merge PRs.

UnicodeEncodeError is occurred when comparing two strings with any unicode character. This PR fixes this error.

Relative issue: #1864.

Error reproduction:

$ cat test.py
# -*- coding: utf-8 -*-
def test_with_unicode_literal():
    assert u'테스트' == u'Test'

$ py.test test.py
==================================================== test session starts =====================================================
platform darwin -- Python 2.7.12, pytest-3.0.0, py-1.4.31, pluggy-0.3.1
rootdir: /Users/bright/Playground/test_test, inifile:
collected 1 items
test.py
INTERNALERROR> Traceback (most recent call last):
INTERNALERROR>   File "/REDUCED/lib/python2.7/site-packages/_pytest/main.py", line 96, in wrap_session
INTERNALERROR>     session.exitstatus = doit(config, session) or 0
INTERNALERROR>   File "/REDUCED/lib/python2.7/site-packages/_pytest/main.py", line 131, in _main
INTERNALERROR>     config.hook.pytest_runtestloop(session=session)
INTERNALERROR>   File "/REDUCED/lib/python2.7/site-packages/_pytest/vendored_packages/pluggy.py", line 724, in __call__
INTERNALERROR>     return self._hookexec(self, self._nonwrappers + self._wrappers, kwargs)
INTERNALERROR>   File "/REDUCED/lib/python2.7/site-packages/_pytest/vendored_packages/pluggy.py", line 338, in _hookexec
INTERNALERROR>     return self._inner_hookexec(hook, methods, kwargs)
INTERNALERROR>   File "/REDUCED/lib/python2.7/site-packages/_pytest/vendored_packages/pluggy.py", line 333, in <lambda>
INTERNALERROR>     _MultiCall(methods, kwargs, hook.spec_opts).execute()
INTERNALERROR>   File "/REDUCED/lib/python2.7/site-packages/_pytest/vendored_packages/pluggy.py", line 596, in execute
INTERNALERROR>     res = hook_impl.function(*args)
INTERNALERROR>   File "/REDUCED/lib/python2.7/site-packages/_pytest/main.py", line 152, in pytest_runtestloop
INTERNALERROR>     item.config.hook.pytest_runtest_protocol(item=item, nextitem=nextitem)
INTERNALERROR>   File "/REDUCED/lib/python2.7/site-packages/_pytest/vendored_packages/pluggy.py", line 724, in __call__
INTERNALERROR>     return self._hookexec(self, self._nonwrappers + self._wrappers, kwargs)
INTERNALERROR>   File "/REDUCED/lib/python2.7/site-packages/_pytest/vendored_packages/pluggy.py", line 338, in _hookexec
INTERNALERROR>     return self._inner_hookexec(hook, methods, kwargs)
INTERNALERROR>   File "/REDUCED/lib/python2.7/site-packages/_pytest/vendored_packages/pluggy.py", line 333, in <lambda>
INTERNALERROR>     _MultiCall(methods, kwargs, hook.spec_opts).execute()
INTERNALERROR>   File "/REDUCED/lib/python2.7/site-packages/_pytest/vendored_packages/pluggy.py", line 595, in execute
INTERNALERROR>     return _wrapped_call(hook_impl.function(*args), self.execute)
INTERNALERROR>   File "/REDUCED/lib/python2.7/site-packages/_pytest/vendored_packages/pluggy.py", line 253, in _wrapped_call
INTERNALERROR>     return call_outcome.get_result()
INTERNALERROR>   File "/REDUCED/lib/python2.7/site-packages/_pytest/vendored_packages/pluggy.py", line 279, in get_result
INTERNALERROR>     _reraise(*ex)  # noqa
INTERNALERROR>   File "/REDUCED/lib/python2.7/site-packages/_pytest/vendored_packages/pluggy.py", line 264, in __init__
INTERNALERROR>     self.result = func()
INTERNALERROR>   File "/REDUCED/lib/python2.7/site-packages/_pytest/vendored_packages/pluggy.py", line 596, in execute
INTERNALERROR>     res = hook_impl.function(*args)
INTERNALERROR>   File "/REDUCED/lib/python2.7/site-packages/_pytest/runner.py", line 66, in pytest_runtest_protocol
INTERNALERROR>     runtestprotocol(item, nextitem=nextitem)
INTERNALERROR>   File "/REDUCED/lib/python2.7/site-packages/_pytest/runner.py", line 79, in runtestprotocol
INTERNALERROR>     reports.append(call_and_report(item, "call", log))
INTERNALERROR>   File "/REDUCED/lib/python2.7/site-packages/_pytest/runner.py", line 133, in call_and_report
INTERNALERROR>     call = call_runtest_hook(item, when, **kwds)
INTERNALERROR>   File "/REDUCED/lib/python2.7/site-packages/_pytest/runner.py", line 151, in call_runtest_hook
INTERNALERROR>     return CallInfo(lambda: ihook(item=item, **kwds), when=when)
INTERNALERROR>   File "/REDUCED/lib/python2.7/site-packages/_pytest/runner.py", line 168, in __init__
INTERNALERROR>     self.excinfo = ExceptionInfo()
INTERNALERROR>   File "/REDUCED/lib/python2.7/site-packages/_pytest/_code/code.py", line 357, in __init__
INTERNALERROR>     exprinfo = str(tup[1])
INTERNALERROR> UnicodeEncodeError: 'ascii' codec can't encode characters in position 8-10: ordinal not in range(128)
================================================ no tests ran in 0.01 seconds ================================================

@AiOO AiOO force-pushed the bugfix/assertion-with-unicode branch from 5e37be7 to 6cbcc35 Compare August 25, 2016 16:05
@coveralls
Copy link

Coverage Status

Coverage decreased (-0.02%) to 93.006% when pulling 6cbcc35 on AiOO:bugfix/assertion-with-unicode into 9c45d6c on pytest-dev:master.

try:
exprinfo = str(tup[1])
except UnicodeEncodeError:
exprinfo = unicode(tup[1])
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking at tup[1], it always seems to contain an unicode object, even when there are byte strings in the assertion:

-> exprinfo = str(tup[1])
(Pdb) tup[1]
AssertionError(u"assert 'a' == 'b'\n  - a\n  + b",)

So I think the proper fix would be to always use unicode() and do the check with u'assert ' below.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, tup[1] is an AssertionError instance containing a unicode string. I think the proper fix is actually using py._builtin._totext:

diff --git a/_pytest/_code/code.py b/_pytest/_code/code.py
index 040e4fc..9a6d326 100644
--- a/_pytest/_code/code.py
+++ b/_pytest/_code/code.py
@@ -354,7 +354,7 @@ class ExceptionInfo(object):
             if exprinfo is None and isinstance(tup[1], AssertionError):
                 exprinfo = getattr(tup[1], 'msg', None)
                 if exprinfo is None:
-                    exprinfo = str(tup[1])
+                    exprinfo = py._builtin._totext(tup[1])
                 if exprinfo and exprinfo.startswith('assert '):
                     self._striptext = 'AssertionError: '
         self._excinfo = tup

py._builtin._totext is just unicode in Python 2 and str in Python 3. With the above change the test passes to me.

@coveralls
Copy link

Coverage Status

Coverage decreased (-0.02%) to 93.006% when pulling 6cbcc35 on AiOO:bugfix/assertion-with-unicode into 9c45d6c on pytest-dev:master.

@@ -9,11 +9,16 @@
* Add ``buffer`` attribute to stdin stub class ``pytest.capture.DontReadFromInput``
Thanks `@joguSD`_ for the PR.

* Fix UnicodeEncodeError when string comparison with unicode is failed. (`#1864`_)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpick: "has failed" or "fails" 😁

Also: Use double backticks around UnicodeEncodeError so it appears in a monospaced font (see buffer on the item above this one).

@AiOO AiOO force-pushed the bugfix/assertion-with-unicode branch from 6cbcc35 to 86b8801 Compare August 26, 2016 00:51
@AiOO
Copy link
Contributor Author

AiOO commented Aug 26, 2016

Thanks for your kind review! I've updated this PR.

  1. Use proper method py._builtin._totext instead of str or unicode.
  2. Fix typo error and use backticks.

And,

do the check with u'assert ' below.

I think this fix is unnecessary because below code runs well:

Python 2.7.12 (default, Jun 29 2016, 14:05:02)
[GCC 4.2.1 Compatible Apple LLVM 7.3.0 (clang-703.0.31)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> u'assert: 유니코드'.startswith('assert: ')
True

@AiOO AiOO changed the title Fix UnicodeEncodeError when string comparison with unicode is failed. Fix UnicodeEncodeError when string comparison with unicode has failed. Aug 26, 2016
@coveralls
Copy link

Coverage Status

Coverage remained the same at 93.027% when pulling 86b8801 on AiOO:bugfix/assertion-with-unicode into 9c45d6c on pytest-dev:master.

@nicoddemus
Copy link
Member

do the check with u'assert ' below.
I think this fix is unnecessary because below code runs well:

I agree. 😁

Thanks for the update, I will merge as soon as CI passes.

@nicoddemus
Copy link
Member

Oh, just a tip: on GitHub if you add a string like "Fixes #XXX" or "Resolves #XXX" to the commit message it will automatically close the issue #XXX when merged. See here. 😉

@nicoddemus nicoddemus merged commit a947e83 into pytest-dev:master Aug 26, 2016
@nicoddemus
Copy link
Member

Thanks again for the PR!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants