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

Fixed assertion rewriting for plugins in development mode #1935

Merged
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
5 changes: 4 additions & 1 deletion CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@

*

*
* Assertions are now being rewritten for plugins in development mode
(``pip install -e``) (`#1934`_).
Thanks `@nicoddemus`_ for the PR.

*

Expand All @@ -17,6 +19,7 @@
.. _@philpep: https://github.com/philpep

.. _#1905: https://github.com/pytest-dev/pytest/issues/1905
.. _#1934: https://github.com/pytest-dev/pytest/issues/1934


3.0.2
Expand Down
25 changes: 15 additions & 10 deletions _pytest/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -954,16 +954,21 @@ def _consider_importhook(self, args, entrypoint_name):
else:
self.pluginmanager.rewrite_hook = hook
for entrypoint in pkg_resources.iter_entry_points('pytest11'):
for entry in entrypoint.dist._get_metadata('RECORD'):
fn = entry.split(',')[0]
is_simple_module = os.sep not in fn and fn.endswith('.py')
is_package = fn.count(os.sep) == 1 and fn.endswith('__init__.py')
if is_simple_module:
module_name, ext = os.path.splitext(fn)
hook.mark_rewrite(module_name)
elif is_package:
package_name = os.path.dirname(fn)
hook.mark_rewrite(package_name)
# 'RECORD' available for plugins installed normally (pip install)
# 'SOURCES.txt' available for plugins installed in dev mode (pip install -e)
# for installed plugins 'SOURCES.txt' returns an empty list, and vice-versa
# so it shouldn't be an issue
for metadata in ('RECORD', 'SOURCES.txt'):
for entry in entrypoint.dist._get_metadata(metadata):
fn = entry.split(',')[0]
is_simple_module = os.sep not in fn and fn.endswith('.py')
is_package = fn.count(os.sep) == 1 and fn.endswith('__init__.py')
if is_simple_module:
module_name, ext = os.path.splitext(fn)
hook.mark_rewrite(module_name)
elif is_package:
package_name = os.path.dirname(fn)
hook.mark_rewrite(package_name)
self._warn_about_missing_assertion(mode)

def _warn_about_missing_assertion(self, mode):
Expand Down
18 changes: 14 additions & 4 deletions testing/test_assertion.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,8 @@ def test_foo(pytestconfig):
assert result.ret == 0

@pytest.mark.parametrize('mode', ['plain', 'rewrite'])
def test_installed_plugin_rewrite(self, testdir, mode):
@pytest.mark.parametrize('plugin_state', ['development', 'installed'])
def test_installed_plugin_rewrite(self, testdir, mode, plugin_state):
# Make sure the hook is installed early enough so that plugins
# installed via setuptools are re-written.
testdir.tmpdir.join('hampkg').ensure(dir=1)
Expand All @@ -135,13 +136,22 @@ def check(values, value):
'mainwrapper.py': """
import pytest, pkg_resources

plugin_state = "{plugin_state}"

class DummyDistInfo:
project_name = 'spam'
version = '1.0'

def _get_metadata(self, name):
return ['spamplugin.py,sha256=abc,123',
'hampkg/__init__.py,sha256=abc,123']
# 'RECORD' meta-data only available in installed plugins
if name == 'RECORD' and plugin_state == "installed":
return ['spamplugin.py,sha256=abc,123',
'hampkg/__init__.py,sha256=abc,123']
# 'SOURCES.txt' meta-data only available for plugins in development mode
elif name == 'SOURCES.txt' and plugin_state == "development":
return ['spamplugin.py',
'hampkg/__init__.py']
return []

class DummyEntryPoint:
name = 'spam'
Expand All @@ -159,7 +169,7 @@ def iter_entry_points(name):

pkg_resources.iter_entry_points = iter_entry_points
pytest.main()
""",
""".format(plugin_state=plugin_state),
'test_foo.py': """
def test(check_first):
check_first([10, 30], 30)
Expand Down