feat(redis): add native JSON session storage for 4.1.0
Build & Publish Package / publish (push) Successful in 49s
Build & Publish Package / publish (push) Successful in 49s
- Add opt-in SESSION_REDIS_JSON storage for asyncio Redis backends. - Check JSON command support at startup and reject JSON mode on Trio. - Read legacy strings and migrate sessions on their next save. - Validate JSON objects before transactional replacement and expiry. - Preserve tagged serialization for datetime, tuple, and other types. - Cover command contracts, error handling, and session round-trips. - Document server requirements, permissions, and migration limits. - Normalize indentation and whitespace across code, tests, and examples. - Bump the package and lockfile to 4.1.0 and update the changelog. - Refresh the locked pycparser dependency to 3.12.
This commit is contained in:
+27
-27
@@ -7,39 +7,39 @@ from quart_session import Session
|
||||
|
||||
@pytest.fixture
|
||||
def app_factory():
|
||||
"""Builds a Quart app backed by an in-memory session store."""
|
||||
"""Builds a Quart app backed by an in-memory session store."""
|
||||
|
||||
def _factory(**config) -> Quart:
|
||||
app = Quart(__name__)
|
||||
app.secret_key = "test-secret-key"
|
||||
app.config["SESSION_TYPE"] = "null"
|
||||
app.config.update(config)
|
||||
Session(app)
|
||||
def _factory(**config) -> Quart:
|
||||
app = Quart(__name__)
|
||||
app.secret_key = "test-secret-key"
|
||||
app.config["SESSION_TYPE"] = "null"
|
||||
app.config.update(config)
|
||||
Session(app)
|
||||
|
||||
# 'null' interface is a no-op store, give it a dict so that
|
||||
# open_session() can actually find data again.
|
||||
store: dict = {}
|
||||
interface = app.session_interface
|
||||
# 'null' interface is a no-op store, give it a dict so that
|
||||
# open_session() can actually find data again.
|
||||
store: dict = {}
|
||||
interface = app.session_interface
|
||||
|
||||
async def _get(key: str, app: Optional[Quart] = None):
|
||||
return store.get(key)
|
||||
async def _get(key: str, app: Optional[Quart] = None):
|
||||
return store.get(key)
|
||||
|
||||
async def _set(key: str, value, expiry: Optional[int] = None,
|
||||
app: Optional[Quart] = None):
|
||||
store[key] = value
|
||||
async def _set(key: str, value, expiry: Optional[int] = None,
|
||||
app: Optional[Quart] = None):
|
||||
store[key] = value
|
||||
|
||||
async def _delete(key: str, app: Optional[Quart] = None):
|
||||
store.pop(key, None)
|
||||
async def _delete(key: str, app: Optional[Quart] = None):
|
||||
store.pop(key, None)
|
||||
|
||||
interface.get = _get
|
||||
interface.set = _set
|
||||
interface.delete = _delete
|
||||
interface.get = _get
|
||||
interface.set = _set
|
||||
interface.delete = _delete
|
||||
|
||||
@app.route("/")
|
||||
async def index():
|
||||
session["hits"] = session.get("hits", 0) + 1
|
||||
return {"hits": session["hits"], "sid": session.sid}
|
||||
@app.route("/")
|
||||
async def index():
|
||||
session["hits"] = session.get("hits", 0) + 1
|
||||
return {"hits": session["hits"], "sid": session.sid}
|
||||
|
||||
return app
|
||||
return app
|
||||
|
||||
return _factory
|
||||
return _factory
|
||||
|
||||
Reference in New Issue
Block a user