Skip to main content

Python Web Framework built for learning purposes.

Project description

ZohidPy

PyPI version License purpose

A minimal WSGI web framework built from scratch to understand how web frameworks work internally.

ZohidPy is intentionally small and explicit.
It is designed for learning, experimentation, and understanding routing, middleware, request/response handling, templating, and static file serving without heavy abstractions.


Installation

pip install zohidpy

Quick Start

from waitress import serve
from zohidpy.app import ZohidPy

app = ZohidPy()

@app.route("/home")
def home(request, response):
    response.text = "Hello from ZohidPy!"

if __name__ == "__main__":
    serve(app, listen="localhost:8000")

Run:

python main.py

Visit:

http://localhost:8000/home


Features

  • Function-based routing
  • Class-based routing
  • Dynamic URL parameters
  • JSON / Text / HTML response helpers
  • Jinja2 template rendering
  • Static file serving (WhiteNoise)
  • Middleware system
  • Custom exception handlers
  • Built-in test client
  • Fully WSGI compatible

Routing

Function-Based Routing

@app.route("/home")
def home(request, response):
    response.text = "Hello from home"

Dynamic Routes

@app.route("/hello/{name}")
def greet(request, response, name):
    response.text = f"Hello {name}"

Class-Based Routing

@app.route("/books")
class Books:
    def get(self, request, response):
        response.text = "Books page"

    def post(self, request, response):
        response.text = "Create a book"

If a method is not defined, the framework returns:

405 Method Not Allowed

Restricting Allowed Methods

@app.route("/home", allowed_methods=["post"])
def home(request, response):
    response.text = "POST only"

Response Helpers

JSON

resp.json = {"name": "zohid"}

Automatically sets:

Content-Type: application/json

Plain Text

resp.text = "Hello world"

Sets:

Content-Type: text/plain

HTML

resp.html = "<h1>Hello</h1>"

Sets:

Content-Type: text/html

Templates (Jinja2)

Default directory:

templates/

Example:

@app.route("/template")
def template_handler(req, resp):
    resp.html = app.template(
        "home.html",
        context={"title": "My Page"}
    )

Custom template directory:

app = ZohidPy(templates_dir="my_templates")

Static Files

Static files are served using WhiteNoise.

Default directory:

static/

Accessible via:

/static/filename.css

Custom directory:

app = ZohidPy(static_dir="assets")

Middleware

Create middleware by subclassing Middleware:

from zohidpy.middleware import Middleware

class LoggingMiddleware(Middleware):
    def process_request(self, req):
        print("Request:", req.url)

    def process_response(self, req, resp):
        print("Response generated")

app.add_middleware(LoggingMiddleware)

Middleware lifecycle:

  1. process_request
  2. route handler
  3. process_response

Custom Exception Handling

def on_exception(req, resp, exc):
    resp.text = "Something went wrong"

app.add_exception_handler(on_exception)

Testing

ZohidPy includes a built-in test client:

test_client = app.test_session()

Example test:

def test_home(app, test_client):
    @app.route("/home")
    def home(req, resp):
        resp.text = "Hello"

    response = test_client.get("http://testingserver/home")
    assert response.text == "Hello"

Deployment

ZohidPy is fully WSGI-compatible.

Waitress

waitress-serve --listen=0.0.0.0:8000 main:app

Gunicorn

gunicorn main:app

Internal Architecture Overview

High-level request flow:

  1. WSGI entry point receives request
  2. Static files handled via WhiteNoise
  3. Middleware layer executes
  4. Route resolution via pattern matching
  5. Handler execution
  6. Response object constructs final WebOb response

The design favors clarity over abstraction.


License

This project is licensed under the Apache License 2.0 — see the LICENSE file for details.


Author

Zohidjon Mahmudjonov

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

zohidpy-0.1.3.tar.gz (12.7 kB view details)

Uploaded Source

Built Distribution

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

zohidpy-0.1.3-py2.py3-none-any.whl (9.9 kB view details)

Uploaded Python 2Python 3

File details

Details for the file zohidpy-0.1.3.tar.gz.

File metadata

  • Download URL: zohidpy-0.1.3.tar.gz
  • Upload date:
  • Size: 12.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.10

File hashes

Hashes for zohidpy-0.1.3.tar.gz
Algorithm Hash digest
SHA256 9f74179fb3189415e6a015e7ef144c768ab29e0b246c28b017027520de75c0a1
MD5 6a6d4e3ac27e28108298394a2993a47c
BLAKE2b-256 91ab77f4a8c224745054bd43b5734ea45e399c4ca8e2bae1110bf305ad01308f

See more details on using hashes here.

File details

Details for the file zohidpy-0.1.3-py2.py3-none-any.whl.

File metadata

  • Download URL: zohidpy-0.1.3-py2.py3-none-any.whl
  • Upload date:
  • Size: 9.9 kB
  • Tags: Python 2, Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.10

File hashes

Hashes for zohidpy-0.1.3-py2.py3-none-any.whl
Algorithm Hash digest
SHA256 4087c70e7145c8d59ad2b18f8dbfedb84d563ff40e3b6f8a932109204453cc61
MD5 6067de6507fffdc79a861bed8ba404ea
BLAKE2b-256 0e270b64546cccad4ee28d9ed5759b7fc758308dd49fbdf3352802a1cfc054b7

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