# HG changeset patch -- Bitbucket.org
# Project pytest
# URL http://bitbucket.org/hpk42/pytest/overview
# User holger krekel <hol...@merlinux.eu>
# Date 1290280658 -3600
# Node ID 98e74a494cb2d96e45a4bbcf04e764229ccd0b30
# Parent  d633f6bed7afd820ddc0c6e560f5b63669ab1e60
fix: mark.* objects are now immutable as long as they are not an attribute on a 
function, enables usage like this::

    xfail = pytest.mark.xfail

    @xfail
    def test_func1():
        pass

    @xfail(reason="123")
    def test_func2():
        pass

where previously test_func1 and test_func2 would wrongly share the same reason
because the xfail object was modified in place.

--- a/testing/test_mark.py
+++ b/testing/test_mark.py
@@ -48,6 +48,21 @@ class TestMark:
         assert f.world.args[0] == "hello"
         mark.world("world")(f)
 
+    def test_pytest_mark_reuse(self):
+        mark = Mark()
+        def f():
+            pass
+        w = mark.some
+        w("hello", reason="123")(f)
+        assert f.some.args[0] == "hello"
+        assert f.some.kwargs['reason'] == "123"
+        def g():
+            pass
+        w("world", reason2="456")(g)
+        assert g.some.args[0] == "world"
+        assert 'reason' not in g.some.kwargs
+        assert g.some.kwargs['reason2'] == "456"
+
 class TestFunctional:
     def test_mark_per_function(self, testdir):
         p = testdir.makepyfile("""
@@ -136,7 +151,7 @@ class TestFunctional:
         item, = items
         keywords = item.keywords
         marker = keywords['hello']
-        assert marker.args == ["pos0", "pos1"]
+        assert marker.args == ("pos0", "pos1")
         assert marker.kwargs == {'x': 3, 'y': 2, 'z': 4}
 
     def test_mark_other(self, testdir):

--- a/_pytest/mark.py
+++ b/_pytest/mark.py
@@ -101,10 +101,10 @@ class MarkDecorator:
         def test_function():
             pass
     """
-    def __init__(self, name):
+    def __init__(self, name, args=None, kwargs=None):
         self.markname = name
-        self.kwargs = {}
-        self.args = []
+        self.args = args or ()
+        self.kwargs = kwargs or {}
 
     def __repr__(self):
         d = self.__dict__.copy()
@@ -134,12 +134,12 @@ class MarkDecorator:
                         setattr(func, self.markname, holder)
                     else:
                         holder.kwargs.update(self.kwargs)
-                        holder.args.extend(self.args)
+                        holder.args += self.args
                 return func
-            else:
-                self.args.extend(args)
-        self.kwargs.update(kwargs)
-        return self
+        kw = self.kwargs.copy()
+        kw.update(kwargs)
+        args = self.args + args
+        return self.__class__(self.markname, args=args, kwargs=kw)
 
 class MarkInfo:
     """ Marking object created by :class:`MarkDecorator` instances. """

--- a/CHANGELOG
+++ b/CHANGELOG
@@ -38,7 +38,7 @@ Changes between 1.3.4 and 2.0.0dev0
 - fix bug: unittest collected functions now also can have "pytestmark"
   applied at class/module level
 - add ability to use "class" level for cached_setup helper
-
+- fix strangeness: mark.* objects are now immutable, create new instances
 
 Changes between 1.3.3 and 1.3.4
 ----------------------------------------------
_______________________________________________
py-svn mailing list
py-svn@codespeak.net
http://codespeak.net/mailman/listinfo/py-svn

Reply via email to