Commits

Aymeric Augustin  committed 36c55d8

Port unicode-related code to Python 2 + 3.

  • Participants
  • Parent commits 7d76aca

Comments (0)

Files changed (12)

File docs/conf.py

 master_doc = 'index'
 
 # General information about the project.
-project = u'South'
-copyright = u'2010, Andrew Godwin'
+project = 'South'
+copyright = '2010, Andrew Godwin'
 
 # The version info for the project you're documenting, acts as replacement for
 # |version| and |release|, also used in various other places throughout the
 # Grouping the document tree into LaTeX files. List of tuples
 # (source start file, target name, title, author, documentclass [howto/manual]).
 latex_documents = [
-  ('index', 'South.tex', u'South Documentation',
-   u'Andrew Godwin', 'manual'),
+  ('index', 'South.tex', 'South Documentation',
+   'Andrew Godwin', 'manual'),
 ]
 
 # The name of an image file (relative to this directory) to place at the top of

File south/creator/changes.py

 
 from south.creator.freezer import remove_useless_attributes, freeze_apps, model_key
 from south.utils import auto_through
+from south.utils.py3 import string_types
 
 class BaseChanges(object):
     """
     def is_triple(cls, triple):
         "Returns whether the argument is a triple."
         return isinstance(triple, (list, tuple)) and len(triple) == 3 and \
-            isinstance(triple[0], (str, unicode)) and \
+            isinstance(triple[0], string_types) and \
             isinstance(triple[1], (list, tuple)) and \
             isinstance(triple[2], dict)
 

File south/db/generic.py

             return res
 
 from south.logger import get_logger
+from south.utils.py3 import string_types
 
 
 def alias(attrname):
         This is possible using only columns due to the deterministic
         index naming function which relies on column names.
         """
