text: # 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.
  
  # Note that the unit_tests/__init__.py also mocks out two charmhelpers imports
  # that have side effects that try to apt install modules:
  # sys.modules['charmhelpers.contrib.openstack.utils'] = mock.MagicMock()
  # sys.modules['charmhelpers.contrib.network.ip'] = mock.MagicMock()
  
  import contextlib
  import io
  from unittest import mock
  import unittest
  
  
  @contextlib.contextmanager
  def patch_open():
      '''Patch open() to allow mocking both open() itself and the file that is
      yielded.
  
      Yields the mock for "open" and "file", respectively.'''
      mock_open = mock.MagicMock(spec=open)
      mock_file = mock.MagicMock(spec=io.FileIO)
  
      @contextlib.contextmanager
      def stub_open(*args, **kwargs):
          mock_open(*args, **kwargs)
          yield mock_file
  
      with mock.patch('builtins.open', stub_open):
          yield mock_open, mock_file
  
  
  class BaseTestCase(unittest.TestCase):
  
      def setUp(self):
          self._patches = {}
          self._patches_start = {}
  
      def tearDown(self):
          for k, v in self._patches.items():
              v.stop()
              setattr(self, k, None)
          self._patches = None
          self._patches_start = None
  
      def patch_object(self, obj, attr, return_value=None, name=None, new=None,
                       **kwargs):
          if name is None:
              name = attr
          if new is not None:
              mocked = mock.patch.object(obj, attr, new=new, **kwargs)
          else:
              mocked = mock.patch.object(obj, attr, **kwargs)
          self._patches[name] = mocked
          started = mocked.start()
          if new is None:
              started.return_value = return_value
          self._patches_start[name] = started
          setattr(self, name, started)
  
      def patch(self, item, return_value=None, name=None, new=None, **kwargs):
          if name is None:
              raise RuntimeError("Must pass 'name' to .patch()")
          if new is not None:
              mocked = mock.patch(item, new=new, **kwargs)
          else:
              mocked = mock.patch(item, **kwargs)
          self._patches[name] = mocked
          started = mocked.start()
          if new is None:
              started.return_value = return_value
          self._patches_start[name] = started
          setattr(self, name, started)
  