Skip to main content

Roob

Roob is a small, educational WSGI-compatible Python web framework built from scratch to help you understand how web frameworks work. It's intentionally lightweight and opinionated for learning and experimentation.

Features

  • WSGI Compatible: The framework exposes a callable application usable with any WSGI server.
  • Routing: Supports both automatic (path pattern) and explicit route registration.
  • Handlers: Function-based and class-based handlers are supported.
  • Middlewares: Compose request/response processing via middleware classes. Includes ErrorHandlerMiddleware and helpers.
  • Templating: Provides a templating system accessible via the template() helper on the app.
  • Static Files: Static files (CSS/JS/images) can be served from a static/ directory.
  • Error Handling: Built-in ResponseError and optional middleware to convert exceptions into JSON responses.
  • HTTP Method Control: Route definitions can restrict allowed HTTP methods.
  • Published: The package is available on PyPI for easy installation.

Installation

  • From PyPI: pip install Roob

Quick Start

  • Create a minimal app
from Roob.framework import Roob
app = Roob()

@app.route('/')
def index(request):
    return app.templates_env.get_template('dashboard.html').render()

if __name__ == '__main__':
    from wsgiref.simple_server import make_server
    server = make_server('0.0.0.0', 8080, app)
    print('Serving on http://0.0.0.0:8080')
    server.serve_forever()

Function-based handler

from Roob.framework import Roob
from Roob.models.responses import JSONResponse

app = Roob()

@app.route('/hello')
def hello(request):
    return JSONResponse({"message": "Hello from Roob"})

Class-based Handler

Roob support both automatic and manually registered Class Based handlers

Self registered Class-based Handler

The function names should matched with HTTP request method.

@app.route('/items')
class ItemHandler:
    def __init__(self):
        self.service = ItemService()

    # get all products
    def get(self, request):
        items: list[dict] = self.service.get_items()
        return JSONResponse(items)

    # create a product
    def post(self, request):
        items: dict = self.service.create_items()
        return JSONResponse(items)

Notes:

  • Self registered Class-based handlers are registered as classes. The framework will instantiate the class and call the method matching the HTTP method name (e.g., get, post).

Manually registerd Class-based Handler

If you need both custom handlers in a class then you can register routes manually

from Roob.framework import Roob
from Roob.models.responses import JSONResponse

app = Roob()

class ItemHandlerCustomRouting:
    def get_by_id(self, request, item_id=None):
        return JSONResponse({"item_id": item_id})

    def get_by_category(self, request, category=None):
        # JSONResponse also supports list of classes
        items: list[Item] = items_service.get_by_category()
        return JSONResponse(items)

handler = ItemHandlerCustomRouting()
app.add_route('/items/{item_id:d}', handler.get_by_id)
app.add_route('/items/{category}', handler.get_by_category)

Routing & Path Variables

  • Paths can include variables using the {name} syntax. The framework will parse them and pass as kwargs to your handler.
  • Example: app.add_route('/users/{user_id}', handler) — handler will receive user_id as a keyword argument.

Middlewares & Error Handling

  • Built-in middlewares: ErrorHandlerMiddleware, ReqResLoggingMiddleware, and ExecutionTimeMiddleware are provided in Roob.middlewares package.
  • ResponseError: Raise Roob.exceptions.ResponseError (or its subclasses) from handlers to return structured JSON error responses. The ErrorHandlerMiddleware converts ResponseError into an appropriate JSON response with the specified HTTP status.

Example — adding middleware and a simple error:

from Roob.framework import Roob
from Roob.middlewares import ErrorHandlerMiddleware
from Roob.exceptions import ResponseError

app = Roob()
app.add_middleware(ErrorHandlerMiddleware)

@app.route('/fail')
def fail(request):
    raise ResponseError('This is a custom error', 400)
  • Response JSON
{
    "message": "This is a custom error"
}

Templating

  • The app provides a templating system. Templates are loaded from the templates directory by default. Use app.template(template_name, context) to generate view from a template dynamically.

Example: Register the template if you have a customer template directory

from Roob.framework import Roob
from Roob.models.responses import HTMLResponse

app = Roob(template_dir=f"{cwd}/templates")

@app.route('/dashboard')
def dashboard(request) -> Response:
    name = "Hello User"
    title = "Dashboard View"
    html_content = app.template(
        "dashboard.html", 
        context={"name": name, "title": title}
    )
    return HTMLResponse(html_content)

Static Files

  • Static assets under the static directory are served automatically. Place CSS/JS/images in static/ and reference them from your templates.

WSGI Compatibility

  • The Roob instance is a valid WSGI application. You can run it with any WSGI server (uWSGI, Gunicorn, or wsgiref during development).

You can run the demo application with Gunicorn service using

make run

Tests & Examples

  • See the tests/ and demo_app/ directories in this repository for usage examples and test coverage.

Contributing

  • This project is intended for learning. Contributions that improve docs, add examples, or clarify internals are welcome.

License

  • See the LICENSE file in this repository.

Download files

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

Source Distribution

roob-0.0.3.tar.gz (19.1 kB view details)

Uploaded Source

Built Distribution

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

roob-0.0.3-py3-none-any.whl (23.2 kB view details)

Uploaded Python 3

File details

Details for the file roob-0.0.3.tar.gz.

File metadata

  • Download URL: roob-0.0.3.tar.gz
  • Upload date:
  • Size: 19.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.3

File hashes

Hashes for roob-0.0.3.tar.gz
Algorithm Hash digest
SHA256 deb0ffd9bdd478d844fb89c6e4434a95362e7c9d860878047575765900b7c5f1
MD5 6082fe16f956bf7ddb7331ca81a96336
BLAKE2b-256 7ac21dc8a83f1f0e2c9fab12615f5a72b22da8edcd08c68efb28fa19d8aad2f5

See more details on using hashes here.

File details

Details for the file roob-0.0.3-py3-none-any.whl.

File metadata

  • Download URL: roob-0.0.3-py3-none-any.whl
  • Upload date:
  • Size: 23.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.3

File hashes

Hashes for roob-0.0.3-py3-none-any.whl
Algorithm Hash digest
SHA256 a55bae5ff2eff4e55cb94d09538edea35c80e6c6cbf138bbe04cc0fc55decbe7
MD5 468283973fdc88fecc0cfa1f67aaaca4
BLAKE2b-256 1e3f1946719b024bbaf5ad7640deca1efb99c2fedc43ca5115c0e0e0fdc92987

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

0.0.3 This release

2 files

Supported by

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