More efficient contains method for proxy dict

This commit is contained in:
Konsta Vesterinen
2013-06-05 13:38:42 +03:00
parent 46b19bfdbd
commit e181292bb5
5 changed files with 51 additions and 18 deletions

View File

@@ -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.12.5 (2013-06-05)
^^^^^^^^^^^^^^^^^^^
- ProxyDict now contains None values in cache - more efficient contains method.
0.12.4 (2013-06-01) 0.12.4 (2013-06-01)
^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^

View File

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

View File

@@ -18,10 +18,9 @@ class ProxyDict(object):
return [x[0] for x in self.collection.values(descriptor)] return [x[0] for x in self.collection.values(descriptor)]
def __contains__(self, key): def __contains__(self, key):
try: if key in self.cache:
return key in self.cache or self.fetch(key) is not None return self.cache[key] is not None
except KeyError: return self.fetch(key) is not None
return False
def has_key(self, key): def has_key(self, key):
return self.__contains__(key) return self.__contains__(key)
@@ -29,7 +28,9 @@ class ProxyDict(object):
def fetch(self, key): def fetch(self, key):
session = sa.orm.object_session(self.parent) session = sa.orm.object_session(self.parent)
if session and sa.orm.util.has_identity(self.parent): if session and sa.orm.util.has_identity(self.parent):
return self.collection.filter_by(**{self.key_name: key}).first() obj = self.collection.filter_by(**{self.key_name: key}).first()
self.cache[key] = obj
return obj
def create_new_instance(self, key): def create_new_instance(self, key):
value = self.child_class(**{self.key_name: key}) value = self.child_class(**{self.key_name: key})
@@ -39,8 +40,9 @@ class ProxyDict(object):
def __getitem__(self, key): def __getitem__(self, key):
if key in self.cache: if key in self.cache:
if self.cache[key] is not None:
return self.cache[key] return self.cache[key]
else:
value = self.fetch(key) value = self.fetch(key)
if value: if value:
return value return value

View File

@@ -5,31 +5,37 @@ from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy_utils import ( from sqlalchemy_utils import (
escape_like,
sort_query,
InstrumentedList, InstrumentedList,
PhoneNumber,
PhoneNumberType, PhoneNumberType,
merge
) )
@sa.event.listens_for(sa.engine.Engine, 'before_cursor_execute')
def count_sql_calls(conn, cursor, statement, parameters, context, executemany):
try:
conn.query_count += 1
except AttributeError:
conn.query_count = 0
class TestCase(object): class TestCase(object):
def setup_method(self, method): def setup_method(self, method):
self.engine = create_engine( self.engine = create_engine(
'postgres://postgres@localhost/sqlalchemy_utils_test' 'postgres://postgres@localhost/sqlalchemy_utils_test'
) )
self.connection = self.engine.connect()
self.Base = declarative_base() self.Base = declarative_base()
self.create_models() self.create_models()
self.Base.metadata.create_all(self.engine) self.Base.metadata.create_all(self.connection)
Session = sessionmaker(bind=self.engine) Session = sessionmaker(bind=self.connection)
self.session = Session() self.session = Session()
def teardown_method(self, method): def teardown_method(self, method):
self.session.close_all() self.session.close_all()
self.Base.metadata.drop_all(self.engine) self.Base.metadata.drop_all(self.connection)
self.connection.close()
self.engine.dispose() self.engine.dispose()
def create_models(self): def create_models(self):

View File

@@ -79,6 +79,25 @@ class TestProxyDict(TestCase):
) )
article.translations['en'] article.translations['en']
def test_contains_efficiency(self):
article = self.Article()
self.session.add(article)
self.session.commit()
article.id
query_count = self.connection.query_count
'en' in article.translations
'en' in article.translations
'en' in article.translations
assert self.connection.query_count == query_count + 1
def test_getitem_with_none_value_in_cache(self):
article = self.Article()
self.session.add(article)
self.session.commit()
article.id
'en' in article.translations
assert article.translations['en']
def test_contains(self): def test_contains(self):
article = self.Article() article = self.Article()
assert 'en' not in article.translations assert 'en' not in article.translations