33
44import inspect
55import warnings
6+ import attr
67from collections import namedtuple
78from operator import attrgetter
89from six .moves import map
@@ -185,22 +186,26 @@ def pytest_collection_modifyitems(items, config):
185186 items [:] = remaining
186187
187188
188- class MarkMapping :
189+ @attr .s
190+ class MarkMapping (object ):
189191 """Provides a local mapping for markers where item access
190192 resolves to True if the marker is present. """
191193
192- def __init__ (self , keywords ):
193- mymarks = set ()
194+ own_mark_names = attr .ib ()
195+
196+ @classmethod
197+ def from_keywords (cls , keywords ):
198+ mark_names = set ()
194199 for key , value in keywords .items ():
195200 if isinstance (value , MarkInfo ) or isinstance (value , MarkDecorator ):
196- mymarks .add (key )
197- self . _mymarks = mymarks
201+ mark_names .add (key )
202+ return cls ( mark_names )
198203
199204 def __getitem__ (self , name ):
200- return name in self ._mymarks
205+ return name in self .own_mark_names
201206
202207
203- class KeywordMapping :
208+ class KeywordMapping ( object ) :
204209 """Provides a local mapping for keywords.
205210 Given a list of names, map any substring of one of these names to True.
206211 """
@@ -217,7 +222,7 @@ def __getitem__(self, subname):
217222
218223def matchmark (colitem , markexpr ):
219224 """Tries to match on any marker names, attached to the given colitem."""
220- return eval (markexpr , {}, MarkMapping (colitem .keywords ))
225+ return eval (markexpr , {}, MarkMapping . from_keywords (colitem .keywords ))
221226
222227
223228def matchkeyword (colitem , keywordexpr ):
@@ -306,7 +311,21 @@ def istestfunc(func):
306311 getattr (func , "__name__" , "<lambda>" ) != "<lambda>"
307312
308313
309- class MarkDecorator :
314+ @attr .s (frozen = True )
315+ class Mark (object ):
316+ name = attr .ib ()
317+ args = attr .ib ()
318+ kwargs = attr .ib ()
319+
320+ def combined_with (self , other ):
321+ assert self .name == other .name
322+ return Mark (
323+ self .name , self .args + other .args ,
324+ dict (self .kwargs , ** other .kwargs ))
325+
326+
327+ @attr .s
328+ class MarkDecorator (object ):
310329 """ A decorator for test functions and test classes. When applied
311330 it will create :class:`MarkInfo` objects which may be
312331 :ref:`retrieved by hooks as item keywords <excontrolskip>`.
@@ -340,9 +359,7 @@ def test_function():
340359
341360 """
342361
343- def __init__ (self , mark ):
344- assert isinstance (mark , Mark ), repr (mark )
345- self .mark = mark
362+ mark = attr .ib (validator = attr .validators .instance_of (Mark ))
346363
347364 name = alias ('mark.name' )
348365 args = alias ('mark.args' )
@@ -422,15 +439,6 @@ def store_legacy_markinfo(func, mark):
422439 holder .add_mark (mark )
423440
424441
425- class Mark (namedtuple ('Mark' , 'name, args, kwargs' )):
426-
427- def combined_with (self , other ):
428- assert self .name == other .name
429- return Mark (
430- self .name , self .args + other .args ,
431- dict (self .kwargs , ** other .kwargs ))
432-
433-
434442class MarkInfo (object ):
435443 """ Marking object created by :class:`MarkDecorator` instances. """
436444
0 commit comments