Skip to main content

A pythonic web framework

Project description

lessweb

Lessweb is a ready-to-use, production-grade Python web framework with the following goals:

  • Ready-to-use: Easily parse configuration files, set up logging with ease, and dynamically override configuration items using environ variables.
  • Production-grade: Built on the aiohttp ecosystem and boasting powerful IOC capabilities.
  • Pythonic: Supports the latest Python versions and syntax.

📦 Installation

To install the latest version of lessweb for Python ≥ 3.10, run:

pip install lessweb

Dependencies


⚡ Quick Start Example

Save the following to main.py:

from typing import Annotated
from lessweb import Bridge
from lessweb.annotation import Get

async def hello(*, who: str = 'world') -> Annotated[dict, Get('/')]:
    return {'message': f'Hello, {who}!'}

def main():
    bridge = Bridge()
    bridge.scan(hello)
    bridge.run_app()

if __name__ == '__main__':
    main()

Run your app:

python main.py

Now open your browser at http://localhost:8080

Output:

{"message": "Hello, world!"}

Or try http://127.0.0.1:8080?who=John:

{"message": "Hello, John!"}

📚 Official Documentation


📘 Lessweb Framework Guide

Below is a summarized version of the Quick Start and IOC (Dependency Injection) documentation.


🧭 Endpoint Basics

An endpoint in lessweb is an async function bound to a specific HTTP route (URL). Endpoints can automatically receive parameters from query strings, path variables, or the request body.

Example:

from typing import Annotated
from aiohttp.web import Request
from lessweb import Bridge
from lessweb.annotation import Get, Post

async def get_pet_detail(request: Request) -> Annotated[dict, Get('/pet/{pet_id}')]:
    return {'pet_id': request.match_info['pet_id']}

async def create_pet(request: Request) -> Annotated[dict, Post('/pet')]:
    pet = await request.json()
    return pet

if __name__ == '__main__':
    bridge = Bridge()
    bridge.scan(get_pet_detail, create_pet)
    bridge.run_app()

You can also scan an entire package:

bridge.scan('myapp.endpoint')

Dynamic Path Parameters

Supports regex-based path matching:

async def get_pet_detail(request: Request) -> Annotated[dict, Get('/pet/{pet_id:[0-9]+}')]:
    ...

🧩 Request Parameter Injection

Lessweb automatically injects request data into endpoint parameters:

  • keyword-only parameters (*, name: str) → path/query parameters
  • positional-only parameters (data: Model, /) → JSON body
  • normal parameters (request: Request) → context objects or services

Example:

from pydantic import BaseModel
from lessweb.annotation import Get, Post
from typing import Annotated

class Pet(BaseModel):
    pet_id: int
    name: str

async def get_pet_detail(*, pet_id: int) -> Annotated[dict, Get('/pet/{pet_id}')]:
    return {'pet_id': pet_id}

async def create_pet(pet: Pet, /) -> Annotated[dict, Post('/pet')]:
    return pet

Supported types include:

  • str, int, float, bool, list
  • datetime, date, time
  • enum, Literal, Union, NewType
  • pydantic.BaseModel

💡 JSON Responses

Endpoints can directly return JSON-compatible data:

async def get_pet_list() -> Annotated[dict, Get('/pet')]:
    return [{'pet_id': 1, 'name': 'Kitty'}]

Or use helper functions for advanced responses:

from lessweb import rest_response, rest_error
from aiohttp.web import HTTPBadRequest

async def get_pet_list() -> Annotated[dict, Get('/pet')]:
    return rest_response([{'name': 'Kitty'}], headers={'X-TOKEN': 'abc123'})

async def bad_request() -> Annotated[dict, Get('/error')]:
    raise rest_error(HTTPBadRequest, {'code': -1, 'message': 'Invalid request'})

⚙️ JSON Serialization

Based on orjson with support for:

  • dataclasses
  • datetime / date / time (RFC 3339)
  • enum
  • numpy types
  • uuid
  • pydantic models

Configurable in config.toml:

[lessweb]
orjson_option = 'APPEND_NEWLINE,INDENT_2,UTC_Z'

🧠 Dependency Injection (IOC)

Lessweb’s IOC system auto-injects dependencies based on parameter types, similar to Spring Boot.

Lifecycle Levels

Type Scope Description
Module Process-level singleton e.g. DB connection pool
Middleware Request-level wrapper Pre/post processing
Service Request-level singleton Business logic
Bean Request-level factory result Complex object creation

Example: Modules

class Mysql(Module):
    async def on_startup(self, app):
        self.pool = await aiomysql.create_pool(...)

class RedisModule(Module):
    async def on_startup(self, app):
        self.redis_client = redis.Redis(...)

Example: Middleware

class MysqlConn(Middleware):
    def __init__(self, mysql: Mysql):
        self.mysql = mysql

    async def on_request(self, request, handler):
        async with self.mysql.pool.acquire() as conn:
            self.conn = conn
            return await handler(request)

Example: Services and Beans

class TaskService(Service):
    def __init__(self, dao: Commondao, redis: redis.Redis):
        self.dao = dao
        self.redis = redis

def commondao_bean(mysqlConn: MysqlConn) -> Commondao:
    return Commondao(mysqlConn.conn, mysqlConn.cur)

def redis_bean(redis_module: RedisModule) -> redis.Redis:
    return redis_module.redis_client

Register all in main.py:

def main():
    bridge = Bridge()
    bridge.beans(commondao_bean, redis_bean)
    bridge.middlewares(MysqlConn)
    bridge.scan('src')
    bridge.run_app()

✅ Best Practices

  • Use Middleware for request pre/post hooks (e.g. auth, logging)
  • Use Service for business logic
  • Keep Module dependencies only between other Modules
  • Let Beans create reusable request-scoped objects

📄 License

Lessweb is offered under the Apache 2.0 License.


🧭 Source Code

GitHub Repository: 👉 https://github.com/lessweb/lessweb

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

lessweb-2.2.0.tar.gz (47.2 kB view details)

Uploaded Source

Built Distribution

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

lessweb-2.2.0-py3-none-any.whl (22.4 kB view details)

Uploaded Python 3

File details

Details for the file lessweb-2.2.0.tar.gz.

File metadata

  • Download URL: lessweb-2.2.0.tar.gz
  • Upload date:
  • Size: 47.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.11.8

File hashes

Hashes for lessweb-2.2.0.tar.gz
Algorithm Hash digest
SHA256 1bff733630e4f5186659bab59d66466eeefd53511cc2ff495f75e19c2774686d
MD5 e2ff0fabdf4630915fbde5c1dd1e3a46
BLAKE2b-256 d6d9f78a80d32f6a23df0a6cf4d9359e2ae6f7882e3f6cd4701287422961a344

See more details on using hashes here.

File details

Details for the file lessweb-2.2.0-py3-none-any.whl.

File metadata

  • Download URL: lessweb-2.2.0-py3-none-any.whl
  • Upload date:
  • Size: 22.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.11.8

File hashes

Hashes for lessweb-2.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 a04c937cb5590b1817fc0dc57ce30589bad75fe2d5b1fbc0ec261da078d78aa7
MD5 c7f296fd24c018fdafddfaff8df024dd
BLAKE2b-256 65097661e29330b29e98b74c479e1c750a082550e1fa40fb12dd529915787ae1

See more details on using hashes here.

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