Today I’d like to present the latest version of Mocket through a simple, and hopefully not too boring, example.
Source: http://www.dhgate.com/product/home-office-wall-socket-hidden-covert-camera/233012186.html
For a brief presentation of Mocket read my previous blogpost.
First of all, we need a new virtualenv
.
virtualenv -p python3 todossource todos/bin/activatecd todos
We also need some packages.
pip install requests redis mocket ipython
Extra requirement: a Redis database running locally. On a modern Ubuntu box, installing it it’s simple as firing a
sudo apt install redis-server redis-tools
You can monitor Redis using redis-cli
, typing MONITOR
as first command inside the CLI.
Now it’s time to see something Pythonic. It’s a simple story, with some users and the posts they published, available through a JSON API. With these data, we want to do some counting using IPython and a bunch of Redis commands, to see how users performed as writers.
These are the lines we need to bootstrap the project.
from collections import Counterimport requestsimport redis
# get all usersusers = requests.get('http://jsonplaceholder.typicode.com/users').json()
# users will be retrieved by userIdusers_by_id = {u['id']: u for u in users}
todos = requests.get('http://jsonplaceholder.typicode.com/todos').json()
# let's put some salt and pepper, skipping some todosfiltered_todos = [t for t in todos if 'et' in t['title']]
Copying and pasting them in a IPython session, you should be able to get what follows:
In [9]: len(users_by_id)Out[9]: 10
In [10]: len(filtered_todos)Out[10]: 62
We need a Counter instance, to count how many posts each user has already published.
# use a counter for user todosuser_todos = Counter()for t in random_todos:user_todos[t['userId']] += 1
Again, IPython should show our Counter representation:
In [11]: user_todosOut[11]: Counter({1: 6, 2: 4, 3: 7, 4: 5, 5: 8, 6: 8, 7: 7, 8: 7, 9: 5, 10: 5})
In our case User #5 and #6 are the most productive since they published 8 posts each.
Time for some Redis commands.
# it's going to connect to localhost on port 6379r = redis.StrictRedis()
# be careful when you flush your DB# in case you need it, it's as simple as# r.flushdb()
for k, v in user_todos.items():r.zadd('todos', v, users_by_id[k]['username'])
We have just populated a Redis sorted set with a counter similar to the previous, but using usernames as key.
On IPython we can see what happened:
In [12]: r.zrange('todos', 0, len(todos), desc=True, withscores=True)Out[12]:[(b'Leopoldo_Corkery', 8.0),(b'Kamren', 8.0),(b'Samantha', 7.0),(b'Maxime_Nienow', 7.0),(b'Elwyn.Skiles', 7.0),(b'Bret', 6.0),(b'Moriah.Stanton', 5.0),(b'Karianne', 5.0),(b'Delphine', 5.0),(b'Antonette', 4.0)]
Here are our users, with their username. You see the two top posters we spotted in the Counter. Time for Mocket, and its new recording feature. Let’s add a couple of line to the first script, just after the import definitions.
from collections import Counterimport requestsimport redisfrom mocket import Mocket
Mocket.enable('example', '.')
# get all usersusers = requests.get('http://jsonplaceholder.typicode.com/users').json()
[...]
The classic way of using Mocket was about defining a bunch of Entry instances -aka mocking some resources-. In this example, our goal is having Mocket dumping what runs on real sockets to a file named example.json
that will be created in the local directory specified with the .
we entered as second argument.
That’s exactly what our Mocket.enable('example', '.')
does.
Run again our script. See what’s inside example.json
, it’s pure magic.
Now run the script again and again, and you’ll see how fast it will be, since every response comes directly from our JSON dump.
It’s HTTPretty, vcrpy and much more.
It’s Mocket, the socket mock framework.