Source code for genro_routes.core.decorators

"""Decorator helpers for marking routed methods.

This module contains only marker helpers; no router mutation happens at
decoration time.

``route(*, name=None, endpoint_id=None, media_type=None, **kwargs)``
    Returns a decorator storing metadata on the function under
    ``_route_decorator_kw`` as a list of dicts. All markers belong to the
    class's single router (one router per RoutingClass).

    - Explicit logical name: if ``name`` is provided, the payload sets
      ``entry_name`` to that value. Otherwise the handler name defaults to
      the function name.
    - Result media type: if ``media_type`` is provided (RFC 9110 ``type/subtype``,
      e.g. ``"application/json"``), it is stored under ``metadata["meta"]["media_type"]``
      and surfaced both at runtime (``RouterNode.metadata``) and in the neutral
      ``result`` block of ``nodes()``.
    - Extra ``**kwargs`` are copied verbatim into the payload (e.g. plugin flags).
    - Stacking the decorator registers the same function under multiple
      entry names (aliases).
    - The decorator returns the original function unchanged aside from the marker.

Re-exports
----------
This module re-exports ``RoutingClass`` and ``Router`` for convenience so user
code can import everything from one place.
"""

from __future__ import annotations

from collections.abc import Callable
from typing import Any

from .router import Router
from .routing import RoutingClass

__all__ = ["route", "RoutingClass", "Router"]


[docs] def route( *, name: str | None = None, endpoint_id: str | None = None, media_type: str | None = None, **kwargs: Any, ) -> Callable[[Callable], Callable]: """Mark a bound method for inclusion in the class's router. Args: name: Optional explicit entry name (overrides function name/prefix stripping). endpoint_id: Optional globally unique identifier for reverse lookup. When set, the handler can be resolved via ``router.node("@endpoint_id")``. media_type: Optional result media type (RFC 9110 ``type/subtype``, e.g. ``"application/json"``). Stored under ``metadata["meta"]["media_type"]``; surfaced at runtime via ``RouterNode.metadata`` and in the neutral ``result`` block of ``nodes()``. **kwargs: Extra metadata merged into handler entry (e.g. plugin flags). Returns: Decorator that marks the function for the router. Example:: class Table(RoutingClass): @route() def list_users(self): return ["alice", "bob"] @route(name="custom_name", logging_enabled=False) def get_user(self, user_id): return {"id": user_id} @route(media_type="text/html") def render(self): return "<h1>hi</h1>" """ def decorator(func: Callable) -> Callable: markers = list(getattr(func, "_route_decorator_kw", [])) payload: dict[str, Any] = {} if name is not None: payload["entry_name"] = name if endpoint_id is not None: payload["endpoint_id"] = endpoint_id if media_type is not None: payload["meta_media_type"] = media_type for key, value in kwargs.items(): payload[key] = value markers.append(payload) setattr(func, "_route_decorator_kw", markers) # noqa: B010 return func return decorator