Skip to content

Commit

Permalink
Fix column adaptation
Browse files Browse the repository at this point in the history
  • Loading branch information
kvesteri committed Jul 28, 2017
1 parent 2c044da commit 57f622b
Show file tree
Hide file tree
Showing 6 changed files with 45 additions and 8 deletions.
6 changes: 6 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@ Changelog
Here you can see the full list of changes between each SQLAlchemy-JSON-API release.


0.4.3 (2017-07-28)
^^^^^^^^^^^^^^^^^^

- Fixed column adaptation for hybrid / column properties returning Column objects


0.4.2 (2017-03-17)
^^^^^^^^^^^^^^^^^^

Expand Down
2 changes: 1 addition & 1 deletion sqlalchemy_json_api/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@
from .query_builder import QueryBuilder, RESERVED_KEYWORDS # noqa
from .utils import assert_json_document # noqa

__version__ = '0.4.2'
__version__ = '0.4.3'
5 changes: 2 additions & 3 deletions sqlalchemy_json_api/query_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
UnknownModel
)
from .utils import (
adapt,
chain_if,
get_attrs,
get_descriptor_columns,
Expand Down Expand Up @@ -529,9 +530,7 @@ def adapt_attribute(self, attr_name):
attr_name in hybrids or
attr_name in self.column_property_expressions
):
column = ClauseAdapter(self.from_obj).traverse(
getattr(self.model, attr_name)
)
column = adapt(self.from_obj, getattr(self.model, attr_name))
else:
column = getattr(cols, attr_name)
return self.format_column(column)
Expand Down
8 changes: 8 additions & 0 deletions sqlalchemy_json_api/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,14 @@

import sqlalchemy as sa
from sqlalchemy.orm.attributes import InstrumentedAttribute, QueryableAttribute
from sqlalchemy.sql.util import ClauseAdapter


def adapt(adapt_with, expression):
if isinstance(expression.expression, sa.Column):
cols = get_attrs(adapt_with)
return getattr(cols, expression.name)
return ClauseAdapter(adapt_with).traverse(expression)


def get_attrs(obj):
Expand Down
10 changes: 9 additions & 1 deletion tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -168,9 +168,17 @@ def article_cls(base, category_cls, user_cls):
class Article(base):
__tablename__ = 'article'
id = sa.Column(sa.Integer, primary_key=True)
name = sa.Column(sa.String)
_name = sa.Column('name', sa.String)
name_synonym = sa.orm.synonym('name')

@hybrid_property
def name(self):
return self._name

@name.setter
def name(self, name):
self._name = name

@hybrid_property
def name_upper(self):
return self.name.upper() if self.name else None
Expand Down
22 changes: 19 additions & 3 deletions tests/test_select.py
Original file line number Diff line number Diff line change
Expand Up @@ -429,10 +429,11 @@ def test_fields_parameter_with_hybrid_property(
assert session.execute(query).scalar() == result

@pytest.mark.parametrize(
('fields', 'result'),
('fields', 'should_contain_sql', 'result'),
(
(
{'articles': ['name_upper']},
'upper(main_query.name)',
{
'data': [{
'type': 'articles',
Expand All @@ -443,6 +444,19 @@ def test_fields_parameter_with_hybrid_property(
}]
}
),
(
{'articles': ['name']},
'main_query.name',
{
'data': [{
'type': 'articles',
'id': '1',
'attributes': {
'name': 'Some article'
}
}]
}
),
)
)
def test_hybrid_property_inclusion_uses_clause_adaptation(
Expand All @@ -451,15 +465,17 @@ def test_hybrid_property_inclusion_uses_clause_adaptation(
session,
article_cls,
fields,
result
result,
should_contain_sql
):
query = query_builder.select(
article_cls,
fields=fields,
from_obj=session.query(article_cls)
)
compiled = query.compile(dialect=sa.dialects.postgresql.dialect())
assert 'upper(main_query.name)' in str(compiled)
assert should_contain_sql in str(compiled)
assert session.execute(query).scalar() == result

@pytest.mark.parametrize(
('fields', 'include', 'result'),
Expand Down

0 comments on commit 57f622b

Please sign in to comment.