| | """Application configuration using Pydantic Settings.""" |
| | from typing import Literal |
| | from pydantic import Field |
| | from pydantic_settings import BaseSettings, SettingsConfigDict |
| |
|
| |
|
| | class Settings(BaseSettings): |
| | """Application settings loaded from environment variables.""" |
| |
|
| | model_config = SettingsConfigDict( |
| | env_file=".env", |
| | env_file_encoding="utf-8", |
| | case_sensitive=False, |
| | extra="ignore" |
| | ) |
| |
|
| | |
| | app_name: str = Field(default="CiteScan", description="Application name") |
| | app_version: str = Field(default="1.0.0", description="Application version") |
| | environment: Literal["development", "staging", "production"] = Field( |
| | default="development", |
| | description="Runtime environment" |
| | ) |
| |
|
| | |
| | api_host: str = Field(default="0.0.0.0", description="API server host") |
| | api_port: int = Field(default=8000, description="API server port") |
| | gradio_host: str = Field(default="0.0.0.0", description="Gradio server host") |
| | gradio_port: int = Field(default=7860, description="Gradio server port") |
| |
|
| | |
| | rate_limit_enabled: bool = Field(default=True, description="Enable rate limiting") |
| | rate_limit_requests: int = Field(default=100, description="Max requests per period") |
| | rate_limit_period: int = Field(default=60, description="Rate limit period in seconds") |
| |
|
| | |
| | cache_enabled: bool = Field(default=True, description="Enable caching") |
| | cache_ttl: int = Field(default=3600, description="Cache TTL in seconds") |
| | cache_max_size: int = Field(default=1000, description="Max cached items") |
| |
|
| | |
| | arxiv_rate_limit_delay: float = Field(default=3.0, description="arXiv rate limit delay") |
| | crossref_rate_limit_delay: float = Field(default=1.0, description="CrossRef rate limit delay") |
| | semantic_scholar_rate_limit_delay: float = Field(default=1.0, description="Semantic Scholar rate limit delay") |
| | dblp_rate_limit_delay: float = Field(default=1.0, description="DBLP rate limit delay") |
| | openalex_rate_limit_delay: float = Field(default=1.0, description="OpenAlex rate limit delay") |
| | scholar_rate_limit_delay: float = Field(default=5.0, description="Google Scholar rate limit delay") |
| |
|
| | |
| | request_timeout: int = Field(default=30, description="Request timeout in seconds") |
| | max_workers: int = Field(default=10, description="Max concurrent workers") |
| |
|
| | |
| | log_level: Literal["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"] = Field( |
| | default="INFO", |
| | description="Logging level" |
| | ) |
| | log_format: Literal["json", "text"] = Field(default="json", description="Log format") |
| | log_file: str = Field(default="logs/citescan.log", description="Log file path") |
| |
|
| | |
| | cors_origins: str = Field( |
| | default="http://localhost:3000,http://localhost:8080", |
| | description="Comma-separated CORS origins" |
| | ) |
| |
|
| | |
| | semantic_scholar_api_key: str | None = Field(default=None, description="Semantic Scholar API key") |
| | crossref_api_key: str | None = Field(default=None, description="CrossRef API key") |
| |
|
| | @property |
| | def cors_origins_list(self) -> list[str]: |
| | """Parse CORS origins into a list.""" |
| | return [origin.strip() for origin in self.cors_origins.split(",") if origin.strip()] |
| |
|
| | @property |
| | def is_production(self) -> bool: |
| | """Check if running in production.""" |
| | return self.environment == "production" |
| |
|
| | @property |
| | def is_development(self) -> bool: |
| | """Check if running in development.""" |
| | return self.environment == "development" |
| |
|
| |
|
| | |
| | settings = Settings() |
| |
|