Skip to content

Commit 79117d1

Browse files
committed
feat: Add initial type hints for RedisSession
1 parent e2c14a9 commit 79117d1

2 files changed

Lines changed: 51 additions & 12 deletions

File tree

flask_session/py.typed

Whitespace-only changes.

flask_session/sessions.py

Lines changed: 51 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,24 @@
1212
import os
1313
import sys
1414
import time
15+
import typing as t
1516
from datetime import datetime
17+
from typing import TYPE_CHECKING, Any, ClassVar, Optional, Protocol, Type
1618
from uuid import uuid4
1719

1820
import pytz
21+
from flask.wrappers import Response
1922

2023
try:
2124
import cPickle as pickle
2225
except ImportError:
2326
import pickle # type: ignore[no-redef]
2427

28+
if TYPE_CHECKING:
29+
from redis import Redis
30+
from flask import Flask
31+
from flask.wrappers import Request
32+
2533
from flask.sessions import SessionInterface as FlaskSessionInterface
2634
from flask.sessions import SessionMixin
2735
from itsdangerous import BadSignature, Signer, want_bytes
@@ -38,11 +46,23 @@ def total_seconds(td):
3846
return td.days * 60 * 60 * 24 + td.seconds
3947

4048

49+
class SessionSerializer(Protocol):
50+
def dumps(self, session_content: Any) -> bytes:
51+
"""serialize a session object"""
52+
...
53+
54+
def loads(self, serialized_session: bytes) -> Any:
55+
"""deserialize a session object"""
56+
...
57+
58+
4159
class ServerSideSession(CallbackDict, SessionMixin):
4260
"""Baseclass for server-side based sessions."""
4361

44-
def __init__(self, initial=None, sid=None, permanent=None):
45-
def on_update(self):
62+
def __init__(
63+
self, initial=None, sid: Optional[str] = None, permanent: Optional[bool] = None
64+
):
65+
def on_update(self) -> None:
4666
self.modified = True
4767

4868
CallbackDict.__init__(self, initial, on_update)
@@ -89,16 +109,25 @@ class DynamoDBSession(ServerSideSession):
89109

90110

91111
class PeeweeSession(ServerSideSession):
92-
def __init__(self, initial=None, sid=None, permanent=None, ip=None):
112+
def __init__(
113+
self,
114+
initial=None,
115+
sid: Optional[str] = None,
116+
permanent: Optional[bool] = None,
117+
ip=None,
118+
):
93119
super().__init__(initial, sid, permanent)
94120
self.ip = ip
95121

96122

97123
class SessionInterface(FlaskSessionInterface):
98-
def _generate_sid(self):
124+
serializer: ClassVar[SessionSerializer]
125+
session_class: ClassVar[Type[ServerSideSession]]
126+
127+
def _generate_sid(self) -> str:
99128
return str(uuid4())
100129

101-
def _get_signer(self, app):
130+
def _get_signer(self, app: Flask) -> Optional[Signer]:
102131
if not app.secret_key:
103132
return None
104133
return Signer(app.secret_key, salt="flask-session", key_derivation="hmac")
@@ -107,7 +136,7 @@ def _get_signer(self, app):
107136
class NullSessionInterface(SessionInterface):
108137
"""Used to open a :class:`flask.sessions.NullSession` instance."""
109138

110-
def open_session(self, app, request):
139+
def open_session(self, app: Flask, request: Request) -> None:
111140
return None
112141

113142

@@ -123,10 +152,16 @@ class RedisSessionInterface(SessionInterface):
123152
:param permanent: Whether to use permanent session or not.
124153
"""
125154

126-
serializer = pickle
127-
session_class = RedisSession
155+
serializer: ClassVar[SessionSerializer] = t.cast(SessionSerializer, pickle)
156+
session_class: ClassVar[Type[RedisSession]] = RedisSession
128157

129-
def __init__(self, redis, key_prefix, use_signer=False, permanent=True):
158+
def __init__(
159+
self,
160+
redis: Optional[Redis],
161+
key_prefix: str,
162+
use_signer: bool = False,
163+
permanent: bool = True,
164+
):
130165
if redis is None:
131166
from redis import Redis
132167

@@ -137,7 +172,7 @@ def __init__(self, redis, key_prefix, use_signer=False, permanent=True):
137172
self.permanent = permanent
138173
self.has_same_site_capability = hasattr(self, "get_cookie_samesite")
139174

140-
def open_session(self, app, request):
175+
def open_session(self, app: Flask, request: Request) -> Optional[SessionMixin]:
141176
sid = request.cookies.get(app.config["SESSION_COOKIE_NAME"])
142177
if not sid:
143178
sid = self._generate_sid()
@@ -164,7 +199,9 @@ def open_session(self, app, request):
164199
return self.session_class(sid=sid, permanent=self.permanent)
165200
return self.session_class(sid=sid, permanent=self.permanent)
166201

167-
def save_session(self, app, session, response):
202+
def save_session(
203+
self, app: Flask, session: SessionMixin, response: Response
204+
) -> None:
168205
if not self.should_set_cookie(app, session):
169206
return
170207
domain = self.get_cookie_domain(app)
@@ -202,7 +239,9 @@ def save_session(self, app, session, response):
202239
)
203240

204241
if self.use_signer:
205-
session_id = self._get_signer(app).sign(want_bytes(session.sid))
242+
session_id = t.cast(Signer, self._get_signer(app)).sign(
243+
want_bytes(session.sid)
244+
)
206245
else:
207246
session_id = session.sid
208247
response.set_cookie(

0 commit comments

Comments
 (0)