From 2b531a2f27ff7da62732d46b863f97d6499a53a5 Mon Sep 17 00:00:00 2001
From: Thomas NOEL <tnoel@entrouvert.com>
Date: Tue, 3 Feb 2015 11:28:31 +0100
Subject: [PATCH] migrate_schemas: use django 1.7 if available

---
 .../management/commands/legacy/migrate_schemas.py  |  91 +++++++++++++
 .../management/commands/migrate_schemas.py         | 147 +++++++++------------
 .../management/commands/safemigrate_schemas.py     |  26 ++--
 .../management/commands/sync_schemas.py            |  29 ++--
 4 files changed, 192 insertions(+), 101 deletions(-)
 create mode 100644 entrouvert/djommon/multitenant/management/commands/legacy/migrate_schemas.py

diff --git a/entrouvert/djommon/multitenant/management/commands/legacy/migrate_schemas.py b/entrouvert/djommon/multitenant/management/commands/legacy/migrate_schemas.py
new file mode 100644
index 0000000..5dd204a
--- /dev/null
+++ b/entrouvert/djommon/multitenant/management/commands/legacy/migrate_schemas.py
@@ -0,0 +1,91 @@
+# this file derive from django-tenant-schemas
+#   Author: Bernardo Pires Carneiro
+#   Email: carneiro.be@gmail.com
+#   License: MIT license
+#   Home-page: http://github.com/bcarneiro/django-tenant-schemas
+from django.conf import settings
+from django.db import connection
+from south import migration
+from south.migration.base import Migrations
+from south.management.commands.migrate import Command as MigrateCommand
+from entrouvert.djommon.multitenant.middleware import TenantMiddleware
+from entrouvert.djommon.multitenant.management.commands import SyncCommon
+
+
+class Command(SyncCommon):
+    help = "Migrate schemas with South"
+    option_list = MigrateCommand.option_list + SyncCommon.option_list
+
+    def handle(self, *args, **options):
+        super(Command, self).handle(*args, **options)
+
+        if self.sync_public:
+            self.migrate_public_apps()
+        if self.sync_tenant:
+            self.migrate_tenant_apps(self.domain)
+
+    def _set_managed_apps(self, included_apps, excluded_apps):
+        """ while sync_schemas works by setting which apps are managed, on south we set which apps should be ignored """
+        ignored_apps = []
+        if excluded_apps:
+            for item in excluded_apps:
+                if item not in included_apps:
+                    ignored_apps.append(item)
+
+        for app in ignored_apps:
+            app_label = app.split('.')[-1]
+            settings.SOUTH_MIGRATION_MODULES[app_label] = 'ignore'
+
+    def _save_south_settings(self):
+        self._old_south_modules = None
+        if hasattr(settings, "SOUTH_MIGRATION_MODULES") and settings.SOUTH_MIGRATION_MODULES is not None:
+            self._old_south_modules = settings.SOUTH_MIGRATION_MODULES.copy()
+        else:
+            settings.SOUTH_MIGRATION_MODULES = dict()
+
+    def _restore_south_settings(self):
+        settings.SOUTH_MIGRATION_MODULES = self._old_south_modules
+
+    def _clear_south_cache(self):
+        for mig in list(migration.all_migrations()):
+            delattr(mig._application, "migrations")
+        Migrations._clear_cache()
+
+    def _migrate_schema(self, tenant):
+        connection.set_tenant(tenant, include_public=False)
+        MigrateCommand().execute(*self.args, **self.options)
+
+    def migrate_tenant_apps(self, schema_name=None):
+        self._save_south_settings()
+
+        apps = self.tenant_apps or self.installed_apps
+        self._set_managed_apps(included_apps=apps, excluded_apps=self.shared_apps)
+
+        if schema_name:
+            self._notice("=== Running migrate for schema: %s" % schema_name)
+            connection.set_schema_to_public()
+            tenant = TenantMiddleware.get_tenant_by_hostname(schema_name)
+            self._migrate_schema(tenant)
+        else:
+            all_tenants = TenantMiddleware.get_tenants()
+            if not all_tenants:
+                self._notice("No tenants found")
+
+            for tenant in all_tenants:
+                Migrations._dependencies_done = False  # very important, the dependencies need to be purged from cache
+                self._notice("=== Running migrate for schema %s" % tenant.schema_name)
+                self._migrate_schema(tenant)
+
+        self._restore_south_settings()
+
+    def migrate_public_apps(self):
+        self._save_south_settings()
+
+        apps = self.shared_apps or self.installed_apps
+        self._set_managed_apps(included_apps=apps, excluded_apps=self.tenant_apps)
+
+        self._notice("=== Running migrate for schema public")
+        MigrateCommand().execute(*self.args, **self.options)
+
+        self._clear_south_cache()
+        self._restore_south_settings()
diff --git a/entrouvert/djommon/multitenant/management/commands/migrate_schemas.py b/entrouvert/djommon/multitenant/management/commands/migrate_schemas.py
index 5dd204a..82dd868 100644
--- a/entrouvert/djommon/multitenant/management/commands/migrate_schemas.py
+++ b/entrouvert/djommon/multitenant/management/commands/migrate_schemas.py
@@ -1,91 +1,74 @@
-# this file derive from django-tenant-schemas
-#   Author: Bernardo Pires Carneiro
-#   Email: carneiro.be@gmail.com
-#   License: MIT license
-#   Home-page: http://github.com/bcarneiro/django-tenant-schemas
-from django.conf import settings
+import django
+from optparse import NO_DEFAULT
+
+if django.VERSION >= (1, 7, 0):
+    from django.core.management.commands.migrate import Command as MigrateCommand
+    from django.db.migrations.recorder import MigrationRecorder
 from django.db import connection
