diff --git a/redisco/containers.py b/redisco/containers.py index 7137fcb..79c2e5c 100644 --- a/redisco/containers.py +++ b/redisco/containers.py @@ -65,9 +65,9 @@ def set_expire(self, time=None): @property def db(self): - if self.pipeline: + if self.pipeline is not None: return self.pipeline - if self._db: + if self._db is not None: return self._db if hasattr(self, 'db_cache') and self.db_cache: return self.db_cache @@ -84,6 +84,11 @@ class Set(Container): This class represent a Set in redis. """ + + def __repr__(self): + return "<%s '%s' %s>" % (self.__class__.__name__, self.key, + self.members) + def sadd(self, *values): """ Add the specified members to the Set. @@ -115,7 +120,7 @@ def srem(self, *values): >>> s.add(["1", "2", "3"]) 3 >>> s.srem(["1", "3"]) - True + 2 >>> s.clear() """ @@ -138,9 +143,9 @@ def spop(self): """ return self.db.spop(self.key) - def __repr__(self): - return "<%s '%s' %s>" % (self.__class__.__name__, self.key, - self.members) + #def __repr__(self): + # return "<%s '%s' %s>" % (self.__class__.__name__, self.key, + # self.members) def isdisjoint(self, other): """ @@ -806,23 +811,29 @@ def __iter__(self): def __reversed__(self): return self.revmembers.__iter__() - def __repr__(self): - return "<%s '%s' %s>" % (self.__class__.__name__, self.key, - self.members) + # def __repr__(self): + # return "<%s '%s' %s>" % (self.__class__.__name__, self.key, + # self.members) @property def _min_score(self): """ Returns the minimum score in the SortedSet. """ - return self.zscore(self.__getitem__(0)) + try: + return self.zscore(self.__getitem__(0)) + except IndexError: + return None @property def _max_score(self): """ Returns the maximum score in the SortedSet. """ - return self.zscore(self.__getitem__(-1)) + try: + self.zscore(self.__getitem__(-1)) + except IndexError: + return None def lt(self, v, limit=None, offset=None): """ @@ -835,7 +846,7 @@ def lt(self, v, limit=None, offset=None): """ if limit is not None and offset is None: offset = 0 - return self.zrangebyscore(self._min_score, "(%f" % v, + return self.zrangebyscore("-inf", "(%f" % v, start=offset, num=limit) def le(self, v, limit=None, offset=None): @@ -850,19 +861,19 @@ def le(self, v, limit=None, offset=None): """ if limit is not None and offset is None: offset = 0 - return self.zrangebyscore(self._min_score, v, + return self.zrangebyscore("-inf", v, start=offset, num=limit) - def gt(self, v, limit=None, offset=None): + def gt(self, v, limit=None, offset=None, withscores=False): """Returns the list of the members of the set that have scores greater than v. """ if limit is not None and offset is None: offset = 0 - return self.zrangebyscore("(%f" % v, self._max_score, - start=offset, num=limit) + return self.zrangebyscore("(%f" % v, "+inf", + start=offset, num=limit, withscores=withscores) - def ge(self, v, limit=None, offset=None): + def ge(self, v, limit=None, offset=None, withscores=False): """Returns the list of the members of the set that have scores greater than or equal to v. @@ -873,8 +884,8 @@ def ge(self, v, limit=None, offset=None): """ if limit is not None and offset is None: offset = 0 - return self.zrangebyscore("(%f" % v, self._max_score, - start=offset, num=limit) + return self.zrangebyscore("%f" % v, "+inf", + start=offset, num=limit, withscores=withscores) def between(self, min, max, limit=None, offset=None): """ @@ -939,7 +950,7 @@ def zrem(self, *values): >>> s.add('a', 10) 1 >>> s.zrem('a') - True + 1 >>> s.members [] >>> s.clear() @@ -1036,6 +1047,23 @@ def zrangebyscore(self, min, max, **kwargs): """ return self.db.zrangebyscore(self.key, min, max, **kwargs) + def zrevrangebyscore(self, max, min, **kwargs): + """ + Returns the range of elements included between the scores (min and max) + + >>> s = SortedSet("foo") + >>> s.add('a', 10) + 1 + >>> s.add('b', 20) + 1 + >>> s.add('c', 30) + 1 + >>> s.zrangebyscore(20, 20) + ['b'] + >>> s.clear() + """ + return self.db.zrevrangebyscore(self.key, max, min, **kwargs) + def zcard(self): """ Returns the cardinality of the SortedSet. @@ -1199,7 +1227,7 @@ def hdel(self, *members): >>> h.hset("bar", "value") 1L >>> h.hdel("bar") - True + 1 >>> h.clear() """ return self.db.hdel(self.key, *_parse_values(members)) diff --git a/redisco/models/modelset.py b/redisco/models/modelset.py index 6f0a4d4..b3d8549 100644 --- a/redisco/models/modelset.py +++ b/redisco/models/modelset.py @@ -286,10 +286,9 @@ def _set(self): # For performance reasons, only one zfilter is allowed. if hasattr(self, '_cached_set'): return self._cached_set + s = Set(self.key) if self._zfilters: - self._cached_set = self._add_zfilters() - return self._cached_set - s = Set(self.key, db=self.db) + s = self._add_zfilters(s) if self._filters: s = self._add_set_filter(s) if self._exclusions: @@ -346,7 +345,7 @@ def _add_set_exclusions(self, s): new_set.set_expire() return new_set - def _add_zfilters(self): + def _add_zfilters(self, s): """ This function is the internals of the zfilter function. It will create a SortedSet and will compare the scores to @@ -355,7 +354,6 @@ def _add_zfilters(self): :return: a SortedSet with the ids. """ - k, v = self._zfilters[0].items()[0] try: att, op = k.split('__') @@ -365,6 +363,9 @@ def _add_zfilters(self): desc = self.model_class._attributes[att] zset = SortedSet(index, db=self.db) limit, offset = self._get_limit_and_offset() + new_set_key = "~%s.%s" % ("+".join([self.key, att, op]), id(self)) + new_set_key_temp = "#%s.%s" % ("+".join([self.key, att, op]), id(self)) + members = [] if isinstance(v, (tuple, list,)): min, max = v min = float(desc.typecast_for_storage(min)) @@ -372,15 +373,27 @@ def _add_zfilters(self): else: v = float(desc.typecast_for_storage(v)) if op == 'lt': - return zset.lt(v, limit, offset) + members = zset.lt(v, limit, offset) elif op == 'gt': - return zset.gt(v, limit, offset) + members = zset.gt(v, limit, offset) elif op == 'gte': - return zset.ge(v, limit, offset) + members = zset.ge(v, limit, offset) + elif op == 'le': + members = zset.le(v, limit, offset) elif op == 'lte': - return zset.le(v, limit, offset) + members = zset.le(v, limit, offset) elif op == 'in': - return zset.between(min, max, limit, offset) + members = zset.between(min, max, limit, offset) + + temp_set = Set(new_set_key_temp) + if members: + temp_set.add(*members) + temp_set.set_expire() + + s.intersection(new_set_key, temp_set) + new_set = Set(new_set_key) + new_set.set_expire() + return new_set def _order(self, skey): """ @@ -499,4 +512,3 @@ def _clone(self): c._limit = self._limit c._offset = self._offset return c - diff --git a/requirements.txt b/requirements.txt index f1857b7..65e8e30 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,3 @@ -DateUtils==0.5.2 +DateUtils==0.6.6 hiredis==0.1.1 -redis>=2.4.13 +redis>=2.7.5 diff --git a/setup.py b/setup.py index a10421d..4daeb5d 100644 --- a/setup.py +++ b/setup.py @@ -1,7 +1,7 @@ #!/usr/bin/env python import os -version = '0.2.0' +version = '0.2.4' try: from setuptools import setup