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__)