-from south import migration
-from south.migration.base import Migrations
-from south.management.commands.migrate import Command as MigrateCommand
-from entrouvert.djommon.multitenant.middleware import TenantMiddleware
+from django.conf import settings
+
+from tenant_schemas.utils import get_public_schema_name
+from entrouvert.djommon.multitenant.middleware import TenantMiddleware, TenantNotFound
 from entrouvert.djommon.multitenant.management.commands import SyncCommon
 
 
-class Command(SyncCommon):
-    help = "Migrate schemas with South"
-    option_list = MigrateCommand.option_list + SyncCommon.option_list
+class MigrateSchemasCommand(SyncCommon):
+    help = "Updates database schema. Manages both apps with migrations and those without."
+
+    def run_from_argv(self, argv):
+        """
+        Changes the option_list to use the options from the wrapped command.
+        Adds schema parameter to specify which schema will be used when
+        executing the wrapped command.
+        """
+        self.option_list += MigrateCommand.option_list
+        super(MigrateSchemasCommand, self).run_from_argv(argv)
 
     def handle(self, *args, **options):
-        super(Command, self).handle(*args, **options)
+        super(MigrateSchemasCommand, self).handle(*args, **options)
+        self.PUBLIC_SCHEMA_NAME = get_public_schema_name()
+
+        if self.sync_public and not self.domain:
+            self.domain = self.PUBLIC_SCHEMA_NAME
 
         if self.sync_public:
-            self.migrate_public_apps()
+            self.run_migrations(self.domain, settings.SHARED_APPS)
         if self.sync_tenant:
