Skip to content

Commit

Permalink
Merge pull request #3 from AppsFuel/master
Browse files Browse the repository at this point in the history
Review for Reding
  • Loading branch information
mindflayer committed Sep 14, 2013
2 parents 560935f + 7a5a982 commit fb053d4
Show file tree
Hide file tree
Showing 7 changed files with 325 additions and 384 deletions.
1 change: 1 addition & 0 deletions .gitignore
Expand Up @@ -4,3 +4,4 @@ Reding.egg-info/
.cache/
.coverage
VENV/
.idea/
32 changes: 21 additions & 11 deletions README.md
Expand Up @@ -49,7 +49,8 @@ Server: mindflayer
"vote": 10,
"when": "Fri, 01 Feb 2013 17:57:44 -0000",
"user_id": "gsalluzzo",
"object_id": "978-0132678209"
"object_id": "978-0132678209",
"review": null
}
```
Ehy hackers, I've just used a PUT call, but yes, I know, it's the first vote, I should use a POST one. Reding maps POST method on the PUT one, so the client does not need to know if it's the first time I'm voting this object.
Expand All @@ -68,7 +69,8 @@ Server: mindflayer
"vote": 9,
"when": "Fri, 01 Feb 2013 18:03:16 -0000",
"user_id": "gsalluzzo",
"object_id": "978-0132678209"
"object_id": "978-0132678209",
"review": null
}
```

Expand Down Expand Up @@ -104,7 +106,8 @@ Server: mindflayer
"vote": 10,
"when": "Fri, 01 Feb 2013 18:08:03 -0000",
"user_id": "wchun",
"object_id": "978-0132678209"
"object_id": "978-0132678209",
"review": null
}
```
The author said '10'! What a surprise! :D
Expand Down Expand Up @@ -159,7 +162,8 @@ Server: mindflayer
"vote": 9,
"when": "Fri, 01 Feb 2013 18:03:16 -0000",
"user_id": "gsalluzzo",
"object_id": "978-0132678209"
"object_id": "978-0132678209",
"review": null
}
```

Expand Down Expand Up @@ -187,7 +191,8 @@ Server: mindflayer
"vote": 3,
"when": "Fri, 01 Feb 2013 18:15:38 -0000",
"user_id": "mymom",
"object_id": "978-0132678209"
"object_id": "978-0132678209",
"review": null
}
```

Expand All @@ -209,9 +214,10 @@ Server: mindflayer
}
```

Well, stop programming books...I'm gonna give a '10' to the amazing 'The Lord of the Rings Sketchbook':
Well, stop programming books...I'm gonna give a '10' to the amazing 'The Lord of the Rings Sketchbook',
but this time let me add a review:
```
$ curl -i -XPUT http://localhost:5000/objects/978-0618640140/users/gsalluzzo/ -d "vote=10"
$ curl -i -XPUT http://localhost:5000/objects/978-0618640140/users/gsalluzzo/ -d "vote=10&review=the ☃ loves lotr"
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 110
Expand All @@ -223,11 +229,13 @@ Server: mindflayer
"vote": 10,
"when": "Fri, 01 Feb 2013 18:21:56 -0000",
"user_id": "gsalluzzo",
"object_id": "978-0618640140"
"object_id": "978-0618640140",
"review": "the ☃ loves lotr"
}
}
```

Let's see the books I voted:
Let's see the books I voted and what I wrote about them:
```
$ curl -i http://localhost:5000/users/gsalluzzo/
HTTP/1.1 200 OK
Expand All @@ -241,12 +249,14 @@ Server: mindflayer
"vote": 9,
"when": "Fri, 01 Feb 2013 18:03:16 -0000",
"user_id": "gsalluzzo",
"object_id": "978-0132678209"
"object_id": "978-0132678209",
"review": null
}, {
"vote": 10,
"when": "Fri, 01 Feb 2013 18:21:56 -0000",
"user_id": "gsalluzzo",
"object_id": "978-0618640140"
"object_id": "978-0618640140",
"review": "the ☃ loves lotr"
}]
```

Expand Down
173 changes: 173 additions & 0 deletions reding/managers.py
@@ -0,0 +1,173 @@
from datetime import datetime
import redis
from reding.settings import KEY_CONFIG, REDIS_CONFIG
rclient = redis.StrictRedis(**REDIS_CONFIG)


def get_key_name(template, **kw):
d = KEY_CONFIG.copy()
d.update(dict((key, value) for (key, value) in kw.iteritems() if value))
return template.format(**d)


