Hello community,

here is the log from the commit of package python3-fixtures for 
openSUSE:Factory checked in at 2016-05-30 09:58:41
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python3-fixtures (Old)
 and      /work/SRC/openSUSE:Factory/.python3-fixtures.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python3-fixtures"

Changes:
--------
--- /work/SRC/openSUSE:Factory/python3-fixtures/python3-fixtures.changes        
2016-05-25 21:24:15.000000000 +0200
+++ /work/SRC/openSUSE:Factory/.python3-fixtures.new/python3-fixtures.changes   
2016-05-30 09:58:44.000000000 +0200
@@ -1,0 +2,8 @@
+Sun May 29 03:21:20 UTC 2016 - [email protected]
+
+- update to version 3.0.0:
+  * Monkeypatching of callables has been thoroughly overhauled: there
+    were deep flaws in usability because staticmethod and classmethods
+    are actually descriptors. (Andrew Laski, Robert Collins)
+
+-------------------------------------------------------------------
@@ -7 +14,0 @@
-

Old:
----
  fixtures-2.0.0.tar.gz

New:
----
  fixtures-3.0.0.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python3-fixtures.spec ++++++
--- /var/tmp/diff_new_pack.kJD95K/_old  2016-05-30 09:58:45.000000000 +0200
+++ /var/tmp/diff_new_pack.kJD95K/_new  2016-05-30 09:58:45.000000000 +0200
@@ -17,7 +17,7 @@
 
 
 Name:           python3-fixtures
-Version:        2.0.0
+Version:        3.0.0
 Release:        0
 Summary:        Fixtrues, reusable state for writing clean tests and more
 License:        Apache-2.0 or BSD-3-Clause

++++++ fixtures-2.0.0.tar.gz -> fixtures-3.0.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fixtures-2.0.0/AUTHORS new/fixtures-3.0.0/AUTHORS
--- old/fixtures-2.0.0/AUTHORS  2016-04-07 03:19:48.000000000 +0200
+++ new/fixtures-3.0.0/AUTHORS  2016-05-20 01:03:07.000000000 +0200
@@ -1,4 +1,5 @@
 Andrew Laski <[email protected]>
+Brant Knudson <[email protected]>
 Clark Boylan <[email protected]>
 Dan Kenigsberg <[email protected]>
 Francesco Banconi <[email protected]>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fixtures-2.0.0/ChangeLog new/fixtures-3.0.0/ChangeLog
--- old/fixtures-2.0.0/ChangeLog        2016-04-07 03:19:48.000000000 +0200
+++ new/fixtures-3.0.0/ChangeLog        2016-05-20 01:03:07.000000000 +0200
@@ -1,6 +1,17 @@
 CHANGES
 =======
 
+3.0.0
+-----
+
+* Release 3.0.0
+* Fixup the MonkeyPatch patch
+* Tweak the new tests for consistency
+* Update the semantics on _fixtures.MonkeyPatch
+* Avoid old versions of pbr - we require modern releases
+* Correct MockPatchMultiple example
+* Ignore .tox
+
 2.0.0
 -----
 
@@ -82,30 +93,30 @@
 ------
 
 * Release 0.3.15
-* * ``FakeProcess`` wait() now supports arguments added in Python 3. (Steve 
Kowalik)
-* * ``FakeProcess`` wait() now supports arguments added in Python 3. (Steve 
Kowalik)
-* * ``FakeProcess`` now supports kill(). (Steve Kowalik)
-* * ``FakePopen`` now supports being called under a context manager (IE: 
with). (Steve Kowalik)
-* * ``MonkeyPatch`` now preserves ``staticmethod`` functions. (Dan Kenigsberg)
+* * ``FakeProcess`` wait() now supports arguments added in Python 3.   (Steve 
Kowalik)
+*   * ``FakeProcess`` wait() now supports arguments added in Python 3.       
(Steve Kowalik)
 * * ``FakeProcess`` now supports kill(). (Steve Kowalik)
