[Sqlalchemy-commits] sqlalchemy: - Added accessor to types called "python_type",
Brought to you by:
zzzeek
From: <co...@sq...> - 2011-10-23 17:06:12
|
details: http://hg.sqlalchemy.org/sqlalchemy/sqlalchemy/rev/f9004bb16b94 changeset: 7893:f9004bb16b94 user: zzzeek date: Sun Oct 23 13:05:56 2011 -0400 description: - 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] diffstat: CHANGES | 6 ++++ lib/sqlalchemy/types.py | 65 +++++++++++++++++++++++++++++++++++++++++++++++++ test/sql/test_types.py | 26 +++++++++++++++++++ 3 files changed, 97 insertions(+), 0 deletions(-) diffs (190 lines): diff -r 0e0e14a38554 -r f9004bb16b94 CHANGES --- a/CHANGES Sun Oct 23 12:02:58 2011 -0400 +++ b/CHANGES Sun Oct 23 13:05:56 2011 -0400 @@ -18,6 +18,12 @@ - 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 diff -r 0e0e14a38554 -r f9004bb16b94 lib/sqlalchemy/types.py --- a/lib/sqlalchemy/types.py Sun Oct 23 12:02:58 2011 -0400 +++ b/lib/sqlalchemy/types.py Sun Oct 23 13:05:56 2011 -0400 @@ -112,6 +112,25 @@ """ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ ) 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 @@ 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 diff -r 0e0e14a38554 -r f9004bb16b94 test/sql/test_types.py --- a/test/sql/test_types.py Sun Oct 23 12:02:58 2011 -0400 +++ b/test/sql/test_types.py Sun Oct 23 13:05:56 2011 -0400 @@ -130,6 +130,32 @@ 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(): |