Skip to content

Commit a1cc4ef

Browse files
panagiksasvetlov
authored andcommitted
New async/await syntax and aioredis 1.0.0 compatibility (#234)
* New async/await syntax and aioredis 1.0.0 compatibility * [Travis] Check with Python3.6 * Handle aioredis as optional dependency (and its version) * Gradually deprecate ConnectionsPool * Test missing or old version of aioredis * Add no cover to ImportError
1 parent a73b279 commit a1cc4ef

21 files changed

+342
-402
lines changed

.travis.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ services:
44
- docker
55

66
python:
7-
- 3.4.3
87
- 3.5
8+
- 3.6
99
- nightly
1010

1111
install:

aiohttp_session/__init__.py

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
"""User sessions for aiohttp.web."""
22

33
import abc
4-
import asyncio
54
from collections import MutableMapping
65
import json
76
import time
@@ -94,8 +93,7 @@ def __delitem__(self, key):
9493
STORAGE_KEY = 'aiohttp_session_storage'
9594

9695

97-
@asyncio.coroutine
98-
def get_session(request):
96+
async def get_session(request):
9997
session = request.get(SESSION_KEY)
10098
if session is None:
10199
storage = request.get(STORAGE_KEY)
@@ -104,7 +102,7 @@ def get_session(request):
104102
"Install aiohttp_session middleware "
105103
"in your aiohttp.web.Application")
106104
else:
107-
session = yield from storage.load_session(request)
105+
session = await storage.load_session(request)
108106
if not isinstance(session, Session):
109107
raise RuntimeError(
110108
"Installed {!r} storage should return session instance "
@@ -119,12 +117,11 @@ def session_middleware(storage):
119117
assert isinstance(storage, AbstractStorage), storage
120118

121119
@web.middleware
122-
@asyncio.coroutine
123-
def factory(request, handler):
120+
async def factory(request, handler):
124121
request[STORAGE_KEY] = storage
125122
raise_response = False
126123
try:
127-
response = yield from handler(request)
124+
response = await handler(request)
128125
except web.HTTPException as exc:
129126
response = exc
130127
raise_response = True
@@ -139,7 +136,7 @@ def factory(request, handler):
139136
session = request.get(SESSION_KEY)
140137
if session is not None:
141138
if session._changed:
142-
yield from storage.save_session(request, response, session)
139+
await storage.save_session(request, response, session)
143140
if raise_response:
144141
raise response
145142
return response
@@ -188,14 +185,12 @@ def _get_session_data(self, session):
188185
data = {}
189186
return data
190187

191-
@asyncio.coroutine
192188
@abc.abstractmethod
193-
def load_session(self, request):
189+
async def load_session(self, request):
194190
pass
195191

196-
@asyncio.coroutine
197192
@abc.abstractmethod
198-
def save_session(self, request, response, session):
193+
async def save_session(self, request, response, session):
199194
pass
200195

201196
def load_cookie(self, request):
@@ -231,16 +226,14 @@ def __init__(self, *, cookie_name="AIOHTTP_SESSION",
231226
max_age=max_age, path=path, secure=secure,
232227
httponly=httponly)
233228

234-
@asyncio.coroutine
235-
def load_session(self, request):
229+
async def load_session(self, request):
236230
cookie = self.load_cookie(request)
237231
if cookie is None:
238232
return Session(None, data=None, new=True, max_age=self.max_age)
239233
else:
240234
data = json.loads(cookie)
241235
return Session(None, data=data, new=False, max_age=self.max_age)
242236

243-
@asyncio.coroutine
244-
def save_session(self, request, response, session):
237+
async def save_session(self, request, response, session):
245238
cookie_data = json.dumps(self._get_session_data(session))
246239
self.save_cookie(response, cookie_data, max_age=session.max_age)

aiohttp_session/cookie_storage.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import asyncio
21
import json
32
import base64
43

@@ -26,8 +25,7 @@ def __init__(self, secret_key, *, cookie_name="AIOHTTP_SESSION",
2625
secret_key = base64.urlsafe_b64encode(secret_key)
2726
self._fernet = fernet.Fernet(secret_key)
2827

29-
@asyncio.coroutine
30-
def load_session(self, request):
28+
async def load_session(self, request):
3129
cookie = self.load_cookie(request)
3230
if cookie is None:
3331
return Session(None, data=None, new=True, max_age=self.max_age)
@@ -43,8 +41,7 @@ def load_session(self, request):
4341
"create a new fresh session")
4442
return Session(None, data=None, new=True, max_age=self.max_age)
4543

46-
@asyncio.coroutine
47-
def save_session(self, request, response, session):
44+
async def save_session(self, request, response, session):
4845
if session.empty:
4946
return self.save_cookie(response, '',
5047
max_age=session.max_age)

aiohttp_session/memcached_storage.py

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import asyncio
21
import json
32
import uuid
43

@@ -21,15 +20,14 @@ def __init__(self, memcached_conn, *, cookie_name="AIOHTTP_SESSION",
2120
self._key_factory = key_factory
2221
self.conn = memcached_conn
2322

24-
@asyncio.coroutine
25-
def load_session(self, request):
23+
async def load_session(self, request):
2624
cookie = self.load_cookie(request)
2725
if cookie is None:
2826
return Session(None, data=None, new=True, max_age=self.max_age)
2927
else:
3028
key = str(cookie)
3129
stored_key = (self.cookie_name + '_' + key).encode('utf-8')
32-
data = yield from self.conn.get(stored_key)
30+
data = await self.conn.get(stored_key)
3331
if data is None:
3432
return Session(None, data=None,
3533
new=True, max_age=self.max_age)
@@ -40,8 +38,7 @@ def load_session(self, request):
4038
data = None
4139
return Session(key, data=data, new=False, max_age=self.max_age)
4240

43-
@asyncio.coroutine
44-
def save_session(self, request, response, session):
41+
async def save_session(self, request, response, session):
4542
key = session.identity
4643
if key is None:
4744
key = self._key_factory()
@@ -60,6 +57,6 @@ def save_session(self, request, response, session):
6057
max_age = session.max_age
6158
expire = max_age if max_age is not None else 0
6259
stored_key = (self.cookie_name + '_' + key).encode('utf-8')
63-
yield from self.conn.set(
60+
await self.conn.set(
6461
stored_key, data.encode('utf-8'),
6562
exptime=expire)

aiohttp_session/nacl_storage.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import asyncio
21
import json
32

43
import nacl.secret
@@ -21,8 +20,7 @@ def __init__(self, secret_key, *, cookie_name="AIOHTTP_SESSION",
2120

2221
self._secretbox = nacl.secret.SecretBox(secret_key)
2322

24-
@asyncio.coroutine
25-
def load_session(self, request):
23+
async def load_session(self, request):
2624
cookie = self.load_cookie(request)
2725
if cookie is None:
2826
return Session(None, data=None, new=True, max_age=self.max_age)
@@ -33,8 +31,7 @@ def load_session(self, request):
3331
)
3432
return Session(None, data=data, new=False, max_age=self.max_age)
3533

36-
@asyncio.coroutine
37-
def save_session(self, request, response, session):
34+
async def save_session(self, request, response, session):
3835
if session.empty:
3936
return self.save_cookie(response, session._mapping,
4037
max_age=session.max_age)

aiohttp_session/redis_storage.py

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
1-
import asyncio
1+
try:
2+
import aioredis
3+
except ImportError: # pragma: no cover
4+
aioredis = None
25
import json
36
import uuid
7+
import warnings
48

9+
from distutils.version import StrictVersion
510
from . import AbstractStorage, Session
611

712

@@ -16,20 +21,33 @@ def __init__(self, redis_pool, *, cookie_name="AIOHTTP_SESSION",
1621
super().__init__(cookie_name=cookie_name, domain=domain,
1722
max_age=max_age, path=path, secure=secure,
1823
httponly=httponly)
24+
if aioredis is None:
25+
raise RuntimeError("Please install aioredis")
26+
if StrictVersion(aioredis.__version__).version < (1, 0):
27+
raise RuntimeError("aioredis<1.0 is not supported")
1928
self._encoder = encoder
2029
self._decoder = decoder
2130
self._key_factory = key_factory
31+
if isinstance(redis_pool, aioredis.pool.ConnectionsPool):
32+
warnings.warn(
33+
"using a pool created with aioredis.create_pool is deprecated"
34+
"please use a pool created with aioredis.create_redis_pool",
35+
DeprecationWarning
36+
)
37+
redis_pool = aioredis.commands.Redis(redis_pool)
38+
elif not isinstance(redis_pool, aioredis.commands.Redis):
39+
raise TypeError("Expexted aioredis.commands.Redis got {}".format(
40+
type(redis_pool)))
2241
self._redis = redis_pool
2342

24-
@asyncio.coroutine
25-
def load_session(self, request):
43+
async def load_session(self, request):
2644
cookie = self.load_cookie(request)
2745
if cookie is None:
2846
return Session(None, data=None, new=True, max_age=self.max_age)
2947
else:
30-
with (yield from self._redis) as conn:
48+
with await self._redis as conn:
3149
key = str(cookie)
32-
data = yield from conn.get(self.cookie_name + '_' + key)
50+
data = await conn.get(self.cookie_name + '_' + key)
3351
if data is None:
3452
return Session(None, data=None,
3553
new=True, max_age=self.max_age)
@@ -40,8 +58,7 @@ def load_session(self, request):
4058
data = None
4159
return Session(key, data=data, new=False, max_age=self.max_age)
4260

43-
@asyncio.coroutine
44-
def save_session(self, request, response, session):
61+
async def save_session(self, request, response, session):
4562
key = session.identity
4663
if key is None:
4764
key = self._key_factory()
@@ -57,8 +74,7 @@ def save_session(self, request, response, session):
5774
max_age=session.max_age)
5875

5976
data = self._encoder(self._get_session_data(session))
60-
with (yield from self._redis) as conn:
77+
with await self._redis as conn:
6178
max_age = session.max_age
6279
expire = max_age if max_age is not None else 0
63-
yield from conn.set(self.cookie_name + '_' + key,
64-
data, expire=expire)
80+
await conn.set(self.cookie_name + '_' + key, data, expire=expire)

demo/redis_storage.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,7 @@ async def handler(request):
1717

1818
async def make_redis_pool():
1919
redis_address = ('127.0.0.1', '6379')
20-
return await aioredis.create_pool(
21-
redis_address,
22-
create_connection_timeout=1,
23-
)
20+
return await aioredis.create_redis_pool(redis_address, timeout=1)
2421

2522

2623
def make_app():

docs/index.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ Continious Integration.
115115
Dependencies
116116
------------
117117

118-
- Python 3.3 and :mod:`asyncio` or Python 3.4+
118+
- Python 3.5.3+
119119
- :term:`cryptography` for
120120
:class:`~aiohttp_session.cookie_storage.EncryptedCookieStorage`
121121
- :term:`aioredis` for

requirements-dev.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,13 @@ coverage==4.4.2
33
sphinx==1.6.5
44
pep257==0.7.0
55
-e .
6-
aioredis==0.3.5
6+
aioredis==1.0.0
77
cryptography==2.1.3
88
docker-py==1.10.6
99
pynacl==1.2.0
1010
pytest-aiohttp==0.1.3
1111
pytest-cov==2.5.1
12+
pytest-mock==1.6.3
1213
aiohttp==2.3.2
1314
multidict==3.3.2
1415
chardet==3.0.4

setup.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ def read(f):
1717

1818
install_requires = ['aiohttp>=2.3.0']
1919
extras_require = {
20-
'aioredis': ['aioredis>=0.1.4, <1.0'],
20+
'aioredis': ['aioredis>=1.0.0'],
2121
'aiomcache': ['aiomcache>=0.5.2'],
2222
'pycrypto': ['cryptography'],
2323
'secure': ['cryptography'],
@@ -34,7 +34,6 @@ def read(f):
3434
'Intended Audience :: Developers',
3535
'Programming Language :: Python',
3636
'Programming Language :: Python :: 3',
37-
'Programming Language :: Python :: 3.4',
3837
'Programming Language :: Python :: 3.5',
3938
'Programming Language :: Python :: 3.6',
4039
'Topic :: Internet :: WWW/HTTP',

0 commit comments

Comments
 (0)