BlackSheep is an asynchronous web framework to build event based web applications with Python. It is inspired by Flask, ASP.NET Core, and the work by Yury Selivanov.
pip install blacksheep
from datetime import datetime
from blacksheep import Application
app = Application()
@app.route("/")
async def home():
return f"Hello, World! {datetime.utcnow().isoformat()}"
The documentation offers getting started tutorials:
These project templates can be used to start new applications faster:
Python version 3.7, 3.8, 3.9, or 3.10.
BlackSheep belongs to the category of ASGI web frameworks, so it requires an ASGI HTTP server to run, such as uvicorn, or hypercorn. For example, to use it with uvicorn:
$ pip install uvicorn
To run an application like in the example above, use the methods provided by the ASGI HTTP Server:
# if the BlackSheep app is defined in a file `server.py`
$ uvicorn server:app
To run for production, refer to the documentation of the chosen ASGI server (i.e. for uvicorn).
BlackSheep supports automatic binding of values for request handlers, by type annotation or by conventions. See more here.
from dataclasses import dataclass
from blacksheep import Application, FromJSON, FromQuery
app = Application()
@dataclass
class CreateCatInput:
name: str
@app.router.post("/api/cats")
async def example(data: FromJSON[CreateCatInput]):
# in this example, data is bound automatically reading the JSON
# payload and creating an instance of `CreateCatInput`
...
@app.router.get("/:culture_code/:area")
async def home(culture_code, area):
# in this example, both parameters are obtained from routes with
# matching names
return f"Request for: {culture_code} {area}"
@app.router.get("/api/products")
def get_products(
page: int = 1,
size: int = 30,
search: str = "",
):
# this example illustrates support for implicit query parameters with
# default values
# since the source of page, size, and search is not specified and no
# route parameter matches their name, they are obtained from query string
...
@app.router.get("/api/products2")
def get_products2(
page: FromQuery[int] = FromQuery(1),
size: FromQuery[int] = FromQuery(30),
search: FromQuery[str] = FromQuery(""),
):
# this example illustrates support for explicit query parameters with
# default values
# in this case, parameters are explicitly read from query string
...
It also supports dependency injection, a feature that provides a consistent and clean way to use dependencies in request handlers.
Generation of OpenAPI Documentation.
BlackSheep implements strategies to handle authentication and authorization. These features are documented here:
app.use_authentication()\
.add(ExampleAuthenticationHandler())
app.use_authorization()\
.add(AdminsPolicy())
@auth("admin")
@app.router.get("/")
async def only_for_admins():
...
@auth()
@app.router.get("/")
async def only_for_authenticated_users():
...
Since version 1.2.1
, BlackSheep implements:
Meaning that it is extremely easy to integrate with services such as:
Refer to the documentation for more details and examples.
- ASGI compatibility
- Routing
- Request handlers can be defined as functions, or class methods
- Middlewares
- WebSocket
- Built-in support for dependency injection
- Support for automatic binding of route and query parameters to request handlers methods calls
- Strategy to handle exceptions
- Strategy to handle authentication and authorization
- Built-in support for OpenID Connect authentication using OIDC discovery
- Built-in support for JWT Bearer authentication using OIDC discovery and other sources of JWKS
- Handlers normalization
- Serving static files
- Integration with Jinja2
- Support for serving SPAs that use HTML5 History API for client side routing
- Support for automatic generation of OpenAPI Documentation
- Strategy to handle CORS settings
- Sessions
- Support for automatic binding of
dataclasses
andpydantic
models to handle the request body payload expected by request handlers TestClient
class to simplify testing of applications- Anti Forgery validation to protect against Cross-Site Request Forgery (XSRF/CSRF) attacks
BlackSheep includes an HTTP Client.
Example:
import asyncio
from blacksheep.client import ClientSession
async def client_example(loop):
async with ClientSession() as client:
response = await client.get("https://docs.python.org/3/")
assert response is not None
text = await response.text()
print(text)
loop = asyncio.get_event_loop()
loop.run_until_complete(client_example(loop))
- Python 3.7 (cpython)
- Python 3.8 (cpython)
- Python 3.9 (cpython)
- Python 3.10 (cpython)
- Ubuntu 18.04
- Windows 10
- macOS
Please refer to the documentation website.