Hello community,

here is the log from the commit of package python-fixtures for openSUSE:Factory 
checked in at 2015-08-01 11:38:21
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-fixtures (Old)
 and      /work/SRC/openSUSE:Factory/.python-fixtures.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-fixtures"

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-fixtures/python-fixtures.changes  
2015-05-10 10:46:15.000000000 +0200
+++ /work/SRC/openSUSE:Factory/.python-fixtures.new/python-fixtures.changes     
2015-08-01 11:38:22.000000000 +0200
@@ -1,0 +2,14 @@
+Fri Jul  3 12:09:34 UTC 2015 - [email protected]
+
+- update to 1.3.1:
+  * Clarify the intent around _setUp
+  * Handle BaseException resource leaks as well
+  * Remove trailing whitespace
+  * Deal with resource leaks during setUp
+  * Missed NEWS entry
+  * Fine tune the mock patch
+  * Add a new mockpatch fixture
+  * Document where the project home and source are
+  * Ignore built things
+
+-------------------------------------------------------------------

Old:
----
  fixtures-1.2.0.tar.gz

New:
----
  fixtures-1.3.1.tar.gz

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

Other differences:
------------------
++++++ python-fixtures.spec ++++++
--- /var/tmp/diff_new_pack.eK3vbZ/_old  2015-08-01 11:38:22.000000000 +0200
+++ /var/tmp/diff_new_pack.eK3vbZ/_new  2015-08-01 11:38:22.000000000 +0200
@@ -17,7 +17,7 @@
 
 
 Name:           python-fixtures
-Version:        1.2.0
+Version:        1.3.1
 Release:        0
 Summary:        Fixtures, reusable state for writing clean tests and more
 License:        Apache-2.0 or BSD-3-Clause
@@ -25,6 +25,7 @@
 Url:            https://launchpad.net/python-fixtures
 Source:         
http://pypi.python.org/packages/source/f/fixtures/fixtures-%{version}.tar.gz
 BuildRequires:  python-devel
+BuildRequires:  python-mock
 BuildRequires:  python-pbr >= 0.11
 BuildRequires:  python-testtools >= 0.9.22
 BuildRoot:      %{_tmppath}/%{name}-%{version}-build
@@ -35,7 +36,7 @@
 %else
 BuildArch:      noarch
 %endif
-Requires:       python-testtools
+Requires:       python-testtools >= 0.9.22
 
 %description
 Fixtures defines a Python contract for reusable state / support logic,

++++++ fixtures-1.2.0.tar.gz -> fixtures-1.3.1.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fixtures-1.2.0/AUTHORS new/fixtures-1.3.1/AUTHORS
--- old/fixtures-1.2.0/AUTHORS  2015-05-05 00:14:19.000000000 +0200
+++ new/fixtures-1.3.1/AUTHORS  2015-06-30 04:22:04.000000000 +0200
@@ -9,6 +9,7 @@
 Jonathan Lange <[email protected]>
 Jonathan Lange <[email protected]>
 Joshua Harlow <[email protected]>
+Julien Danjou <[email protected]>
 Martin Pool <[email protected]>
 Robert Collins <[email protected]>
 Sean Dague <[email protected]>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fixtures-1.2.0/ChangeLog new/fixtures-1.3.1/ChangeLog
--- old/fixtures-1.2.0/ChangeLog        2015-05-05 00:14:19.000000000 +0200
+++ new/fixtures-1.3.1/ChangeLog        2015-06-30 04:22:04.000000000 +0200
@@ -1,6 +1,25 @@
 CHANGES
 =======
 
+1.3.1
+-----
+
+* Release 1.3.1
+* Clarify the intent around _setUp
+* Handle BaseException resource leaks as well
+
+1.3.0
+-----
+
+* Release 1.3.0
+* Remove trailing whitespace
+* Deal with resource leaks during setUp
+* Missed NEWS entry
+* Fine tune the mock patch
+* Add a new mockpatch fixture
+* Document where the project home and source are
+* Ignore built things
+
 1.2.0
 -----
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fixtures-1.2.0/NEWS new/fixtures-1.3.1/NEWS
--- old/fixtures-1.2.0/NEWS     2015-05-04 23:50:18.000000000 +0200
+++ new/fixtures-1.3.1/NEWS     2015-06-30 04:21:13.000000000 +0200
@@ -6,6 +6,27 @@
 NEXT
 ~~~~
 
