0.4 release

This commit is contained in:
Konsta Vesterinen
2013-03-15 10:02:28 +02:00
parent a1955c3a00
commit 37e1072787
4 changed files with 29 additions and 39 deletions

View File

@@ -5,6 +5,13 @@ Here you can see the full list of changes between each SQLAlchemy-Utils release.
0.4.0 (2013-03-01)
^^^^^^^^^^^^^^^^^^
- Renamed SmartList to InstrumentedList
- Added instrumented_list decorator
0.3.0 (2013-03-01)
^^^^^^^^^^^^^^^^^^

View File

@@ -24,7 +24,7 @@ class PyTest(Command):
setup(
name='SQLAlchemy-Utils',
version='0.3',
version='0.4',
url='https://github.com/kvesteri/sqlalchemy-utils',
license='BSD',
author='Konsta Vesterinen',

View File

@@ -1,39 +1,28 @@
from functools import wraps
from sqlalchemy.orm import defer
from sqlalchemy.orm.collections import InstrumentedList
from sqlalchemy.orm.collections import InstrumentedList as _InstrumentedList
from sqlalchemy.orm.mapper import Mapper
from sqlalchemy.orm.query import _ColumnEntity
from sqlalchemy.orm.properties import ColumnProperty
from sqlalchemy.sql.expression import desc, asc
class SmartList(InstrumentedList):
def has(self, attr):
"""
Returns True if any member of this collection has given attribute
defined.
class InstrumentedList(_InstrumentedList):
"""Enhanced version of SQLAlchemy InstrumentedList. Provides some
additional functionality."""
Example syntax:
def any(self, attr):
return any(getattr(item, attr) for item in self)
>>> Category.articles.has('name')
def all(self, attr):
return all(getattr(item, attr) for item in self)
:param attr: collection member attribute name
"""
adapter = self._sa_adapter
owner_class = adapter.owner_state.class_
relation = getattr(owner_class, adapter._key).property
relation_class = relation.mapper.class_
if not hasattr(relation_class, attr):
raise AttributeError(
'Class %s does not have attribute named %s' %
(relation_class.__name__, attr)
)
for record in self:
if getattr(record, attr):
return True
return False
def instrumented_list(f):
@wraps(f)
def wrapper(*args, **kwargs):
return InstrumentedList([item for item in f(*args, **kwargs)])
return wrapper
def sort_query(query, sort):

View File

@@ -1,11 +1,10 @@
from pytest import raises
import sqlalchemy as sa
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy_utils import escape_like, sort_query, SmartList
from sqlalchemy_utils import escape_like, sort_query, InstrumentedList
engine = create_engine(
@@ -34,27 +33,22 @@ class Article(Base):
primaryjoin=category_id == Category.id,
backref=sa.orm.backref(
'articles',
collection_class=SmartList
collection_class=InstrumentedList
)
)
class TestSmartList(object):
def test_has_raises_error_for_unknown_attribute(self):
category = Category()
with raises(AttributeError):
category.articles.has('unknown_column')
def test_has_returns_true_if_member_has_attr_defined(self):
class TestInstrumentedList(object):
def test_any_returns_true_if_member_has_attr_defined(self):
category = Category()
category.articles.append(Article())
category.articles.append(Article(name=u'some name'))
assert category.articles.has('name')
assert category.articles.any('name')
def test_has_returns_false_if_no_member_has_attr_defined(self):
def test_any_returns_false_if_no_member_has_attr_defined(self):
category = Category()
category.articles.append(Article())
assert not category.articles.has('name')
assert not category.articles.any('name')
class TestEscapeLike(object):