Add cast_if function
This commit is contained in:
@@ -4,6 +4,12 @@ Changelog
|
|||||||
Here you can see the full list of changes between each SQLAlchemy-Utils release.
|
Here you can see the full list of changes between each SQLAlchemy-Utils release.
|
||||||
|
|
||||||
|
|
||||||
|
0.30.14 (2015-07-23)
|
||||||
|
^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
- Added cast_if utility function
|
||||||
|
|
||||||
|
|
||||||
0.30.13 (2015-07-21)
|
0.30.13 (2015-07-21)
|
||||||
^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
@@ -4,6 +4,12 @@ ORM helpers
|
|||||||
.. module:: sqlalchemy_utils.functions
|
.. module:: sqlalchemy_utils.functions
|
||||||
|
|
||||||
|
|
||||||
|
cast_if
|
||||||
|
-------
|
||||||
|
|
||||||
|
.. autofunction:: cast_if
|
||||||
|
|
||||||
|
|
||||||
escape_like
|
escape_like
|
||||||
-----------
|
-----------
|
||||||
|
|
||||||
|
@@ -11,6 +11,7 @@ from .expression_parser import ExpressionParser # noqa
|
|||||||
from .expressions import Asterisk, row_to_json # noqa
|
from .expressions import Asterisk, row_to_json # noqa
|
||||||
from .functions import ( # noqa
|
from .functions import ( # noqa
|
||||||
analyze,
|
analyze,
|
||||||
|
cast_if,
|
||||||
create_database,
|
create_database,
|
||||||
create_mock_engine,
|
create_mock_engine,
|
||||||
database_exists,
|
database_exists,
|
||||||
@@ -92,4 +93,4 @@ from .types import ( # noqa
|
|||||||
WeekDaysType
|
WeekDaysType
|
||||||
)
|
)
|
||||||
|
|
||||||
__version__ = '0.30.13'
|
__version__ = '0.30.14'
|
||||||
|
@@ -19,6 +19,7 @@ from .foreign_keys import ( # noqa
|
|||||||
)
|
)
|
||||||
from .mock import create_mock_engine, mock_engine # noqa
|
from .mock import create_mock_engine, mock_engine # noqa
|
||||||
from .orm import ( # noqa
|
from .orm import ( # noqa
|
||||||
|
cast_if,
|
||||||
get_bind,
|
get_bind,
|
||||||
get_class_by_table,
|
get_class_by_table,
|
||||||
get_column_key,
|
get_column_key,
|
||||||
|
@@ -153,6 +153,57 @@ def get_type(expr):
|
|||||||
raise TypeError("Couldn't inspect type.")
|
raise TypeError("Couldn't inspect type.")
|
||||||
|
|
||||||
|
|
||||||
|
def cast_if(expression, type_):
|
||||||
|
"""
|
||||||
|
Produce a CAST expression but only if given expression is not of given type
|
||||||
|
already.
|
||||||
|
|
||||||
|
Assume we have a model with two fields id (Integer) and name (String).
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
import sqlalchemy as sa
|
||||||
|
from sqlalchemy_utils import cast_if
|
||||||
|
|
||||||
|
|
||||||
|
cast_if(User.id, sa.Integer) # "user".id
|
||||||
|
cast_if(User.name, sa.String) # "user".name
|
||||||
|
cast_if(User.id, sa.String) # CAST("user".id AS TEXT)
|
||||||
|
|
||||||
|
|
||||||
|
This function supports scalar values as well.
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
cast_if(1, sa.Integer) # 1
|
||||||
|
cast_if('text', sa.String) # 'text'
|
||||||
|
cast_if(1, sa.String) # CAST(1 AS TEXT)
|
||||||
|
|
||||||
|
|
||||||
|
:param expression:
|
||||||
|
A SQL expression, such as a ColumnElement expression or a Python string
|
||||||
|
which will be coerced into a bound literal value.
|
||||||
|
:param type_:
|
||||||
|
A TypeEngine class or instance indicating the type to which the CAST
|
||||||
|
should apply.
|
||||||
|
|
||||||
|
.. versionadded: 0.30.14
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
expr_type = get_type(expression)
|
||||||
|
except TypeError:
|
||||||
|
expr_type = expression
|
||||||
|
check_type = type_().python_type
|
||||||
|
else:
|
||||||
|
check_type = type_
|
||||||
|
|
||||||
|
return (
|
||||||
|
sa.cast(expression, type_)
|
||||||
|
if not isinstance(expr_type, check_type)
|
||||||
|
else expression
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def get_column_key(model, column):
|
def get_column_key(model, column):
|
||||||
"""
|
"""
|
||||||
Return the key for given column in given model.
|
Return the key for given column in given model.
|
||||||
|
46
tests/functions/test_cast_if.py
Normal file
46
tests/functions/test_cast_if.py
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
import pytest
|
||||||
|
import sqlalchemy as sa
|
||||||
|
from sqlalchemy.ext.declarative import declarative_base
|
||||||
|
|
||||||
|
from sqlalchemy_utils import cast_if
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(scope='class')
|
||||||
|
def base():
|
||||||
|
return declarative_base()
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(scope='class')
|
||||||
|
def article_cls(base):
|
||||||
|
class Article(base):
|
||||||
|
__tablename__ = 'article'
|
||||||
|
id = sa.Column(sa.Integer, primary_key=True)
|
||||||
|
name = sa.Column(sa.String)
|
||||||
|
name_synonym = sa.orm.synonym('name')
|
||||||
|
|
||||||
|
return Article
|
||||||
|
|
||||||
|
|
||||||
|
class TestCastIf(object):
|
||||||
|
def test_column(self, article_cls):
|
||||||
|
expr = article_cls.__table__.c.name
|
||||||
|
assert cast_if(expr, sa.String) is expr
|
||||||
|
|
||||||
|
def test_column_property(self, article_cls):
|
||||||
|
expr = article_cls.name.property
|
||||||
|
assert cast_if(expr, sa.String) is expr
|
||||||
|
|
||||||
|
def test_instrumented_attribute(self, article_cls):
|
||||||
|
expr = article_cls.name
|
||||||
|
assert cast_if(expr, sa.String) is expr
|
||||||
|
|
||||||
|
def test_synonym(self, article_cls):
|
||||||
|
expr = article_cls.name_synonym
|
||||||
|
assert cast_if(expr, sa.String) is expr
|
||||||
|
|
||||||
|
def test_scalar_selectable(self, article_cls):
|
||||||
|
expr = sa.select([article_cls.id]).as_scalar()
|
||||||
|
assert cast_if(expr, sa.Integer) is expr
|
||||||
|
|
||||||
|
def test_scalar(self):
|
||||||
|
assert cast_if('something', sa.String) == 'something'
|
Reference in New Issue
Block a user