Added get_type utility function

This commit is contained in:
Konsta Vesterinen
2015-06-05 14:29:48 +03:00
parent 810f38a26f
commit c0bd2c2bca
6 changed files with 107 additions and 2 deletions

View File

@@ -4,6 +4,12 @@ Changelog
Here you can see the full list of changes between each SQLAlchemy-Utils release.
0.30.9 (2015-06-05)
^^^^^^^^^^^^^^^^^^^
- Added get_type utility function
0.30.8 (2015-06-05)
^^^^^^^^^^^^^^^^^^^

View File

@@ -70,6 +70,12 @@ get_tables
.. autofunction:: get_tables
get_type
--------
.. autofunction:: get_type
has_changes
-----------

View File

@@ -28,6 +28,7 @@ from .functions import ( # noqa
get_query_entities,
get_referencing_foreign_keys,
get_tables,
get_type,
group_foreign_keys,
has_changes,
has_index,
@@ -91,4 +92,4 @@ from .types import ( # noqa
WeekDaysType
)
__version__ = '0.30.8'
__version__ = '0.30.9'

View File

@@ -29,6 +29,7 @@ from .orm import ( # noqa
get_primary_keys,
get_query_entities,
get_tables,
get_type,
getdotattr,
has_changes,
identity,

View File

@@ -14,7 +14,7 @@ from sqlalchemy.ext.hybrid import hybrid_property
from sqlalchemy.orm import mapperlib
from sqlalchemy.orm.attributes import InstrumentedAttribute
from sqlalchemy.orm.exc import UnmappedInstanceError
from sqlalchemy.orm.properties import ColumnProperty
from sqlalchemy.orm.properties import ColumnProperty, RelationshipProperty
from sqlalchemy.orm.query import _ColumnEntity
from sqlalchemy.orm.session import object_session
from sqlalchemy.orm.util import AliasedInsp
@@ -105,6 +105,54 @@ def get_class_by_table(base, table, data=None):
return None
def get_type(expr):
"""
Return the associated type with given Column, InstrumentedAttribute,
ColumnProperty, RelationshipProperty or other similar SQLAlchemy construct.
For constructs wrapping columns this is the column type. For relationships
this function returns the relationship mapper class.
:param expr:
SQLAlchemy Column, InstrumentedAttribute, ColumnProperty or other
similar SA construct.
::
class User(Base):
__tablename__ = 'user'
id = sa.Column(sa.Integer, primary_key=True)
name = sa.Column(sa.String)
class Article(Base):
__tablename__ = 'article'
id = sa.Column(sa.Integer, primary_key=True)
author_id = sa.Column(sa.Integer, sa.ForeignKey(User.id))
author = sa.orm.relationship(User)
get_type(User.__table__.c.name) # sa.String()
get_type(User.name) # sa.String()
get_type(User.name.property) # sa.String()
get_type(Article.author) # User
.. versionadded: 0.30.9
"""
if hasattr(expr, 'type'):
return expr.type
elif isinstance(expr, InstrumentedAttribute):
expr = expr.property
if isinstance(expr, ColumnProperty):
return expr.columns[0].type
elif isinstance(expr, RelationshipProperty):
return expr.mapper.class_
raise TypeError("Couldn't inspect type.")
def get_column_key(model, column):
"""
Return the key for given column in given model.

View File

@@ -0,0 +1,43 @@
import sqlalchemy as sa
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy_utils import get_type
from tests import TestCase
class TestGetType(object):
def setup_method(self, method):
Base = declarative_base()
class User(Base):
__tablename__ = 'user'
id = sa.Column(sa.Integer, primary_key=True)
class Article(Base):
__tablename__ = 'article'
id = sa.Column(sa.Integer, primary_key=True)
author_id = sa.Column(sa.Integer, sa.ForeignKey(User.id))
author = sa.orm.relationship(User)
some_property = sa.orm.column_property(
sa.func.coalesce(id, 1)
)
self.Article = Article
self.User = User
def test_instrumented_attribute(self):
assert isinstance(get_type(self.Article.id), sa.Integer)
def test_column_property(self):
assert isinstance(get_type(self.Article.id.property), sa.Integer)
def test_column(self):
assert isinstance(get_type(self.Article.__table__.c.id), sa.Integer)
def test_calculated_column_property(self):
assert isinstance(get_type(self.Article.some_property), sa.Integer)
def test_relationship_property(self):
assert get_type(self.Article.author) == self.User