Fixes to signals

The sender is the class of the document not the instance - easier to
hook into
This commit is contained in:
Ross Lawley 2011-06-14 16:56:04 +01:00
parent 576db9ca88
commit cb1dfdfac6
4 changed files with 81 additions and 30 deletions

View File

@ -30,20 +30,20 @@ Example usage::
return self.name return self.name
@classmethod @classmethod
def pre_save(cls, instance, **kwargs): def pre_save(cls, sender, document, **kwargs):
logging.debug("Pre Save: %s" % instance.name) logging.debug("Pre Save: %s" % document.name)
@classmethod @classmethod
def post_save(cls, instance, **kwargs): def post_save(cls, sender, document, **kwargs):
logging.debug("Post Save: %s" % instance.name) logging.debug("Post Save: %s" % document.name)
if 'created' in kwargs: if 'created' in kwargs:
if kwargs['created']: if kwargs['created']:
logging.debug("Created") logging.debug("Created")
else: else:
logging.debug("Updated") logging.debug("Updated")
signals.pre_save.connect(Author.pre_save) signals.pre_save.connect(Author.pre_save, sender=Author)
signals.post_save.connect(Author.post_save) signals.post_save.connect(Author.post_save, sender=Author)
.. _blinker: http://pypi.python.org/pypi/blinker .. _blinker: http://pypi.python.org/pypi/blinker

View File

@ -600,7 +600,7 @@ class TopLevelDocumentMetaclass(DocumentMetaclass):
class BaseDocument(object): class BaseDocument(object):
def __init__(self, **values): def __init__(self, **values):
signals.pre_init.send(self, values=values) signals.pre_init.send(self.__class__, document=self, values=values)
self._data = {} self._data = {}
# Assign default values to instance # Assign default values to instance
@ -619,7 +619,7 @@ class BaseDocument(object):
except AttributeError: except AttributeError:
pass pass
signals.post_init.send(self) signals.post_init.send(self.__class__, document=self)
def _get_FIELD_display(self, field): def _get_FIELD_display(self, field):
"""Returns the display value for a choice field""" """Returns the display value for a choice field"""

View File

@ -91,7 +91,7 @@ class Document(BaseDocument):
For example, ``save(..., w=2, fsync=True)`` will wait until at least two servers For example, ``save(..., w=2, fsync=True)`` will wait until at least two servers
have recorded the write and will force an fsync on each server being written to. have recorded the write and will force an fsync on each server being written to.
""" """
signals.pre_save.send(self) signals.pre_save.send(self.__class__, document=self)
if validate: if validate:
self.validate() self.validate()
@ -122,7 +122,7 @@ class Document(BaseDocument):
id_field = self._meta['id_field'] id_field = self._meta['id_field']
self[id_field] = self._fields[id_field].to_python(object_id) self[id_field] = self._fields[id_field].to_python(object_id)
self._changed_fields = [] self._changed_fields = []
signals.post_save.send(self, created=created) signals.post_save.send(self.__class__, document=self, created=created)
def delete(self, safe=False): def delete(self, safe=False):
"""Delete the :class:`~mongoengine.Document` from the database. This """Delete the :class:`~mongoengine.Document` from the database. This
@ -130,7 +130,7 @@ class Document(BaseDocument):
:param safe: check if the operation succeeded before returning :param safe: check if the operation succeeded before returning
""" """
signals.pre_delete.send(self) signals.pre_delete.send(self.__class__, document=self)
id_field = self._meta['id_field'] id_field = self._meta['id_field']
object_id = self._fields[id_field].to_mongo(self[id_field]) object_id = self._fields[id_field].to_mongo(self[id_field])
@ -140,7 +140,7 @@ class Document(BaseDocument):
message = u'Could not delete document (%s)' % err.message message = u'Could not delete document (%s)' % err.message
raise OperationError(message) raise OperationError(message)
signals.post_delete.send(self) signals.post_delete.send(self.__class__, document=self)
def reload(self): def reload(self):
"""Reloads all attributes from the database. """Reloads all attributes from the database.

View File

