Skip to main content

a little opinionated framework for creating spic & span apis

Project description

spic

Code Coverage Ruff PyPI - Version PyPI - Python Version Hatch project

spic

Table of Contents

Intro

spic is an ASGI based api router with minimal dependencies and strong typing.

Rationale

  • popular libraries have dependencies which are moving commercial
  • no popular libraries for core python dataclass structures

Features

familiar methods

# ./main.py

from spic.app import Slip

app = Slip(title="my-api", version="0.1")

@app.get("/health")
async def status_handler():
    return {"status": "healthy ✨"}

app.collapse() # collapse routes

# hypercorn main:app --reload

dependency injection

# ./main.py

from spic.params import Header, Query

...

@app.get("/merged")
async def merged_params(x_usr_token: Header[str], query: Query[str]):
    return {
        "X-Usr-Token": x_usr_token,
        "query", query
    }


app.collapse()

dataclass support

# ./main.py
from dataclasses import dataclass
from spic.params import Header, Query

...

@dataclass
class QueryArgs:
    query: Query[str]
    x_usr_token: Header[str]

@app.get("/class_base")
async def model_params(model: QueryArgs):
    return {
        "X-Usr-Token": model.x_usr_token,
        "query", model.query
    }

generic dataclass serialization (pyserde)

# ./models.py
from serde import serde
from dataclasses import dataclass

@serde
@dataclass
class QueryArgs:
    query: Query[str]
    x_usr_token: Header[str]

# OR

# ./models.py
from spic.utils import schema

@schema
class QueryArgs:
    query: Query[str]
    x_usr_token: Header[str]

...
# ./main.py
...
@app.get("/serializable")
async def get_model(model: QueryArgs):
    return model # json

beartype validation

# ./client.py
from httpx import get
...

get(
    "http://localhost:8000/class_base?query=query-str-value" # missing header
).json()
# powered by beartype

# >> {
# >>  "errors": [
# >>    {
# >>      "key": "X_Usr_Token",
# >>      "expected": "string",
# >>      "given": "None",
# >>      "sources": ["header"]
# >>    }
# >>  ]
# >> }

performance

We currently test 3 primary use cases:

  • request param args -> function kwargs (no metaclass & valid)
    • 1.953ms overhead deserialization + reserialization (1000 ops)
  • request param args -> metaclass kwargs (dataclass)
    • 2.718ms overhead deserialization + reserialization (1000 ops)
  • invalid request param -> metaclass kwargs (raises errors & generates exception subclass)
    • 2.865ms overhead deserialization + reserialization (1000 ops)

Installation

pip install spic[core]

License

spic is distributed under the terms of the MIT license.

Download files

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

Source Distribution

spic-0.0.5.tar.gz (24.4 kB view hashes)

Uploaded Source

Built Distribution

spic-0.0.5-py3-none-any.whl (21.6 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