remove NodeMarkers, turn own_markers into a list and use iter_markers api exclusively

This commit is contained in:
Ronny Pfannschmidt 2018-03-29 18:24:10 +02:00
parent 8805036fd8
commit dbb1b5a227
7 changed files with 24 additions and 37 deletions

View File

@ -983,7 +983,7 @@ class FixtureManager(object):
argnames = getfuncargnames(func, cls=cls) argnames = getfuncargnames(func, cls=cls)
else: else:
argnames = () argnames = ()
usefixtures = flatten(uf_mark.args for uf_mark in node.find_markers("usefixtures")) usefixtures = flatten(mark.args for mark in node.iter_markers() if mark.name == "usefixtures")
initialnames = argnames initialnames = argnames
initialnames = tuple(usefixtures) + initialnames initialnames = tuple(usefixtures) + initialnames
fm = node.session._fixturemanager fm = node.session._fixturemanager

View File

@ -35,7 +35,7 @@ class MarkEvaluator(object):
return not hasattr(self, 'exc') return not hasattr(self, 'exc')
def _get_marks(self): def _get_marks(self):
return list(self.item.find_markers(self._mark_name)) return [x for x in self.item.iter_markers() if x.name == self._mark_name]
def invalidraise(self, exc): def invalidraise(self, exc):
raises = self.get('raises') raises = self.get('raises')

View File

@ -1,8 +1,6 @@
from __future__ import absolute_import, division, print_function from __future__ import absolute_import, division, print_function
import os import os
from itertools import chain
from operator import itemgetter
import six import six
import py import py
import attr import attr
@ -10,7 +8,7 @@ import attr
import _pytest import _pytest
import _pytest._code import _pytest._code
from _pytest.mark.structures import NodeKeywords, NodeMarkers, MarkInfo from _pytest.mark.structures import NodeKeywords, MarkInfo
SEP = "/" SEP = "/"
@ -91,7 +89,9 @@ class Node(object):
#: keywords/markers collected from all scopes #: keywords/markers collected from all scopes
self.keywords = NodeKeywords(self) self.keywords = NodeKeywords(self)
self._markers = NodeMarkers()
#: the marker objects belonging to this node
self.own_markers = []
#: allow adding of extra keywords to use for matching #: allow adding of extra keywords to use for matching
self.extra_keyword_matches = set() self.extra_keyword_matches = set()
@ -181,30 +181,13 @@ class Node(object):
elif not isinstance(marker, MarkDecorator): elif not isinstance(marker, MarkDecorator):
raise ValueError("is not a string or pytest.mark.* Marker") raise ValueError("is not a string or pytest.mark.* Marker")
self.keywords[marker.name] = marker self.keywords[marker.name] = marker
self._markers.update([marker]) self.own_markers.append(marker)
def find_markers(self, name):
"""find all marks with the given name on the node and its parents
:param str name: name of the marker
:returns: iterator over marks matching the name"""
return map(itemgetter(1), self.find_markers_with_node(name))
def find_markers_with_node(self, name):
"""find all marks with the given name on the node and its parents
:param str name: name of the marker
:returns: iterator over (node, mark) matching the name
"""
for node in reversed(self.listchain()):
for mark in node._markers.find(name):
yield node, mark
def iter_markers(self): def iter_markers(self):
""" """
iterate over all markers of the node iterate over all markers of the node
""" """
return chain.from_iterable(x._markers for x in reversed(self.listchain())) return (x[1] for x in self.iter_markers_with_node())
def iter_markers_with_node(self): def iter_markers_with_node(self):
""" """
@ -212,7 +195,7 @@ class Node(object):
returns sequence of tuples (node, mark) returns sequence of tuples (node, mark)
""" """
for node in reversed(self.listchain()): for node in reversed(self.listchain()):
for mark in node._markers: for mark in node.own_markers:
yield node, mark yield node, mark
def get_marker(self, name): def get_marker(self, name):
@ -223,7 +206,7 @@ class Node(object):
deprecated deprecated
""" """
markers = list(self.find_markers(name)) markers = [x for x in self.iter_markers() if x.name == name]
if markers: if markers:
return MarkInfo(markers) return MarkInfo(markers)

