Skip to main content

Fastipy is a fast and easy-to-use open source Python library for developing RESTful APIs. Inspired by the FastAPI and Fastify syntax and powered by uvicorn ASGI web server.

Project description

Fastipy

What is it and what is it for

Fastipy is a fast and easy-to-use open source Python library for developing RESTful APIs.

Powered by uvicorn

Installation

pip install fastipy

Examples

Example for GET Route with Query Params

from fastipy import Fastipy, Request, Reply

app = Fastipy()

# Routes can be async or sync functions, but reply send functions are async
# The handler returns the default HTTP status code 200
@app.get("/")
def home(req: Request, _):
  # Get query params age
  age = req.query["age"]
  # Example: Recovery all persons from database with this age and print the html
  print("<h1>Retrieving all persons</h1><ul><li>A Person</li></ul>")

Example for GET Route with Params, CORS and multiple methods

from fastipy import Fastipy, Request, Reply

app = Fastipy().cors()

@app.get("/user/:id")
@app.post("/user/:id")
async def getUser(req: Request, reply: Reply):
  # get users from database
  for i in users:
    if i["id"] == req.params["id"]:
      # All response functions are asynchronous
      return await reply.send(i)

  await reply.send_code(404)

Example for POST Route with Body

from fastipy import Fastipy, Request, Reply

app = Fastipy()

@app.post("/user")
async def createUser(req: Request, reply: Reply):
  user = req.body.json
  # Save user in database
  await reply.code(201).send("Created")

Example for PUT Route with Body

from fastipy import Fastipy, Request, Reply

app = Fastipy()

@app.put("/user")
async def createUser(req: Request, reply: Reply):
  user = req.body.json
  # Update user in database
  await reply.type("text/html").code(201).send("<h1>Created</h1>")

Example for GET Route with file stream

from fastipy import Fastipy, Request, Reply

app = Fastipy()

@app.get("/stream")
async def streamFile(_, reply: Reply):
  # It could be an asynchronous generator
  def generator():
    with open("file.txt") as f:
        for line in f:
            yield line

  await reply.send(generator())

Adding custom serializer to Reply send

from fastipy import Fastipy, Request, Reply

app = Fastipy()

app.add_serializer(
    validation=lambda data: isinstance(data, str),
    serializer=lambda data: ("application/json", json.dumps({"error": data})),
)

@app.get("/")
async def customSerializer(_, reply: Reply):
    await reply.code(404).send("Field not found")

Running

Running Fastipy application in development is easy

import uvicorn

if __name__ == "__main__":
  # main:app indicates the FILE:VARIABLE

  # The file is the main file where Fastipy() is instantiated
  # The variable is the name of the variable that contains the instance of Fastipy()

  # You can find more configurations here https://www.uvicorn.org/

  # set reload to True for automatic reloading!
  uvicorn.run("main:app", log_level="debug", port=8000, reload=True, loop="asyncio")

See more examples in examples folder

Creating plugins

# chat.py
from fastipy import FastipyInstance, Reply

# Plugins can be asynchronous or synchronized functions
# Plugins have access to the main instance, which means they can use all of Fastipy's functions
def chatRoutes(app: FastipyInstance, options: dict):
  @app.get("/")
  async def index(_, reply: Reply):
    await reply.send_code(200)

  @app.get("/chat")
  async def test(_, reply: Reply):
    await reply.send_code(200)
# message.py
from fastipy import FastipyInstance, Reply

async def messageRoutes(app: FastipyInstance, options: dict):
  @message.get("/")
  async def index(_, reply: Reply):
    await reply.send_code(200)

  @message.get("/message")
  async def test(_, reply: Reply):
    await reply.send_code(200)

  app.name("custom plugin name")
# main.py
from fastipy import Fastipy

from message import messageRoutes
from chat import chatRoutes

app = Fastipy().cors()

app.register(messageRoutes, {"prefix": "/message"})
app.register(chatRoutes, {"prefix": "/chat"})

Hooks

from fastipy import Fastipy, Request, Reply

app = Fastipy()

# The preHandler hook is called before the request handler
@app.hook("preHandler")
def preHandler(req: Request, reply: Reply):
  print("onRequest hook")

# The onRequest hook is called when the request is handled
@app.hook("onRequest")
def onRequest(req: Request, reply: Reply):
  print("onRequest hook")

# The onResponse hook is called when the reply sends a response
@app.hook("onResponse")
def onResponse(req: Request, reply: Reply):
  print("onResponse hook")

# The onError hook is called when an error occurs
@app.hook("onError")
def onError(error: Exception, req: Request, reply: Reply):
  print(f"onError hook exception: {error}")

# A hook will only be linked to a route if its declaration precedes the route
# The order of hooks of the same type is important
@app.get("/")
async def index(_, reply: Reply):
  await reply.send_code(200)

End to End tests

# See more in https://www.starlette.io/testclient/
from fastipy import TestClient
from main import app

client = TestClient(app)

response = client.post("/")
assert response.status_code == 200
assert response.text == "Hello World"

Application Deploy

For production deployment, please refer to this uvicorn guide.

Change Log

Version 1.5.3

Todo

Added

Changed

  • Fixing and improving CORS header generation
  • Fixing Reply class that didn't store decorators

Contributors

How to Contributing

Open pull request

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

fastipy-1.5.3.tar.gz (42.9 kB view hashes)

Uploaded Source

Built Distribution

fastipy-1.5.3-py3-none-any.whl (51.9 kB view hashes)

Uploaded Python 3

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page