Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 1 addition & 11 deletions velocix/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,8 @@
from velocix.http.multipart import MultipartForm, UploadFile

# OpenAPI and Documentation
from velocix.openapi.auto_docs import AutoDocRouter, enable_auto_docs
from velocix.openapi.auto_docs import enable_auto_docs
from velocix.openapi.decorators import operation, parameter, response
from velocix.openapi.decorators_style import Body, Path, delete, get, patch, post, put
from velocix.openapi.generator import OpenAPIGenerator
from velocix.security.cors import CORSMiddleware

Expand Down Expand Up @@ -139,20 +138,11 @@ def create_app(
"PlainTextResponse",
"RedirectResponse",
# OpenAPI & Documentation
"AutoDocRouter",
"enable_auto_docs",
"OpenAPIGenerator",
"operation",
"parameter",
"response",
# Decorator-style syntax
"get",
"post",
"put",
"delete",
"patch",
"Path",
"Body",
# Parameter markers
"Query",
"Header",
Expand Down
70 changes: 1 addition & 69 deletions velocix/core/depends.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import inspect
import types
from collections.abc import Callable
from typing import Any, TypeVar, Union, get_args, get_origin, get_type_hints
from typing import Any, Union, get_args, get_origin, get_type_hints

import msgspec
import orjson
Expand Down Expand Up @@ -84,8 +84,6 @@ def _extract_marker(annotation: Any) -> tuple[Any, Any] | None:
]
_plan_cache: dict[int, tuple[Callable[..., Any], PlanEntry]] = {}

T = TypeVar("T")


class Depends:
"""
Expand Down Expand Up @@ -656,69 +654,3 @@ async def resolve_dependencies(

return kwargs


class DependencyCache:
"""
Request-scoped dependency cache (FastAPI pattern).
Automatically managed by resolve_dependencies.
"""

__slots__ = ("_cache",)

def __init__(self):
self._cache: dict[str, Any] = {}

def get(self, key: str, default: Any = None) -> Any:
"""Get cached dependency"""
return self._cache.get(key, default)

def set(self, key: str, value: Any) -> None:
"""Cache dependency"""
self._cache[key] = value

def clear(self) -> None:
"""Clear all cached dependencies"""
self._cache.clear()

def __contains__(self, key: str) -> bool:
return key in self._cache

def __len__(self) -> int:
return len(self._cache)


def inject(dependency: Callable[..., T]) -> T:
"""
Type-safe dependency injection helper.

Usage:
async def get_db() -> Database:
return Database()

@app.get("/users")
async def get_users(db: Database = inject(get_db)):
return await db.fetch_all()