+1.3.1
+~~~~~
+
+* ``Fixture.setUp`` now uses a bare except: and will thus catch BaseException.
+  Any non-Exception-subclass errors are raised verbatim after calling
+  ``cleanUp``, to avoid inappropriate masking in callers. (Robert Collins)
+
+1.3.0
+~~~~~
+
+* Add MockPatch, MockPatchMultiple, MockPatchObject - adapters to mock.
+  (Julien Danjou, Robert Collins)
+
+* Fixture.setUp should no longer be overridden in subclasses. Instead
+  override _setUp. This permits the Fixture base class to detect failures
+  during _setUp and trigger any registered cleanups, attach any details
+  to the failure exception and propogate that to callers. Overriding of
+  setUp is still supported: this adds a new interface for simpler
+  implementation of the contract of a fixture.
+  (Robert Collins, #1456361, #1456353)
+
 1.2.0
 ~~~~~
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fixtures-1.2.0/PKG-INFO new/fixtures-1.3.1/PKG-INFO
--- old/fixtures-1.2.0/PKG-INFO 2015-05-05 00:14:19.000000000 +0200
+++ new/fixtures-1.3.1/PKG-INFO 2015-06-30 04:22:04.000000000 +0200
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: fixtures
-Version: 1.2.0
+Version: 1.3.1
 Summary: Fixtures, reusable state for writing clean tests and more.
 Home-page: https://launchpad.net/python-fixtures
 Author: Robert Collins
@@ -87,19 +87,20 @@
         Creating Fixtures
         =================
         
-        Minimally, subclass Fixture, define setUp to initialize your state and 
schedule
+        Minimally, subclass Fixture, define _setUp to initialize your state 
and schedule
         a cleanup for when cleanUp is called and you're done::
         
           >>> import unittest
           >>> import fixtures
           >>> class NoddyFixture(fixtures.Fixture):
-          ...     def setUp(self):
-          ...         super(NoddyFixture, self).setUp()
+          ...     def _setUp(self):
           ...         self.frobnozzle = 42
           ...         self.addCleanup(delattr, self, 'frobnozzle')
         
-        This will initialize frobnozzle when setUp is called, and when cleanUp 
is
-        called get rid of the frobnozzle attribute.
+        This will initialize frobnozzle when ``setUp`` is called, and when 
``cleanUp``
+        is called get rid of the frobnozzle attribute. Prior to version 1.3.0 
fixtures
+        recommended overriding ``setUp``. This is still supported, but since 
it is
+        harder to write leak-free fixtures in this fashion, it is not 
recommended.
         
         If your fixture has diagnostic data - for instance the log file of an
         application server, or log messages, it can expose that by creating a 
content
@@ -107,8 +108,7 @@
         
           >>> from testtools.content import text_content
           >>> class WithLog(fixtures.Fixture):
-          ...     def setUp(self):
-          ...         super(WithLog, self).setUp()
+          ...     def _setUp(self):
           ...         self.addDetail('message', text_content('foo bar baz'))
         
         The method ``useFixture`` will use another fixture, call ``setUp`` on 
it, call
@@ -116,8 +116,7 @@
         the fixture. This allows simple composition of different fixtures.
         
           >>> class ReusingFixture(fixtures.Fixture):
-          ...     def setUp(self):
-          ...         super(ReusingFixture, self).setUp()
+          ...     def _setUp(self):
           ...         self.noddy = self.useFixture(NoddyFixture())
         
         There is a helper for adapting a function or function pair into 
Fixtures. it
@@ -162,9 +161,9 @@
         clean up after a fixture has been used, all fixtures define a 
``cleanUp``
         method which should be called when a fixture is finished with.
         
-        Because its nice to be able to build a particular set of related 
fixtures in
-        advance of using them, fixtures also have define a ``setUp`` method 
which
-        should be called before trying to use them.
+        Because it's nice to be able to build a particular set of related 
fixtures in
+        advance of using them, fixtures also have a ``setUp`` method which 
should be
+        called before trying to use them.
         
         One common desire with fixtures that are expensive to create is to 
reuse them
         in many test cases; to support this the base Fixture also defines a 
``reset``
@@ -211,8 +210,7 @@
           >>> import sys
           >>> from fixtures.fixture import MultipleExceptions
           >>> class BrokenFixture(fixtures.Fixture):
-          ...     def setUp(self):
-          ...         fixtures.Fixture.setUp(self)
+          ...     def _setUp(self):
           ...         self.addCleanup(lambda:1/0)
           ...         self.addCleanup(lambda:1/0)
           >>> fixture = BrokenFixture()
@@ -226,12 +224,32 @@
         
         Fixtures often expose diagnostic details that can be useful for 
tracking down
         issues. The ``getDetails`` method will return a dict of all the 
attached
-        details. Each detail object is an instance of 
``testtools.content.Content``.
+        details, but can only be called before ``cleanUp`` is called. Each 
detail
+        object is an instance of ``testtools.content.Content``.
         
           >>> with WithLog() as l:
           ...     print(l.getDetails()['message'].as_text())
           foo bar baz
         
+        Errors in setUp
+        +++++++++++++++
+        
+        The examples above used ``_setUp`` rather than ``setUp`` because the 
base
+        class implementation of ``setUp`` acts to reduce the chance of leaking
+        external resources if an error is raised from ``_setUp``. Specifically,
+        ``setUp`` contains a try:/except: block which catches all exceptions, 
captures
+        any registered detail objects, and calls ``self.cleanUp`` before 
propogating
+        the error. As long as you take care to register any cleanups before 
calling
+        the code that may fail, this will cause them to be cleaned up. The 
captured
+        detail objects are provided to the args of the raised exception.
+        
+        If the error that occured was a subclass of ``Exception`` then 
``setUp`` will
+        raise ``MultipleExceptions`` with the last element being a 
``SetupError`` that
+        contains the detail objects. Otherwise, to prevent causing normally
+        uncatchable errors like KeyboardInterrupt being caught inappropriately 
in the
+        calling layer, the original exception will be raised as-is and no 
diagnostic
+        data other than that from the original exception will be available.
+        
         Shared Dependencies
         +++++++++++++++++++
         
@@ -308,7 +326,8 @@
         
         In addition to the Fixture, FunctionFixture and MethodFixture classes 
fixtures
         includes a number of precanned fixtures. The API docs for fixtures 
will list
-        the complete set of these, should the dcs be out of date or not to 
hand.
+        the complete set of these, should the dcs be out of date or not to 
hand. For
+        the complete feature set of each fixture please see the API docs.
         
         ByteStream
         ++++++++++
@@ -348,6 +367,34 @@
           >>> from testtools.compat import BytesIO
           >>> fixture = fixtures.FakePopen(lambda _:{'stdout': 
BytesIO('foobar')})
         
+        MockPatchObject
+        +++++++++++++++
+        
+        Adapts ``mock.patch.object`` to be used as a Fixture.
+        
+          >>> class Fred:
+          ...     value = 1
+          >>> fixture = fixtures.MockPatchObject(Fred, 'value', 2)
+          >>> with fixture:
+          ...     Fred().value
+          2
+          >>> Fred().value
+          1
+        
+        MockPatch
+        +++++++++
+        
+        Adapts ``mock.patch`` to be used as a Fixture.
+        
+          >>> fixture = fixtures.MockPatch('subprocess.Popen.returncode', 3)
+        
+        MockPatchMultiple
+        +++++++++++++++++
+        
+        Adapts ``mock.patch.multiple`` to be used as a Fixture.
+        
+          >>> fixture = fixtures.MockPatch('subprocess.Popen', returncode=3)
+        
         MonkeyPatch
         +++++++++++
         
@@ -447,6 +494,13 @@
         *Note:* Currently supported only on Unix because it relies on the 
``alarm``
         system call.
         
+        Contributing
+        ============
+        
+        Fixtures has its project homepage on Launchpad
+        <https://launchpad.net/python-fixtures>. Source code is hosted on 
GitHub
+        <https://github.com/testing-cabal/fixtures>.
+        
         
 Platform: UNKNOWN
 Classifier: Development Status :: 6 - Mature
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fixtures-1.2.0/README new/fixtures-1.3.1/README
--- old/fixtures-1.2.0/README   2014-09-25 04:37:13.000000000 +0200
+++ new/fixtures-1.3.1/README   2015-06-30 02:56:38.000000000 +0200
@@ -79,19 +79,20 @@
 Creating Fixtures
 =================
 
-Minimally, subclass Fixture, define setUp to initialize your state and schedule
+Minimally, subclass Fixture, define _setUp to initialize your state and 
schedule
 a cleanup for when cleanUp is called and you're done::
 
   >>> import unittest
   >>> import fixtures
   >>> class NoddyFixture(fixtures.Fixture):
-  ...     def setUp(self):
-  ...         super(NoddyFixture, self).setUp()
+  ...     def _setUp(self):
   ...         self.frobnozzle = 42
   ...         self.addCleanup(delattr, self, 'frobnozzle')
 
-This will initialize frobnozzle when setUp is called, and when cleanUp is
-called get rid of the frobnozzle attribute.
+This will initialize frobnozzle when ``setUp`` is called, and when ``cleanUp``
+is called get rid of the frobnozzle attribute. Prior to version 1.3.0 fixtures
+recommended overriding ``setUp``. This is still supported, but since it is
+harder to write leak-free fixtures in this fashion, it is not recommended.
 
 If your fixture has diagnostic data - for instance the log file of an
 application server, or log messages, it can expose that by creating a content
@@ -99,8 +100,7 @@
 
   >>> from testtools.content import text_content
   >>> class WithLog(fixtures.Fixture):
-  ...     def setUp(self):
-  ...         super(WithLog, self).setUp()
+  ...     def _setUp(self):
   ...         self.addDetail('message', text_content('foo bar baz'))
 
 The method ``useFixture`` will use another fixture, call ``setUp`` on it, call
@@ -108,8 +108,7 @@
 the fixture. This allows simple composition of different fixtures.
 
   >>> class ReusingFixture(fixtures.Fixture):
-  ...     def setUp(self):
-  ...         super(ReusingFixture, self).setUp()
+  ...     def _setUp(self):
   ...         self.noddy = self.useFixture(NoddyFixture())
 
 There is a helper for adapting a function or function pair into Fixtures. it
@@ -154,9 +153,9 @@
 clean up after a fixture has been used, all fixtures define a ``cleanUp``
 method which should be called when a fixture is finished with.
 
-Because its nice to be able to build a particular set of related fixtures in
-advance of using them, fixtures also have define a ``setUp`` method which
-should be called before trying to use them.
+Because it's nice to be able to build a particular set of related fixtures in
+advance of using them, fixtures also have a ``setUp`` method which should be
+called before trying to use them.
 
 One common desire with fixtures that are expensive to create is to reuse them
 in many test cases; to support this the base Fixture also defines a ``reset``
@@ -203,8 +202,7 @@
   >>> import sys
   >>> from fixtures.fixture import MultipleExceptions
   >>> class BrokenFixture(fixtures.Fixture):
-  ...     def setUp(self):
-  ...         fixtures.Fixture.setUp(self)
+  ...     def _setUp(self):
   ...         self.addCleanup(lambda:1/0)
   ...         self.addCleanup(lambda:1/0)
   >>> fixture = BrokenFixture()
@@ -218,12 +216,32 @@
 
 Fixtures often expose diagnostic details that can be useful for tracking down
 issues. The ``getDetails`` method will return a dict of all the attached
-details. Each detail object is an instance of ``testtools.content.Content``.
+details, but can only be called before ``cleanUp`` is called. Each detail
+object is an instance of ``testtools.content.Content``.
 
   >>> with WithLog() as l:
   ...     print(l.getDetails()['message'].as_text())
   foo bar baz
 
+Errors in setUp
++++++++++++++++
+
+The examples above used ``_setUp`` rather than ``setUp`` because the base
+class implementation of ``setUp`` acts to reduce the chance of leaking
+external resources if an error is raised from ``_setUp``. Specifically,
+``setUp`` contains a try:/except: block which catches all exceptions, captures
+any registered detail objects, and calls ``self.cleanUp`` before propogating
+the error. As long as you take care to register any cleanups before calling
+the code that may fail, this will cause them to be cleaned up. The captured
+detail objects are provided to the args of the raised exception.
+
+If the error that occured was a subclass of ``Exception`` then ``setUp`` will
+raise ``MultipleExceptions`` with the last element being a ``SetupError`` that
+contains the detail objects. Otherwise, to prevent causing normally
+uncatchable errors like KeyboardInterrupt being caught inappropriately in the
+calling layer, the original exception will be raised as-is and no diagnostic
+data other than that from the original exception will be available.
+
 Shared Dependencies
 +++++++++++++++++++
 
@@ -300,7 +318,8 @@
 
 In addition to the Fixture, FunctionFixture and MethodFixture classes fixtures
 includes a number of precanned fixtures. The API docs for fixtures will list
-the complete set of these, should the dcs be out of date or not to hand.
+the complete set of these, should the dcs be out of date or not to hand. For
+the complete feature set of each fixture please see the API docs.
 
 ByteStream
 ++++++++++
@@ -340,6 +359,34 @@
   >>> from testtools.compat import BytesIO
   >>> fixture = fixtures.FakePopen(lambda _:{'stdout': BytesIO('foobar')})
 
+MockPatchObject
++++++++++++++++
+
+Adapts ``mock.patch.object`` to be used as a Fixture.
+
+  >>> class Fred:
+  ...     value = 1
+  >>> fixture = fixtures.MockPatchObject(Fred, 'value', 2)
+  >>> with fixture:
+  ...     Fred().value
+  2
+  >>> Fred().value
+  1
+
+MockPatch
++++++++++
+
+Adapts ``mock.patch`` to be used as a Fixture.
+
+  >>> fixture = fixtures.MockPatch('subprocess.Popen.returncode', 3)
+
+MockPatchMultiple
++++++++++++++++++
+
+Adapts ``mock.patch.multiple`` to be used as a Fixture.
+
+  >>> fixture = fixtures.MockPatch('subprocess.Popen', returncode=3)
+
 MonkeyPatch
 +++++++++++
 
@@ -438,3 +485,10 @@
 
 *Note:* Currently supported only on Unix because it relies on the ``alarm``
 system call.
+
+Contributing
+============
+
+Fixtures has its project homepage on Launchpad
+<https://launchpad.net/python-fixtures>. Source code is hosted on GitHub
+<https://github.com/testing-cabal/fixtures>.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fixtures-1.2.0/fixtures/__init__.py 
new/fixtures-1.3.1/fixtures/__init__.py
--- old/fixtures-1.2.0/fixtures/__init__.py     2015-05-04 23:49:57.000000000 
+0200
+++ new/fixtures-1.3.1/fixtures/__init__.py     2015-06-22 08:56:00.000000000 
+0200
@@ -54,12 +54,17 @@
     'LogHandler',
     'LoggerFixture',
     'MethodFixture',
+    'MockPatch',
+    'MockPatchMultiple',
+    'MockPatchObject',
     'MonkeyPatch',
+    'MultipleExceptions',
     'NestedTempfile',
     'PackagePathEntry',
     'PopenFixture',
     'PythonPackage',
     'PythonPathEntry',
+    'SetupError',
     'StringStream',
     'TempDir',
     'TempHomeDir',
@@ -76,6 +81,8 @@
     Fixture,
     FunctionFixture,
     MethodFixture,
+    MultipleExceptions,
+    SetupError,
     )
 from fixtures._fixtures import (
     ByteStream,
@@ -86,6 +93,9 @@
     FakePopen,
     LoggerFixture,
     LogHandler,
+    MockPatch,
+    MockPatchMultiple,
+    MockPatchObject,
     MonkeyPatch,
     NestedTempfile,
     PackagePathEntry,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fixtures-1.2.0/fixtures/_fixtures/__init__.py 
new/fixtures-1.3.1/fixtures/_fixtures/__init__.py
--- old/fixtures-1.2.0/fixtures/_fixtures/__init__.py   2015-05-04 
23:49:57.000000000 +0200
+++ new/fixtures-1.3.1/fixtures/_fixtures/__init__.py   2015-06-22 
02:24:03.000000000 +0200
@@ -25,6 +25,9 @@
     'FakePopen',
     'LoggerFixture',
     'LogHandler',
+    'MockPatch',
+    'MockPatchMultiple',
+    'MockPatchObject',
     'MonkeyPatch',
     'NestedTempfile',
     'PackagePathEntry',
@@ -49,6 +52,11 @@
     LoggerFixture,
     LogHandler,
     )
