Skip to main content

A production-ready, high-performance, async-first Python web framework.

Project description

🐍 OpenViper

A production-ready, high-performance, async-first Python web framework.

The freedom of a minimal core. The power of a full stack.

Python License Version


OpenViper is a production-ready, high-performance, async-first Python web framework designed to be both flexible and batteries-included. It gives you the freedom of a minimal, unopinionated core when you want control, while also providing a rich, fully integrated stack when you want to move fast.

Out of the box it includes a powerful ORM with model lifecycle and events, built-in authentication and authorization, an Admin UI, background task processing, a pluggable AI provider registry, and automatic OpenAPI documentation.

Whether you're building lean APIs or full-scale platforms, OpenViper scales with you — without forcing you into rigid architectural constraints.


✨ Features

🔀 Routing function-based and class-based (View) routes, path params, route groups
🗄️ ORM Async models, QuerySet API, migrations, lifecycle hooks, model events
🔐 Auth Session + JWT, password hashing, roles, permissions, @login_required
🖥️ Admin UI Auto-discovered SPA — CRUD, bulk actions, change history, inlines
🔧 Middleware Auth, CORS, CSRF, rate-limiting, security headers
⚙️ Background Tasks Task queue with retry, priorities, model-event hooks
🕐 Scheduler Cron and interval periodic jobs built into the framework
🤖 AI Registry Unified async API — OpenAI, Anthropic, Gemini, Ollama, Grok, custom
📦 Serializers Pydantic-based, ModelSerializer, Serializer, nested, partial updates, role-aware
📄 OpenAPI Live Swagger + ReDoc UIs auto-generated from your routes

🚀 Quick Start

Install

pip install openviper

Minimal — single file

# app.py
from openviper import OpenViper, JSONResponse
from openviper.http.request import Request

app = OpenViper(title="My API")


@app.get("/")
async def index(request: Request) -> JSONResponse:
    return JSONResponse({"message": "Hello, OpenViper!"})

@app.get("/users/{user_id}")
async def get_user(request: Request, user_id: int) -> JSONResponse:
    return JSONResponse({"id": user_id, "name": "Alice"})

@app.post("/users")
async def create_user(request: Request) -> JSONResponse:
    body = await request.json()
    return JSONResponse({"created": True, **body}, status_code=201)
openviper run app --reload

Open in your browser:

  • APIhttp://localhost:8000
  • Swagger UIhttp://localhost:8000/open-api/docs
  • ReDochttp://localhost:8000/open-api/redoc

Full project (with DB, auth, admin)

# Scaffold a new project
openviper create-project myproject
cd myproject
openviper create-app blog

# Configure your myproject/settings.py


# Run migrations and create an admin user
python viperctl.py makemigrations
python viperctl.py migrate
python viperctl.py createsuperuser

# Start everything
python viperctl.py runserver    # web server
python viperctl.py runworker    # background task worker (separate terminal)

📚 Core Concepts

Models & ORM

# blog/models.py
from openviper.db import Model
from openviper.db.fields import (
    CharField, TextField, BooleanField, DateTimeField, ForeignKey,
)
from openviper.auth import get_user_model

User = get_user_model()

class Post(Model):
    _app_name = "blog"

    title      = CharField(max_length=255)
    content    = TextField()
    author     = ForeignKey(User, on_delete="CASCADE")
    published  = BooleanField(default=False)
    created_at = DateTimeField(auto_now_add=True)
    updated_at = DateTimeField(auto_now=True)

    class Meta:
        table_name = "blog_posts"

    async def after_insert(self):
        # Lifecycle hook — enqueue moderation task after every new post
        print("Post created:", self.title)
        send_welcome_email.send_with_options(args=(self.id,), delay=5_000)

    async def on_update(self):
        # Lifecycle hook — update timestamp before every update
        print("Post updated:", self.title)

    async def on_delete(self):
        # Lifecycle hook — delete related comments after every post deletion
        print("Post deleted:", self.title)

QuerySet API:

