Ticket #1138 (closed defect: worksforme)

Opened 2 years ago

Last modified 2 years ago

Cannot call south's syncdb from test environment

Reported by: carneiro.be@… Owned by: andrew
Priority: minor Milestone:
Component: commands Version: unknown
Keywords: Cc:

Description

I'm trying to call south's syncdb from my test environment. It crashes and burns with the following error:

ImportError: No module named <south.management.commands.MigrateAndSyncCommand object at 0x335ed50>.management.commands.syncdb

I noticed that using SOUTH_TESTS_MIGRATE = False it works, however this shouldn't be necessary. Investigating further, I think I've managed to track the problem.

Django's get_commands() returns me

{'dbshell': 'django.core', 'compilemessages': 'django.core', 'dumpdata': 'django.core', ..., 'syncdb': <south.management.commands.MigrateAndSyncCommand? object at 0x335ed50>, ... , 'sqlflush': 'django.core', 'loaddata': 'django.core', 'sqlindexes': 'django.core'}

And this is coming from south's

/south/management/commands/__init__.py

inside the function patch_for_test_db_setup

    if hasattr(settings, "SOUTH_TESTS_MIGRATE") and not settings.SOUTH_TESTS_MIGRATE:
        management._commands['syncdb'] = 'django.core'
    else:
        management._commands['syncdb'] = MigrateAndSyncCommand() # guilty?

doesn't django expect some sort of string instead of an object?
Thanks in advance!

Change History

comment:1 Changed 2 years ago by andrew

  • Status changed from new to infoneeded

What version of South and Django are you running? That override works has worked fine for me in the past.

comment:2 Changed 2 years ago by carneiro.be@…

  • Status changed from infoneeded to assigned

Sorry, forgot to write it. South 0.7.5 and Django-dev (1.5).

comment:3 Changed 2 years ago by andrew

  • Status changed from assigned to infoneeded

Can you try replicating it using Django 1.4 please? South doesn't support unreleased Django as a general rule.

comment:4 Changed 2 years ago by carneiro.be@…

  • Status changed from infoneeded to assigned

Ok, just tested it with Django==1.4 (pip install django). Sorry, I got the same error.

ImportError: No module named <south.management.commands.MigrateAndSyncCommand object at 0x1db4b90>.management.commands.syncdb

The relevant traceback is:

cmdclass = load_command_class(get_commands()[obj.COMMAND_NAME], obj.COMMAND_NAME) # with obj.COMMAND_NAME == syncdb

which calls

module = import_module('%s.management.commands.%s' % (app_name, name)) # as app_name is not a string but <south.management.commands.MigrateAndSyncCommand? object at 0x335ed50>, it fails.

Thanks in advance for your help! Really, south is awesome. By the way, maybe if you can point me a direction to look at, I can try to make a patch and submit it.

comment:5 Changed 2 years ago by andrew

Can I have the full traceback? Django supports having classes there, if you look at call_command:

    try:
        app_name = get_commands()[name]
        if isinstance(app_name, BaseCommand):
            # If the command is already loaded, use it directly.
            klass = app_name
        else:
            klass = load_command_class(app_name, name)
    except KeyError:
        raise CommandError("Unknown command: %r" % name)

so I'd like to see the full call stack to try and work out why it's not picking up the right thing.

comment:6 Changed 2 years ago by carneiro.be@…

oh, thanks for your reply. With your last reply I noticed where my mistake was. The thing is, I have a command called sync_schemas which calls sync_db on every schema on my database. So I have a __new__ method which was trying to load the syncdb command simply by calling:

cmdclass = load_command_class(get_commands()[obj.COMMAND_NAME], obj.COMMAND_NAME)

This was fixed using the snippet you posted above from django

app_name = get_commands()[obj.COMMAND_NAME]
if isinstance(app_name, BaseCommand):
    # If the command is already loaded, use it directly.
    cmdclass = app_name
else:
    cmdclass = load_command_class(app_name, obj.COMMAND_NAME)

Many thanks for your insight and time! I'm sorry that it was my fault. You can mark this as resolved.

comment:7 Changed 2 years ago by andrew

  • Status changed from assigned to closed
  • Resolution set to worksforme

Ah, that makes sense! Closing the ticket.

Note: See TracTickets for help on using tickets.