Ticket #596 (assigned defect)

Opened 4 years ago

Last modified 3 weeks ago

South emits signals which do not honor Django's expectations.

Reported by: Alexis Petrounias Owned by: andrew
Priority: minor Milestone: 1.0
Component: migrations Version: 0.7.2
Keywords: signals Cc:

Description

During unit testing for any project with South installed, Model signals (such as post_delete) are being issued by South with MigrationHistory? as the sender. It appears that the sender does not satisfy all of Django's expectations.

Specifically, it is not possible to load the ContentType? of the sender, as the following code:

ContentType.objects.get_for_model(sender)

will result in the following exception:

    ... ContentType.objects.get_for_model(sender) ...
  File ".../django/contrib/contenttypes/models.py", line 40, in get_for_model
    self._add_to_cache(self.db, ct)
  File ".../django/contrib/contenttypes/models.py", line 70, in _add_to_cache
    key = (model._meta.app_label, model._meta.object_name.lower())
AttributeError: 'NoneType' object has no attribute '_meta'

A workaround is to check at the signal listener whether the sender of a signal is MigrationHistory? and ignore the signal, however, this is ad-hoc and creates an explicit South dependency.

Change History

comment:1 follow-up: ↓ 2 Changed 4 years ago by andrew

  • Status changed from new to infoneeded
  • Milestone set to 1.0

It looks like these are just signals for South's built-in tracking model - do you have a global listener for all model changes, or something? If you do, you'll already have to make an exception for MigrationHistory?, since you really shouldn't be doing anything to it.

Also, there _should_ be a content type for MigrationHistory?, since it's created using syncdb, not migrate; are you sure the thing you're passing into the get_for_model call is the MigrationHistory? model?-

comment:2 in reply to: ↑ 1 Changed 4 years ago by Alexis Petrounias

Replying to andrew:

It looks like these are just signals for South's built-in tracking model - do you have a global listener for all model changes, or something? If you do, you'll already have to make an exception for MigrationHistory?, since you really shouldn't be doing anything to it.

Indeed, there is a global listener for post_delete events in the code which lead the manifestation of this issue. Catching the AttributeError? and inspecting the sender parameter to the signal reveals that the exception is raised only when sender is of class MigrationHistory?.

An exception for MigrationHistory?, in the form of:

if not sender == MigrationHistory

successfully sidesteps the exceptional condition.

Also, there _should_ be a content type for MigrationHistory?, since it's created using syncdb, not migrate; are you sure the thing you're passing into the get_for_model call is the MigrationHistory? model?-

I can confirm that only the sender parameter is ever passed to get_for_model. I agree that MigrationHistory? should have a ContentType? registered through syncdb; it is not present after syncdb and / or migrate. However, in a clean database the specific ContentType? is present; furthermore, if the ContentType? is manually created from shell, the problem does not persist.

Therefore, I believe this issue now concerns the possibility that MigrationHistory? is not properly synched to the database, or somehow its ContentType? gets deleted. At any rate, when the ContentType? is missing, neither syncdb nor migrate rectifies or detects this, nor do any unit tests by South or Django detect it. It is not clear to me where unit testing for this situation should be included.

Unfortunately we need more testing in order to replicate the issue.

comment:3 Changed 4 years ago by andrew

Right. Does this happen only during ./manage.py test, then, or on a normal fresh install too?

Note: See TracTickets for help on using tickets.