]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
Added UnicodeText alias
authorJason Kirtland <jek@discorporate.us>
Wed, 9 Jan 2008 20:22:41 +0000 (20:22 +0000)
committerJason Kirtland <jek@discorporate.us>
Wed, 9 Jan 2008 20:22:41 +0000 (20:22 +0000)
lib/sqlalchemy/__init__.py
lib/sqlalchemy/types.py
test/dialect/mysql.py
test/sql/testtypes.py

index 8bc1c45977190e94121e7fb2ddb813a6d1e9446f..0fc4e117ef9ed8dc98ec49bd6c0625dc778baa30 100644 (file)
@@ -7,9 +7,9 @@
 import inspect
 from sqlalchemy.types import \
     BLOB, BOOLEAN, CHAR, CLOB, DATE, DATETIME, DECIMAL, FLOAT, INT, \
-    NCHAR, NUMERIC, SMALLINT, TEXT, Text, TIME, TIMESTAMP, VARCHAR, \
+    NCHAR, NUMERIC, SMALLINT, TEXT, TIME, TIMESTAMP, VARCHAR, \
     Binary, Boolean, Date, DateTime, Float, Integer, Interval, Numeric, \
-    PickleType, SmallInteger, String, Time, Unicode
+    PickleType, SmallInteger, String, Text, Time, Unicode, UnicodeText
 
 from sqlalchemy.sql import \
     func, modifier, text, literal, literal_column, null, alias, \
index 1a5d0ab56123a68cff12f59970cbbe7b31b9d7bb..2de54804ab95f72e5d965fb8b6f6e30dbcf0341b 100644 (file)
@@ -4,8 +4,8 @@
 # This module is part of SQLAlchemy and is released under
 # the MIT License: http://www.opensource.org/licenses/mit-license.php
 
-"""defines genericized SQL types, each represented by a subclass of 
-[sqlalchemy.types#AbstractType].  Dialects define further subclasses of these 
+"""defines genericized SQL types, each represented by a subclass of
+[sqlalchemy.types#AbstractType].  Dialects define further subclasses of these
 types.
 
 For more information see the SQLAlchemy documentation on types.
@@ -17,7 +17,7 @@ __all__ = [ 'TypeEngine', 'TypeDecorator', 'AbstractType',
             'BOOLEAN', 'SMALLINT', 'DATE', 'TIME',
             'String', 'Integer', 'SmallInteger','Smallinteger',
             'Numeric', 'Float', 'DateTime', 'Date', 'Time', 'Binary',
-            'Boolean', 'Unicode', 'PickleType', 'Interval',
+            'Boolean', 'Unicode', 'UnicodeText', 'PickleType', 'Interval',
             'type_map'
             ]
 
@@ -222,7 +222,7 @@ class TypeDecorator(AbstractType):
         by default calls dialect.type_descriptor(self.impl), but
         can be overridden to provide different behavior.
         """
-        
+
         return dialect.type_descriptor(self.impl)
 
     def __getattr__(self, key):
@@ -235,10 +235,10 @@ class TypeDecorator(AbstractType):
 
     def process_bind_param(self, value, dialect):
         raise NotImplementedError()
-    
+
     def process_result_value(self, value, dialect):
         raise NotImplementedError()
-        
+
     def bind_processor(self, dialect):
         if self.__class__.process_bind_param.func_code is not TypeDecorator.process_bind_param.func_code:
             impl_processor = self.impl.bind_processor(dialect)
@@ -342,12 +342,12 @@ class Concatenable(object):
 
 class String(Concatenable, TypeEngine):
     """A sized string type.
-    
+
     Usually corresponds to VARCHAR.  Can also take Python unicode objects
-    and encode to the database's encoding in bind params (and the reverse for 
+    and encode to the database's encoding in bind params (and the reverse for
     result sets.)