-        if isinstance(column_names, (str, unicode)):
+        if isinstance(column_names, string_types):
             column_names = [column_names]
         name = self.create_index_name(table_name, column_names)
         sql = self.drop_index_string % {

File south/db/sql_server/pyodbc.py

 from south.db import generic
 from south.db.generic import delete_column_constraints, invalidate_table_constraints, copy_column_constraints
 from south.exceptions import ConstraintDropped
-from django.utils.encoding import smart_unicode
+try:
+    from django.utils.encoding import smart_text                    # Django >= 1.5
+except ImportError:
+    from django.utils.encoding import smart_unicode as smart_text   # Django < 1.5
 from django.core.management.color import no_style
 
 class DatabaseOperations(generic.DatabaseOperations):
         value = field.get_db_prep_save(value, connection=conn)
         # This is still a Python object -- nobody expects to need a literal.
         if isinstance(value, basestring):
-            return smart_unicode(value)
+            return smart_text(value)
         elif isinstance(value, (date,time,datetime)):
             return value.isoformat()
         else:

File south/exceptions.py

         self.matches = matches
 
     def __str__(self):
-        self.matches_list = "\n    ".join([unicode(m) for m in self.matches])
+        self.matches_list = "\n    ".join([str(m) for m in self.matches])
         return ("Prefix '%(prefix)s' matches more than one migration:\n"
                 "    %(matches_list)s") % self.__dict__
 
         self.ghosts = ghosts
 
     def __str__(self):
-        self.ghosts_list = "\n    ".join([unicode(m) for m in self.ghosts])
+        self.ghosts_list = "\n    ".join([str(m) for m in self.ghosts])
         return ("\n\n ! These migrations are in the database but not on disk:\n"
                 "    %(ghosts_list)s\n"
                 " ! I'm not trusting myself; either fix this yourself by fiddling\n"
         self.trace = trace
 
     def __str__(self):
-        trace = " -> ".join([unicode(s) for s in self.trace])
+        trace = " -> ".join([str(s) for s in self.trace])
         return ("Found circular dependency:\n"
                 "    %s") % trace
 

File south/migration/base.py

         return self.app_label() + ':' + self.name()
 
     def __repr__(self):
-        return u'<Migration: %s>' % unicode(self)
+        return '<Migration: %s>' % str(self)
 
     def __eq__(self, other):
         return self.app_label() == other.app_label() and self.name() == other.name()

File south/models.py

     def get_migration(self):
         return self.get_migrations().migration(self.migration)
     
-    def __unicode__(self):
+    def __str__(self):
         return "<%s: %s>" % (self.app_name, self.migration)

File south/modelsinspector.py

 import decimal
 
 from south.utils import get_attribute, auto_through
+from south.utils.py3 import text_type
 
 from django.db import models
 from django.db.models.base import ModelBase, Model
             
     # Lazy-eval functions get eval'd.
     if isinstance(value, Promise):
-        value = unicode(value)
+        value = text_type(value)
     # If the value is the same as the default, omit it for clarity
     if "default" in options and value == options['default']:
         raise IsDefault
     "Takes a value and cleans it up (so e.g. it has timezone working right)"
     # Lazy-eval functions get eval'd.
     if isinstance(value, Promise):
-        value = unicode(value)
+        value = text_type(value)
     # Callables get called.
     if not options.get('is_django_function', False) and callable(value) and not isinstance(value, ModelBase):
         # Datetime.datetime.now is special, as we can access it from the eval

File south/orm.py

 from south.utils import ask_for_it_by_name, datetime_utils
 from south.hacks import hacks
 from south.exceptions import UnfreezeMeLater, ORMBaseNotIncluded, ImpossibleORMUnfreeze
+from south.utils.py3 import string_types
 
 
 class ModelsLocals(object):
                 continue
             elif not params:
                 raise ValueError("Field '%s' on model '%s.%s' has no definition." % (fname, app, name))
-            elif isinstance(params, (str, unicode)):
+            elif isinstance(params, string_types):
                 # It's a premade definition string! Let's hope it works...
                 code = params
                 extra_imports = {}

File south/tests/db.py

 from django.db import connection, models, IntegrityError
 
 from south.tests import unittest, skipIf, skipUnless
+from south.utils.py3 import text_type
 
 # Create a list of error classes from the various database libraries
 errors = []
         db.alter_column("test_char_to_text", "textcol", models.TextField())
         db.execute_deferred_sql()
         after = db.execute("select * from test_char_to_text")[0][0]
-        after = unicode(after) # Oracle text fields return a sort of lazy string -- force evaluation
+        after = text_type(after) # Oracle text fields return a sort of lazy string -- force evaluation
         self.assertEqual(value, after, "Change from char to text altered value [ %r != %r ]" % (value, after))
 
     def test_datetime_default(self):

File south/tests/logic.py

         
         # We should finish with all migrations
         self.assertListEqual(
-            ((u"fakeapp", u"0001_spam"),
-             (u"fakeapp", u"0002_eggs"),
-             (u"fakeapp", u"0003_alter_spam"),),
+            (("fakeapp", "0001_spam"),
+             ("fakeapp", "0002_eggs"),
+             ("fakeapp", "0003_alter_spam"),),
             MigrationHistory.objects.values_list("app_name", "migration"),
         )
         
         
         # Did it go in?
         self.assertListEqual(
-            ((u"fakeapp", u"0002_eggs"),),
+            (("fakeapp", "0002_eggs"),),
             MigrationHistory.objects.values_list("app_name", "migration"),
         )
         
         
         # Nothing should have changed (no merge mode!)
         self.assertListEqual(
-            ((u"fakeapp", u"0002_eggs"),),
+            (("fakeapp", "0002_eggs"),),
             MigrationHistory.objects.values_list("app_name", "migration"),
         )
         
         
         # We should finish with all migrations
         self.assertListEqual(
-            ((u"fakeapp", u"0001_spam"),
-             (u"fakeapp", u"0002_eggs"),
-             (u"fakeapp", u"0003_alter_spam"),),
+            (("fakeapp", "0001_spam"),
+             ("fakeapp", "0002_eggs"),
+             ("fakeapp", "0003_alter_spam"),),
             MigrationHistory.objects.values_list("app_name", "migration"),
         )
         
         migrate_app(migrations, target_name="0002", fake=False)
         self.failIf(null_ok())
         self.assertListEqual(
-            ((u"fakeapp", u"0001_spam"),
-             (u"fakeapp", u"0002_eggs"),),
+            (("fakeapp", "0001_spam"),
+             ("fakeapp", "0002_eggs"),),
             MigrationHistory.objects.values_list("app_name", "migration"),
         )
         
         migrate_app(migrations, target_name="0003", fake=False)
         self.assert_(null_ok(False))
         self.assertListEqual(
-            ((u"fakeapp", u"0001_spam"),
-             (u"fakeapp", u"0002_eggs"),
-             (u"fakeapp", u"0003_alter_spam"),),
+            (("fakeapp", "0001_spam"),
+             ("fakeapp", "0002_eggs"),
+             ("fakeapp", "0003_alter_spam"),),
             MigrationHistory.objects.values_list("app_name", "migration"),
         )
 
         migrate_app(migrations, target_name="0002", fake=False)
         self.failIf(null_ok(), 'weight not null after migration')
         self.assertListEqual(
-            ((u"fakeapp", u"0001_spam"),
-             (u"fakeapp", u"0002_eggs"),),
+            (("fakeapp", "0001_spam"),
+             ("fakeapp", "0002_eggs"),),
             MigrationHistory.objects.values_list("app_name", "migration"),
         )
         

File south/utils/py3.py

+"""
+Python 2 + 3 compatibility functions. This is a very small subset of six.
+"""
+
+import sys
+
+PY3 = sys.version_info[0] == 3
+
+if PY3:
+    string_types = str,
+    text_type = str
+
+else:
+    string_types = basestring,
+    text_type = unicode