turn Markinfo into atts clsas, and return correct instances of it from node.get_marker

This commit is contained in:
Ronny Pfannschmidt 2018-03-19 18:39:56 +01:00
parent 775fb96ac3
commit 159ea9b7c0
4 changed files with 21 additions and 13 deletions

View File

@ -4,9 +4,10 @@ from operator import attrgetter
import inspect import inspect
import attr import attr
from ..deprecated import MARK_PARAMETERSET_UNPACKING, MARK_INFO_ATTRIBUTE from ..deprecated import MARK_PARAMETERSET_UNPACKING, MARK_INFO_ATTRIBUTE
from ..compat import NOTSET, getfslineno from ..compat import NOTSET, getfslineno
from six.moves import map from six.moves import map, reduce
EMPTY_PARAMETERSET_OPTION = "empty_parameter_set_mark" EMPTY_PARAMETERSET_OPTION = "empty_parameter_set_mark"
@ -233,7 +234,7 @@ def store_legacy_markinfo(func, mark):
raise TypeError("got {mark!r} instead of a Mark".format(mark=mark)) raise TypeError("got {mark!r} instead of a Mark".format(mark=mark))
holder = getattr(func, mark.name, None) holder = getattr(func, mark.name, None)
if holder is None: if holder is None:
holder = MarkInfo(mark) holder = MarkInfo.for_mark(mark)
setattr(func, mark.name, holder) setattr(func, mark.name, holder)
else: else:
holder.add_mark(mark) holder.add_mark(mark)
@ -266,18 +267,24 @@ def _marked(func, mark):
return any(mark == info.combined for info in func_mark) return any(mark == info.combined for info in func_mark)
@attr.s
class MarkInfo(object): class MarkInfo(object):
""" Marking object created by :class:`MarkDecorator` instances. """ """ Marking object created by :class:`MarkDecorator` instances. """
def __init__(self, mark): _marks = attr.ib()
assert isinstance(mark, Mark), repr(mark) combined = attr.ib(
self.combined = mark repr=False,
self._marks = [mark] default=attr.Factory(lambda self: reduce(Mark.combined_with, self._marks),
takes_self=True))
name = alias('combined.name', warning=MARK_INFO_ATTRIBUTE) name = alias('combined.name', warning=MARK_INFO_ATTRIBUTE)
args = alias('combined.args', warning=MARK_INFO_ATTRIBUTE) args = alias('combined.args', warning=MARK_INFO_ATTRIBUTE)
kwargs = alias('combined.kwargs', warning=MARK_INFO_ATTRIBUTE) kwargs = alias('combined.kwargs', warning=MARK_INFO_ATTRIBUTE)
@classmethod
def for_mark(cls, mark):
return cls([mark])
def __repr__(self): def __repr__(self):
return "<MarkInfo {0!r}>".format(self.combined) return "<MarkInfo {0!r}>".format(self.combined)
@ -288,7 +295,7 @@ class MarkInfo(object):
def __iter__(self): def __iter__(self):
""" yield MarkInfo objects each relating to a marking-call. """ """ yield MarkInfo objects each relating to a marking-call. """
return map(MarkInfo, self._marks) return map(MarkInfo.for_mark, self._marks)
class MarkGenerator(object): class MarkGenerator(object):

View File

@ -4,12 +4,11 @@ import os
import six import six
import py import py
import attr import attr
from more_itertools import first
import _pytest import _pytest
import _pytest._code import _pytest._code
from _pytest.mark.structures import NodeKeywords, NodeMarkers from _pytest.mark.structures import NodeKeywords, NodeMarkers, MarkInfo
SEP = "/" SEP = "/"
@ -194,7 +193,9 @@ class Node(object):
def get_marker(self, name): def get_marker(self, name):
""" get a marker object from this node or None if """ get a marker object from this node or None if
the node doesn't have a marker with that name. """ the node doesn't have a marker with that name. """
return first(self.find_markers(name), None) markers = list(self.find_markers(name))
if markers:
return MarkInfo(markers)
def listextrakeywords(self): def listextrakeywords(self):
""" Return a set of all extra keywords in self and any parents.""" """ Return a set of all extra keywords in self and any parents."""

View File

@ -60,8 +60,7 @@ def catch_warnings_for_item(item):
for arg in inifilters: for arg in inifilters:
_setoption(warnings, arg) _setoption(warnings, arg)
mark = item.get_marker('filterwarnings') for mark in item.find_markers('filterwarnings'):
if mark:
for arg in mark.args: for arg in mark.args:
warnings._setoption(arg) warnings._setoption(arg)

View File

@ -14,7 +14,7 @@ ignore_markinfo = pytest.mark.filterwarnings('ignore:MarkInfo objects:_pytest.de
class TestMark(object): class TestMark(object):
def test_markinfo_repr(self): def test_markinfo_repr(self):
from _pytest.mark import MarkInfo, Mark from _pytest.mark import MarkInfo, Mark
m = MarkInfo(Mark("hello", (1, 2), {})) m = MarkInfo.for_mark(Mark("hello", (1, 2), {}))
repr(m) repr(m)
@pytest.mark.parametrize('attr', ['mark', 'param']) @pytest.mark.parametrize('attr', ['mark', 'param'])
@ -684,6 +684,7 @@ class TestFunctional(object):
reprec = testdir.inline_run() reprec = testdir.inline_run()
reprec.assertoutcome(passed=1) reprec.assertoutcome(passed=1)
@ignore_markinfo
def test_keyword_added_for_session(self, testdir): def test_keyword_added_for_session(self, testdir):
testdir.makeconftest(""" testdir.makeconftest("""
import pytest import pytest