Welcome to uapi!#
uapi is an elegant, fast, and high-level framework for writing network services in Python 3.10 and later.
Using uapi enables you to:
write either async or sync styles of handlers, depending on the underlying framework used.
use and customize a depedency injection system, based on incant.
automatically serialize and deserialize data through attrs and cattrs.
generate and use OpenAPI descriptions of your endpoints.
optionally type-check your handlers with Mypy.
write and use powerful middleware.
integrate with existing apps based on Django, Starlette, Flask, Quart or Aiohttp.
Installation#
uapi requires an underlying web framework to run. If you are unsure which to pick, we recommend Starlette for a good balance of features and speed.
$ pip install uapi starlette uvicorn
$ pip install uapi flask gunicorn
$ pip install uapi quart uvicorn
$ pip install uapi django gunicorn
$ pip install uapi aiohttp
Your First Handler#
Let’s write a very simple Hello World HTTP handler and expose it on the root path.
Before we start writing our handlers, we need something to register them with. In uapi, that something is an instance of an App
.
from uapi.starlette import App
app = App()
@app.get("/")
async def hello() -> str:
return "hello world"
from uapi.flask import App
app = App()
@app.get("/")
def hello() -> str:
return "hello world"
from uapi.quart import App
app = App()
@app.get("/")
async def hello() -> str:
return "hello world"
from uapi.django import App
app = App()
@app.get("/")
def hello() -> str:
return "hello world"
from uapi.aiohttp import App
app = App()
@app.get("/")
async def hello() -> str:
return "hello world"
Note
uapi uses type hints in certain places to minimize boilerplate code. This doesn’t mean you’re required to type-check your code using a tool like Mypy, however. We’re not the Python police; you do you.
Mypy’s pretty great, though.
Let’s start serving the file.
Change the code to the following, and run it:
from asyncio import run
from uapi.starlette import App
app = App()
@app.get("/")
async def hello() -> str:
return "hello world"
run(app.run())
Change the code to the following, and run it:
from uapi.flask import App
app = App()
@app.get("/")
def hello() -> str:
return "hello world"
app.run(__name__)
Change the code to the following, and run it:
from asyncio import run
from uapi.quart import App
app = App()
@app.get("/")
async def hello() -> str:
return "hello world"
run(app.run(__name__))
Unfortunately, Django is too complex to be able to spin up a development server quickly.
Please see the Django section for information on how to integrate a uapi App
into a Django site.
Change the code to the following, and run it:
from asyncio import run
from uapi.aiohttp import App
app = App()
@app.get("/")
async def hello() -> str:
return "hello world"
run(app.run())
Your app is now running in development mode on localhost, port 8000.
$ curl 127.0.0.1:8000
hello world⏎