View File

@ -117,8 +117,9 @@ def pytest_generate_tests(metafunc):
if hasattr(metafunc.function, attr): if hasattr(metafunc.function, attr):
msg = "{0} has '{1}', spelling should be 'parametrize'" msg = "{0} has '{1}', spelling should be 'parametrize'"
raise MarkerError(msg.format(metafunc.function.__name__, attr)) raise MarkerError(msg.format(metafunc.function.__name__, attr))
for marker in metafunc.definition.find_markers('parametrize'): for marker in metafunc.definition.iter_markers():
metafunc.parametrize(*marker.args, **marker.kwargs) if marker.name == 'parametrize':
metafunc.parametrize(*marker.args, **marker.kwargs)
def pytest_configure(config): def pytest_configure(config):
@ -221,7 +222,7 @@ class PyobjMixin(PyobjContext):
# XXX evil hack # XXX evil hack
# used to avoid Instance collector marker duplication # used to avoid Instance collector marker duplication
if self._ALLOW_MARKERS: if self._ALLOW_MARKERS:
self._markers.update(get_unpacked_marks(self.obj)) self.own_markers.extend(get_unpacked_marks(self.obj))
return obj return obj
def fset(self, value): def fset(self, value):
@ -1132,7 +1133,7 @@ class Function(FunctionMixin, nodes.Item, fixtures.FuncargnamesCompatAttr):
self.obj = callobj self.obj = callobj
self.keywords.update(self.obj.__dict__) self.keywords.update(self.obj.__dict__)
self._markers.update(get_unpacked_marks(self.obj)) self.own_markers.extend(get_unpacked_marks(self.obj))
if callspec: if callspec:
self.callspec = callspec self.callspec = callspec
# this is total hostile and a mess # this is total hostile and a mess
@ -1142,7 +1143,7 @@ class Function(FunctionMixin, nodes.Item, fixtures.FuncargnamesCompatAttr):
# feel free to cry, this was broken for years before # feel free to cry, this was broken for years before
# and keywords cant fix it per design # and keywords cant fix it per design
self.keywords[mark.name] = mark self.keywords[mark.name] = mark
self._markers.update(callspec.marks) self.own_markers.extend(callspec.marks)
if keywords: if keywords:
self.keywords.update(keywords) self.keywords.update(keywords)

View File

@ -64,7 +64,9 @@ def pytest_runtest_setup(item):
item._skipped_by_mark = True item._skipped_by_mark = True
skip(eval_skipif.getexplanation()) skip(eval_skipif.getexplanation())
for skip_info in item.find_markers('skip'): for skip_info in item.iter_markers():
if skip_info.name != 'skip':
continue
item._skipped_by_mark = True item._skipped_by_mark = True
if 'reason' in skip_info.kwargs: if 'reason' in skip_info.kwargs:
skip(skip_info.kwargs['reason']) skip(skip_info.kwargs['reason'])

View File

@ -60,9 +60,10 @@ def catch_warnings_for_item(item):
for arg in inifilters: for arg in inifilters:
_setoption(warnings, arg) _setoption(warnings, arg)
for mark in item.find_markers('filterwarnings'): for mark in item.iter_markers():
for arg in mark.args: if mark.name == 'filterwarnings':
warnings._setoption(arg) for arg in mark.args:
warnings._setoption(arg)
yield yield

View File

@ -533,7 +533,7 @@ class TestFunctional(object):
items, rec = testdir.inline_genitems(p) items, rec = testdir.inline_genitems(p)
for item in items: for item in items:
print(item, item.keywords) print(item, item.keywords)
assert list(item.find_markers('a')) assert [x for x in item.iter_markers() if x.name == 'a']
def test_mark_decorator_subclass_does_not_propagate_to_base(self, testdir): def test_mark_decorator_subclass_does_not_propagate_to_base(self, testdir):
p = testdir.makepyfile(""" p = testdir.makepyfile("""