-            self.migrate_tenant_apps(self.domain)
-
-    def _set_managed_apps(self, included_apps, excluded_apps):
-        """ while sync_schemas works by setting which apps are managed, on south we set which apps should be ignored """
-        ignored_apps = []
-        if excluded_apps:
-            for item in excluded_apps:
-                if item not in included_apps:
-                    ignored_apps.append(item)
-
-        for app in ignored_apps:
-            app_label = app.split('.')[-1]
-            settings.SOUTH_MIGRATION_MODULES[app_label] = 'ignore'
-
-    def _save_south_settings(self):
-        self._old_south_modules = None
-        if hasattr(settings, "SOUTH_MIGRATION_MODULES") and settings.SOUTH_MIGRATION_MODULES is not None:
-            self._old_south_modules = settings.SOUTH_MIGRATION_MODULES.copy()
-        else:
-            settings.SOUTH_MIGRATION_MODULES = dict()
-
-    def _restore_south_settings(self):
-        settings.SOUTH_MIGRATION_MODULES = self._old_south_modules
-
-    def _clear_south_cache(self):
-        for mig in list(migration.all_migrations()):
-            delattr(mig._application, "migrations")
-        Migrations._clear_cache()
-
-    def _migrate_schema(self, tenant):
-        connection.set_tenant(tenant, include_public=False)
-        MigrateCommand().execute(*self.args, **self.options)
-
-    def migrate_tenant_apps(self, schema_name=None):
-        self._save_south_settings()
-
-        apps = self.tenant_apps or self.installed_apps
-        self._set_managed_apps(included_apps=apps, excluded_apps=self.shared_apps)
-
-        if schema_name:
-            self._notice("=== Running migrate for schema: %s" % schema_name)
-            connection.set_schema_to_public()
-            tenant = TenantMiddleware.get_tenant_by_hostname(schema_name)
-            self._migrate_schema(tenant)
-        else:
-            all_tenants = TenantMiddleware.get_tenants()
-            if not all_tenants:
-                self._notice("No tenants found")
-
-            for tenant in all_tenants:
-                Migrations._dependencies_done = False  # very important, the dependencies need to be purged from cache
-                self._notice("=== Running migrate for schema %s" % tenant.schema_name)
-                self._migrate_schema(tenant)
-
-        self._restore_south_settings()
-
-    def migrate_public_apps(self):
-        self._save_south_settings()
-
-        apps = self.shared_apps or self.installed_apps
-        self._set_managed_apps(included_apps=apps, excluded_apps=self.tenant_apps)
-
-        self._notice("=== Running migrate for schema public")
-        MigrateCommand().execute(*self.args, **self.options)
-
-        self._clear_south_cache()
-        self._restore_south_settings()
+            if self.domain and self.domain != self.PUBLIC_SCHEMA_NAME:
+                try:
+                    tenant = TenantMiddleware.get_tenant_by_hostname(self.domain)
+                except TenantNotFound:
+                    raise RuntimeError('Schema "{}" does not exist'.format(
+                        self.domain))
+                else:
+                    self.run_migrations(tenant.schema_name, settings.TENANT_APPS)
+            else:
+                all_tenants = TenantMiddleware.get_tenants()
+                for tenant in all_tenants:
+                    self.run_migrations(tenant.schema_name, settings.TENANT_APPS)
+
+    def run_migrations(self, schema_name, included_apps):
+        self._notice("=== Running migrate for schema %s" % schema_name)
+        connection.set_schema(schema_name)
+        command = MigrateCommand()
+
+        defaults = {}
+        for opt in MigrateCommand.option_list:
+            if opt.dest in self.options:
+                defaults[opt.dest] = self.options[opt.dest]
+            elif opt.default is NO_DEFAULT:
+                defaults[opt.dest] = None
+            else:
+                defaults[opt.dest] = opt.default
+
+        command.execute(*self.args, **defaults)
+        connection.set_schema_to_public()
+
+    def _notice(self, output):
+        self.stdout.write(self.style.NOTICE(output))
+
+
+if django.VERSION >= (1, 7, 0):
+    Command = MigrateSchemasCommand
+else:
+    from .legacy.migrate_schemas import Command
diff --git a/entrouvert/djommon/multitenant/management/commands/safemigrate_schemas.py b/entrouvert/djommon/multitenant/management/commands/safemigrate_schemas.py
index 0516111..207441a 100644
--- a/entrouvert/djommon/multitenant/management/commands/safemigrate_schemas.py
+++ b/entrouvert/djommon/multitenant/management/commands/safemigrate_schemas.py
@@ -3,18 +3,21 @@
 #   Email: carneiro.be@gmail.com
 #   License: MIT license
 #   Home-page: http://github.com/bcarneiro/django-tenant-schemas