-* * ``FakePopen`` now works under a context manager itself. (Steve Kowalik, 
#1358085)
+* * ``FakePopen`` now supports being called under a context manager (IE: 
with).   (Steve Kowalik)
+* * ``MonkeyPatch`` now preserves ``staticmethod`` functions.   (Dan 
Kenigsberg)
+*   * ``FakeProcess`` now supports kill(). (Steve Kowalik)
+* * ``FakePopen`` now works under a context manager itself.   (Steve Kowalik, 
#1358085)
 * MonkeyPatch staticmethod
 
 0.3.14
 ------
 
 * Release 0.3.14
-* * ``FakePopen`` can now override the returncode attribute. (Robert Collins)
+* * ``FakePopen`` can now override the returncode attribute.   (Robert Collins)
 * More releasing docs
 
 0.3.13
 ------
 
 * Release 0.3.13
-* * Documentation hopefully covers ``TestWithFixtures`` a little better. 
(Robert Collins, #1102688)
+* * Documentation hopefully covers ``TestWithFixtures`` a little better.   
(Robert Collins, #1102688)
 * Ignore an egg-info directory if it exists
-* * ``setup.py`` now lists the ``testtools`` dependency which was missing. 
(Robert Collins, #1103823)
-* * ``FakePopen`` now accepts all the parameters available in Python 2.7. 
(Robert Collins)
+* * ``setup.py`` now lists the ``testtools`` dependency which was missing.   
(Robert Collins, #1103823)
+* * ``FakePopen`` now accepts all the parameters available in Python 2.7.   
(Robert Collins)
 
 0.3.12
 ------
@@ -118,12 +129,12 @@
 ------
 
 * Release 0.3.11
-* * pydoc is recommended as a source of info about fixtures. (Robert Collins, 
#812845)
-* * The docs for fixtures have been updated to cover the full API. (Robert 
Collins, #1071649)
-* * ``DetailStream`` was ambiguous about whether it handled bytes or 
characters, which matters a lot for Python3. It now is deprecated with 
ByteStream and StringStream replacing it. (Robert Collins)
+* * pydoc is recommended as a source of info about fixtures.   (Robert 
Collins, #812845)
+* * The docs for fixtures have been updated to cover the full API.   (Robert 
Collins, #1071649)
+* * ``DetailStream`` was ambiguous about whether it handled bytes or 
characters,   which matters a lot for Python3. It now is deprecated with 
ByteStream and   StringStream replacing it. (Robert Collins)
 * Update docs
-* * ``DetailStream`` was ambiguous about whether it handled bytes or 
characters, which matters a lot for Python3. It now is deprecated with 
ByteStream and StringStream replacing it. (Robert Collins)
-* * ``FakeLogger`` has been split out into a ``LogHandler`` fixture that can 
inject arbitrary handlers, giving more flexability. (Jonathan Lange)
+* * ``DetailStream`` was ambiguous about whether it handled bytes or 
characters,   which matters a lot for Python3. It now is deprecated with 
ByteStream and   StringStream replacing it. (Robert Collins)
+* * ``FakeLogger`` has been split out into a ``LogHandler`` fixture that can   
inject arbitrary handlers, giving more flexability. (Jonathan Lange)
 * Drop the MementoHandler stuff
 * Rest of the tests for LogHandler
 * Give up on MementoHandler, just test LogHandler instead
@@ -132,12 +143,12 @@
 * Extract the handler managing bit of FakeLogger into its own fixture
 * Add MementoHandler
 * Release 0.3.10
-* * New ``DetailStream`` fixture to add file-like object content to testtools 
details. This allows for easy capture of sys.stdout and sys.stderr for example. 
(Clark Boylan)
+* * New ``DetailStream`` fixture to add file-like object content to testtools  
 details. This allows for easy capture of sys.stdout and sys.stderr for   
example. (Clark Boylan)
 * Document DetailStream
-* * New ``DetailStream`` fixture to add file-like object content to testtools 
details. This allows for easy capture of sys.stdout and sys.stderr for example. 
(Clark Boylan)
-* * Factor out new ``CallMany`` class to isolate the cleanup logic. (Robert 
Collins)
+* * New ``DetailStream`` fixture to add file-like object content to testtools  
 details. This allows for easy capture of sys.stdout and sys.stderr for   
example. (Clark Boylan)
+* * Factor out new ``CallMany`` class to isolate the cleanup logic.   (Robert 
Collins)
 * Add 'join' method to TempDir
-* Revert filetree patch, r54. Now in lp:treeshape
+* Revert filetree patch, r54.  Now in lp:treeshape
 * Rename to 'join'
 * Update NEWS
 * Add an 'abspath' helper
@@ -169,7 +180,7 @@
 * Initial creation of FileTree
 * Add a matcher, because I can't bear to write that code again
 * Clean up pyflakes
-* Export TempHomeDir. Otherwise it's imported here for no reason
+* Export TempHomeDir.  Otherwise it's imported here for no reason
 
 0.3.9
 -----
@@ -218,7 +229,7 @@
 * Bump version to 0.3.7 beta
 * Typo
 * Extend TempDir to allow controlling the root directory
-* * On Python 2.7 and above the _fixtures tests are no longer run twice. 
(Robert Collins)
+* * On Python 2.7 and above the _fixtures tests are no longer run twice.   
(Robert Collins)
 * Note in NEWS the new testtools version dependency as well
 * NEWS & README
 * Pretty sure this is a py3 thing
@@ -227,7 +238,7 @@
 * Release 0.3.6
 * Another small API break - sorry. Fixture.getDetails no longer returns the 
internal details dict (self._details). Access that directly if needed. It now 
looks for details in used fixtures and returns those as well as details added 
directly. (RobertCollins, #780806)
 * New fixture ``PackagePathEntry`` which patches the path of an existing 
package, allowing importing part of it from aonther directory. (Robert Collins)
-* * Details from child fixtures for both Fixture and TestWithFixtures no 
longer quash same-named details if testtools 0.9.11 is available (for the 
gather_details helper). (Gavin Panella, #796253)
+* * Details from child fixtures for both Fixture and TestWithFixtures no 
longer   quash same-named details if testtools 0.9.11 is available (for the   
gather_details helper).   (Gavin Panella, #796253)
 * Test failure on some setups in 
test_cleanUp_raise_first_false_callscleanups_returns_exceptions. (Gavin 
Panella, #796249)
 * Gather details from fixtures that fail to setUp() in TestWithFixtures
 * Use testtools.helpers.try_import instead of try:except:
@@ -235,7 +246,7 @@
 * Reminder to self to skip test if gather_details is not available
 * Test against types.TracebackType instead of the type of the current 
traceback in sys.exc_info()
 * Gather details from fixtures that fail to setUp()
-* * New fixture ``PythonPathEntry`` which patches sys.path. (Robert Collins, 
#737503)
+* * New fixture ``PythonPathEntry`` which patches sys.path.   (Robert Collins, 
#737503)
 * Better docs for cleanUp and exceptions
 * Document sharing dependencies somewhat
 * Release 0.3.5
@@ -251,7 +262,7 @@
 * Ship new packages
 * Release 0.3.1
 * Add a communicate method to FakeProcess
-* * Experimental PopenFixture providing a test double for testing code that 
runs external processes. (Robert Collins)
+* * Experimental PopenFixture providing a test double for testing code that 
runs   external processes. (Robert Collins)
 * Fixup cleanUp protocol for good
 * Stop silently swallowing exceptions during cleanUp
 * Cause cleanup failures to cause test failures
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fixtures-2.0.0/NEWS new/fixtures-3.0.0/NEWS
--- old/fixtures-2.0.0/NEWS     2016-04-07 03:17:41.000000000 +0200
+++ new/fixtures-3.0.0/NEWS     2016-05-20 01:01:08.000000000 +0200
@@ -6,6 +6,13 @@
 NEXT
 ~~~~
 
+3.0.0
+~~~~~
+
+* Monkeypatching of callables has been thoroughly overhauled: there were deep
+  flaws in usability because staticmethod and classmethods are actually
+  descriptors. (Andrew Laski, Robert Collins)
+
 2.0
 ~~~
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fixtures-2.0.0/PKG-INFO new/fixtures-3.0.0/PKG-INFO
--- old/fixtures-2.0.0/PKG-INFO 2016-04-07 03:19:48.000000000 +0200
+++ new/fixtures-3.0.0/PKG-INFO 2016-05-20 01:03:07.000000000 +0200
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: fixtures
-Version: 2.0.0
+Version: 3.0.0
 Summary: Fixtures, reusable state for writing clean tests and more.
 Home-page: https://launchpad.net/python-fixtures
 Author: Robert Collins
@@ -401,7 +401,7 @@
         
         Adapts ``mock.patch.multiple`` to be used as a Fixture.
         
-          >>> fixture = fixtures.MockPatch('subprocess.Popen', returncode=3)
+          >>> fixture = fixtures.MockPatchMultiple('subprocess.Popen', 
returncode=3)
         
         MonkeyPatch
         +++++++++++
@@ -412,6 +412,9 @@
           ...     pass
           >>> fixture = fixtures.MonkeyPatch('__builtin__.open', fake_open)
         
+        Note that there are some complexities when patching methods - please 
see the
+        API documentation for details.
+        
         NestedTempfile
         ++++++++++++++
         
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fixtures-2.0.0/README new/fixtures-3.0.0/README
--- old/fixtures-2.0.0/README   2016-04-07 02:32:14.000000000 +0200
+++ new/fixtures-3.0.0/README   2016-05-19 12:27:44.000000000 +0200
@@ -393,7 +393,7 @@
 
 Adapts ``mock.patch.multiple`` to be used as a Fixture.
 
-  >>> fixture = fixtures.MockPatch('subprocess.Popen', returncode=3)
+  >>> fixture = fixtures.MockPatchMultiple('subprocess.Popen', returncode=3)
 
 MonkeyPatch
 +++++++++++
@@ -404,6 +404,9 @@
   ...     pass
   >>> fixture = fixtures.MonkeyPatch('__builtin__.open', fake_open)
 
+Note that there are some complexities when patching methods - please see the
+API documentation for details.
+
 NestedTempfile
 ++++++++++++++
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fixtures-2.0.0/fixtures/_fixtures/monkeypatch.py 
new/fixtures-3.0.0/fixtures/_fixtures/monkeypatch.py
--- old/fixtures-2.0.0/fixtures/_fixtures/monkeypatch.py        2016-04-07 
02:32:40.000000000 +0200
+++ new/fixtures-3.0.0/fixtures/_fixtures/monkeypatch.py        2016-05-20 
00:14:52.000000000 +0200
@@ -17,27 +17,79 @@
     'MonkeyPatch'
     ]
 
+import functools
 import sys
 import types
 
 from fixtures import Fixture
 
 
-def _setattr(obj, name, value):
-    """Handle some corner cases when calling setattr.
+_class_types = (type, )
+if getattr(types, 'ClassType', None):
+    # Python 2 has multiple types of classes.
+    _class_types = _class_types + (types.ClassType,)
 
-    setattr transforms a function into instancemethod, so where appropriate
-    value needs to be wrapped with staticmethod().
+
+def _coerce_values(obj, name, new_value, sentinel):
+    """Return an adapted (new_value, old_value) for patching obj.name.
+    
+    setattr transforms a function into an instancemethod when set on a class.
+    This checks if the attribute to be replaced is a callable descriptor -
+    staticmethod, classmethod, or types.FunctionType - and wraps new_value if
+    necessary.
+    
+    This also checks getattr(obj, name) and wraps it if necessary
+    since the staticmethod wrapper isn't preserved.
+
+    :param obj: The object with an attribute being patched.
+    :param name: The name of the attribute being patched.
+    :param new_value: The new value to be assigned.
+    :param sentinel: If no old_value existed, the sentinel is returned to
+        indicate that.
     """
-    if sys.version_info[0] == 2:
-        class_types = (type, types.ClassType)
-    else:
-        # All classes are <class 'type'> in Python 3
-        class_types = type
-    if (isinstance(obj, class_types) and
-            isinstance(value, types.FunctionType)):
-        value = staticmethod(value)
-    setattr(obj, name, value)
+    old_value = getattr(obj, name, sentinel)
+    if not isinstance(obj, _class_types):
+        # We may be dealing with an instance of a class. In that case the
+        # attribute may be the result of a descriptor lookup (or a __getattr__
+        # override etc). Its incomplete, but generally good enough to just
+        # look and see if name is in the instance dict.
+        try:
+            obj.__dict__[name]
+        except (AttributeError, KeyError):
+            return (new_value, sentinel)
+        else:
+            return (new_value, old_value)
+
+    # getattr() returns a function, this access pattern will return a
+    # staticmethod/classmethod if the name method is defined that way
+    old_attribute = obj.__dict__.get(name)
+    if old_attribute is not None:
+        old_value = old_attribute
+
+    # If new_value is not callable, no special handling is needed.
+    # (well, technically the same descriptor issue can happen with
+    # user supplied descriptors, but that is arguably a feature - someone can
+    # deliberately install a different descriptor.
+    if not callable(new_value):
+        return (new_value, old_value)
+
+    if isinstance(old_value, staticmethod):
+        new_value = staticmethod(new_value)
+    elif isinstance(old_value, classmethod):
+        new_value = classmethod(new_value)
+    elif isinstance(old_value, types.FunctionType):
+        if hasattr(new_value, '__get__'):
+            # new_value is a descriptor, and that would result in it being
+            # rebound if we assign it to a class - we want to preserve the
+            # bound state rather than having it bound to the new object
+            # it has been patched onto.
+            captured_method = new_value
+            @functools.wraps(old_value)
+            def avoid_get(*args, **kwargs):
+                return captured_method(*args, **kwargs)
+            new_value = avoid_get
+
+    return (new_value, old_value)
 
 
 class MonkeyPatch(Fixture):
@@ -54,6 +106,26 @@
 
         During setup the name will be deleted or assigned the requested value,
         and this will be restored in cleanUp.
+
+        When patching methods, the call signature of name should be a subset
+        of the parameters which can be used to call new_value.
+
+        For instance.
+
+        >>> class T:
+        ...     def method(self, arg1):
+        ...         pass
+        >>> class N:
+        ...     @staticmethod
+        ...     def newmethod(arg1):
+        ...         pass
+
+        Patching N.newmethod on top of T.method and then calling T().method(1)
+        will not work because they do not have compatible call signatures -
+        self will be passed to newmethod because the callable (N.newmethod)
+        is placed onto T as a regular function. This allows capturing all the
+        supplied parameters while still consulting local state in your
+        new_value.
         """
         Fixture.__init__(self)
         self.name = name
@@ -72,16 +144,17 @@
         for component in components[1:]:
             current = getattr(current, component)
         sentinel = object()
-        old_value = getattr(current, attribute, sentinel)
+        new_value, old_value = _coerce_values(current, attribute,
+                self.new_value, sentinel)
         if self.new_value is self.delete:
             if old_value is not sentinel:
                 delattr(current, attribute)
         else:
-            _setattr(current, attribute, self.new_value)
+            setattr(current, attribute, new_value)
         if old_value is sentinel:
             self.addCleanup(self._safe_delete, current, attribute)
         else:
-            self.addCleanup(_setattr, current, attribute, old_value)
+            self.addCleanup(setattr, current, attribute, old_value)
 
     def _safe_delete(self, obj, attribute):
         """Delete obj.attribute handling the case where its missing."""
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/fixtures-2.0.0/fixtures/tests/_fixtures/test_monkeypatch.py 
new/fixtures-3.0.0/fixtures/tests/_fixtures/test_monkeypatch.py
--- old/fixtures-2.0.0/fixtures/tests/_fixtures/test_monkeypatch.py     
2016-04-07 02:32:40.000000000 +0200
+++ new/fixtures-3.0.0/fixtures/tests/_fixtures/test_monkeypatch.py     
2016-05-20 00:15:24.000000000 +0200
@@ -13,16 +13,52 @@
 # license you chose for the specific language governing permissions and
 # limitations under that license.
 
+import functools
+
 import testtools
+from testtools.matchers import Is
 
 from fixtures import MonkeyPatch, TestWithFixtures
 
 reference = 23
 
 class C(object):
+    def foo(self, arg):
+        return arg
+    @staticmethod
+    def foo_static(): pass
+    @classmethod
+    def foo_cls(cls): pass
+
+class D(object):
+    def bar(self): pass
+    def bar_two_args(self, arg):
+        return (self, arg)
+    @classmethod
+    def bar_cls(cls):
+        return cls
+    @classmethod
+    def bar_cls_args(cls, *args):
+        return (cls,) + args
+    @staticmethod
+    def bar_static():
+        pass
     @staticmethod
-    def foo(): pass
-def bar(): pass
+    def bar_static_args(*args):
+        return args
+    def bar_self_referential(self, *args, **kwargs):
+        self.bar()
+
+INST_C = C()
+
+def fake(*args):
+    return args
+def fake2(arg): pass
+def fake_no_args(): pass
+def fake_no_args2(): pass
+@staticmethod
+def fake_static(): pass
+
 
 class TestMonkeyPatch(testtools.TestCase, TestWithFixtures):
 
@@ -72,14 +108,318 @@
             fixture.cleanUp()
             self.assertFalse('new_attr' in globals())
 
-    def test_patch_staticmethod(self):
-        oldfoo = C.foo
+    def _check_restored_static_or_class_method(self, oldmethod, oldmethod_inst,
+            klass, methodname):
+        restored_method = getattr(klass, methodname)
+        restored_method_inst = getattr(klass(), methodname)
+        self.assertEqual(oldmethod, restored_method)
+        self.assertEqual(oldmethod, restored_method_inst)
+        self.assertEqual(oldmethod_inst, restored_method)
+        self.assertEqual(oldmethod_inst, restored_method_inst)
+        restored_method()
+        restored_method_inst()
+
+    def test_patch_staticmethod_with_staticmethod(self):
+        oldmethod = C.foo_static
+        oldmethod_inst = C().foo_static
+        fixture = MonkeyPatch(
+            'fixtures.tests._fixtures.test_monkeypatch.C.foo_static',
+            D.bar_static)
+        with fixture:
+            C.foo_static()
+            C().foo_static()
+        self._check_restored_static_or_class_method(oldmethod, oldmethod_inst,
+                C, 'foo_static')
+
+    def test_patch_staticmethod_with_classmethod(self):
+        oldmethod = C.foo_static
+        oldmethod_inst = C().foo_static
+        fixture = MonkeyPatch(
+            'fixtures.tests._fixtures.test_monkeypatch.C.foo_static',
+            D.bar_cls)
+        with fixture:
+            C.foo_static()
+            C().foo_static()
+        self._check_restored_static_or_class_method(oldmethod, oldmethod_inst,
+                C, 'foo_static')
+
+    def test_patch_staticmethod_with_function(self):
+        oldmethod = C.foo_static
+        oldmethod_inst = C().foo_static
+        fixture = MonkeyPatch(
+            'fixtures.tests._fixtures.test_monkeypatch.C.foo_static',
+            fake_no_args)
+        with fixture:
+            C.foo_static()
+            C().foo_static()
+        self._check_restored_static_or_class_method(oldmethod, oldmethod_inst,
+                C, 'foo_static')
+
+    def test_patch_staticmethod_with_boundmethod(self):
+        oldmethod = C.foo_static
+        oldmethod_inst = C().foo_static
+        fixture = MonkeyPatch(
+            'fixtures.tests._fixtures.test_monkeypatch.C.foo_static',
+            D().bar)
+        with fixture:
+            C.foo_static()
+            C().foo_static()
+        self._check_restored_static_or_class_method(oldmethod, oldmethod_inst,
+                C, 'foo_static')
+
+    def test_patch_classmethod_with_staticmethod(self):
+        oldmethod = C.foo_cls
+        oldmethod_inst = C().foo_cls
+        fixture = MonkeyPatch(
+            'fixtures.tests._fixtures.test_monkeypatch.C.foo_cls',
+            D.bar_static_args)
+        with fixture:
+            (cls,) = C.foo_cls()
+            self.expectThat(cls, Is(C))
+            (cls,) = C().foo_cls()
+            self.expectThat(cls, Is(C))
+        self._check_restored_static_or_class_method(oldmethod, oldmethod_inst,
+                C, 'foo_cls')
+
+    def test_patch_classmethod_with_classmethod(self):
+        oldmethod = C.foo_cls
+        oldmethod_inst = C().foo_cls
+        fixture = MonkeyPatch(
+            'fixtures.tests._fixtures.test_monkeypatch.C.foo_cls',
+            D.bar_cls_args)
+        with fixture:
+            cls, target_class = C.foo_cls()
+            self.expectThat(cls, Is(D))
+            self.expectThat(target_class, Is(C))
+            cls, target_class = C().foo_cls()
+            self.expectThat(cls, Is(D))
+            self.expectThat(target_class, Is(C))
+        self._check_restored_static_or_class_method(oldmethod, oldmethod_inst,
+                C, 'foo_cls')
+
+    def test_patch_classmethod_with_function(self):
+        oldmethod = C.foo_cls
+        oldmethod_inst = C().foo_cls
+        fixture = MonkeyPatch(
+            'fixtures.tests._fixtures.test_monkeypatch.C.foo_cls',
+            fake)
+        with fixture:
+            (cls,) = C.foo_cls()
+            self.expectThat(cls, Is(C))
+            (cls, arg) = C().foo_cls(1)
+            self.expectThat(cls, Is(C))
+            self.assertEqual(1, arg)
+        self._check_restored_static_or_class_method(oldmethod, oldmethod_inst,
+                C, 'foo_cls')
+
+    def test_patch_classmethod_with_boundmethod(self):
+        oldmethod = C.foo_cls
+        oldmethod_inst = C().foo_cls
+        d = D()
+        fixture = MonkeyPatch(
+            'fixtures.tests._fixtures.test_monkeypatch.C.foo_cls',
+            d.bar_two_args)
+        with fixture:
+            slf, cls = C.foo_cls()
+            self.expectThat(slf, Is(d))
+            self.expectThat(cls, Is(C))
+            slf, cls = C().foo_cls()
+            self.expectThat(slf, Is(d))
+            self.expectThat(cls, Is(C))
+        self._check_restored_static_or_class_method(oldmethod, oldmethod_inst,
+                C, 'foo_cls')
+
+    def test_patch_function_with_staticmethod(self):
+        oldmethod = fake_no_args
+        fixture = MonkeyPatch(
+            'fixtures.tests._fixtures.test_monkeypatch.fake_no_args',
+            D.bar_static)
+        with fixture:
+            fake_no_args()
+        self.assertEqual(oldmethod, fake_no_args)
+
+    def test_patch_function_with_classmethod(self):
+        oldmethod = fake_no_args
+        fixture = MonkeyPatch(
+            'fixtures.tests._fixtures.test_monkeypatch.fake_no_args',
+            D.bar_cls)
+        with fixture:
+            fake_no_args()
+        self.assertEqual(oldmethod, fake_no_args)
+
+    def test_patch_function_with_function(self):
+        oldmethod = fake_no_args
+        fixture = MonkeyPatch(
+            'fixtures.tests._fixtures.test_monkeypatch.fake_no_args',
+            fake_no_args2)
+        with fixture:
+            fake_no_args()
+        self.assertEqual(oldmethod, fake_no_args)
+
+    def test_patch_function_with_partial(self):
+        oldmethod = fake_no_args
+        fixture = MonkeyPatch(
+            'fixtures.tests._fixtures.test_monkeypatch.fake_no_args',
+            functools.partial(fake, 1))
+        with fixture:
+            (ret,) = fake_no_args()
+            self.assertEqual(1, ret)
+        self.assertEqual(oldmethod, fake_no_args)
+
+    def test_patch_function_with_boundmethod(self):
+        oldmethod = fake_no_args
+        fixture = MonkeyPatch(
+            'fixtures.tests._fixtures.test_monkeypatch.fake_no_args',
+            D().bar)
+        with fixture:
+            fake_no_args()
+        self.assertEqual(oldmethod, fake_no_args)
+
+    def test_patch_boundmethod_with_staticmethod(self):
+        oldmethod = INST_C.foo
+        fixture = MonkeyPatch(
+            'fixtures.tests._fixtures.test_monkeypatch.INST_C.foo',
+            D.bar_static)
+        with fixture:
+            INST_C.foo()
+        self.assertEqual(oldmethod, INST_C.foo)
+
+    def test_patch_boundmethod_with_classmethod(self):
+        oldmethod = INST_C.foo
+        fixture = MonkeyPatch(
+            'fixtures.tests._fixtures.test_monkeypatch.INST_C.foo',
+            D.bar_cls)
+        with fixture:
+            INST_C.foo()
+        self.assertEqual(oldmethod, INST_C.foo)
+
+    def test_patch_boundmethod_with_function(self):
+        oldmethod = INST_C.foo
+        fixture = MonkeyPatch(
+            'fixtures.tests._fixtures.test_monkeypatch.INST_C.foo',
+            fake_no_args)
+        with fixture:
+            INST_C.foo()
+        self.assertEqual(oldmethod, INST_C.foo)
+
+    def test_patch_boundmethod_with_boundmethod(self):
+        oldmethod = INST_C.foo
+        fixture = MonkeyPatch(
+            'fixtures.tests._fixtures.test_monkeypatch.INST_C.foo',
+            D().bar)
+        with fixture:
+            INST_C.foo()
+        self.assertEqual(oldmethod, INST_C.foo)
+        sentinel = object()
+        self.assertEqual(sentinel, INST_C.__dict__.get('foo', sentinel))
+
+    def test_patch_unboundmethod_with_staticmethod(self):
+        oldmethod = C.foo
         fixture = MonkeyPatch(
             'fixtures.tests._fixtures.test_monkeypatch.C.foo',
-            bar)
+            D.bar_static_args)
         with fixture:
-            C.foo()
-            C().foo()
-        self.assertEqual(oldfoo, C.foo)
-        self.assertEqual(oldfoo, C().foo)
+            target_self, arg = INST_C.foo(1)
+            self.expectThat(target_self, Is(INST_C))
+            self.assertEqual(1, arg)
+        self.assertEqual(oldmethod, C.foo)
 
+    def test_patch_unboundmethod_with_classmethod(self):
+        oldmethod = C.foo
+        fixture = MonkeyPatch(
+            'fixtures.tests._fixtures.test_monkeypatch.C.foo',
+            D.bar_cls_args)
+        with fixture:
+            c = C()
+            cls, target_self, arg = c.foo(1)
+            self.expectThat(cls, Is(D))
+            self.expectThat(target_self, Is(c))
+            self.assertEqual(1, arg)
+        self.assertEqual(oldmethod, C.foo)
+
+    def test_patch_unboundmethod_with_function(self):
+        oldmethod = C.foo
+        fixture = MonkeyPatch(
+            'fixtures.tests._fixtures.test_monkeypatch.C.foo',
+            fake)
+        with fixture:
+            c = C()
+            target_self, arg = c.foo(1)
+            self.expectThat(target_self, Is(c))
+            self.assertTrue(1, arg)
+        self.assertEqual(oldmethod, C.foo)
+
+    def test_patch_unboundmethod_with_boundmethod(self):
+        oldmethod = C.foo
+        d = D()
+        fixture = MonkeyPatch(
+            'fixtures.tests._fixtures.test_monkeypatch.C.foo',
+            d.bar_two_args)
+        with fixture:
+            c = C()
+            slf, target_self = c.foo()
+            self.expectThat(slf, Is(d))
+            self.expectThat(target_self, Is(c))
+        self.assertEqual(oldmethod, C.foo)
+
+    def test_double_patch_instancemethod(self):
+        oldmethod = C.foo
+        oldmethod_inst = C().foo
+        fixture1 = MonkeyPatch(
+            'fixtures.tests._fixtures.test_monkeypatch.C.foo',
+            fake)
+        fixture2 = MonkeyPatch(
+            'fixtures.tests._fixtures.test_monkeypatch.C.foo',
+            fake2)
+        with fixture1:
+            with fixture2:
+                C().foo()
+        self.assertEqual(oldmethod, C.foo)
+        # The method address changes with each instantiation of C, and method
+        # equivalence just tests that. Compare the code objects instead.
+        self.assertEqual(oldmethod_inst.__code__, C().foo.__code__)
+
+    def test_double_patch_staticmethod(self):
+        oldmethod = C.foo_static
+        oldmethod_inst = C().foo_static
+        fixture1 = MonkeyPatch(
+            'fixtures.tests._fixtures.test_monkeypatch.C.foo_static',
+            fake_no_args)
+        fixture2 = MonkeyPatch(
+            'fixtures.tests._fixtures.test_monkeypatch.C.foo_static',
+            fake_static)
+        with fixture1:
+            with fixture2:
+                C.foo_static()
+                C().foo_static()
+        self._check_restored_static_or_class_method(oldmethod, oldmethod_inst,
+            C, 'foo_static')
+
+    def test_double_patch_classmethod(self):
+        oldmethod = C.foo_cls
+        oldmethod_inst = C().foo_cls
+        fixture1 = MonkeyPatch(
+            'fixtures.tests._fixtures.test_monkeypatch.C.foo_cls',
+            fake)
+        fixture2 = MonkeyPatch(
+            'fixtures.tests._fixtures.test_monkeypatch.C.foo_cls',
+            fake2)
+        with fixture1:
+            with fixture2:
+                C.foo_cls()
+                C().foo_cls()
+        self._check_restored_static_or_class_method(oldmethod, oldmethod_inst,
+            C, 'foo_cls')
+
+    def test_patch_c_foo_with_instance_d_bar_self_referential(self):
+        oldmethod = C.foo
+        oldmethod_inst = C().foo
+        fixture = MonkeyPatch(
+            'fixtures.tests._fixtures.test_monkeypatch.C.foo',
+            D().bar_self_referential)
+        with fixture:
+            C().foo()
+        self.assertEqual(oldmethod, C.foo)
+        # The method address changes with each instantiation of C, and method
+        # equivalence just tests that. Compare the code objects instead.
+        self.assertEqual(oldmethod_inst.__code__, C().foo.__code__)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fixtures-2.0.0/fixtures.egg-info/PKG-INFO 
new/fixtures-3.0.0/fixtures.egg-info/PKG-INFO
--- old/fixtures-2.0.0/fixtures.egg-info/PKG-INFO       2016-04-07 
03:19:48.000000000 +0200
+++ new/fixtures-3.0.0/fixtures.egg-info/PKG-INFO       2016-05-20 
01:03:06.000000000 +0200
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: fixtures
-Version: 2.0.0
+Version: 3.0.0
 Summary: Fixtures, reusable state for writing clean tests and more.
 Home-page: https://launchpad.net/python-fixtures
 Author: Robert Collins
@@ -401,7 +401,7 @@
         
         Adapts ``mock.patch.multiple`` to be used as a Fixture.
         
-          >>> fixture = fixtures.MockPatch('subprocess.Popen', returncode=3)
+          >>> fixture = fixtures.MockPatchMultiple('subprocess.Popen', 
returncode=3)
         
         MonkeyPatch
         +++++++++++
@@ -412,6 +412,9 @@
           ...     pass
           >>> fixture = fixtures.MonkeyPatch('__builtin__.open', fake_open)
         
+        Note that there are some complexities when patching methods - please 
see the
+        API documentation for details.
+        
         NestedTempfile
         ++++++++++++++
         
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fixtures-2.0.0/fixtures.egg-info/pbr.json 
new/fixtures-3.0.0/fixtures.egg-info/pbr.json
--- old/fixtures-2.0.0/fixtures.egg-info/pbr.json       2016-04-07 
03:19:48.000000000 +0200
+++ new/fixtures-3.0.0/fixtures.egg-info/pbr.json       2016-05-20 
01:03:06.000000000 +0200
@@ -1 +1 @@
-{"git_version": "820f12b", "is_release": true}
\ No newline at end of file
+{"is_release": true, "git_version": "c2c28a1"}
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fixtures-2.0.0/setup.cfg new/fixtures-3.0.0/setup.cfg
--- old/fixtures-2.0.0/setup.cfg        2016-04-07 03:19:48.000000000 +0200
+++ new/fixtures-3.0.0/setup.cfg        2016-05-20 01:03:07.000000000 +0200
@@ -31,7 +31,7 @@
        docutils
 
 [egg_info]
-tag_date = 0
 tag_build = 
+tag_date = 0
 tag_svn_revision = 0
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fixtures-2.0.0/setup.py new/fixtures-3.0.0/setup.py
--- old/fixtures-2.0.0/setup.py 2014-09-25 04:43:13.000000000 +0200
+++ new/fixtures-3.0.0/setup.py 2016-05-18 05:46:25.000000000 +0200
@@ -3,5 +3,5 @@
 import setuptools
 
 setuptools.setup(
-    setup_requires=['pbr'],
+    setup_requires=['pbr>0.11'],
     pbr=True)


Reply via email to