Skip to content
This repository was archived by the owner on Apr 21, 2021. It is now read-only.
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 32 additions & 19 deletions fixture_generator/management/commands/generate_fixture.py
Original file line number Diff line number Diff line change
@@ -1,22 +1,29 @@
import os
from optparse import make_option

from django.core.management import BaseCommand, call_command, CommandError
from django.core.management.commands.dumpdata import Command as DumpDataCommand
from django.core.management import BaseCommand, call_command
from django.conf import settings
from django.db import router, connections
from django.utils.importlib import import_module
from django.utils.module_loading import module_has_submodule

try:
# Django versions >= 1.9
from django.utils.module_loading import import_module
except ImportError:
# Django versions < 1.9
from django.utils.importlib import import_module

from django.utils.module_loading import module_has_submodule

FIXTURE_DATABASE = "__fixture_gen__"


class CircularDependencyError(Exception):
"""
Raised when there is a circular dependency in fixture requirements.
"""
pass


def linearize_requirements(available_fixtures, fixture, seen=None):
if seen is None:
seen = set([fixture])
Expand Down Expand Up @@ -59,20 +66,25 @@ def allow_syncdb(self, db, model):


class Command(BaseCommand):
option_list = tuple(
opt for opt in DumpDataCommand.option_list
if "--database" not in opt._long_opts and "--exclude" not in opt._long_opts
)
args = "app_label.fixture"

def handle(self, fixture, **options):
def add_arguments(self, parser):
parser.add_argument('fixture', type=str,
help='Indicates the fixture_gen app_name.method that you would like to generate')
parser.add_argument("--format", default="json", dest="format",
help="Specifies the output serialization format for fixtures.")
parser.add_argument("--indent", default=None, dest="indent", type=int,
help="Specifies the indent level to use when pretty-printing output")

def handle(self, *args, **options):
fixture = options['fixture']
format = options['format']
indent = options['indent']
available_fixtures = {}
for app in settings.INSTALLED_APPS:
try:
fixture_gen = import_module(".fixture_gen", app)
except ImportError:
if module_has_submodule(import_module(app), "fixture_gen"):
raise
raise
continue
for obj in fixture_gen.__dict__.values():
if getattr(obj, "__fixture_gen__", False):
Expand All @@ -86,26 +98,27 @@ def handle(self, fixture, **options):
for app_label, fixture_name in available_fixtures
)
raise CommandError("Fixture generator '%s' not found, available "
"choices: %s" % (fixture, available))
"choices: %s" % (fixture, available))

requirements, models = linearize_requirements(available_fixtures, fixture)

settings.DATABASES[FIXTURE_DATABASE] = {
"ENGINE": "django.db.backends.sqlite3",
"NAME": ":memory:",
}

old_routers = router.routers
router.routers = [FixtureRouter(models)]

try:
# migrate_all=True is for south, Django just absorbs it
call_command("syncdb", database=FIXTURE_DATABASE, verbosity=0,
interactive=False, migrate_all=True)
call_command("migrate", database=FIXTURE_DATABASE, verbosity=0,
interactive=False)
for fixture_func in requirements:
fixture_func()
call_command("dumpdata",
*["%s.%s" % (m._meta.app_label, m._meta.object_name) for m in models],
**dict(options, verbosity=0, database=FIXTURE_DATABASE)
)
*["%s.%s" % (m._meta.app_label, m._meta.object_name) for m in models],
**dict(format=format, indent=indent, verbosity=0, database=FIXTURE_DATABASE)
)
finally:
del settings.DATABASES[FIXTURE_DATABASE]
if isinstance(connections._connections, dict):
Expand Down