+from fixtures._fixtures.mockpatch import (
+    MockPatch,
+    MockPatchMultiple,
+    MockPatchObject,
+    )
 from fixtures._fixtures.monkeypatch import MonkeyPatch
 from fixtures._fixtures.popen import (
     FakePopen,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fixtures-1.2.0/fixtures/_fixtures/environ.py 
new/fixtures-1.3.1/fixtures/_fixtures/environ.py
--- old/fixtures-1.2.0/fixtures/_fixtures/environ.py    2014-09-25 
04:31:06.000000000 +0200
+++ new/fixtures-1.3.1/fixtures/_fixtures/environ.py    2015-06-22 
08:56:00.000000000 +0200
@@ -40,8 +40,7 @@
         self.varname = varname
         self.newvalue = newvalue
 
-    def setUp(self):
-        super(EnvironmentVariable, self).setUp()
+    def _setUp(self):
         varname = self.varname
         orig_value = os.environ.get(varname)
         if orig_value is not None:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fixtures-1.2.0/fixtures/_fixtures/logger.py 
new/fixtures-1.3.1/fixtures/_fixtures/logger.py
--- old/fixtures-1.2.0/fixtures/_fixtures/logger.py     2015-03-26 
21:33:59.000000000 +0100
+++ new/fixtures-1.3.1/fixtures/_fixtures/logger.py     2015-06-22 
08:56:00.000000000 +0200
@@ -46,8 +46,7 @@
         self._level = level
         self._nuke_handlers = nuke_handlers
 
-    def setUp(self):
-        super(LogHandler, self).setUp()
+    def _setUp(self):
         logger = getLogger(self._name)
         if self._level:
             self.addCleanup(logger.setLevel, logger.level)
@@ -95,8 +94,7 @@
         self._nuke_handlers = nuke_handlers
         self._formatter = formatter
 
-    def setUp(self):
-        super(FakeLogger, self).setUp()
+    def _setUp(self):
         name = _u("pythonlogging:'%s'") % self._name
         output = self.useFixture(StringStream(name)).stream
         self._output = output
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fixtures-1.2.0/fixtures/_fixtures/mockpatch.py 
new/fixtures-1.3.1/fixtures/_fixtures/mockpatch.py
--- old/fixtures-1.2.0/fixtures/_fixtures/mockpatch.py  1970-01-01 
01:00:00.000000000 +0100
+++ new/fixtures-1.3.1/fixtures/_fixtures/mockpatch.py  2015-06-22 
08:56:00.000000000 +0200
@@ -0,0 +1,71 @@
+# Copyright 2010 United States Government as represented by the
+# Administrator of the National Aeronautics and Space Administration.
+# Copyright 2013 Hewlett-Packard Development Company, L.P.
+# All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+import extras
+
+import fixtures
+
+mock = extras.try_imports(['unittest.mock', 'mock'], None)
+mock_default = extras.try_imports(
+    ['unittest.mock.DEFAULT', 'mock.DEFAULT'], None)
+
+
+class _Base(fixtures.Fixture):
+    def _setUp(self):
+        _p = self._get_p()
+        self.addCleanup(_p.stop)
+        self.mock = _p.start()
+
+
+class MockPatchObject(_Base):
+    """Deal with code around mock."""
+
+    def __init__(self, obj, attr, new=mock_default, **kwargs):
+        super(MockPatchObject, self).__init__()
+        self._get_p = lambda: mock.patch.object(obj, attr, new, **kwargs)
+
+
+class MockPatch(_Base):
+    """Deal with code around mock.patch."""
+
+    def __init__(self, obj, new=mock_default, **kwargs):
+        super(MockPatch, self).__init__()
+        self._get_p = lambda: mock.patch(obj, new, **kwargs)
+
+
+class MockPatchMultiple(_Base):
+    """Deal with code around mock.patch.multiple."""
+
+    # Default value to trigger a MagicMock to be created for a named
+    # attribute.
+    DEFAULT = mock_default
+
+    def __init__(self, obj, **kwargs):
+        """Initialize the mocks
+
+        Pass name=value to replace obj.name with value.
+
+        Pass name=Multiple.DEFAULT to replace obj.name with a
+        MagicMock instance.
+
+        :param obj: Object or name containing values being mocked.
+        :type obj: str or object
+        :param kwargs: names and values of attributes of obj to be mocked.
+
+        """
+        super(MockPatchMultiple, self).__init__()
+        self._get_p = lambda: mock.patch.multiple(obj, **kwargs)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fixtures-1.2.0/fixtures/_fixtures/monkeypatch.py 
new/fixtures-1.3.1/fixtures/_fixtures/monkeypatch.py
--- old/fixtures-1.2.0/fixtures/_fixtures/monkeypatch.py        2014-09-25 
04:31:06.000000000 +0200
+++ new/fixtures-1.3.1/fixtures/_fixtures/monkeypatch.py        2015-06-22 
08:56:00.000000000 +0200
@@ -42,8 +42,7 @@
         self.name = name
         self.new_value = new_value
     
-    def setUp(self):
-        Fixture.setUp(self)
+    def _setUp(self):
         location, attribute = self.name.rsplit('.', 1)
         # Import, swallowing all errors as any element of location may be
         # a class or some such thing.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fixtures-1.2.0/fixtures/_fixtures/packagepath.py 
new/fixtures-1.3.1/fixtures/_fixtures/packagepath.py
--- old/fixtures-1.2.0/fixtures/_fixtures/packagepath.py        2014-09-25 
04:31:06.000000000 +0200
+++ new/fixtures-1.3.1/fixtures/_fixtures/packagepath.py        2015-06-22 
08:56:00.000000000 +0200
@@ -39,8 +39,7 @@
         self.packagename = packagename
         self.directory = directory
 
-    def setUp(self):
-        Fixture.setUp(self)
+    def _setUp(self):
         path = sys.modules[self.packagename].__path__
         if self.directory in path:
             return
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fixtures-1.2.0/fixtures/_fixtures/popen.py 
new/fixtures-1.3.1/fixtures/_fixtures/popen.py
--- old/fixtures-1.2.0/fixtures/_fixtures/popen.py      2014-09-25 
04:31:06.000000000 +0200
+++ new/fixtures-1.3.1/fixtures/_fixtures/popen.py      2015-06-22 
08:56:00.000000000 +0200
@@ -95,8 +95,7 @@
         super(FakePopen, self).__init__()
         self.get_info = get_info
 
-    def setUp(self):
-        super(FakePopen, self).setUp()
+    def _setUp(self):
         self.addCleanup(setattr, subprocess, 'Popen', subprocess.Popen)
         subprocess.Popen = self
         self.procs = []
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fixtures-1.2.0/fixtures/_fixtures/pythonpackage.py 
new/fixtures-1.3.1/fixtures/_fixtures/pythonpackage.py
--- old/fixtures-1.2.0/fixtures/_fixtures/pythonpackage.py      2014-09-25 
04:31:06.000000000 +0200
+++ new/fixtures-1.3.1/fixtures/_fixtures/pythonpackage.py      2015-06-22 
08:56:00.000000000 +0200
@@ -47,8 +47,7 @@
         self.modulelist = modulelist
         self.init = init
 
-    def setUp(self):
-        Fixture.setUp(self)
+    def _setUp(self):
         self.base = self.useFixture(TempDir()).path
         base = self.base
         root = os.path.join(base, self.packagename)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fixtures-1.2.0/fixtures/_fixtures/pythonpath.py 
new/fixtures-1.3.1/fixtures/_fixtures/pythonpath.py
--- old/fixtures-1.2.0/fixtures/_fixtures/pythonpath.py 2014-09-25 
04:31:06.000000000 +0200
+++ new/fixtures-1.3.1/fixtures/_fixtures/pythonpath.py 2015-06-22 
08:56:00.000000000 +0200
@@ -35,8 +35,7 @@
         """
         self.directory = directory
 
-    def setUp(self):
-        Fixture.setUp(self)
+    def _setUp(self):
         if self.directory in sys.path:
             return
         self.addCleanup(sys.path.remove, self.directory)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fixtures-1.2.0/fixtures/_fixtures/streams.py 
new/fixtures-1.3.1/fixtures/_fixtures/streams.py
--- old/fixtures-1.2.0/fixtures/_fixtures/streams.py    2014-09-25 
04:31:06.000000000 +0200
+++ new/fixtures-1.3.1/fixtures/_fixtures/streams.py    2015-06-22 
08:56:00.000000000 +0200
@@ -42,8 +42,7 @@
         self._detail_name = detail_name
         self._stream_factory = stream_factory
 
-    def setUp(self):
-        super(Stream, self).setUp()
+    def _setUp(self):
         write_stream, read_stream = self._stream_factory()
         self.stream = write_stream
         self.addDetail(self._detail_name,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fixtures-1.2.0/fixtures/_fixtures/tempdir.py 
new/fixtures-1.3.1/fixtures/_fixtures/tempdir.py
--- old/fixtures-1.2.0/fixtures/_fixtures/tempdir.py    2014-09-25 
04:31:06.000000000 +0200
+++ new/fixtures-1.3.1/fixtures/_fixtures/tempdir.py    2015-06-22 
08:56:00.000000000 +0200
@@ -39,8 +39,7 @@
         """
         self.rootdir = rootdir
 
-    def setUp(self):
-        super(TempDir, self).setUp()
+    def _setUp(self):
         self.path = tempfile.mkdtemp(dir=self.rootdir)
         self.addCleanup(shutil.rmtree, self.path, ignore_errors=True)
 
@@ -63,8 +62,7 @@
     down.
     """
 
-    def setUp(self):
-        super(NestedTempfile, self).setUp()
+    def _setUp(self):
         tempdir = self.useFixture(TempDir()).path
         patch = fixtures.MonkeyPatch("tempfile.tempdir", tempdir)
         self.useFixture(patch)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fixtures-1.2.0/fixtures/_fixtures/temphomedir.py 
new/fixtures-1.3.1/fixtures/_fixtures/temphomedir.py
--- old/fixtures-1.2.0/fixtures/_fixtures/temphomedir.py        2014-09-25 
04:31:06.000000000 +0200
+++ new/fixtures-1.3.1/fixtures/_fixtures/temphomedir.py        2015-06-22 
08:56:00.000000000 +0200
@@ -27,6 +27,6 @@
     :ivar path: the path of the temporary directory.
     """
 
-    def setUp(self):
-        super(TempHomeDir, self).setUp()
+    def _setUp(self):
+        super(TempHomeDir, self)._setUp()
         self.useFixture(fixtures.EnvironmentVariable("HOME", self.path))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fixtures-1.2.0/fixtures/_fixtures/timeout.py 
new/fixtures-1.3.1/fixtures/_fixtures/timeout.py
--- old/fixtures-1.2.0/fixtures/_fixtures/timeout.py    2014-09-25 
04:31:06.000000000 +0200
+++ new/fixtures-1.3.1/fixtures/_fixtures/timeout.py    2015-06-22 
08:56:00.000000000 +0200
@@ -51,8 +51,7 @@
     def signal_handler(self, signum, frame):
         raise TimeoutException()
 
-    def setUp(self):
-        super(Timeout, self).setUp()
+    def _setUp(self):
         if self.alarm_fn is None:
             return  # Can't run on Windows
         if self.gentle:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fixtures-1.2.0/fixtures/_fixtures/warnings.py 
new/fixtures-1.3.1/fixtures/_fixtures/warnings.py
--- old/fixtures-1.2.0/fixtures/_fixtures/warnings.py   2015-05-04 
23:49:57.000000000 +0200
+++ new/fixtures-1.3.1/fixtures/_fixtures/warnings.py   2015-06-22 
08:56:00.000000000 +0200
@@ -34,8 +34,7 @@
     def _showwarning(self, *args, **kwargs):
         self.captures.append(warnings.WarningMessage(*args, **kwargs))
 
-    def setUp(self):
-        super(WarningsCapture, self).setUp()
+    def _setUp(self):
         patch = fixtures.MonkeyPatch("warnings.showwarning", self._showwarning)
         self.useFixture(patch)
         self.captures = []
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fixtures-1.2.0/fixtures/fixture.py 
new/fixtures-1.3.1/fixtures/fixture.py
--- old/fixtures-1.2.0/fixtures/fixture.py      2014-09-25 04:31:06.000000000 
+0200
+++ new/fixtures-1.3.1/fixtures/fixture.py      2015-06-30 03:01:38.000000000 
+0200
@@ -18,11 +18,13 @@
     'FunctionFixture',
     'MethodFixture',
     'MultipleExceptions',
+    'SetupError',
     ]
 
 import itertools
 import sys
 
