diff --git a/pyproject.toml b/pyproject.toml index e2ba789..f4b37d2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -23,11 +23,7 @@ classifiers = [ dependencies = [ "granian>=1.0.0", "orjson>=3.9.0", - "pydantic>=2.0.0,<3.0.0", - "pydantic-settings>=2.0.0", - "asyncpg>=0.29.0", "prometheus-client>=0.19.0", - "python-jose[cryptography]>=3.3.0", "python-multipart>=0.0.6", "httpx>=0.25.0", "aiofiles>=23.0.0", diff --git a/requirements.txt b/requirements.txt index 5f2e85d..b6ded9f 100644 --- a/requirements.txt +++ b/requirements.txt @@ -14,6 +14,8 @@ xxhash>=3.6.0 itsdangerous>=2.0.0 nh3>=0.2.0 aiofiles>=23.0.0 +prometheus-client>=0.19.0 +httpx>=0.25.0 pytest>=7.4.0 mypy>=1.7.0 ruff>=0.5.0 diff --git a/velocix/__init__.py b/velocix/__init__.py index d7e3f9d..1b570d4 100644 --- a/velocix/__init__.py +++ b/velocix/__init__.py @@ -4,7 +4,6 @@ Built on top of: - Granian (Rust ASGI server) - orjson (Rust JSON serialization) -- httptools (C HTTP parsing) - msgspec (Rust-speed validation) - Radix tree routing with advanced caching """ diff --git a/velocix/config/settings.py b/velocix/config/settings.py deleted file mode 100644 index 4733824..0000000 --- a/velocix/config/settings.py +++ /dev/null @@ -1,73 +0,0 @@ -"""Application settings with pydantic-settings""" - -from typing import Any - -from pydantic import Field -from pydantic_settings import BaseSettings, SettingsConfigDict - - -class Settings(BaseSettings): - """Application configuration""" - - host: str = Field(default="0.0.0.0", description="Server host") - port: int = Field(default=8000, description="Server port") - workers: int = Field(default=4, description="Number of workers") - reload: bool = Field(default=False, description="Auto-reload on code changes") - - database_url: str = Field(default="", description="PostgreSQL connection string") - db_pool_min: int = Field(default=10, description="Minimum pool connections") - db_pool_max: int = Field(default=20, description="Maximum pool connections") - db_health_check_interval: int = Field( - default=30, description="Health check interval in seconds" - ) - - jwt_secret: str = Field(default="", description="JWT secret key") - jwt_algorithm: str = Field(default="HS256", description="JWT algorithm") - jwt_access_token_expire: int = Field( - default=3600, description="Access token expiration in seconds" - ) - jwt_refresh_token_expire: int = Field( - default=604800, description="Refresh token expiration in seconds" - ) - - cors_enabled: bool = Field(default=False, description="Enable CORS") - cors_origins: list[str] = Field(default=["*"], description="Allowed origins") - cors_methods: list[str] = Field( - default=["GET", "POST", "PUT", "DELETE", "PATCH"], description="Allowed methods" - ) - cors_headers: list[str] = Field(default=["*"], description="Allowed headers") - cors_credentials: bool = Field(default=False, description="Allow credentials") - - rate_limit_enabled: bool = Field(default=False, description="Enable rate limiting") - rate_limit_requests: int = Field(default=100, description="Requests per window") - rate_limit_window: int = Field(default=60, description="Time window in seconds") - rate_limit_burst: int = Field(default=0, description="Burst size (0 = same as requests)") - - log_level: str = Field(default="INFO", description="Logging level") - debug: bool = Field(default=False, description="Debug mode") - - metrics_enabled: bool = Field(default=True, description="Enable Prometheus metrics") - - model_config = SettingsConfigDict(case_sensitive=False, extra="ignore") - - def get_db_pool_config(self) -> dict[str, int]: - """Get database pool configuration""" - return { - "min_size": self.db_pool_min, - "max_size": self.db_pool_max, - "health_check_interval": self.db_health_check_interval, - } - - def get_cors_config(self) -> dict[str, Any]: - """Get CORS configuration""" - return { - "allow_origins": self.cors_origins, - "allow_methods": self.cors_methods, - "allow_headers": self.cors_headers, - "allow_credentials": self.cors_credentials, - } - - def get_rate_limit_config(self) -> dict[str, int]: - """Get rate limit configuration""" - burst = self.rate_limit_burst if self.rate_limit_burst > 0 else self.rate_limit_requests - return {"rate": self.rate_limit_requests, "per": self.rate_limit_window, "burst": burst} diff --git a/velocix/openapi/auto_docs.py b/velocix/openapi/auto_docs.py index e1b98cd..cea3a74 100644 --- a/velocix/openapi/auto_docs.py +++ b/velocix/openapi/auto_docs.py @@ -42,18 +42,6 @@ def is_msgspec_struct(annotation: Any) -> bool: return False -def is_pydantic_model(annotation: Any) -> bool: - """Check if annotation is a Pydantic BaseModel""" - try: - from pydantic import BaseModel - - if hasattr(annotation, "__mro__"): - return BaseModel in annotation.__mro__ - except (ImportError, AttributeError): - pass - return False - - def is_body_parameter(param_name: str, param: inspect.Parameter, annotation: Any) -> bool: """ Determine if a parameter should be treated as request body. @@ -73,8 +61,8 @@ def is_body_parameter(param_name: str, param: inspect.Parameter, annotation: Any if param_name.lower() == "request": return False - # If annotation is a Struct or Pydantic model, it's a body parameter - if is_msgspec_struct(annotation) or is_pydantic_model(annotation): + # If annotation is a Struct, it's a body parameter + if is_msgspec_struct(annotation): return True # Complex types without default values are likely body params @@ -300,37 +288,6 @@ def _build_schema_from_type_info(type_info: Any) -> dict[str, Any]: return {"type": "object"} -def generate_schema_from_pydantic(model_class: Any) -> dict[str, Any]: - """Generate OpenAPI schema from Pydantic model""" - try: - # Try Pydantic v2 schema generation - if hasattr(model_class, "model_json_schema"): - return dict(model_class.model_json_schema()) - # Fallback to Pydantic v1 - elif hasattr(model_class, "schema"): - return dict(model_class.schema()) - except Exception: - pass - - # Manual fallback - schema_props = {} - required_fields = [] - - if hasattr(model_class, "__fields__"): - for field_name, field in model_class.__fields__.items(): - field_type = field.annotation if hasattr(field, "annotation") else field.type_ - schema_props[field_name] = {"type": python_type_to_schema_type(field_type).value} - if field.required if hasattr(field, "required") else True: - required_fields.append(field_name) - - schema = {"type": "object", "properties": schema_props} - - if required_fields: - schema["required"] = required_fields - - return schema - - def generate_operation_from_function( func: Any, path: str, @@ -488,8 +445,6 @@ def generate_operation_from_function( schema, defs = generate_schema_from_struct(annotation) if schema_registry is not None: schema_registry.update(defs) - elif is_pydantic_model(annotation): - schema = generate_schema_from_pydantic(annotation) else: # Generic schema for dict/list/other types origin = get_origin(annotation)