Aymeric Augustin committed a355d0f

Various Python 3 compatibility fixes.

These changes were picked and adapted from 2to3's output.

  • Participants
  • Parent commits 9c40d81

Comments (0)

Files changed (12)

File south/creator/

 from south.modelsinspector import value_clean
 from south.creator.freezer import remove_useless_attributes, model_key
 from south.utils import datetime_utils
+from south.utils.py3 import raw_input
 class Action(object):

File south/creator/

                     old_unique_together = [old_unique_together]
                 if new_unique_together and isinstance(new_unique_together[0], string_types):
                     new_unique_together = [new_unique_together]
-                old_unique_together = map(set, old_unique_together)
-                new_unique_together = map(set, new_unique_together)
+                old_unique_together = list(map(set, old_unique_together))
+                new_unique_together = list(map(set, new_unique_together))
                 # See if any appeared or disappeared
                 for item in old_unique_together:
                     if item not in new_unique_together:

File south/db/

         # Finally, actually change the column
         if self.allows_combined_alters:
-            sqls, values = zip(*sqls)
+            sqls, values = list(zip(*sqls))
                 "ALTER TABLE %s %s;" % (self.quote_name(table_name), ", ".join(sqls)),

File south/db/

             if table is INVALID:
                 raise INVALID
             elif column_name is None:
-                return table.items()
+                return list(table.items())
                 return table[column_name]
             except KeyError:
                 signals[app_label] = list(model_names)
         # Send only one signal per app.
-        for (app_label, model_names) in signals.iteritems():
+        for (app_label, model_names) in signals.items():
             self.really_send_create_signal(app_label, list(set(model_names)),

File south/management/commands/

 from __future__ import print_function
 import os.path, re, sys
+from functools import reduce
 from optparse import make_option
 from import BaseCommand

File south/migration/

 from __future__ import print_function
 from copy import copy, deepcopy
-from cStringIO import StringIO
 import datetime
 import inspect
+import io
 import sys
 import traceback
     def __init__(self, migrator, *args, **kwargs):
         self._migrator = copy(migrator)
         attributes = dict([(k, getattr(self, k))
-                           for k in self.__class__.__dict__.iterkeys()
+                           for k in self.__class__.__dict__
                            if not k.startswith('__')])
         self._migrator.__dict__['_wrapper'] = self
         old_debug, old_dry_run = south.db.db.debug, south.db.db.dry_run
         south.db.db.debug = south.db.db.dry_run = True
         stdout = sys.stdout
-        sys.stdout = StringIO()
+        sys.stdout = io.StringIO()

File south/

             func_name = getattr(value, '__name__', None)
             if func_name == 'set_on_delete':
                 # we must inspect the function closure to see what parameters were passed in
-                closure_contents = value.func_closure[0].cell_contents
+                closure_contents = value.__closure__[0].cell_contents
                 if closure_contents is None:
                     return "%s.SET_NULL" % (django_db_models_module)
                 # simple function we can perhaps cope with:
     "proxy": ["proxy", {"default": False, "ignore_missing": True}],
-# 2.4 compatability
-any = lambda x: reduce(lambda y, z: y or z, x, False)
 def add_introspection_rules(rules=[], patterns=[]):
     "Allows you to add some introspection rules at runtime, e.g. for 3rd party apps."

File south/tests/

             def to_python(self, value):
                 if not value or isinstance(value, list):
                     return value
-                return map(int, value.split(','))
+                return list(map(int, value.split(',')))
         false_value = db.has_booleans and 'False' or '0'
         defaults = (

File south/tests/

     def __metaclass__(name, bases, dict_):
         decorator = skipUnless(db.backend_name == "mysql", 'MySQL-specific tests')
-        for key, method in dict_.iteritems():
+        for key, method in dict_.items():
             if key.startswith('test'):
                 dict_[key] = decorator(method)

File south/tests/fakeapp/

 class HorribleModel(models.Model):
     "A model to test the edge cases of model parsing"
-    ZERO, ONE = range(2)
+    ZERO, ONE = 0, 1
     # First, some nice fields
     name = models.CharField(max_length=255)

File south/tests/

+import io
 import logging
 import os
 import tempfile
 from south.tests import unittest
-import StringIO
 import sys
 from django.conf import settings
         settings.SOUTH_LOGGING_ON = False
         # Set root logger to capture WARNING and worse
-        logging_stream = StringIO.StringIO()
+        logging_stream = io.StringIO()
         logging.basicConfig(stream=logging_stream, level=logging.WARNING)
         db.create_table("test12", [('email_confirmed', models.BooleanField(default=False))])

File south/utils/

 if PY3:
     string_types = str,
     text_type = str
+    raw_input = input
     string_types = basestring,
     text_type = unicode
+    raw_input = raw_input