Hey all,
I know that we have ctx property in the Request class in order to store arbitrary data.
But for that purpose, we should create a middleware and attach a key to the context, it doesn’t look as redundant steps?
I have been thinking about, what will be if we will attach context object to the Request class itself.
It will avoid us creating middlewares etc.and will make the flexibility of the context object in general better, IMO.
and I already playing with it, and show you the code snippet above.
class Request:
__slots__ = (
......
"context",
)
def __init__(self, url_bytes, headers, version, method, transport, app):
......
self.context = Context()
The Context class will look like
import typing
class Singleton:
_instances = {}
def __new__(klass, *args, **kwargs):
if klass not in klass._instances:
klass._instances[klass] = super(Singleton, klass).__new__(klass, *args, **kwargs)
return klass._instances[klass]
class Context(Singleton):
def __setattr__(self, key, value):
self.__dict__.__setitem__(key, value)
def __setitem__(self, key: str, value: typing.Any) -> typing.NoReturn:
self.__dict__[key] = value
def __getitem__(self, key: str):
return self.__dict__[key]
def pop(self, key: str, default: typing.Any = None) -> typing.Any:
return self.__dict__.pop(key, default)
def get(self, key: str) -> typing.Any:
return self.__dict__.get(key)
def __contains__(self, key: str) -> bool:
return key in self.__dict__
and the usage of the Context
from sanic import Sanic
from sanic.response import json
app = Sanic("App Name")
@app.route("/set_context_variable")
async def set_context(request):
request.context.check_data = 'hello world'
return json({"context": "world"})
@app.route("/check_context_variable")
async def check_context(request):
return json({"context": f'{request.context.get("check_data")}'})
@app.route('/delete_context_variable')
async def delete_context_variable(request):
request.context.pop('check_data')
return json({"context": f'{request.context.get("check_data")}'})
if __name__ == "__main__":
app.run(host="0.0.0.0", port=8000, auto_reload=True)
if it sounds reasonable, I can make draft PR.