Package: chasha
ChashaChasha (rus: Chalice) is a microframework for use in serverless applications on lambdas/cloud functions.
It does not have any dependencies only using standard library
Since changing version on serverless functions is simple, the minimal python requirement is 3.10Supported platforms:Yandex CloudWSGI- for testing purposes (if you need something similar - just take FastAPI)Installationpip install chashaGetting startedA minimal Chasha app looks like thisfromchashaimportChashaapp=Chasha()@app.route('/')defhello():return{'message':'hello'}if__name__=='__main__':fromwsgiref.simple_serverimportmake_serverfromchasha.contrib.adapters.wsgiimportWSGIAdapterwithmake_server('',8080,WSGIAdapter(app).handler)ashttpd:httpd.serve_forever()First you need to create an app, then you can use the following decorators to create route handlers:route(path: str, http_methods: list[str] = None)Creates a route on the following path, when specified withouthttp_methodskwargs handles any HTTp verbget(path: str)Shortcut forroute(path, http_methods=['GET'])post(path: str)Shortcut forroute(path, http_methods=['POST'])The handler function returns content of the response,
it could be of type dict for json responses, string for raw data response and special wrapper for html response@app.route('/')defhello():returnapp.html('<html><body>Hello World</body></html>')Sub routersIn order to organize your api routes sub routers are introduced. The sub router calledChashka(Small Chasha, rus: cup)app=Chasha()api=Chashka(path_prefix='/api')# routesapp.include_app(api)Path parametersPath parameters declared as python format string and passed to the handler function with the same name.
Type will be converted based on function argument type annotation@app.get('/items/{item_id}')defget_item(item_id:int):return{'id':item_id}Dependency InjectionChasha supports simple but powerful DI mechanism, lets break down the following examplefromchashaimportChasha,DI,InjectContextapp=Chasha()defhello_world(context:InjectContext):# startupyieldf"Hello, world from attr '{context.param_name}'"# teardown@app.route('/')defhello(greet:str=DI.inject(hello_world)):return{'message':greet}Functionhello_worldwill be injected into handlerhelloasgreetfunction parameter.There is a special non-required attribute in dependency function with the typeInjectContext(name of the argument does not matter) which contains context of the current injection.InjectContextshould be considered as advanced usage since there are already implemented dependencies
for basic needs.Request and Response objectSometimes it's needed to access current Request and modify Response objects, there are corresponding dependencies for this case:@app.route('/')defhello(request:Request=DI.request(),response:Response=DI.response()):response.set_header('X-CHASHA-GREET','Hello, world')return{'message':request.get_header('user-agent')}Query ParamsIt's possible to access query parameters viaRequestobject, but it's preferred to use special injection@app.route('/add')defhello(a:int=DI.query(),b:int=DI.query()):return{'message':a+b}Dependencyquery(name: str, default = None)can override name and provide default,
in case the parameter is missing and no default provided response will fail with 405 codeRequest payloadIt's possible to access query parameters viaRequestobject, but it's preferred to use special injection@app.route('/add')defhello(data:int=DI.json_body()):return{'message':data}CookiesTo read and set cookies use special injectionDI.cookies@app.route('/')defindex(cookies:DI.Cookies=DI.cookies()):cookies.set('greeted','true')return{'message':cookies.get('greet')}Exception handlingTo handle uncaught exception use decoratorChasha.exception_handlerand it's shortcutshandle_500andhandle_404Handler takes one positional argument - raised exception, also handler fully supports dependencies.@app.handle_500()defon_500(_:Exception):return{'message':'ooops'}@app.route('/')defhello():raiseException()Serve requestsAfter you create your app - you need to serve HTTP requests somehow, for this you need to use adapters.
Add the following lines of code to your API Gateway Cloud Function handler to start using Chasha over Yandex Clouddefhandler(event,context):fromchasha.contrib.adapters.yandeximportYandexCloudAdapterreturnYandexCloudAdapter(app).handler(event,context)WSGI AdapterChasha also ships with WSGI adapter to ease local development, it can be used with any wsgi app server of choice,
or even with builtin serverif__name__=='__main__':fromwsgiref.simple_serverimportmake_serverfromchasha.contrib.adapters.wsgiimportWSGIAdapterwithmake_server('',8080,WSGIAdapter(app).handler)ashttpd:httpd.serve_forever()