Spaces:
Running
Running
Commit ·
9be6e36
1
Parent(s): 9daa38c
refactor(config): Improve configuration management and code readability
Browse files- Refactor configuration file with enhanced code formatting
- Improve line spacing and readability in config.py
- Add more consistent line breaks and indentation
- Optimize environment variable retrieval with clearer logic
- Enhance code structure for better maintainability
- Ensure consistent code style across configuration settings
- app/config/config.py +64 -44
- app/nosql.py +1 -0
app/config/config.py
CHANGED
|
@@ -30,9 +30,11 @@ def build_database_uri(env: Dict[str, str] = os.environ) -> str:
|
|
| 30 |
port = env.get("DB_PORT") or "5432"
|
| 31 |
dbname = env.get("DB_NAME")
|
| 32 |
|
| 33 |
-
missing = [k for k, v in {
|
|
|
|
| 34 |
if missing:
|
| 35 |
-
raise ValueError(
|
|
|
|
| 36 |
|
| 37 |
# Optional extras
|
| 38 |
schema = env.get("DB_SCHEMA") # e.g., "trans"
|
|
@@ -55,33 +57,37 @@ DATABASE_URL: str = DATABASE_URI
|
|
| 55 |
|
| 56 |
class Settings:
|
| 57 |
"""Application configuration settings"""
|
| 58 |
-
|
| 59 |
# Database settings
|
| 60 |
DATABASE_URL: str = DATABASE_URL
|
| 61 |
MONGO_URI: str = os.getenv("MONGO_URI", "")
|
| 62 |
DB_NAME: str = os.getenv("DB_NAME", "book-my-service")
|
| 63 |
-
|
| 64 |
# Redis/Cache settings
|
| 65 |
CACHE_URI: str = os.getenv("CACHE_URI", "redis://localhost:6379")
|
| 66 |
CACHE_K: str = os.getenv("CACHE_K", "")
|
| 67 |
-
|
| 68 |
# Cache key prefixes (configurable via environment variables)
|
| 69 |
CART_KEY_PREFIX: str = os.getenv("CART_KEY_PREFIX", "cart")
|
| 70 |
ORDER_KEY_PREFIX: str = os.getenv("ORDER_KEY_PREFIX", "order")
|
| 71 |
-
APPOINTMENTS_KEY_PREFIX: str = os.getenv(
|
| 72 |
-
|
|
|
|
| 73 |
# Payment settings
|
| 74 |
RAZORPAY_KEY_ID: str = os.getenv("RAZORPAY_KEY_ID", "")
|
| 75 |
RAZORPAY_KEY_SECRET: str = os.getenv("RAZORPAY_KEY_SECRET", "")
|
| 76 |
-
|
| 77 |
# JWT settings
|
| 78 |
# Prefer MHS-specific envs; gracefully fall back to UMS-compatible names
|
| 79 |
-
JWT_SECRET_KEY: str = os.getenv(
|
| 80 |
-
|
|
|
|
|
|
|
| 81 |
JWT_ACCESS_TOKEN_EXPIRE_MINUTES: int = int(
|
| 82 |
-
os.getenv("JWT_ACCESS_TOKEN_EXPIRE_MINUTES",
|
|
|
|
| 83 |
)
|
| 84 |
-
|
| 85 |
# Security settings
|
| 86 |
# Include Hugging Face Spaces by default to avoid 400s behind their proxy.
|
| 87 |
# Override via ALLOWED_HOSTS env var in production as needed.
|
|
@@ -93,54 +99,67 @@ class Settings:
|
|
| 93 |
"CORS_ORIGINS",
|
| 94 |
"http://localhost:3000,http://127.0.0.1:3000"
|
| 95 |
).split(",")
|
| 96 |
-
|
| 97 |
# Rate limiting
|
| 98 |
RATE_LIMIT_CALLS: int = int(os.getenv("RATE_LIMIT_CALLS", "100"))
|
| 99 |
RATE_LIMIT_PERIOD: int = int(os.getenv("RATE_LIMIT_PERIOD", "60"))
|
| 100 |
-
|
| 101 |
# NLP Configuration
|
| 102 |
SPACY_MODEL: str = os.getenv("SPACY_MODEL", "en_core_web_sm")
|
| 103 |
-
SENTENCE_TRANSFORMER_MODEL: str = os.getenv(
|
| 104 |
-
|
| 105 |
-
|
| 106 |
-
|
| 107 |
-
|
| 108 |
-
|
| 109 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 110 |
# Performance settings
|
| 111 |
-
ASYNC_PROCESSOR_MAX_WORKERS: int = int(
|
| 112 |
-
|
| 113 |
-
|
|
|
|
|
|
|
| 114 |
# Business settings
|
| 115 |
-
DEFAULT_SEARCH_RADIUS_METERS: int = int(
|
|
|
|
| 116 |
MAX_ENTITY_MATCHES: int = int(os.getenv("MAX_ENTITY_MATCHES", "10"))
|
| 117 |
MAX_SEMANTIC_MATCHES: int = int(os.getenv("MAX_SEMANTIC_MATCHES", "5"))
|
| 118 |
-
|
| 119 |
# Security settings
|
| 120 |
-
MAX_REQUEST_SIZE: int = int(
|
|
|
|
| 121 |
MAX_STRING_LENGTH: int = int(os.getenv("MAX_STRING_LENGTH", "1000"))
|
| 122 |
MAX_LIST_ITEMS: int = int(os.getenv("MAX_LIST_ITEMS", "100"))
|
| 123 |
-
RATE_LIMIT_REQUESTS_PER_MINUTE: int = int(
|
|
|
|
| 124 |
RATE_LIMIT_BURST: int = int(os.getenv("RATE_LIMIT_BURST", "10"))
|
| 125 |
-
|
| 126 |
# Logging settings
|
| 127 |
-
LOG_SANITIZATION_ENABLED: bool = os.getenv(
|
|
|
|
| 128 |
MAX_LOG_VALUE_LENGTH: int = int(os.getenv("MAX_LOG_VALUE_LENGTH", "500"))
|
| 129 |
NLP_LOG_LEVEL: str = os.getenv("NLP_LOG_LEVEL", "INFO")
|
| 130 |
-
ENABLE_PERFORMANCE_LOGGING: bool = os.getenv(
|
| 131 |
-
|
|
|
|
| 132 |
# Environment
|
| 133 |
ENVIRONMENT: str = os.getenv("ENVIRONMENT", "development")
|
| 134 |
-
|
| 135 |
@classmethod
|
| 136 |
def get_cache_key(cls, key_type: str, *args) -> str:
|
| 137 |
"""
|
| 138 |
Generate cache keys using configurable prefixes
|
| 139 |
-
|
| 140 |
Args:
|
| 141 |
key_type: Type of cache key (cart, order, appointments)
|
| 142 |
*args: Additional arguments to include in the key
|
| 143 |
-
|
| 144 |
Returns:
|
| 145 |
str: Formatted cache key
|
| 146 |
"""
|
|
@@ -152,12 +171,12 @@ class Settings:
|
|
| 152 |
return f"{cls.APPOINTMENTS_KEY_PREFIX}:{':'.join(map(str, args))}"
|
| 153 |
else:
|
| 154 |
raise ValueError(f"Unknown cache key type: {key_type}")
|
| 155 |
-
|
| 156 |
@classmethod
|
| 157 |
def validate_required_settings(cls) -> Dict[str, bool]:
|
| 158 |
"""
|
| 159 |
Validate that required settings are present
|
| 160 |
-
|
| 161 |
Returns:
|
| 162 |
Dict with validation results
|
| 163 |
"""
|
|
@@ -168,14 +187,14 @@ class Settings:
|
|
| 168 |
"cache_k": bool(cls.CACHE_K),
|
| 169 |
"jwt_secret": bool(cls.JWT_SECRET_KEY)
|
| 170 |
}
|
| 171 |
-
|
| 172 |
return validations
|
| 173 |
-
|
| 174 |
@classmethod
|
| 175 |
def get_missing_settings(cls) -> list:
|
| 176 |
"""
|
| 177 |
Get list of missing required settings
|
| 178 |
-
|
| 179 |
Returns:
|
| 180 |
List of missing setting names
|
| 181 |
"""
|
|
@@ -190,13 +209,14 @@ settings = Settings()
|
|
| 190 |
def validate_configuration():
|
| 191 |
"""
|
| 192 |
Validate configuration on startup
|
| 193 |
-
|
| 194 |
Raises:
|
| 195 |
ValueError: If required configuration is missing
|
| 196 |
"""
|
| 197 |
missing = settings.get_missing_settings()
|
| 198 |
if missing:
|
| 199 |
-
raise ValueError(
|
| 200 |
-
|
|
|
|
| 201 |
print("✅ Configuration validation passed")
|
| 202 |
-
return True
|
|
|
|
| 30 |
port = env.get("DB_PORT") or "5432"
|
| 31 |
dbname = env.get("DB_NAME")
|
| 32 |
|
| 33 |
+
missing = [k for k, v in {
|
| 34 |
+
"DB_USER": user, "DB_PASSWORD": password, "DB_NAME": dbname}.items() if not v]
|
| 35 |
if missing:
|
| 36 |
+
raise ValueError(
|
| 37 |
+
f"Missing required environment variables: {', '.join(missing)}")
|
| 38 |
|
| 39 |
# Optional extras
|
| 40 |
schema = env.get("DB_SCHEMA") # e.g., "trans"
|
|
|
|
| 57 |
|
| 58 |
class Settings:
|
| 59 |
"""Application configuration settings"""
|
| 60 |
+
|
| 61 |
# Database settings
|
| 62 |
DATABASE_URL: str = DATABASE_URL
|
| 63 |
MONGO_URI: str = os.getenv("MONGO_URI", "")
|
| 64 |
DB_NAME: str = os.getenv("DB_NAME", "book-my-service")
|
| 65 |
+
|
| 66 |
# Redis/Cache settings
|
| 67 |
CACHE_URI: str = os.getenv("CACHE_URI", "redis://localhost:6379")
|
| 68 |
CACHE_K: str = os.getenv("CACHE_K", "")
|
| 69 |
+
|
| 70 |
# Cache key prefixes (configurable via environment variables)
|
| 71 |
CART_KEY_PREFIX: str = os.getenv("CART_KEY_PREFIX", "cart")
|
| 72 |
ORDER_KEY_PREFIX: str = os.getenv("ORDER_KEY_PREFIX", "order")
|
| 73 |
+
APPOINTMENTS_KEY_PREFIX: str = os.getenv(
|
| 74 |
+
"APPOINTMENTS_KEY_PREFIX", "appointments")
|
| 75 |
+
|
| 76 |
# Payment settings
|
| 77 |
RAZORPAY_KEY_ID: str = os.getenv("RAZORPAY_KEY_ID", "")
|
| 78 |
RAZORPAY_KEY_SECRET: str = os.getenv("RAZORPAY_KEY_SECRET", "")
|
| 79 |
+
|
| 80 |
# JWT settings
|
| 81 |
# Prefer MHS-specific envs; gracefully fall back to UMS-compatible names
|
| 82 |
+
JWT_SECRET_KEY: str = os.getenv(
|
| 83 |
+
"JWT_SECRET_KEY") or os.getenv("SECRET_KEY")
|
| 84 |
+
JWT_ALGORITHM: str = os.getenv(
|
| 85 |
+
"JWT_ALGORITHM") or os.getenv("ALGORITHM", "HS256")
|
| 86 |
JWT_ACCESS_TOKEN_EXPIRE_MINUTES: int = int(
|
| 87 |
+
os.getenv("JWT_ACCESS_TOKEN_EXPIRE_MINUTES",
|
| 88 |
+
os.getenv("ACCESS_TOKEN_EXPIRE_MINUTES", "30"))
|
| 89 |
)
|
| 90 |
+
|
| 91 |
# Security settings
|
| 92 |
# Include Hugging Face Spaces by default to avoid 400s behind their proxy.
|
| 93 |
# Override via ALLOWED_HOSTS env var in production as needed.
|
|
|
|
| 99 |
"CORS_ORIGINS",
|
| 100 |
"http://localhost:3000,http://127.0.0.1:3000"
|
| 101 |
).split(",")
|
| 102 |
+
|
| 103 |
# Rate limiting
|
| 104 |
RATE_LIMIT_CALLS: int = int(os.getenv("RATE_LIMIT_CALLS", "100"))
|
| 105 |
RATE_LIMIT_PERIOD: int = int(os.getenv("RATE_LIMIT_PERIOD", "60"))
|
| 106 |
+
|
| 107 |
# NLP Configuration
|
| 108 |
SPACY_MODEL: str = os.getenv("SPACY_MODEL", "en_core_web_sm")
|
| 109 |
+
SENTENCE_TRANSFORMER_MODEL: str = os.getenv(
|
| 110 |
+
"SENTENCE_TRANSFORMER_MODEL", "all-MiniLM-L6-v2")
|
| 111 |
+
ENABLE_ADVANCED_NLP: bool = os.getenv(
|
| 112 |
+
"ENABLE_ADVANCED_NLP", "true").lower() == "true"
|
| 113 |
+
ENABLE_SEMANTIC_MATCHING: bool = os.getenv(
|
| 114 |
+
"ENABLE_SEMANTIC_MATCHING", "true").lower() == "true"
|
| 115 |
+
ENABLE_CONTEXT_PROCESSING: bool = os.getenv(
|
| 116 |
+
"ENABLE_CONTEXT_PROCESSING", "true").lower() == "true"
|
| 117 |
+
ENABLE_INTENT_CLASSIFICATION: bool = os.getenv(
|
| 118 |
+
"ENABLE_INTENT_CLASSIFICATION", "true").lower() == "true"
|
| 119 |
+
SEMANTIC_SIMILARITY_THRESHOLD: float = float(
|
| 120 |
+
os.getenv("SEMANTIC_SIMILARITY_THRESHOLD", "0.6"))
|
| 121 |
+
|
| 122 |
# Performance settings
|
| 123 |
+
ASYNC_PROCESSOR_MAX_WORKERS: int = int(
|
| 124 |
+
os.getenv("ASYNC_PROCESSOR_MAX_WORKERS", "4"))
|
| 125 |
+
CACHE_DURATION_SECONDS: int = int(
|
| 126 |
+
os.getenv("CACHE_DURATION_SECONDS", "3600"))
|
| 127 |
+
|
| 128 |
# Business settings
|
| 129 |
+
DEFAULT_SEARCH_RADIUS_METERS: int = int(
|
| 130 |
+
os.getenv("DEFAULT_SEARCH_RADIUS_METERS", "5000"))
|
| 131 |
MAX_ENTITY_MATCHES: int = int(os.getenv("MAX_ENTITY_MATCHES", "10"))
|
| 132 |
MAX_SEMANTIC_MATCHES: int = int(os.getenv("MAX_SEMANTIC_MATCHES", "5"))
|
| 133 |
+
|
| 134 |
# Security settings
|
| 135 |
+
MAX_REQUEST_SIZE: int = int(
|
| 136 |
+
os.getenv("MAX_REQUEST_SIZE", "10485760")) # 10MB
|
| 137 |
MAX_STRING_LENGTH: int = int(os.getenv("MAX_STRING_LENGTH", "1000"))
|
| 138 |
MAX_LIST_ITEMS: int = int(os.getenv("MAX_LIST_ITEMS", "100"))
|
| 139 |
+
RATE_LIMIT_REQUESTS_PER_MINUTE: int = int(
|
| 140 |
+
os.getenv("RATE_LIMIT_RPM", "60"))
|
| 141 |
RATE_LIMIT_BURST: int = int(os.getenv("RATE_LIMIT_BURST", "10"))
|
| 142 |
+
|
| 143 |
# Logging settings
|
| 144 |
+
LOG_SANITIZATION_ENABLED: bool = os.getenv(
|
| 145 |
+
"LOG_SANITIZATION_ENABLED", "true").lower() == "true"
|
| 146 |
MAX_LOG_VALUE_LENGTH: int = int(os.getenv("MAX_LOG_VALUE_LENGTH", "500"))
|
| 147 |
NLP_LOG_LEVEL: str = os.getenv("NLP_LOG_LEVEL", "INFO")
|
| 148 |
+
ENABLE_PERFORMANCE_LOGGING: bool = os.getenv(
|
| 149 |
+
"ENABLE_PERFORMANCE_LOGGING", "true").lower() == "true"
|
| 150 |
+
|
| 151 |
# Environment
|
| 152 |
ENVIRONMENT: str = os.getenv("ENVIRONMENT", "development")
|
| 153 |
+
|
| 154 |
@classmethod
|
| 155 |
def get_cache_key(cls, key_type: str, *args) -> str:
|
| 156 |
"""
|
| 157 |
Generate cache keys using configurable prefixes
|
| 158 |
+
|
| 159 |
Args:
|
| 160 |
key_type: Type of cache key (cart, order, appointments)
|
| 161 |
*args: Additional arguments to include in the key
|
| 162 |
+
|
| 163 |
Returns:
|
| 164 |
str: Formatted cache key
|
| 165 |
"""
|
|
|
|
| 171 |
return f"{cls.APPOINTMENTS_KEY_PREFIX}:{':'.join(map(str, args))}"
|
| 172 |
else:
|
| 173 |
raise ValueError(f"Unknown cache key type: {key_type}")
|
| 174 |
+
|
| 175 |
@classmethod
|
| 176 |
def validate_required_settings(cls) -> Dict[str, bool]:
|
| 177 |
"""
|
| 178 |
Validate that required settings are present
|
| 179 |
+
|
| 180 |
Returns:
|
| 181 |
Dict with validation results
|
| 182 |
"""
|
|
|
|
| 187 |
"cache_k": bool(cls.CACHE_K),
|
| 188 |
"jwt_secret": bool(cls.JWT_SECRET_KEY)
|
| 189 |
}
|
| 190 |
+
|
| 191 |
return validations
|
| 192 |
+
|
| 193 |
@classmethod
|
| 194 |
def get_missing_settings(cls) -> list:
|
| 195 |
"""
|
| 196 |
Get list of missing required settings
|
| 197 |
+
|
| 198 |
Returns:
|
| 199 |
List of missing setting names
|
| 200 |
"""
|
|
|
|
| 209 |
def validate_configuration():
|
| 210 |
"""
|
| 211 |
Validate configuration on startup
|
| 212 |
+
|
| 213 |
Raises:
|
| 214 |
ValueError: If required configuration is missing
|
| 215 |
"""
|
| 216 |
missing = settings.get_missing_settings()
|
| 217 |
if missing:
|
| 218 |
+
raise ValueError(
|
| 219 |
+
f"Missing required configuration: {', '.join(missing)}")
|
| 220 |
+
|
| 221 |
print("✅ Configuration validation passed")
|
| 222 |
+
return True
|
app/nosql.py
CHANGED
|
@@ -22,6 +22,7 @@ try:
|
|
| 22 |
validate_configuration()
|
| 23 |
except ValueError as e:
|
| 24 |
logger.error(f"Configuration validation failed: {e}")
|
|
|
|
| 25 |
raise
|
| 26 |
|
| 27 |
# MongoDB configuration using settings
|
|
|
|
| 22 |
validate_configuration()
|
| 23 |
except ValueError as e:
|
| 24 |
logger.error(f"Configuration validation failed: {e}")
|
| 25 |
+
# In production, we want to fail fast if configuration is missing
|
| 26 |
raise
|
| 27 |
|
| 28 |
# MongoDB configuration using settings
|