+import six
 from testtools.compat import (
     advance_iterator,
     reraise,
@@ -49,6 +51,13 @@
         target_details[name] = content_object
 
 
+class SetupError(Exception):
+    """Setup failed.
+
+    args[0] will be a details dict.
+    """
+
+
 class Fixture(object):
     """A Fixture representing some state or resource.
 
@@ -97,6 +106,10 @@
 
         This should not typically be overridden, see addCleanup instead.
 
+        cleanUp may be called once and only once after setUp() has been called.
+        The base implementation of setUp will automatically call cleanUp if
+        an exception occurs within setUp itself.
+
         :param raise_first: Deprecated parameter from before testtools gained
             MultipleExceptions. raise_first defaults to True. When True
             if a single exception is raised, it is reraised after all the
@@ -111,7 +124,7 @@
         try:
             return self._cleanups(raise_errors=raise_first)
         finally:
-            self._clear_cleanups()
+            self._remove_state()
 
     def _clear_cleanups(self):
         """Clean the cleanup queue without running them.
@@ -126,6 +139,15 @@
         self._details = {}
         self._detail_sources = []
 
+    def _remove_state(self):
+        """Remove the internal state.
+
+        Called from cleanUp to put the fixture back into a not-ready state.
+        """
+        self._cleanups = None
+        self._details = None
+        self._detail_sources = None
+
     def __enter__(self):
         self.setUp()
         return self
@@ -134,7 +156,7 @@
         try:
             self._cleanups()
         finally:
-            self._clear_cleanups()
+            self._remove_state()
         return False # propogate exceptions from the with body.
 
     def getDetails(self):
@@ -153,16 +175,56 @@
     def setUp(self):
         """Prepare the Fixture for use.
 
-        This should be overridden by most concrete fixtures. When overriding
-        be sure to include self.addCleanup calls to restore the fixture to
-        an un-setUp state, so that a single Fixture instance can be reused.
+        This should not be overridden. Concrete fixtures should implement
+        _setUp. Overriding of setUp is still supported, just not recommended.
 
-        After setUp is called, the fixture will have one or more attributes
+        After setUp has completed, the fixture will have one or more attributes
         which can be used (these depend totally on the concrete subclass).
 
+        :raises: MultipleExceptions if _setUp fails. The last exception
+            captured within the MultipleExceptions will be a SetupError
+            exception.
         :return: None.
+
+        :changed in 1.3: The recommendation to override setUp has been
+            reversed - before 1.3, setUp() should be overridden, now it should
+            not be.
+        :changed in 1.3.1: BaseException is now caught, and only subclasses of
+            Exception are wrapped in MultipleExceptions.
         """
         self._clear_cleanups()
+        try:
+            self._setUp()
+        except:
+            err = sys.exc_info()
+            details = {}
+            if gather_details is not None:
+                # Materialise all details since we're about to cleanup.
+                gather_details(self.getDetails(), details)
+            else:
+                details = self.getDetails()
+            errors = [err] + self.cleanUp(raise_first=False)
+            try:
+                raise SetupError(details)
+            except SetupError as e:
+                errors.append(sys.exc_info())
+            if issubclass(err[0], Exception):
+                raise MultipleExceptions(*errors)
+            else:
+                six.reraise(*err)
+
+    def _setUp(self):
+        """Template method for subclasses to override.
+
+        Override this to customise the fixture. When overriding
+        be sure to include self.addCleanup calls to restore the fixture to
+        an un-setUp state, so that a single Fixture instance can be reused.
+
+        Fixtures will never have a body in _setUp - calling super() is
+        entirely at the discretion of subclasses.
+
+        :return: None.
+        """
 
     def reset(self):
         """Reset a setUp Fixture to the 'just setUp' state again.
@@ -183,15 +245,23 @@
         """Use another fixture.
 
         The fixture will be setUp, and self.addCleanup(fixture.cleanUp) called.
+        If the fixture fails to set up, useFixture will attempt to gather its
+        details into this fixture's details to aid in debugging.
 
         :param fixture: The fixture to use.
         :return: The fixture, after setting it up and scheduling a cleanup for
            it.
+        :raises: Any errors raised by the fixture's setUp method.
         """
         try:
             fixture.setUp()
+        except MultipleExceptions as e:
+            if e.args[-1][0] is SetupError:
+                combine_details(e.args[-1][1].args[0], self._details)
+            raise
         except:
-            # The child failed to come up, capture any details it has (copying
+            # The child failed to come up and didn't raise MultipleExceptions
+            # which we can understand... capture any details it has (copying
             # the content, it may go away anytime).
             if gather_details is not None:
                 gather_details(fixture.getDetails(), self._details)
@@ -249,8 +319,7 @@
         self.cleanup_fn = cleanup_fn
         self.reset_fn = reset_fn
 
-    def setUp(self):
-        super(FunctionFixture, self).setUp()
+    def _setUp(self):
         fn_result = self.setup_fn()
         self._maybe_cleanup(fn_result)
 
@@ -323,8 +392,7 @@
             reset = getattr(obj, 'reset', None)
         self._reset = reset
 
-    def setUp(self):
-        super(MethodFixture, self).setUp()
+    def _setUp(self):
         self._setup()
 
     def cleanUp(self):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fixtures-1.2.0/fixtures/tests/_fixtures/__init__.py 
new/fixtures-1.3.1/fixtures/tests/_fixtures/__init__.py
--- old/fixtures-1.2.0/fixtures/tests/_fixtures/__init__.py     2015-03-26 
03:46:21.000000000 +0100
+++ new/fixtures-1.3.1/fixtures/tests/_fixtures/__init__.py     2015-06-22 
02:24:03.000000000 +0200
@@ -17,6 +17,7 @@
     test_modules = [
         'environ',
         'logger',
+        'mockpatch',
         'monkeypatch',
         'packagepath',
         'popen',
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/fixtures-1.2.0/fixtures/tests/_fixtures/test_mockpatch.py 
new/fixtures-1.3.1/fixtures/tests/_fixtures/test_mockpatch.py
--- old/fixtures-1.2.0/fixtures/tests/_fixtures/test_mockpatch.py       
1970-01-01 01:00:00.000000000 +0100
+++ new/fixtures-1.3.1/fixtures/tests/_fixtures/test_mockpatch.py       
2015-06-22 02:24:03.000000000 +0200
@@ -0,0 +1,72 @@
+# Copyright 2014 IBM Corp.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+
+import extras
+mock = extras.try_imports(['unittest.mock', 'mock'], None)
+import testtools
+
+from fixtures import (
+    MockPatch,
+    MockPatchMultiple,
+    MockPatchObject,
+)
+
+
+class Foo(object):
+    def bar(self):
+        return self
+
+
+def mocking_bar(self):
+    return 'mocked!'
+
+
+class TestMockPatch(testtools.TestCase):
+    def test_mock_patch_with_replacement(self):
+        self.useFixture(MockPatch('%s.Foo.bar' % (__name__), mocking_bar))
+        instance = Foo()
+        self.assertEqual(instance.bar(), 'mocked!')
+
+    def test_mock_patch_without_replacement(self):
+        self.useFixture(MockPatch('%s.Foo.bar' % (__name__)))
+        instance = Foo()
+        self.assertIsInstance(instance.bar(), mock.MagicMock)
+
+
+class TestMockMultiple(testtools.TestCase):
+    def test_mock_multiple_with_replacement(self):
+        self.useFixture(MockPatchMultiple('%s.Foo' % (__name__),
+                                          bar=mocking_bar))
+        instance = Foo()
+        self.assertEqual(instance.bar(), 'mocked!')
+
+    def test_mock_patch_without_replacement(self):
+        self.useFixture(MockPatchMultiple(
+            '%s.Foo' % (__name__),
+            bar=MockPatchMultiple.DEFAULT))
+        instance = Foo()
+        self.assertIsInstance(instance.bar(), mock.MagicMock)
+
+
+class TestMockPatchObject(testtools.TestCase):
+    def test_mock_patch_object_with_replacement(self):
+        self.useFixture(MockPatchObject(Foo, 'bar', mocking_bar))
+        instance = Foo()
+        self.assertEqual(instance.bar(), 'mocked!')
+
+    def test_mock_patch_object_without_replacement(self):
+        self.useFixture(MockPatchObject(Foo, 'bar'))
+        instance = Foo()
+        self.assertIsInstance(instance.bar(), mock.MagicMock)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fixtures-1.2.0/fixtures/tests/test_fixture.py 
new/fixtures-1.3.1/fixtures/tests/test_fixture.py
--- old/fixtures-1.2.0/fixtures/tests/test_fixture.py   2014-09-25 
04:31:06.000000000 +0200
+++ new/fixtures-1.3.1/fixtures/tests/test_fixture.py   2015-06-30 
02:51:08.000000000 +0200
@@ -122,7 +122,7 @@
     @require_gather_details
     def test_useFixture_details_captured_from_setUp(self):
         # Details added during fixture set-up are gathered even if setUp()
-        # fails with an exception.
+        # fails with an unknown exception.
         class SomethingBroke(Exception): pass
         class BrokenFixture(fixtures.Fixture):
             def setUp(self):
@@ -143,6 +143,24 @@
             {"content": text_content("foobar")},
             simple_fixture.getDetails())
 
+    @require_gather_details
+    def test_useFixture_details_captured_from_setUp_MultipleExceptions(self):
+        # Details added during fixture set-up are gathered even if setUp()
+        # fails with (cleanly - with MultipleExceptions / SetupError).
+        class SomethingBroke(Exception): pass
+        class BrokenFixture(fixtures.Fixture):
+            def _setUp(self):
+                self.addDetail('content', text_content("foobar"))
+                raise SomethingBroke()
+        class SimpleFixture(fixtures.Fixture):
+            def _setUp(self):
+                self.useFixture(BrokenFixture())
+        simple = SimpleFixture()
+        e = self.assertRaises(fixtures.MultipleExceptions, simple.setUp)
+        self.assertEqual(
+            {"content": text_content("foobar")},
+            e.args[-1][1].args[0])
+
     def test_getDetails(self):
         fixture = fixtures.Fixture()
         with fixture:
@@ -162,7 +180,7 @@
             self.assertEqual({}, parent.getDetails())
             # After cleanup the child details are still gone.
             child.addDetail('foo', 'content')
-        self.assertEqual({}, parent.getDetails())
+        self.assertRaises(TypeError, parent.getDetails)
 
     def test_duplicate_details_are_disambiguated(self):
         parent = fixtures.Fixture()
@@ -185,7 +203,74 @@
             self.assertEqual({}, fixture.getDetails())
             fixture.addDetail('foo', 'content')
         # Cleanup clears the details too.
-        self.assertEqual({}, fixture.getDetails())
+        self.assertRaises(TypeError, fixture.getDetails)
+
+    def test_setUp_subclassed(self):
+        # Even though its no longer recommended, we need to be sure that
+        # overriding setUp and calling super().setUp still works.
+        class Subclass(fixtures.Fixture):
+            def setUp(self):
+                super(Subclass, self).setUp()
+                self.fred = 1
+                self.addCleanup(setattr, self, 'fred', 2)
+        with Subclass() as f:
+            self.assertEqual(1, f.fred)
+        self.assertEqual(2, f.fred)
+
+    def test__setUp(self):
+        # _setUp is called, and cleanups can be registered by it.
+        class Subclass(fixtures.Fixture):
+            def _setUp(self):
+                self.fred = 1
+                self.addCleanup(setattr, self, 'fred', 2)
+        with Subclass() as f:
+            self.assertEqual(1, f.fred)
+        self.assertEqual(2, f.fred)
+
+    def test__setUp_fails(self):
+        # when _setUp fails, the fixture is left ready-to-setUp, and any
+        # details added during _setUp are captured.
+        class Subclass(fixtures.Fixture):
+            def _setUp(self):
+                self.addDetail('log', text_content('stuff'))
+                1/0
+        f = Subclass()
+        e = self.assertRaises(fixtures.MultipleExceptions, f.setUp)
+        self.assertRaises(TypeError, f.cleanUp)
+        self.assertIsInstance(e.args[0][1], ZeroDivisionError)
+        self.assertIsInstance(e.args[1][1], fixtures.SetupError)
+        self.assertEqual('stuff', e.args[1][1].args[0]['log'].as_text())
+
+    def test__setUp_fails_cleanUp_fails(self):
+        # when _setUp fails, cleanups are called, and their failure is captured
+        # into the MultipleExceptions instance.
+        class Subclass(fixtures.Fixture):
+            def _setUp(self):
+                self.addDetail('log', text_content('stuff'))
+                self.addCleanup(lambda: 1/0)
+                raise Exception('fred')
+        f = Subclass()
+        e = self.assertRaises(fixtures.MultipleExceptions, f.setUp)
+        self.assertRaises(TypeError, f.cleanUp)
+        self.assertEqual(Exception, e.args[0][0])
+        self.assertEqual(ZeroDivisionError, e.args[1][0])
+        self.assertEqual(fixtures.SetupError, e.args[2][0])
+        self.assertEqual('stuff', e.args[2][1].args[0]['log'].as_text())
+
+    def test_setup_failures_with_base_exception(self):
+        # when _setUp fails with a BaseException (or subclass thereof) that
+        # exception is propogated as is, but we still call cleanups etc.
+        class MyBase(BaseException):pass
+        log = []
+        class Subclass(fixtures.Fixture):
+            def _setUp(self):
+                self.addDetail('log', text_content('stuff'))
+                self.addCleanup(log.append, 'cleaned')
+                raise MyBase('fred')
+        f = Subclass()
+        e = self.assertRaises(MyBase, f.setUp)
+        self.assertRaises(TypeError, f.cleanUp)
+        self.assertEqual(['cleaned'], log)
 
 
 class TestFunctionFixture(testtools.TestCase):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fixtures-1.2.0/fixtures.egg-info/PKG-INFO 
new/fixtures-1.3.1/fixtures.egg-info/PKG-INFO
--- old/fixtures-1.2.0/fixtures.egg-info/PKG-INFO       2015-05-05 
00:14:19.000000000 +0200
+++ new/fixtures-1.3.1/fixtures.egg-info/PKG-INFO       2015-06-30 
04:22:04.000000000 +0200
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: fixtures
-Version: 1.2.0
+Version: 1.3.1
 Summary: Fixtures, reusable state for writing clean tests and more.
 Home-page: https://launchpad.net/python-fixtures
 Author: Robert Collins
@@ -87,19 +87,20 @@
         Creating Fixtures
         =================
         
-        Minimally, subclass Fixture, define setUp to initialize your state and 
schedule
+        Minimally, subclass Fixture, define _setUp to initialize your state 
and schedule
         a cleanup for when cleanUp is called and you're done::
         
           >>> import unittest
           >>> import fixtures
           >>> class NoddyFixture(fixtures.Fixture):
-          ...     def setUp(self):
-          ...         super(NoddyFixture, self).setUp()
+          ...     def _setUp(self):
           ...         self.frobnozzle = 42
           ...         self.addCleanup(delattr, self, 'frobnozzle')
         
-        This will initialize frobnozzle when setUp is called, and when cleanUp 
is
-        called get rid of the frobnozzle attribute.
+        This will initialize frobnozzle when ``setUp`` is called, and when 
``cleanUp``
+        is called get rid of the frobnozzle attribute. Prior to version 1.3.0 
fixtures
+        recommended overriding ``setUp``. This is still supported, but since 
it is
+        harder to write leak-free fixtures in this fashion, it is not 
recommended.
         
         If your fixture has diagnostic data - for instance the log file of an
         application server, or log messages, it can expose that by creating a 
content
@@ -107,8 +108,7 @@
         
           >>> from testtools.content import text_content
           >>> class WithLog(fixtures.Fixture):
-          ...     def setUp(self):
-          ...         super(WithLog, self).setUp()
+          ...     def _setUp(self):
           ...         self.addDetail('message', text_content('foo bar baz'))
         
         The method ``useFixture`` will use another fixture, call ``setUp`` on 
it, call
@@ -116,8 +116,7 @@
         the fixture. This allows simple composition of different fixtures.
         
           >>> class ReusingFixture(fixtures.Fixture):
-          ...     def setUp(self):
-          ...         super(ReusingFixture, self).setUp()
+          ...     def _setUp(self):
           ...         self.noddy = self.useFixture(NoddyFixture())
         
         There is a helper for adapting a function or function pair into 
Fixtures. it
@@ -162,9 +161,9 @@
         clean up after a fixture has been used, all fixtures define a 
``cleanUp``
         method which should be called when a fixture is finished with.
         
-        Because its nice to be able to build a particular set of related 
fixtures in
-        advance of using them, fixtures also have define a ``setUp`` method 
which
-        should be called before trying to use them.
+        Because it's nice to be able to build a particular set of related 
fixtures in
+        advance of using them, fixtures also have a ``setUp`` method which 
should be
+        called before trying to use them.
         
         One common desire with fixtures that are expensive to create is to 
reuse them
         in many test cases; to support this the base Fixture also defines a 
``reset``
@@ -211,8 +210,7 @@
           >>> import sys
           >>> from fixtures.fixture import MultipleExceptions
           >>> class BrokenFixture(fixtures.Fixture):
-          ...     def setUp(self):
-          ...         fixtures.Fixture.setUp(self)
+          ...     def _setUp(self):
           ...         self.addCleanup(lambda:1/0)
           ...         self.addCleanup(lambda:1/0)
           >>> fixture = BrokenFixture()
@@ -226,12 +224,32 @@
         
         Fixtures often expose diagnostic details that can be useful for 
tracking down
         issues. The ``getDetails`` method will return a dict of all the 
attached
-        details. Each detail object is an instance of 
``testtools.content.Content``.
+        details, but can only be called before ``cleanUp`` is called. Each 
detail
+        object is an instance of ``testtools.content.Content``.
         
           >>> with WithLog() as l:
           ...     print(l.getDetails()['message'].as_text())
           foo bar baz
         
+        Errors in setUp
+        +++++++++++++++
+        
+        The examples above used ``_setUp`` rather than ``setUp`` because the 
base
+        class implementation of ``setUp`` acts to reduce the chance of leaking
+        external resources if an error is raised from ``_setUp``. Specifically,
+        ``setUp`` contains a try:/except: block which catches all exceptions, 
captures
+        any registered detail objects, and calls ``self.cleanUp`` before 
propogating
+        the error. As long as you take care to register any cleanups before 
calling
+        the code that may fail, this will cause them to be cleaned up. The 
captured
+        detail objects are provided to the args of the raised exception.
+        
+        If the error that occured was a subclass of ``Exception`` then 
``setUp`` will
+        raise ``MultipleExceptions`` with the last element being a 
``SetupError`` that
+        contains the detail objects. Otherwise, to prevent causing normally
+        uncatchable errors like KeyboardInterrupt being caught inappropriately 
in the
+        calling layer, the original exception will be raised as-is and no 
diagnostic
+        data other than that from the original exception will be available.
+        
         Shared Dependencies
         +++++++++++++++++++
         
@@ -308,7 +326,8 @@
         
         In addition to the Fixture, FunctionFixture and MethodFixture classes 
fixtures
         includes a number of precanned fixtures. The API docs for fixtures 
will list
-        the complete set of these, should the dcs be out of date or not to 
hand.
+        the complete set of these, should the dcs be out of date or not to 
hand. For
+        the complete feature set of each fixture please see the API docs.
         
         ByteStream
         ++++++++++
@@ -348,6 +367,34 @@
           >>> from testtools.compat import BytesIO
           >>> fixture = fixtures.FakePopen(lambda _:{'stdout': 
BytesIO('foobar')})
         
+        MockPatchObject
+        +++++++++++++++
+        
+        Adapts ``mock.patch.object`` to be used as a Fixture.
+        
+          >>> class Fred:
+          ...     value = 1
+          >>> fixture = fixtures.MockPatchObject(Fred, 'value', 2)
+          >>> with fixture:
+          ...     Fred().value
+          2
+          >>> Fred().value
+          1
+        
+        MockPatch
+        +++++++++
+        
+        Adapts ``mock.patch`` to be used as a Fixture.
+        
+          >>> fixture = fixtures.MockPatch('subprocess.Popen.returncode', 3)
+        
+        MockPatchMultiple
+        +++++++++++++++++
+        
+        Adapts ``mock.patch.multiple`` to be used as a Fixture.
+        
+          >>> fixture = fixtures.MockPatch('subprocess.Popen', returncode=3)
+        
         MonkeyPatch
         +++++++++++
         
@@ -447,6 +494,13 @@
         *Note:* Currently supported only on Unix because it relies on the 
``alarm``
         system call.
         
+        Contributing
+        ============
+        
+        Fixtures has its project homepage on Launchpad
+        <https://launchpad.net/python-fixtures>. Source code is hosted on 
GitHub
+        <https://github.com/testing-cabal/fixtures>.
+        
         
 Platform: UNKNOWN
 Classifier: Development Status :: 6 - Mature
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fixtures-1.2.0/fixtures.egg-info/SOURCES.txt 
new/fixtures-1.3.1/fixtures.egg-info/SOURCES.txt
--- old/fixtures-1.2.0/fixtures.egg-info/SOURCES.txt    2015-05-05 
00:14:19.000000000 +0200
+++ new/fixtures-1.3.1/fixtures.egg-info/SOURCES.txt    2015-06-30 
04:22:04.000000000 +0200
@@ -13,6 +13,7 @@
 requirements.txt
 setup.cfg
 setup.py
+test-requirements.txt
 tox.ini
 fixtures/__init__.py
 fixtures/callmany.py
@@ -28,6 +29,7 @@
 fixtures/_fixtures/__init__.py
 fixtures/_fixtures/environ.py
 fixtures/_fixtures/logger.py
+fixtures/_fixtures/mockpatch.py
 fixtures/_fixtures/monkeypatch.py
 fixtures/_fixtures/packagepath.py
 fixtures/_fixtures/popen.py
@@ -46,6 +48,7 @@
 fixtures/tests/_fixtures/__init__.py
 fixtures/tests/_fixtures/test_environ.py
 fixtures/tests/_fixtures/test_logger.py
+fixtures/tests/_fixtures/test_mockpatch.py
 fixtures/tests/_fixtures/test_monkeypatch.py
 fixtures/tests/_fixtures/test_packagepath.py
 fixtures/tests/_fixtures/test_popen.py
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fixtures-1.2.0/fixtures.egg-info/pbr.json 
new/fixtures-1.3.1/fixtures.egg-info/pbr.json
--- old/fixtures-1.2.0/fixtures.egg-info/pbr.json       2015-05-05 
00:14:19.000000000 +0200
+++ new/fixtures-1.3.1/fixtures.egg-info/pbr.json       2015-06-30 
04:22:04.000000000 +0200
@@ -1 +1 @@
-{"is_release": true, "git_version": "f7502e8"}
\ No newline at end of file
+{"is_release": true, "git_version": "09afde5"}
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fixtures-1.2.0/fixtures.egg-info/requires.txt 
new/fixtures-1.3.1/fixtures.egg-info/requires.txt
--- old/fixtures-1.2.0/fixtures.egg-info/requires.txt   2015-05-05 
00:14:19.000000000 +0200
+++ new/fixtures-1.3.1/fixtures.egg-info/requires.txt   2015-06-30 
04:22:04.000000000 +0200
@@ -1,2 +1,3 @@
 pbr>=0.11
+six
 testtools>=0.9.22
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fixtures-1.2.0/requirements.txt 
new/fixtures-1.3.1/requirements.txt
--- old/fixtures-1.2.0/requirements.txt 2015-05-04 06:04:12.000000000 +0200
+++ new/fixtures-1.3.1/requirements.txt 2015-06-30 02:52:47.000000000 +0200
@@ -1,2 +1,3 @@
 pbr>=0.11
+six
 testtools>=0.9.22
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fixtures-1.2.0/test-requirements.txt 
new/fixtures-1.3.1/test-requirements.txt
--- old/fixtures-1.2.0/test-requirements.txt    1970-01-01 01:00:00.000000000 
+0100
+++ new/fixtures-1.3.1/test-requirements.txt    2015-06-22 02:24:03.000000000 
+0200
@@ -0,0 +1 @@
+mock;python_version<'3.3'


Reply via email to