-    
-    a String with no length will adapt itself automatically to a Text 
+
+    a String with no length will adapt itself automatically to a Text
     object at the dialect level (this behavior is deprecated in 0.4).
     """
     def __init__(self, length=None, convert_unicode=False, assert_unicode=None):
@@ -395,7 +395,7 @@ class String(Concatenable, TypeEngine):
         if _for_ddl and self.length is None:
             warn_deprecated("Using String type with no length for CREATE TABLE is deprecated; use the Text type explicitly")
         return TypeEngine.dialect_impl(self, dialect, **kwargs)
-        
+
     def get_search_list(self):
         l = super(String, self).get_search_list()
         # if we are String or Unicode with no length,
@@ -409,14 +409,26 @@ class String(Concatenable, TypeEngine):
     def get_dbapi_type(self, dbapi):
         return dbapi.STRING
 
+class Text(String):
+    def dialect_impl(self, dialect, **kwargs):
+        return TypeEngine.dialect_impl(self, dialect, **kwargs)
+
 class Unicode(String):
     """A synonym for String(length, convert_unicode=True, assert_unicode='warn')."""
-    
+
     def __init__(self, length=None, **kwargs):
         kwargs['convert_unicode'] = True
         kwargs['assert_unicode'] = 'warn'
         super(Unicode, self).__init__(length=length, **kwargs)
 
+class UnicodeText(Text):
+    """A synonym for Text(convert_unicode=True, assert_unicode='warn')."""
+
+    def __init__(self, length=None, **kwargs):
+        kwargs['convert_unicode'] = True
+        kwargs['assert_unicode'] = 'warn'
+        super(UnicodeText, self).__init__(length=length, **kwargs)
+
 class Integer(TypeEngine):
     """Integer datatype."""
 
@@ -426,13 +438,11 @@ class Integer(TypeEngine):
 class SmallInteger(Integer):
     """Smallint datatype."""
 
-    pass
-
 Smallinteger = SmallInteger
 
 class Numeric(TypeEngine):
     """Numeric datatype, usually resolves to DECIMAL or NUMERIC."""
-    
+
     def __init__(self, precision=10, length=2, asdecimal=True):
         self.precision = precision
         self.length = length
@@ -654,10 +664,7 @@ class Interval(TypeDecorator):
             return process
 
 class FLOAT(Float): pass
-class Text(String):
-    def dialect_impl(self, dialect, **kwargs):
-        return TypeEngine.dialect_impl(self, dialect, **kwargs)
-    
+
 TEXT = Text
 class NUMERIC(Numeric): pass
 class DECIMAL(Numeric): pass
@@ -690,4 +697,3 @@ type_map = {
     dt.timedelta : Interval,
     type(None): NullType
 }
-
index 5f5c4a750737b88528f79663506cb7a3acb0dc70..0a9153327082fa85b12b3b999912238666091349 100644 (file)
@@ -1,5 +1,5 @@
 import testbase
-import sets
+import sets, warnings
 from sqlalchemy import *
 from sqlalchemy import sql, exceptions
 from sqlalchemy.databases import mysql
@@ -632,6 +632,11 @@ class TypesTest(AssertMixin):
         specs = [( String(), mysql.MSText(), ),
                  ( String(1), mysql.MSString(1), ),
                  ( String(3), mysql.MSString(3), ),
+                 ( Text(), mysql.MSText(), ),
+                 ( Unicode(), mysql.MSText(), ),
+                 ( Unicode(1), mysql.MSString(1), ),
+                 ( Unicode(3), mysql.MSString(3), ),
+                 ( UnicodeText(), mysql.MSText(), ),
                  ( mysql.MSChar(1), ),
                  ( mysql.MSChar(3), ),
                  ( NCHAR(2), mysql.MSChar(2), ),
@@ -660,7 +665,13 @@ class TypesTest(AssertMixin):
         m = MetaData(db)
         t_table = Table('mysql_types', m, *columns)
         try:
-            m.create_all()
+            try:
+                warnings.filterwarnings('ignore',
+                                        'Using String type with no length.*')
+                m.create_all()
+            finally:
+                warnings.filterwarnings("always",
+                                        'Using String type with no length.*')
 
             m2 = MetaData(db)
             rt = Table('mysql_types', m2, autoload=True)
@@ -876,6 +887,7 @@ class SQLTest(SQLCompileTest):
 
             (String, "CAST(t.col AS CHAR)"),
             (Unicode, "CAST(t.col AS CHAR)"),
+            (UnicodeText, "CAST(t.col AS CHAR)"),
             (VARCHAR, "CAST(t.col AS CHAR)"),
             (NCHAR, "CAST(t.col AS CHAR)"),
             (CHAR, "CAST(t.col AS CHAR)"),
index 7bd012f42f1e0c288f863cc0fa54d34b2245d28b..98a8ca0e138d55cb9d094eae9a7207bf23c6f46f 100644 (file)
@@ -47,7 +47,7 @@ class AdaptTest(PersistTest):
             impl = String
             def copy(self):
                 return MyDecoratedType()
-            
+
         col = Column('', MyDecoratedType)
         dialect_type = col.type.dialect_impl(dialect)
         assert isinstance(dialect_type.impl, oracle.OracleText), repr(dialect_type.impl)
@@ -82,21 +82,25 @@ class AdaptTest(PersistTest):
             (oracle_dialect, VARCHAR(), oracle.OracleString),
             (oracle_dialect, String(50), oracle.OracleString),
             (oracle_dialect, Unicode(), oracle.OracleText),
+            (oracle_dialect, UnicodeText(), oracle.OracleText),
             (oracle_dialect, NCHAR(), oracle.OracleString),
             (mysql_dialect, String(), mysql.MSText),
             (mysql_dialect, VARCHAR(), mysql.MSString),
             (mysql_dialect, String(50), mysql.MSString),
             (mysql_dialect, Unicode(), mysql.MSText),
+            (mysql_dialect, UnicodeText(), mysql.MSText),
             (mysql_dialect, NCHAR(), mysql.MSNChar),
             (postgres_dialect, String(), postgres.PGText),
             (postgres_dialect, VARCHAR(), postgres.PGString),
             (postgres_dialect, String(50), postgres.PGString),
             (postgres_dialect, Unicode(), postgres.PGText),
+            (postgres_dialect, UnicodeText(), postgres.PGText),
             (postgres_dialect, NCHAR(), postgres.PGString),
             (firebird_dialect, String(), firebird.FBText),
             (firebird_dialect, VARCHAR(), firebird.FBString),
             (firebird_dialect, String(50), firebird.FBString),
             (firebird_dialect, Unicode(), firebird.FBText),
+            (firebird_dialect, UnicodeText(), firebird.FBText),
             (firebird_dialect, NCHAR(), firebird.FBString),
         ]:
             assert isinstance(start.dialect_impl(dialect), test), "wanted %r got %r" % (test, start.dialect_impl(dialect))
@@ -124,7 +128,7 @@ class UserDefinedTest(PersistTest):
             [1200, 1500, 900],
             [1800, 2250, 1350],
             l
-            
+
         ):
             for col in row[1:8]:
                 self.assertEquals(col, assertstr)
@@ -132,7 +136,7 @@ class UserDefinedTest(PersistTest):
             self.assertEquals(row[9], assertint2)
             for col in (row[4], row[5], row[7]):
                 assert isinstance(col, unicode)
-                
+
     def setUpAll(self):
         global users, metadata
 
@@ -304,7 +308,7 @@ class UnicodeTest(AssertMixin):
         unicode_table = Table('unicode_table', metadata,
             Column('id', Integer, Sequence('uni_id_seq', optional=True), primary_key=True),
             Column('unicode_varchar', Unicode(250)),
-            Column('unicode_text', Unicode),
+            Column('unicode_text', UnicodeText),
             Column('plain_varchar', String(250))
             )
         unicode_table.create()
@@ -330,30 +334,34 @@ class UnicodeTest(AssertMixin):
         self.assert_(isinstance(x['unicode_text'], unicode) and x['unicode_text'] == unicodedata)
         if isinstance(x['plain_varchar'], unicode):
             # SQLLite and MSSQL return non-unicode data as unicode
-            self.assert_(testbase.db.name in ('sqlite', 'mssql'))
+            self.assert_(testing.against('sqlite', 'mssql'))
             self.assert_(x['plain_varchar'] == unicodedata)
             print "it's %s!" % testbase.db.name
         else:
             self.assert_(not isinstance(x['plain_varchar'], unicode) and x['plain_varchar'] == rawdata)
-    
+
     def testassert(self):
         import warnings
 
         warnings.filterwarnings("always", r".*non-unicode bind")
-        
-        # test that data still goes in if warning is emitted....
-        unicode_table.insert().execute(unicode_varchar='im not unicode')
-        assert select([unicode_table.c.unicode_varchar]).execute().fetchall() == [('im not unicode', )]
-        
+
+        ## test that data still goes in if warning is emitted....
+        unicode_table.insert().execute(unicode_varchar='not unicode')
+        assert (select([unicode_table.c.unicode_varchar]).execute().fetchall()
+                == [('not unicode', )])
+
         warnings.filterwarnings("error", r".*non-unicode bind")
-        
         try:
-            unicode_table.insert().execute(unicode_varchar='im not unicode')
-            assert False
-        except RuntimeWarning, e:
-            assert str(e) == "Unicode type received non-unicode bind param value 'im not unicode'", str(e)
+            try:
+                unicode_table.insert().execute(unicode_varchar='not unicode')
+                assert False
+            except RuntimeWarning, e:
+                assert str(e) == "Unicode type received non-unicode bind param value 'not unicode'", str(e)
+        finally:
+            warnings.filterwarnings("always", r".*non-unicode bind")
 
-        unicode_engine = engines.utf8_engine(options={'convert_unicode':True, 'assert_unicode':True})
+        unicode_engine = engines.utf8_engine(options={'convert_unicode':True,
+                                                      'assert_unicode':True})
         try:
             try:
                 unicode_engine.execute(unicode_table.insert(), plain_varchar='im not unicode')
@@ -363,7 +371,7 @@ class UnicodeTest(AssertMixin):
         finally:
             unicode_engine.dispose()
 
-    @testing.unsupported('oracle')
+    @testing.fails_on('oracle')
     def testblanks(self):
         unicode_table.insert().execute(unicode_varchar=u'')
         assert select([unicode_table.c.unicode_varchar]).scalar() == u''
@@ -482,40 +490,40 @@ class ExpressionTest(AssertMixin):
                 return process
             def adapt_operator(self, op):
                 return {operators.add:operators.sub, operators.sub:operators.add}.get(op, op)
-                
+
         meta = MetaData(testbase.db)
-        test_table = Table('test', meta, 
+        test_table = Table('test', meta,
             Column('id', Integer, primary_key=True),
             Column('data', String(30)),
             Column('timestamp', Date),
             Column('value', MyCustomType))
-        
+
         meta.create_all()
-        
+
         test_table.insert().execute({'id':1, 'data':'somedata', 'timestamp':datetime.date(2007, 10, 15), 'value':25})
-        
+
     def tearDownAll(self):
         meta.drop_all()
-    
+
     def test_control(self):
         assert testbase.db.execute("select value from test").scalar() == 250
-        
+
         assert test_table.select().execute().fetchall() == [(1, 'somedata', datetime.date(2007, 10, 15), 25)]
-        
+
     def test_bind_adapt(self):
         expr = test_table.c.timestamp == bindparam("thedate")
         assert expr.right.type.__class__ == test_table.c.timestamp.type.__class__
-        
+
         assert testbase.db.execute(test_table.select().where(expr), {"thedate":datetime.date(2007, 10, 15)}).fetchall() == [(1, 'somedata', datetime.date(2007, 10, 15), 25)]
 
         expr = test_table.c.value == bindparam("somevalue")
         assert expr.right.type.__class__ == test_table.c.value.type.__class__
         assert testbase.db.execute(test_table.select().where(expr), {"somevalue":25}).fetchall() == [(1, 'somedata', datetime.date(2007, 10, 15), 25)]
-        
+
 
     def test_operator_adapt(self):
         """test type-based overloading of operators"""
-        
+
         # test string concatenation
         expr = test_table.c.data + "somedata"
         assert testbase.db.execute(select([expr])).scalar() == "somedatasomedata"
@@ -526,7 +534,7 @@ class ExpressionTest(AssertMixin):
         # test custom operator conversion
         expr = test_table.c.value + 40
         assert expr.type.__class__ is test_table.c.value.type.__class__
-        
+
         # + operator converted to -
         # value is calculated as: (250 - (40 * 10)) / 10 == -15
         assert testbase.db.execute(select([expr.label('foo')])).scalar() == -15
@@ -534,7 +542,7 @@ class ExpressionTest(AssertMixin):
         # this one relies upon anonymous labeling to assemble result
         # processing rules on the column.
         assert testbase.db.execute(select([expr])).scalar() == -15
-        
+
 class DateTest(AssertMixin):
     def setUpAll(self):
         global users_with_date, insert_data
@@ -651,19 +659,19 @@ class DateTest(AssertMixin):
             self.assert_(x.adatetime.__class__ == datetime.datetime)
 
             t.delete().execute()
-            
+
             # test mismatched date/datetime
             t.insert().execute(adate=d2, adatetime=d2)
             self.assertEquals(select([t.c.adate, t.c.adatetime], t.c.adate==d1).execute().fetchall(), [(d1, d2)])
             self.assertEquals(select([t.c.adate, t.c.adatetime], t.c.adate==d1).execute().fetchall(), [(d1, d2)])
-            
+
         finally:
             t.drop(checkfirst=True)
 
 class StringTest(AssertMixin):
     def test_nolen_string_deprecated(self):
         metadata = MetaData(testbase.db)
-        foo =Table('foo', metadata, 
+        foo =Table('foo', metadata,
             Column('one', String))
 
         import warnings
@@ -680,7 +688,7 @@ class StringTest(AssertMixin):
             assert False
         except SADeprecationWarning, e:
             assert "Using String type with no length" in str(e)
-        
+
         bar = Table('bar', metadata, Column('one', String(40)))
 
         try:
@@ -692,8 +700,8 @@ class StringTest(AssertMixin):
         finally:
             bar.drop()
             warnings.filterwarnings("always", r"Using String type with no length.*")
-            
-            
+
+
 class NumericTest(AssertMixin):
     def setUpAll(self):
         global numeric_table, metadata