From 853975d93b72a08175a313d5c5c4958b5f55935b Mon Sep 17 00:00:00 2001 From: Ronny Pfannschmidt Date: Wed, 20 Jun 2018 22:36:04 +0200 Subject: [PATCH 1/4] add failing test for #3605 --- testing/test_mark.py | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/testing/test_mark.py b/testing/test_mark.py index 084e3c3a5..8842d73a9 100644 --- a/testing/test_mark.py +++ b/testing/test_mark.py @@ -1130,3 +1130,41 @@ def test_addmarker_getmarker(): node.add_marker("b") node.get_marker("a").combined node.get_marker("b").combined + + +@pytest.mark.issue("https://github.com/pytest-dev/pytest/issues/3605") +def test_markers_from_parametrize(testdir): + testdir.makepyfile( + """ + from __future__ import print_function + import pytest + + first_custom_mark = pytest.mark.custom_marker + custom_mark = pytest.mark.custom_mark + @pytest.fixture(autouse=True) + def trigger(request): + custom_mark =request.node.get_marker('custom_mark') + print("Custom mark %s" % custom_mark) + + @custom_mark("custom mark non parametrized") + def test_custom_mark_non_parametrized(): + print("Hey from test") + + @pytest.mark.parametrize( + "obj_type", + [ + first_custom_mark("first custom mark")("template"), + pytest.param( # Think this should be recommended way? + "disk", + marks=custom_mark('custom mark1') + ), + custom_mark("custom mark2")("vm"), # Tried also this + ] + ) + def test_custom_mark_parametrized(obj_type): + print("obj_type is:", obj_type) + """ + ) + + result = testdir.runpytest() + result.assertoutcome(failed=0) From 78a82c05ef8662afa79721807a112d29e3b7c1bc Mon Sep 17 00:00:00 2001 From: Ronny Pfannschmidt Date: Wed, 20 Jun 2018 22:44:19 +0200 Subject: [PATCH 2/4] consistent failure on all python versions for test_markers_from_parametrize --- testing/test_mark.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/testing/test_mark.py b/testing/test_mark.py index 8842d73a9..087502fcd 100644 --- a/testing/test_mark.py +++ b/testing/test_mark.py @@ -1133,6 +1133,7 @@ def test_addmarker_getmarker(): @pytest.mark.issue("https://github.com/pytest-dev/pytest/issues/3605") +@pytest.mark.filterwarnings("ignore") def test_markers_from_parametrize(testdir): testdir.makepyfile( """ @@ -1167,4 +1168,4 @@ def test_markers_from_parametrize(testdir): ) result = testdir.runpytest() - result.assertoutcome(failed=0) + result.assert_outcomes(failed=0) From b8486037d3fc7c61c742ced91ef3109da1448439 Mon Sep 17 00:00:00 2001 From: Ronny Pfannschmidt Date: Thu, 21 Jun 2018 08:00:23 +0200 Subject: [PATCH 3/4] fix #3605 - unpack markdecorators from parameterization --- changelog/3605.bugfix.rst | 1 + src/_pytest/mark/structures.py | 5 ++++- src/_pytest/python.py | 10 +++++++--- testing/test_mark.py | 2 +- 4 files changed, 13 insertions(+), 5 deletions(-) create mode 100644 changelog/3605.bugfix.rst diff --git a/changelog/3605.bugfix.rst b/changelog/3605.bugfix.rst new file mode 100644 index 000000000..2d8513332 --- /dev/null +++ b/changelog/3605.bugfix.rst @@ -0,0 +1 @@ +unpack marks from parameterization to prevent the markdecorator missmatch bug. diff --git a/src/_pytest/mark/structures.py b/src/_pytest/mark/structures.py index eb0349c2f..a04918f9d 100644 --- a/src/_pytest/mark/structures.py +++ b/src/_pytest/mark/structures.py @@ -225,9 +225,12 @@ def get_unpacked_marks(obj): obtain the unpacked marks that are stored on an object """ mark_list = getattr(obj, "pytestmark", []) - if not isinstance(mark_list, list): mark_list = [mark_list] + return normalize_mark_list(mark_list) + + +def normalize_mark_list(mark_list): return [getattr(mark, "mark", mark) for mark in mark_list] # unpack MarkDecorator diff --git a/src/_pytest/python.py b/src/_pytest/python.py index 8a9c15dc2..724a6098a 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -39,7 +39,11 @@ from _pytest.compat import ( get_default_arg_names, ) from _pytest.outcomes import fail -from _pytest.mark.structures import transfer_markers, get_unpacked_marks +from _pytest.mark.structures import ( + transfer_markers, + get_unpacked_marks, + normalize_mark_list, +) # relative paths that we use to filter traceback entries from appearing to the user; @@ -773,7 +777,7 @@ class CallSpec2(object): self.indices[arg] = param_index self._arg2scopenum[arg] = scopenum self._idlist.append(id) - self.marks.extend(marks) + self.marks.extend(normalize_mark_list(marks)) def setall(self, funcargs, id, param): for x in funcargs: @@ -1254,7 +1258,7 @@ class Function(FunctionMixin, nodes.Item, fixtures.FuncargnamesCompatAttr): # feel free to cry, this was broken for years before # and keywords cant fix it per design self.keywords[mark.name] = mark - self.own_markers.extend(callspec.marks) + self.own_markers.extend(normalize_mark_list(callspec.marks)) if keywords: self.keywords.update(keywords) diff --git a/testing/test_mark.py b/testing/test_mark.py index 087502fcd..f87a4eded 100644 --- a/testing/test_mark.py +++ b/testing/test_mark.py @@ -1168,4 +1168,4 @@ def test_markers_from_parametrize(testdir): ) result = testdir.runpytest() - result.assert_outcomes(failed=0) + result.assert_outcomes(passed=4) From 643e5a9c445a8104e0eff4d3b0bef025bd342912 Mon Sep 17 00:00:00 2001 From: Ronny Pfannschmidt Date: Tue, 26 Jun 2018 21:56:00 +0200 Subject: [PATCH 4/4] fix docs --- changelog/3605.bugfix.rst | 2 +- src/_pytest/mark/structures.py | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/changelog/3605.bugfix.rst b/changelog/3605.bugfix.rst index 2d8513332..58a294ecb 100644 --- a/changelog/3605.bugfix.rst +++ b/changelog/3605.bugfix.rst @@ -1 +1 @@ -unpack marks from parameterization to prevent the markdecorator missmatch bug. +no longer ValueError when using the ``get_marker`` api. diff --git a/src/_pytest/mark/structures.py b/src/_pytest/mark/structures.py index a04918f9d..d416e422b 100644 --- a/src/_pytest/mark/structures.py +++ b/src/_pytest/mark/structures.py @@ -231,6 +231,12 @@ def get_unpacked_marks(obj): def normalize_mark_list(mark_list): + """ + normalizes marker decorating helpers to mark objects + + :type mark_list: List[Union[Mark, Markdecorator]] + :rtype: List[Mark] + """ return [getattr(mark, "mark", mark) for mark in mark_list] # unpack MarkDecorator