def zrange(start, end, reverse):
if not reverse:
return rclient.zrangebyscore, start, end
else:
return rclient.zrevrangebyscore, end, start


class ObjectSubjectsManager(object):
def __init__(self, **kwargs):
self.template = get_key_name('{prefix}:{object}:{{object_id}}:{subjects}', **kwargs)
self.template_review = get_key_name('{prefix}:{object}:{{object_id}}:review:{subjects}', **kwargs)

def count(self, object_id, min_vote='-inf', max_vote='+inf'):
return rclient.zcount(
name=self.template.format(object_id=object_id),
min=min_vote,
max=max_vote,
)

def scoredrange(self, object_id, offset, size, min_vote='-inf', max_vote='+inf', reverse=False):
func, min_vote, max_vote = zrange(min_vote, max_vote, reverse)
return func(
name=self.template.format(object_id=object_id),
min=min_vote,
max=max_vote,
start=offset,
num=size,
withscores=True,
)

def score(self, object_id, user_id):
return rclient.zscore(
name=self.template.format(object_id=object_id),
value=user_id,
)

def review(self, object_id, user_id):
return rclient.hget(
name=self.template_review.format(object_id=object_id),
key=user_id,
)

def reviews(self, object_id, *user_ids):
return dict(zip(user_ids, rclient.hmget(
self.template_review.format(object_id=object_id), user_ids
)))

def create(self, object_id, user_id, vote, review):
rclient.zadd(
self.template.format(object_id=object_id),
vote,
user_id,
)
name = self.template_review.format(object_id=object_id)
if review:
rclient.hset(name, user_id, review)
else:
rclient.hdel(name, user_id)

def remove(self, object_id, user_id):
rclient.zrem(
self.template.format(object_id=object_id),
user_id,
)
rclient.hdel(
self.template_review.format(object_id=object_id),
user_id,
)


class SubjectObjectsManager(object):
def __init__(self, **kwargs):
self.template = get_key_name('{prefix}:{subject}:{{user_id}}:{objects}', **kwargs)

def scoredrange(self, user_id, offset, size, min_vote='-inf', max_vote='+inf', reverse=False):
func, min_vote, max_vote = zrange(min_vote, max_vote, reverse)
scored = func(
name=self.template.format(user_id=user_id),
min=min_vote,
max=max_vote,
start=offset,
num=size,
withscores=True,
)
return [(k, datetime.fromtimestamp(v)) for k, v in scored]

def score(self, user_id, object_id):
try:
return datetime.fromtimestamp(rclient.zscore(
name=self.template.format(user_id=user_id),
value=object_id,
))
except TypeError:
return 0

def create(self, user_id, object_id, timestamp):
rclient.zadd(
self.template.format(user_id=user_id),
timestamp,
object_id,
)

def remove(self, user_id, object_id):
rclient.zrem(
self.template.format(user_id=user_id),
object_id,
)


class ObjectsManager(object):
def __init__(self, **kwargs):
self.template = get_key_name('{prefix}:{objects}', **kwargs)

def scoredrange(self, offset, size, min_vote='-inf', max_vote='+inf', reverse=False):
func, min_vote, max_vote = zrange(min_vote, max_vote, reverse)
return func(
name=self.template,
min=min_vote,
max=max_vote,
start=offset,
num=size,
withscores=True,
)

def score(self, object_id):
return rclient.zscore(
name=self.template,
value=object_id,
)

def incrby(self, object_id, delta):
rclient.zincrby(
name=self.template,
value=object_id,
amount=delta,
)

def remove(self, object_id):
rclient.zrem(
self.template,
object_id,
)

def filtered(self, objects, now, reverse):
if not objects:
return []

tmp_key = '{0}:tmp:{1}'.format(self.template, now)
tmp_dest_key = '{0}:tmp_dest:{1}'.format(self.template, now)

rclient.sadd(tmp_key, *objects)
rclient.zinterstore(tmp_dest_key, (self.template, tmp_key), aggregate='SUM')

if reverse:
zsorted = rclient.zrevrangebyscore(tmp_dest_key, '+inf', '-inf')
else:
zsorted = rclient.zrangebyscore(tmp_dest_key, '-inf', '+inf')

rclient.delete(tmp_key, tmp_dest_key)

return zsorted + list(set(objects).difference(set(zsorted)))

0 comments on commit fb053d4

Please sign in to comment.