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)
