Aymeric Augustin  committed a28c70e

Port metaclasses to Python 2 + 3.

  • Participants
  • Parent commits a355d0f
  • Branches default

Comments (0)

Files changed (4)

File south/migration/

 from south.orm import FakeORM
 from south.utils import memoize, ask_for_it_by_name, datetime_utils
 from south.migration.utils import app_label_to_app_module
-from south.utils.py3 import string_types
+from south.utils.py3 import string_types, with_metaclass
 def all_migrations(applications=None):
         self.instances = {}
-class Migrations(list):
+class Migrations(with_metaclass(MigrationsMetaclass, list)):
     Holds a list of Migration objects for a particular app.
-    __metaclass__ = MigrationsMetaclass
     if getattr(settings, "SOUTH_USE_PYC", False):
         MIGRATION_FILENAME = re.compile(r'(?!__init__)' # Don't match
                                         r'[0-9a-zA-Z_]*' # Don't match dotfiles, or names with dots/invalid chars in them

File south/tests/

 from django.db import connection, models, IntegrityError
 from south.tests import unittest, skipIf, skipUnless
-from south.utils.py3 import text_type
+from south.utils.py3 import text_type, with_metaclass
 # Create a list of error classes from the various database libraries
 errors = []
         Datetimes are handled in test_datetime_default.
-        class CustomField(models.CharField):
-            __metaclass__ = models.SubfieldBase
+        class CustomField(with_metaclass(models.SubfieldBase, models.CharField)):
             description = 'CustomField'
             def get_default(self):
                 if self.has_default():

File south/tests/

 from south.db import db, generic, mysql
 from django.db import connection, models
+from south.utils.py3 import with_metaclass
-class TestMySQLOperations(unittest.TestCase):
-    """MySQL-specific tests"""
-    # A class decoration may be used in lieu of this when Python 2.5 is the
-    # minimum.
-    def __metaclass__(name, bases, dict_):
+# A class decoration may be used in lieu of this when Python 2.5 is the
+# minimum.
+class TestMySQLOperationsMeta(type):
+    def __new__(mcs, name, bases, dict_):
         decorator = skipUnless(db.backend_name == "mysql", 'MySQL-specific tests')
         for key, method in dict_.items():
             if key.startswith('test'):
                 dict_[key] = decorator(method)
-        return type(name, bases, dict_)
+        return type.__new__(mcs, name, bases, dict_)
+class TestMySQLOperations(with_metaclass(TestMySQLOperationsMeta, unittest.TestCase)):
+    """MySQL-specific tests"""
     def setUp(self):
         db.debug = False

File south/utils/

     string_types = basestring,
     text_type = unicode
     raw_input = raw_input
+def with_metaclass(meta, base=object):
+    """Create a base class with a metaclass."""
+    return meta("NewBase", (base,), {})