]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
- Added accessor to types called "python_type",
authorMike Bayer <mike_mp@zzzcomputing.com>
Sun, 23 Oct 2011 17:05:56 +0000 (13:05 -0400)
committerMike Bayer <mike_mp@zzzcomputing.com>
Sun, 23 Oct 2011 17:05:56 +0000 (13:05 -0400)
returns the rudimentary Python type object
for a particular TypeEngine instance, if known,
else raises NotImplementedError.  [ticket:77]

CHANGES
lib/sqlalchemy/types.py
test/sql/test_types.py

diff --git a/CHANGES b/CHANGES
index 7dea5bae31dacd1571d16f47f8f6de9ed2218c6e..52ba8cdc9457a659aaaaeb03606b63c65a455ef0 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -18,6 +18,12 @@ CHANGES
    - Cls.column.collate("some collation") now
      works.  [ticket:1776]  Also in 0.6.9
 
+- sql
+   - Added accessor to types called "python_type",
+     returns the rudimentary Python type object
+     for a particular TypeEngine instance, if known,
+     else raises NotImplementedError.  [ticket:77]
+
 0.7.3
 =====
 - general
index 5c9ea99c3b98ea8c85bb391578b488d2153b5de4..e58313466aa7e8e02b1133c75364660775487164 100644 (file)
@@ -112,6 +112,25 @@ class TypeEngine(AbstractType):
         """
         return None
 
+    @property
+    def python_type(self):
+        """Return the Python type object expected to be returned
+        by instances of this type, if known.   
+        
+        Basically, for those types which enforce a return type,
+        or are known across the board to do such for all common 
+        DBAPIs (like ``int`` for example), will return that type.
+        
+        If a return type is not defined, raises
+        ``NotImplementedError``.
+        
+        Note that any type also accommodates NULL in SQL which
+        means you can also get back ``None`` from any type
+        in practice.
+
+        """
+        raise NotImplementedError()
+
     def with_variant(self, type_, dialect_name):
         """Produce a new type object that will utilize the given 
         type when applied to the dialect of the given name.
@@ -1069,6 +1088,13 @@ class String(Concatenable, TypeEngine):
         else:
             return None
 
+    @property
+    def python_type(self):
+        if self.convert_unicode:
+            return unicode
+        else:
+            return str
+
     def get_dbapi_type(self, dbapi):
         return dbapi.STRING
 
@@ -1176,6 +1202,10 @@ class Integer(_DateAffinity, TypeEngine):
     def get_dbapi_type(self, dbapi):
         return dbapi.NUMBER
 
+    @property
+    def python_type(self):
+        return int
+
     @util.memoized_property
     def _expression_adaptations(self):
         # TODO: need a dictionary object that will
@@ -1311,6 +1341,13 @@ class Numeric(_DateAffinity, TypeEngine):
     def get_dbapi_type(self, dbapi):
         return dbapi.NUMBER
 
+    @property
+    def python_type(self):
+        if self.asdecimal:
+            return decimal.Decimal
+        else:
+            return float
+
     def bind_processor(self, dialect):
         if dialect.supports_native_decimal:
             return None
@@ -1456,6 +1493,10 @@ class DateTime(_DateAffinity, TypeEngine):
     def get_dbapi_type(self, dbapi):
         return dbapi.DATETIME
 
+    @property
+    def python_type(self):
+        return dt.datetime
+
     @util.memoized_property
     def _expression_adaptations(self):
         return {
@@ -1477,6 +1518,10 @@ class Date(_DateAffinity,TypeEngine):
     def get_dbapi_type(self, dbapi):
         return dbapi.DATETIME
 
+    @property
+    def python_type(self):
+        return dt.date
+
     @util.memoized_property
     def _expression_adaptations(self):
         return {
@@ -1513,6 +1558,10 @@ class Time(_DateAffinity,TypeEngine):
     def get_dbapi_type(self, dbapi):
         return dbapi.DATETIME
 
+    @property
+    def python_type(self):
+        return dt.time
+
     @util.memoized_property
     def _expression_adaptations(self):
         return {
@@ -1533,6 +1582,14 @@ class _Binary(TypeEngine):
     def __init__(self, length=None):
         self.length = length
 
+    @property
+    def python_type(self):
+        #Py3K
+        #return bytes
+        # Py2K
+        return str
+        # end Py2K
+
     # Python 3 - sqlite3 doesn't need the `Binary` conversion
     # here, though pg8000 does to indicate "bytea"
     def bind_processor(self, dialect):
@@ -1948,6 +2005,10 @@ class Boolean(TypeEngine, SchemaType):
                     )
         table.append_constraint(e)
 
+    @property
+    def python_type(self):
+        return bool
+
     def bind_processor(self, dialect):
         if dialect.supports_native_boolean:
             return None
@@ -2014,6 +2075,10 @@ class Interval(_DateAffinity, TypeDecorator):
                         day_precision=self.day_precision,
                         **kw)
 
+    @property
+    def python_type(self):
+        return dt.timedelta
+
     def bind_processor(self, dialect):
         impl_processor = self.impl.bind_processor(dialect)
         epoch = self.epoch
index 77d6bb50638a73061dce692c47bd68f98e47f862..50cb0ba06684dcdbde9be5ec7eec17a572794b58 100644 (file)
@@ -130,6 +130,32 @@ class AdaptTest(fixtures.TestBase):
                         getattr(t2, k) == t1.__dict__[k] or \
                         t1.__dict__[k] is None
 
+    def test_python_type(self):
+        eq_(types.Integer().python_type, int)
+        eq_(types.Numeric().python_type, decimal.Decimal)
+        eq_(types.Numeric(asdecimal=False).python_type, float)
+        # Py3K
+        #eq_(types.LargeBinary().python_type, bytes)
+        # Py2K
+        eq_(types.LargeBinary().python_type, str)
+        # end Py2K
+        eq_(types.Float().python_type, float)
+        eq_(types.Interval().python_type, datetime.timedelta)
+        eq_(types.Date().python_type, datetime.date)
+        eq_(types.DateTime().python_type, datetime.datetime)
+        # Py3K
+        #eq_(types.String().python_type, unicode)
+        # Py2K
+        eq_(types.String().python_type, str)
+        # end Py2K
+        eq_(types.Unicode().python_type, unicode)
+        eq_(types.String(convert_unicode=True).python_type, unicode)
+
+        assert_raises(
+            NotImplementedError,
+            lambda: types.TypeEngine().python_type
+        )
+
     @testing.uses_deprecated()
     def test_repr(self):
         for typ in self._all_types():