Skip to content

Commit 4914135

Browse files
introduce name filtering for marker iteration again
1 parent 35f53a7 commit 4914135

File tree

11 files changed

+67
-33
lines changed

11 files changed

+67
-33
lines changed

_pytest/fixtures.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -988,7 +988,7 @@ def getfixtureinfo(self, node, func, cls, funcargs=True):
988988
argnames = getfuncargnames(func, cls=cls)
989989
else:
990990
argnames = ()
991-
usefixtures = flatten(mark.args for mark in node.iter_markers() if mark.name == "usefixtures")
991+
usefixtures = flatten(mark.args for mark in node.iter_markers(name="usefixtures"))
992992
initialnames = argnames
993993
initialnames = tuple(usefixtures) + initialnames
994994
fm = node.session._fixturemanager

_pytest/mark/evaluate.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ def wasvalid(self):
3535
return not hasattr(self, 'exc')
3636

3737
def _get_marks(self):
38-
return [x for x in self.item.iter_markers() if x.name == self._mark_name]
38+
return list(self.item.iter_markers(name=self._mark_name))
3939

4040
def invalidraise(self, exc):
4141
raises = self.get('raises')

_pytest/nodes.py

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -183,20 +183,32 @@ def add_marker(self, marker):
183183
self.keywords[marker.name] = marker
184184
self.own_markers.append(marker)
185185

186-
def iter_markers(self):
186+
def iter_markers(self, name=None):
187187
"""
188+
:param name: if given, filter the results by the name attribute
189+
188190
iterate over all markers of the node
189191
"""
190-
return (x[1] for x in self.iter_markers_with_node())
192+
return (x[1] for x in self.iter_markers_with_node(name=name))
191193

192-
def iter_markers_with_node(self):
194+
def iter_markers_with_node(self, name=None):
193195
"""
196+
:param name: if given, filter the results by the name attribute
197+
194198
iterate over all markers of the node
195199
returns sequence of tuples (node, mark)
196200
"""
197201
for node in reversed(self.listchain()):
198202
for mark in node.own_markers:
199-
yield node, mark
203+
if name is None or getattr(mark, 'name', None) == name:
204+
yield node, mark
205+
206+
def get_closest_marker(self, name, default=None):
207+
"""return the first marker matching the name
208+
:param default: fallback return value of no marker was found
209+
:param name: name to filter by
210+
"""
211+
return next(self.iter_markers(name=name), default)
200212

201213
def get_marker(self, name):
202214
""" get a marker object from this node or None if
@@ -206,7 +218,7 @@ def get_marker(self, name):
206218
207219
deprecated
208220
"""
209-
markers = [x for x in self.iter_markers() if x.name == name]
221+
markers = list(self.iter_markers(name=name))
210222
if markers:
211223
return MarkInfo(markers)
212224

_pytest/python.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -118,9 +118,8 @@ def pytest_generate_tests(metafunc):
118118
if hasattr(metafunc.function, attr):
119119
msg = "{0} has '{1}', spelling should be 'parametrize'"
120120
raise MarkerError(msg.format(metafunc.function.__name__, attr))
121-
for marker in metafunc.definition.iter_markers():
122-
if marker.name == 'parametrize':
123-
metafunc.parametrize(*marker.args, **marker.kwargs)
121+
for marker in metafunc.definition.iter_markers(name='parametrize'):
122+
metafunc.parametrize(*marker.args, **marker.kwargs)
124123

125124

126125
def pytest_configure(config):

_pytest/skipping.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,7 @@ def pytest_runtest_setup(item):
6464
item._skipped_by_mark = True
6565
skip(eval_skipif.getexplanation())
6666

67-
for skip_info in item.iter_markers():
68-
if skip_info.name != 'skip':
69-
continue
67+
for skip_info in item.iter_markers(name='skip'):
7068
item._skipped_by_mark = True
7169
if 'reason' in skip_info.kwargs:
7270
skip(skip_info.kwargs['reason'])

_pytest/warnings.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -60,10 +60,9 @@ def catch_warnings_for_item(item):
6060
for arg in inifilters:
6161
_setoption(warnings, arg)
6262

63-
for mark in item.iter_markers():
64-
if mark.name == 'filterwarnings':
65-
for arg in mark.args:
66-
warnings._setoption(arg)
63+
for mark in item.iter_markers(name='filterwarnings'):
64+
for arg in mark.args:
65+
warnings._setoption(arg)
6766

6867
yield
6968

changelog/3446.feature

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
introduce node.get_closest_marker(name, default=None) to support simple marker usage setups.

changelog/3459.feature

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Introduce optional name based filtering for iter_markers

doc/en/example/markers.rst

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -330,7 +330,7 @@ specifies via named environments::
330330
"env(name): mark test to run only on named environment")
331331

332332
def pytest_runtest_setup(item):
333-
envnames = [mark.args[0] for mark in item.iter_markers() if mark.name == "env"]
333+
envnames = [mark.args[0] for mark in item.iter_markers(name='env')]
334334
if envnames:
335335
if item.config.getoption("-E") not in envnames:
336336
pytest.skip("test requires env in %r" % envnames)
@@ -402,10 +402,9 @@ Below is the config file that will be used in the next examples::
402402
import sys
403403

404404
def pytest_runtest_setup(item):
405-
for marker in item.iter_markers():
406-
if marker.name == 'my_marker':
407-
print(marker)
408-
sys.stdout.flush()
405+
for marker in item.iter_markers(name='my_marker'):
406+
print(marker)
407+
sys.stdout.flush()
409408

410409
A custom marker can have its argument set, i.e. ``args`` and ``kwargs`` properties, defined by either invoking it as a callable or using ``pytest.mark.MARKER_NAME.with_args``. These two methods achieve the same effect most of the time.
411410

@@ -458,10 +457,9 @@ test function. From a conftest file we can read it like this::
458457
import sys
459458

460459
def pytest_runtest_setup(item):
461-
for mark in item.iter_markers():
462-
if mark.name == 'glob':
463-
print ("glob args=%s kwargs=%s" %(mark.args, mark.kwargs))
464-
sys.stdout.flush()
460+
for mark in item.iter_markers(name='glob'):
461+
print ("glob args=%s kwargs=%s" %(mark.args, mark.kwargs))
462+
sys.stdout.flush()
465463

466464
Let's run this without capturing output and see what we get::
467465

doc/en/usage.rst

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -274,10 +274,9 @@ Alternatively, you can integrate this functionality with custom markers:
274274
275275
def pytest_collection_modifyitems(session, config, items):
276276
for item in items:
277-
for marker in item.iter_markers():
278-
if marker.name == 'test_id':
279-
test_id = marker.args[0]
280-
item.user_properties.append(('test_id', test_id))
277+
for marker in item.iter_markers(name='test_id'):
278+
test_id = marker.args[0]
279+
item.user_properties.append(('test_id', test_id))
281280
282281
And in your tests:
283282

0 commit comments

Comments
 (0)