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)
else:
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 = tuple(usefixtures) + initialnames
fm = node.session._fixturemanager

View File

@ -35,7 +35,7 @@ class MarkEvaluator(object):
return not hasattr(self, 'exc')
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):
raises = self.get('raises')

View File

@ -1,8 +1,6 @@
from __future__ import absolute_import, division, print_function
import os
from itertools import chain
from operator import itemgetter
import six
import py
import attr
@ -10,7 +8,7 @@ import attr
import _pytest
import _pytest._code
from _pytest.mark.structures import NodeKeywords, NodeMarkers, MarkInfo
from _pytest.mark.structures import NodeKeywords, MarkInfo
SEP = "/"
@ -91,7 +89,9 @@ class Node(object):
#: keywords/markers collected from all scopes
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
self.extra_keyword_matches = set()
@ -181,30 +181,13 @@ class Node(object):
elif not isinstance(marker, MarkDecorator):
raise ValueError("is not a string or pytest.mark.* Marker")
self.keywords[marker.name] = marker
self._markers.update([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
self.own_markers.append(marker)
def iter_markers(self):
"""
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):
"""
@ -212,7 +195,7 @@ class Node(object):
returns sequence of tuples (node, mark)
"""
for node in reversed(self.listchain()):
for mark in node._markers:
for mark in node.own_markers:
yield node, mark
def get_marker(self, name):
@ -223,7 +206,7 @@ class Node(object):
deprecated
"""
markers = list(self.find_markers(name))
markers = [x for x in self.iter_markers() if x.name == name]
if markers:
return MarkInfo(markers)

View File

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

View File

@ -64,7 +64,9 @@ def pytest_runtest_setup(item):
item._skipped_by_mark = True
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
if 'reason' in skip_info.kwargs:
skip(skip_info.kwargs['reason'])

View File

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

View File

@ -533,7 +533,7 @@ class TestFunctional(object):
items, rec = testdir.inline_genitems(p)
for item in items:
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):
p = testdir.makepyfile("""