This is a type-safe alternative to Depends() that works better
with type checkers like mypy.
"""
return Depends(dependency) # type: ignore


# Cleanup old cache entries to prevent memory leaks
def cleanup_caches(max_size: int = 1000) -> None:
"""Clean up signature and type hints caches"""
global _sig_cache, _type_hints_cache, _plan_cache

if len(_sig_cache) > max_size:
# Keep most recent entries
sig_items = list(_sig_cache.items())
_sig_cache = dict(sig_items[-max_size:])

if len(_type_hints_cache) > max_size:
hints_items = list(_type_hints_cache.items())
_type_hints_cache = dict(hints_items[-max_size:])

if len(_plan_cache) > max_size:
plan_items = list(_plan_cache.items())
_plan_cache = dict(plan_items[-max_size:])
9 changes: 1 addition & 8 deletions velocix/core/router.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,11 @@
from collections import defaultdict
from collections.abc import Callable
from dataclasses import dataclass, field
from typing import Any, Optional, Protocol
from typing import Any, Optional

from .exceptions import MethodNotAllowed, NotFound


class HandlerProtocol(Protocol):
"""Protocol for route handlers"""

def __call__(self, *args: Any, **kwargs: Any) -> Any: ...


@dataclass
class RouteMetrics:
"""Per-route hit tracking, only attached when Router(metrics_enabled=True)"""
Expand Down Expand Up @@ -77,7 +71,6 @@ def __init__(self, *, metrics_enabled: bool = False):
"WEBSOCKET": RouteNode(),
}
self.static_routes: dict[str, dict[str, Callable]] = defaultdict(dict)
self.dynamic_patterns: list[tuple] = []
self.middleware_stack: list[Callable] = []
# Flat (method, path, handler, name) registration log for include_router
self._registered: list[tuple[str, str, Callable, str | None]] = []
Expand Down
31 changes: 0 additions & 31 deletions velocix/openapi/__init__.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
"""OpenAPI support for Velocix"""

from .auto_docs import (
AutoDocRouter,
auto_document_function,
create_auto_router,
enable_auto_docs,
generate_operation_from_function,
)
Expand All @@ -21,23 +19,9 @@
string_schema,
tag,
)
from .decorators_style import (
Body,
Path,
Query,
VelocixStyleDocs,
create_docs,
delete,
get,
post,
put,
responses,
tags,
)
from .generator import (
OpenAPIGenerator,
ReDocHandler,
SwaggerUIHandler,
create_openapi_generator,
setup_docs_routes,
)
Expand Down Expand Up @@ -86,26 +70,11 @@
"object_schema",
# Generator
"OpenAPIGenerator",
"SwaggerUIHandler",
"ReDocHandler",
"create_openapi_generator",
"setup_docs_routes",
# Velocix-style (recommended)
"get",
"post",
"put",
"delete",
"Path",
"Query",
"Body",
"responses",
"tags",
"VelocixStyleDocs",
"create_docs",
# Auto-documentation (zero decorators!)
"AutoDocRouter",
"enable_auto_docs",
"create_auto_router",
"auto_document_function",
"generate_operation_from_function",
]
65 changes: 0 additions & 65 deletions velocix/openapi/auto_docs.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
"""Automatic OpenAPI generation from function signatures"""

import inspect
from collections.abc import Callable
from typing import Any, get_origin, get_type_hints

from ..core.depends import Depends
Expand Down Expand Up @@ -505,65 +504,6 @@ def auto_document_function(func: Any, path: str, method: str) -> Any:
return func


class AutoDocRouter:
"""Router that automatically generates OpenAPI documentation"""

def __init__(self, auto_docs: bool = True, auto_tags: bool = True):
self.routes: list[Any] = []
self.auto_docs = auto_docs
self.auto_tags = auto_tags

def _add_route(self, path: str, method: str, handler: Any) -> Any:
"""Add route with automatic documentation"""
if self.auto_docs:
handler = auto_document_function(handler, path, method)

route = type("Route", (), {"path": path, "method": method.upper(), "handler": handler})()

self.routes.append(route)
return handler

def get(self, path: str) -> Callable:
"""GET route with auto-docs"""

def decorator(func: Any) -> Any:
return self._add_route(path, "GET", func)

return decorator

def post(self, path: str) -> Callable:
"""POST route with auto-docs"""

def decorator(func: Any) -> Any:
return self._add_route(path, "POST", func)

return decorator

def put(self, path: str) -> Callable:
"""PUT route with auto-docs"""

def decorator(func: Any) -> Any:
return self._add_route(path, "PUT", func)

return decorator

def delete(self, path: str) -> Callable:
"""DELETE route with auto-docs"""

def decorator(func: Any) -> Any:
return self._add_route(path, "DELETE", func)

return decorator

def patch(self, path: str) -> Callable:
"""PATCH route with auto-docs"""

def decorator(func: Any) -> Any:
return self._add_route(path, "PATCH", func)

return decorator


# Integration with existing Velocix router
def enable_auto_docs(
app: Any,
Expand Down Expand Up @@ -644,8 +584,3 @@ async def get_redoc():

return app


# Convenience function
def create_auto_router(auto_docs: bool = True, auto_tags: bool = True) -> AutoDocRouter:
"""Create a router with automatic OpenAPI documentation"""
return AutoDocRouter(auto_docs=auto_docs, auto_tags=auto_tags)
Loading
Loading