# All published posts, newest first
posts = await Post.objects.filter(published=True).order_by("-created_at").all()

# Single record — returns None if not found
post = await Post.objects.get_or_none(id=42)

# Count
drafts = await Post.objects.filter(published=False).count()

# Async iteration
async for post in Post.objects.filter(author_id=user.id):
    print(post.title)

# Bulk update
await Post.objects.filter(author_id=user.id).update(published=True)

Admin Panel

Register models in blog/admin.py — OpenViper discovers it automatically:

from openviper.admin import ModelAdmin, ActionResult, action, register
from .models import Post

@register(Post)
class PostAdmin(ModelAdmin):
    list_display  = ["id", "title", "author", "published", "created_at"]
    list_filter   = ["published"]
    search_fields = ["title", "content"]
    actions       = ["publish_selected"]

    @action(description="Publish selected posts")
    async def publish_selected(self, queryset, request):
        count = await queryset.update(published=True)
        return ActionResult(success=True, count=count, message=f"Published {count} posts.")

start server

python viperctl.py runserver

Visit http://localhost:8000/admin

Background Tasks

# blog/tasks.py
from openviper.tasks import task

@task()
async def send_welcome_email(post_id: int):
    """
    Do something
    """

Periodic Scheduler

from openviper.tasks.scheduler import periodic
from openviper.tasks.schedule import CronSchedule, IntervalSchedule
from datetime import timedelta

@periodic(every=60)
async def morning_digest():
    ...

@periodic(every=300)
async def refresh_cache():
    ...
python viperctl.py runworker

📂 Examples

Example Description
todoapp Single-file app — auth, admin, SQLite, HTML templates
ai_moderation_platform Multi-app platform — AI moderation, Dramatiq tasks, Docker, PostgreSQL
ai_smart_recipe_generator AI-powered recipe generator with meal planning and nutrition analysis
ecommerce_clone Full e-commerce platform — products, orders, cart, chat, admin
custom_provider_demo Writing and registering a custom AI provider plugin
flexible Minimal decorator-based routing example
fx FX / financial data example
tp Minimal project scaffold example

📖 Documentation

Full reference documentation lives in https://mymi14s.github.io/openviper/.


⚙️ Requirements

  • Python ≥ 3.14
  • Supported DB driver — PostgreSQL, MySQL/MariaDB, SQLite

📜 License

MIT — see LICENSE.

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

openviper-0.0.1.tar.gz (935.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

openviper-0.0.1-py3-none-any.whl (1.0 MB view details)

Uploaded Python 3

File details

Details for the file openviper-0.0.1.tar.gz.

File metadata

  • Download URL: openviper-0.0.1.tar.gz
  • Upload date:
  • Size: 935.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for openviper-0.0.1.tar.gz
Algorithm Hash digest
SHA256 3af6738b1c1485d6fe45e3bd9b6f525da87c6574370a55a3b4e27224784b1e49
MD5 b88f3a011978fdf65f9cb73f7a3f2991
BLAKE2b-256 113fc59f6c426c96b502a4547bece6da2f8db5e80c40adf0aa5e1439cdbae731

See more details on using hashes here.

Provenance

The following attestation bundles were made for openviper-0.0.1.tar.gz:

Publisher: release.yml on mymi14s/openviper

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file openviper-0.0.1-py3-none-any.whl.

File metadata

  • Download URL: openviper-0.0.1-py3-none-any.whl
  • Upload date:
  • Size: 1.0 MB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for openviper-0.0.1-py3-none-any.whl
Algorithm Hash digest
SHA256 db2800c36e4b86e8b0434b2ea7c764accdbe4aa169621159ea866ee6d26c716c
MD5 da56a810151db0554c747fd2995b89de
BLAKE2b-256 0226f8109b063a837f6766ff9963590af472a956f5adfa0ce1269dc7db73c36d

See more details on using hashes here.

Provenance

The following attestation bundles were made for openviper-0.0.1-py3-none-any.whl:

Publisher: release.yml on mymi14s/openviper

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

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