@ -28,21 +28,21 @@ class SignalTests(unittest.TestCase):
return self.name return self.name
@classmethod @classmethod
def pre_init(cls, instance, **kwargs): def pre_init(cls, sender, document, *args, **kwargs):
signal_output.append('pre_init signal, %s' % cls.__name__) signal_output.append('pre_init signal, %s' % cls.__name__)
signal_output.append(str(kwargs['values'])) signal_output.append(str(kwargs['values']))
@classmethod @classmethod
def post_init(cls, instance, **kwargs): def post_init(cls, sender, document, **kwargs):
signal_output.append('post_init signal, %s' % instance) signal_output.append('post_init signal, %s' % document)
@classmethod @classmethod
def pre_save(cls, instance, **kwargs): def pre_save(cls, sender, document, **kwargs):
signal_output.append('pre_save signal, %s' % instance) signal_output.append('pre_save signal, %s' % document)
@classmethod @classmethod
def post_save(cls, instance, **kwargs): def post_save(cls, sender, document, **kwargs):
signal_output.append('post_save signal, %s' % instance) signal_output.append('post_save signal, %s' % document)
if 'created' in kwargs: if 'created' in kwargs:
if kwargs['created']: if kwargs['created']:
signal_output.append('Is created') signal_output.append('Is created')
@ -50,15 +50,52 @@ class SignalTests(unittest.TestCase):
signal_output.append('Is updated') signal_output.append('Is updated')
@classmethod @classmethod
def pre_delete(cls, instance, **kwargs): def pre_delete(cls, sender, document, **kwargs):
signal_output.append('pre_delete signal, %s' % instance) signal_output.append('pre_delete signal, %s' % document)
@classmethod @classmethod
def post_delete(cls, instance, **kwargs): def post_delete(cls, sender, document, **kwargs):
signal_output.append('post_delete signal, %s' % instance) signal_output.append('post_delete signal, %s' % document)
self.Author = Author self.Author = Author
class Another(Document):
name = StringField()
def __unicode__(self):
return self.name
@classmethod
def pre_init(cls, sender, document, **kwargs):
signal_output.append('pre_init Another signal, %s' % cls.__name__)
signal_output.append(str(kwargs['values']))
@classmethod
def post_init(cls, sender, document, **kwargs):
signal_output.append('post_init Another signal, %s' % document)
@classmethod
def pre_save(cls, sender, document, **kwargs):
signal_output.append('pre_save Another signal, %s' % document)
@classmethod
def post_save(cls, sender, document, **kwargs):
signal_output.append('post_save Another signal, %s' % document)
if 'created' in kwargs:
if kwargs['created']:
signal_output.append('Is created')
else:
signal_output.append('Is updated')
@classmethod
def pre_delete(cls, sender, document, **kwargs):
signal_output.append('pre_delete Another signal, %s' % document)
@classmethod
def post_delete(cls, sender, document, **kwargs):
signal_output.append('post_delete Another signal, %s' % document)
self.Another = Another
# Save up the number of connected signals so that we can check at the end # Save up the number of connected signals so that we can check at the end
# that all the signals we register get properly unregistered # that all the signals we register get properly unregistered
self.pre_signals = ( self.pre_signals = (
@ -70,12 +107,19 @@ class SignalTests(unittest.TestCase):
len(signals.post_delete.receivers) len(signals.post_delete.receivers)
) )
signals.pre_init.connect(Author.pre_init) signals.pre_init.connect(Author.pre_init, sender=Author)
signals.post_init.connect(Author.post_init) signals.post_init.connect(Author.post_init, sender=Author)
signals.pre_save.connect(Author.pre_save) signals.pre_save.connect(Author.pre_save, sender=Author)
signals.post_save.connect(Author.post_save) signals.post_save.connect(Author.post_save, sender=Author)
signals.pre_delete.connect(Author.pre_delete) signals.pre_delete.connect(Author.pre_delete, sender=Author)
signals.post_delete.connect(Author.post_delete) signals.post_delete.connect(Author.post_delete, sender=Author)
signals.pre_init.connect(Another.pre_init, sender=Another)
signals.post_init.connect(Another.post_init, sender=Another)
signals.pre_save.connect(Another.pre_save, sender=Another)
signals.post_save.connect(Another.post_save, sender=Another)
signals.pre_delete.connect(Another.pre_delete, sender=Another)
signals.post_delete.connect(Another.post_delete, sender=Another)
def tearDown(self): def tearDown(self):
signals.pre_init.disconnect(self.Author.pre_init) signals.pre_init.disconnect(self.Author.pre_init)
@ -85,6 +129,13 @@ class SignalTests(unittest.TestCase):
signals.post_save.disconnect(self.Author.post_save) signals.post_save.disconnect(self.Author.post_save)
signals.pre_save.disconnect(self.Author.pre_save) signals.pre_save.disconnect(self.Author.pre_save)
signals.pre_init.disconnect(self.Another.pre_init)
signals.post_init.disconnect(self.Another.post_init)
signals.post_delete.disconnect(self.Another.post_delete)
signals.pre_delete.disconnect(self.Another.pre_delete)
signals.post_save.disconnect(self.Another.post_save)
signals.pre_save.disconnect(self.Another.pre_save)
# Check that all our signals got disconnected properly. # Check that all our signals got disconnected properly.
post_signals = ( post_signals = (
len(signals.pre_init.receivers), len(signals.pre_init.receivers),