def start(self):
        assert not self.active

        try:
            # Apply the RabbitMQ virtual host patch
            self._vhostPatch = RabbitmqVirtualHostPatch(
                clientLabel=self._clientLabel, kw=None, logger=self._logger)
            self._vhostPatch.start()
            # Apply Model Checkpoint Manager patch
            self._modelCheckpointPatch = ModelCheckpointStoragePatch(
                kw=None, logger=self._logger)
            self._modelCheckpointPatch.start()

            # Self-validation
            actualVhost = (
                amqp.connection.getRabbitmqConnectionParameters().vhost)
            assert actualVhost == self._vhostPatch._vhost, (
                "Expected vhost=%r, but got vhost=%r") % (self._vhost,
                                                          actualVhost)
        except Exception:
            self._logger.exception("patch failed, removing sub-patches")
            self._removePatches()
            raise

        self.active = True
        self._logger.info("%s: applied patch", self.__class__.__name__)
  def start(self):
    assert not self.active

    try:
      # Apply the RabbitMQ virtual host patch
      self._vhostPatch = RabbitmqVirtualHostPatch(clientLabel=self._clientLabel,
                                                  kw=None, logger=self._logger)
      self._vhostPatch.start()
      # Apply Model Checkpoint Manager patch
      self._modelCheckpointPatch = ModelCheckpointStoragePatch(
        kw=None, logger=self._logger)
      self._modelCheckpointPatch.start()

      # Self-validation
      actualVhost = (
          amqp.connection.getRabbitmqConnectionParameters().vhost)
      assert actualVhost == self._vhostPatch._vhost, (
        "Expected vhost=%r, but got vhost=%r") % (
        self._vhost, actualVhost)
    except Exception:
      self._logger.exception("patch failed, removing sub-patches")
      self._removePatches()
      raise

    self.active = True
    self._logger.info("%s: applied patch", self.__class__.__name__)
class ModelSwapperIsolationPatch(object):
    """ An instance of this class may be used as a decorator, class decorator or
  Context Manager for redirecting ModelSwapperInterface input, result and
  notification endpoints as well as model checkpoints both in-proc and in
  subprocesses. Deletes the redirected endpoints and model checkpoints on stop.
  """
    def __init__(self, clientLabel, kw=None, logger=logging):
        """
    clientLabel: this string will be used to construct the temporary endpoint
      names. The following characters are permitted, and it shouldn't be too
      long: [._a-zA-Z]. This may be helpful with diagnostics. A specific test
      class name (or similar) would make a reasonable clientLabel.
    kw: name of keyword argument to add to the decorated function(s). Its value
      will be a reference to this instance of ModelSwapperIsolationPatch.
      Ignored when this instance is used as context manager. Defaults to kw=None
      to avoid having it added to the keyword args.
    """
        self.active = False
        """ True when applied successfully; False after successfully removed or not
    applied """

        self._clientLabel = clientLabel
        self._kw = kw
        self._logger = logger

        self._vhostPatch = None
        """ RabbitMQ virtual host patch """

        self._modelCheckpointPatch = None
        """ Model checkpoint storage patch """

    def __enter__(self):
        self.start()
        return self

    def __exit__(self, *args):
        self.stop()
        return False

    def __call__(self, f):
        """ Implement the function or class decorator """
        if isinstance(f, types.TypeType):
            return self._decorateClass(f)

        @functools.wraps(f)
        def applyModelSwapperIsolationPatch(*args, **kwargs):
            self.start()
            try:
                if self._kw is not None:
                    kwargs[self._kw] = self
                return f(*args, **kwargs)
            finally:
                self.stop()

        return applyModelSwapperIsolationPatch

    def _decorateClass(self, targetClass):
        """ Decorate the test methods in the given class. Honors
    `mock.patch.TEST_PREFIX` for choosing which methods to wrap
    """
        for attrName in dir(targetClass):
            if attrName.startswith(patch.TEST_PREFIX):
                f = getattr(targetClass, attrName)
                if callable(f):
                    decoratedFunc = ModelSwapperIsolationPatch(
                        self._clientLabel, self._kw, self._logger)(f)
                    setattr(targetClass, attrName, decoratedFunc)
        return targetClass

    def start(self):
        assert not self.active

        try:
            # Apply the RabbitMQ virtual host patch
            self._vhostPatch = RabbitmqVirtualHostPatch(
                clientLabel=self._clientLabel, kw=None, logger=self._logger)
            self._vhostPatch.start()
            # Apply Model Checkpoint Manager patch
            self._modelCheckpointPatch = ModelCheckpointStoragePatch(
                kw=None, logger=self._logger)
            self._modelCheckpointPatch.start()

            # Self-validation
            actualVhost = (
                amqp.connection.getRabbitmqConnectionParameters().vhost)
            assert actualVhost == self._vhostPatch._vhost, (
                "Expected vhost=%r, but got vhost=%r") % (self._vhost,
                                                          actualVhost)
        except Exception:
            self._logger.exception("patch failed, removing sub-patches")
            self._removePatches()
            raise

        self.active = True
        self._logger.info("%s: applied patch", self.__class__.__name__)

    def stop(self):
        assert self.active

        self._removePatches()

        self.active = False

    def _removePatches(self):
        """ NOTE: may be called intenrally to clean-up mid-application of patch
    """
        try:
            if (self._modelCheckpointPatch is not None
                    and self._modelCheckpointPatch.active):
                self._modelCheckpointPatch.stop()
            else:
                assert not self.active
        finally:
            if self._vhostPatch is not None and self._vhostPatch.active:
                self._vhostPatch.stop()
            else:
                assert not self.active

        self._logger.info("%s: removed patch", self.__class__.__name__)
