Skip to content

Nebula - 3.3.0

Choose a tag to compare

@VxidDev VxidDev released this 03 Apr 16:16

Nebula 3.3.0 - Release Notes

What’s New

⚠️ Error Dispatcher & Injection System (Major)

Nebula introduces a flexible injection system for error handlers along with a fully redesigned error dispatch pipeline.

Error handlers can now declare exactly what they need, and Nebula will inject it automatically.


Error Handler Injection

Error handlers now support explicit parameter injection.

Supported parameters:

  • request - current request object
  • scope - raw ASGI scope
  • receive - ASGI receive callable
  • send - ASGI send callable
  • code - HTTP status code

Example

@app.error_handler(404)
async def not_found(request, code):
    return f"<h1>{code} - {request.path} not found</h1>"

Only declared parameters are passed, nothing extra.


⚠️ Important Behavior

  • Injection is name-based, not positional
  • Only explicitly declared parameters are provided
  • Works for both sync and async handlers
  • No runtime introspection, everything is cached at registration

Error Dispatcher

Nebula’s internal _dispatch_error system has been completely redesigned.

Key Improvements

  • Zero overhead at runtime

    • No inspect calls during request handling
  • 🧠 Precomputed handler metadata

    • Accepted parameters cached
    • Async/sync status cached
  • 🔁 Unified execution path

    • Same logic for all error handlers

How It Works

  1. Error occurs (404 / 405 / 500 or HTTPException)
  2. Matching handler is resolved
  3. Required parameters are injected
  4. Handler is executed (sync or async)
  5. Return value is normalized into a Response

Strict Signature Validation

Error handlers are now validated at registration time.

Allowed parameters:

{"scope", "receive", "send", "request", "code"}

Example (invalid)

@app.error_handler(404)
def handler(foo):  # ❌ not allowed
    ...

➡️ Raises:

ExtraArgumentsDetected

⚠️ Behavior Note

  • Invalid signatures fail early (at startup)
  • Prevents runtime bugs and undefined behavior
  • Ensures consistent handler contracts

Automatic Response Handling

Error handlers can return any supported type:

  • Response → used directly

  • dict / listJSONResponse

  • str → auto-detected:

    • HTML → HTMLResponse
    • URL → RedirectResponse
    • otherwise → PlainTextResponse

Example

@app.error_handler(500)
def internal_error(code):
    return {"error": "Internal Server Error", "status": code}

Request Context Access

Nebula now provides a global request proxy:

from nebula import request

@app.error_handler(500)
def handler():
    return f"Error on {request.path}"

⚠️ Important Behavior

  • Powered by ContextVar (async-safe)
  • Only available inside request lifecycle
  • Access outside request raises:
RuntimeError

Default Error Handlers

Built-in handlers (404, 405, 500) now:

  • Use the same injection system
  • Follow the same response normalization rules
  • Are fully replaceable via @app.error_handler(...)

Internal Improvements

  • Added _error_handler_params cache
  • Added _error_handler_is_async cache
  • Removed runtime inspect usage from hot path
  • Improved separation of dispatch and execution
  • Optimized error handling performance

⚠️ Breaking Changes

1. Restricted Error Handler Signatures

Old:

def handler(foo, bar): ...

New:

def handler(request, code): ...

Only supported parameters are allowed.