Skip to content

Handle import errors with non-ascii messages when importing plugins #2000

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

Merged
merged 2 commits into from
Oct 17, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,16 @@
* Import errors when collecting test modules now display the full traceback (`#1976`_).
Thanks `@cwitty`_ for the report and `@nicoddemus`_ for the PR.

*
* When loading plugins, import errors which contain non-ascii messages are now properly handled in Python 2 (`#1998`_).
Thanks `@nicoddemus`_ for the PR.

*


.. _@cwitty: https://github.com/cwitty

.. _#1976: https://github.com/pytest-dev/pytest/issues/1976
.. _#1998: https://github.com/pytest-dev/pytest/issues/1998



Expand All @@ -28,7 +30,7 @@
(``pip install -e``) (`#1934`_).
Thanks `@nicoddemus`_ for the PR.

* Fix pkg_resources import error in Jython projects (`#1853`).
* Fix pkg_resources import error in Jython projects (`#1853`_).
Thanks `@raquel-ucl`_ for the PR.

* Got rid of ``AttributeError: 'Module' object has no attribute '_obj'`` exception
Expand All @@ -48,6 +50,7 @@
.. _@axil: https://github.com/axil
.. _@tgoodlet: https://github.com/tgoodlet

.. _#1853: https://github.com/pytest-dev/pytest/issues/1853
.. _#1905: https://github.com/pytest-dev/pytest/issues/1905
.. _#1934: https://github.com/pytest-dev/pytest/issues/1934
.. _#1944: https://github.com/pytest-dev/pytest/issues/1944
Expand Down
16 changes: 15 additions & 1 deletion _pytest/compat.py
Original file line number Diff line number Diff line change
Expand Up @@ -213,4 +213,18 @@ def _is_unittest_unexpected_success_a_failure():
Changed in version 3.4: Returns False if there were any
unexpectedSuccesses from tests marked with the expectedFailure() decorator.
"""
return sys.version_info >= (3, 4)
return sys.version_info >= (3, 4)


if _PY3:
def safe_str(v):
"""returns v as string"""
return str(v)
else:
def safe_str(v):
"""returns v as string, converting to ascii if necessary"""
try:
return str(v)
except UnicodeError:
errors = 'replace'
return v.encode('ascii', errors)
3 changes: 2 additions & 1 deletion _pytest/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import _pytest.hookspec # the extension point definitions
import _pytest.assertion
from _pytest._pluggy import PluginManager, HookimplMarker, HookspecMarker
from _pytest.compat import safe_str

hookimpl = HookimplMarker("pytest")
hookspec = HookspecMarker("pytest")
Expand Down Expand Up @@ -405,7 +406,7 @@ def import_plugin(self, modname):
try:
__import__(importspec)
except ImportError as e:
new_exc = ImportError('Error importing plugin "%s": %s' % (modname, e))
new_exc = ImportError('Error importing plugin "%s": %s' % (modname, safe_str(e.args[0])))
# copy over name and path attributes
for attr in ('name', 'path'):
if hasattr(e, attr):
Expand Down
12 changes: 9 additions & 3 deletions testing/test_pluginmanager.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# encoding: UTF-8
import pytest
import py
import os
Expand Down Expand Up @@ -179,15 +180,20 @@ def test_default_markers(testdir):
])


def test_importplugin_issue375(testdir, pytestpm):
def test_importplugin_error_message(testdir, pytestpm):
"""Don't hide import errors when importing plugins and provide
an easy to debug message.

See #375 and #1998.
"""
testdir.syspathinsert(testdir.tmpdir)
testdir.makepyfile(qwe="import aaaa")
testdir.makepyfile(qwe="""
# encoding: UTF-8
raise ImportError(u'Not possible to import: ☺')
""")
with pytest.raises(ImportError) as excinfo:
pytestpm.import_plugin("qwe")
expected = '.*Error importing plugin "qwe": No module named \'?aaaa\'?'
expected = '.*Error importing plugin "qwe": Not possible to import: .'
assert py.std.re.match(expected, str(excinfo.value))


Expand Down