-from django.conf import settings
-from django.db import connection
-from south import migration
-from south.migration.base import Migrations
-from entrouvert.djommon.multitenant.middleware import TenantMiddleware
+import django
+
+if django.VERSION < (1, 7, 0):
+    from django.conf import settings
+    from django.db import connection
+    from south import migration
+    from south.migration.base import Migrations
+    from entrouvert.djommon.multitenant.middleware import TenantMiddleware
+    from entrouvert.djommon.management.commands.safemigrate import Command as SafeMigrateCommand
+    from entrouvert.djommon.multitenant.management.commands.sync_schemas import Command as MTSyncCommand
+    from entrouvert.djommon.multitenant.management.commands.migrate_schemas import Command as MTMigrateCommand
 from entrouvert.djommon.multitenant.management.commands import SyncCommon
-from entrouvert.djommon.management.commands.safemigrate import Command as SafeMigrateCommand
-from entrouvert.djommon.multitenant.management.commands.sync_schemas import Command as MTSyncCommand
-from entrouvert.djommon.multitenant.management.commands.migrate_schemas import Command as MTMigrateCommand
 
 
-class Command(SyncCommon):
+class SafeMigrateCommand(SyncCommon):
     help = "Safely migrate schemas with South"
     option_list = MTMigrateCommand.option_list
 
@@ -95,3 +98,8 @@ class Command(SyncCommon):
 
         self._clear_south_cache()
         self._restore_south_settings()
+
+if django.VERSION < (1, 7, 0):
+    Command = SafeMigrateCommand
+else:
+    raise RuntimeError('Django 1.7: please use migrate_schemas')
diff --git a/entrouvert/djommon/multitenant/management/commands/sync_schemas.py b/entrouvert/djommon/multitenant/management/commands/sync_schemas.py
index 92f5a40..59887f6 100644
--- a/entrouvert/djommon/multitenant/management/commands/sync_schemas.py
+++ b/entrouvert/djommon/multitenant/management/commands/sync_schemas.py
@@ -3,19 +3,22 @@
 #   Email: carneiro.be@gmail.com
 #   License: MIT license
 #   Home-page: http://github.com/bcarneiro/django-tenant-schemas
-from django.conf import settings
-from django.contrib.contenttypes.models import ContentType
-from django.db.models import get_apps, get_models
-if "south" in settings.INSTALLED_APPS:
-    from south.management.commands.syncdb import Command as SyncdbCommand
-else:
-    from django.core.management.commands.syncdb import Command as SyncdbCommand
-from django.db import connection
-from entrouvert.djommon.multitenant.middleware import TenantMiddleware
+import django
+
+if django.VERSION < (1, 7, 0):
+    from django.conf import settings
+    from django.contrib.contenttypes.models import ContentType
+    from django.db.models import get_apps, get_models
+    if "south" in settings.INSTALLED_APPS:
+        from south.management.commands.syncdb import Command as SyncdbCommand
+    else:
+        from django.core.management.commands.syncdb import Command as SyncdbCommand
+    from django.db import connection
+    from entrouvert.djommon.multitenant.middleware import TenantMiddleware
 from entrouvert.djommon.multitenant.management.commands import SyncCommon
 
 
-class Command(SyncCommon):
+class SyncSchemasCommand(SyncCommon):
     help = "Sync schemas based on TENANT_APPS and SHARED_APPS settings"
     option_list = SyncdbCommand.option_list + SyncCommon.option_list
 
@@ -78,3 +81,9 @@ class Command(SyncCommon):
         apps = self.shared_apps or self.installed_apps
         self._set_managed_apps(apps)
         SyncdbCommand().execute(**self.options)
+
+if django.VERSION < (1, 7, 0):
+    Command = SyncSchemasCommand
+else:
+    raise RuntimeError('Django 1.7: use migrate_schemas')
+
-- 
2.1.4