class ModelSwapperIsolationPatch(object):
  """ An instance of this class may be used as a decorator, class decorator or
  Context Manager for redirecting ModelSwapperInterface input, result and
  notification endpoints as well as model checkpoints both in-proc and in
  subprocesses. Deletes the redirected endpoints and model checkpoints on stop.
  """

  def __init__(self, clientLabel, kw=None, logger=logging):
    """
    clientLabel: this string will be used to construct the temporary endpoint
      names. The following characters are permitted, and it shouldn't be too
      long: [._a-zA-Z]. This may be helpful with diagnostics. A specific test
      class name (or similar) would make a reasonable clientLabel.
    kw: name of keyword argument to add to the decorated function(s). Its value
      will be a reference to this instance of ModelSwapperIsolationPatch.
      Ignored when this instance is used as context manager. Defaults to kw=None
      to avoid having it added to the keyword args.
    """
    self.active = False
    """ True when applied successfully; False after successfully removed or not
    applied """

    self._clientLabel = clientLabel
    self._kw = kw
    self._logger = logger

    self._vhostPatch = None
    """ RabbitMQ virtual host patch """

    self._modelCheckpointPatch = None
    """ Model checkpoint storage patch """


  def __enter__(self):
    self.start()
    return self


  def __exit__(self, *args):
    self.stop()
    return False


  def __call__(self, f):
    """ Implement the function or class decorator """
    if isinstance(f, types.TypeType):
      return self._decorateClass(f)

    @functools.wraps(f)
    def applyModelSwapperIsolationPatch(*args, **kwargs):
      self.start()
      try:
        if self._kw is not None:
          kwargs[self._kw] = self
        return f(*args, **kwargs)
      finally:
        self.stop()

    return applyModelSwapperIsolationPatch


  def _decorateClass(self, targetClass):
    """ Decorate the test methods in the given class. Honors
    `mock.patch.TEST_PREFIX` for choosing which methods to wrap
    """
    for attrName in dir(targetClass):
      if attrName.startswith(patch.TEST_PREFIX):
        f = getattr(targetClass, attrName)
        if callable(f):
          decoratedFunc = ModelSwapperIsolationPatch(
            self._clientLabel, self._kw, self._logger)(f)
          setattr(targetClass, attrName, decoratedFunc)
    return targetClass


  def start(self):
    assert not self.active

    try:
      # Apply the RabbitMQ virtual host patch
      self._vhostPatch = RabbitmqVirtualHostPatch(clientLabel=self._clientLabel,
                                                  kw=None, logger=self._logger)
      self._vhostPatch.start()
      # Apply Model Checkpoint Manager patch
      self._modelCheckpointPatch = ModelCheckpointStoragePatch(
        kw=None, logger=self._logger)
      self._modelCheckpointPatch.start()

      # Self-validation
      actualVhost = (
          amqp.connection.getRabbitmqConnectionParameters().vhost)
      assert actualVhost == self._vhostPatch._vhost, (
        "Expected vhost=%r, but got vhost=%r") % (
        self._vhost, actualVhost)
    except Exception:
      self._logger.exception("patch failed, removing sub-patches")
      self._removePatches()
      raise

    self.active = True
    self._logger.info("%s: applied patch", self.__class__.__name__)


  def stop(self):
    assert self.active

    self._removePatches()

    self.active = False


  def _removePatches(self):
    """ NOTE: may be called intenrally to clean-up mid-application of patch
    """
    try:
      if (self._modelCheckpointPatch is not None
          and self._modelCheckpointPatch.active):
        self._modelCheckpointPatch.stop()
      else:
        assert not self.active
    finally:
      if self._vhostPatch is not None and self._vhostPatch.active:
        self._vhostPatch.stop()
      else:
        assert not self.active

    self._logger.info("%s: removed patch", self.__class__.__name__)