From 25539c56cc8fae6d270a944a02cedcb419d1c516 Mon Sep 17 00:00:00 2001 From: berkay Date: Wed, 15 Jan 2025 13:39:17 +0300 Subject: [PATCH] error response due to language models are updated --- DockerApiServices/AllApiNeeds/app.py | 18 +--- DockerApiServices/AllApiNeeds/app_handler.py | 48 ++------- DockerApiServices/AllApiNeeds/create_file.py | 10 +- .../AllApiNeeds/middleware/auth_middleware.py | 100 +++++++----------- .../AllApiNeeds/open_api_creator.py | 10 +- .../AllApiNeeds/routers/__init__.py | 4 +- .../AllApiNeeds/routers/base_router.py | 6 +- DockerApiServices/AuthServiceApi/Dockerfile | 3 + DockerApiServices/README.md | 20 ++-- .../ErrorHandlers/api_exc_handler.py | 70 +++++++----- ErrorHandlers/__init__.py | 3 +- ErrorHandlers/base.py | 6 +- ErrorHandlers/bases.py | 37 +++---- ErrorHandlers/statuses.py | 5 +- LanguageModels/Errors/__init__.py | 4 +- LanguageModels/Errors/base_languages.py | 9 +- .../Errors/merge_all_error_languages.py | 18 ++++ 17 files changed, 163 insertions(+), 208 deletions(-) create mode 100644 LanguageModels/Errors/merge_all_error_languages.py diff --git a/DockerApiServices/AllApiNeeds/app.py b/DockerApiServices/AllApiNeeds/app.py index 0e06c49..fe7c11f 100644 --- a/DockerApiServices/AllApiNeeds/app.py +++ b/DockerApiServices/AllApiNeeds/app.py @@ -17,21 +17,11 @@ from prometheus_fastapi_instrumentator import Instrumentator from app_handler import setup_middleware, get_uvicorn_config -print("Loading app.py module...") - -# Initialize FastAPI application -app = create_app(routers=routers) - -# Setup Prometheus metrics -Instrumentator().instrument(app=app).expose(app=app) - -# Configure middleware and exception handlers -setup_middleware(app) +app = create_app(routers=routers) # Initialize FastAPI application +Instrumentator().instrument(app=app).expose(app=app) # Setup Prometheus metrics +setup_middleware(app) # Configure middleware and exception handlers if __name__ == "__main__": - print("Starting server from __main__...") - # Run the application with Uvicorn - uvicorn_config = get_uvicorn_config() - print(f"Using config: {uvicorn_config}") + uvicorn_config = get_uvicorn_config() # Run the application with Uvicorn uvicorn.Server(uvicorn.Config(**uvicorn_config)).run() diff --git a/DockerApiServices/AllApiNeeds/app_handler.py b/DockerApiServices/AllApiNeeds/app_handler.py index 9a5c290..4ed65bd 100644 --- a/DockerApiServices/AllApiNeeds/app_handler.py +++ b/DockerApiServices/AllApiNeeds/app_handler.py @@ -12,14 +12,8 @@ from typing import Dict, Any from fastapi.middleware.cors import CORSMiddleware from fastapi import FastAPI, Request, HTTPException, status from fastapi.responses import JSONResponse - -from ErrorHandlers.bases import ( - BaseErrorModelClass, - StatusesModelClass, - LanguageModelClass, -) -from ErrorHandlers import statuses -from middleware.auth_middleware import MiddlewareModule +from ErrorHandlers.Exceptions.api_exc import HTTPExceptionApi +from middleware.auth_middleware import RequestTimingMiddleware def setup_cors_middleware(app: FastAPI) -> None: @@ -38,33 +32,6 @@ def setup_cors_middleware(app: FastAPI) -> None: ) -async def http_exception_handler(request: Request, exc: HTTPException) -> JSONResponse: - """ - Handle HTTP exceptions and return formatted error responses. - - Args: - request: FastAPI request object - exc: HTTP exception instance - - Returns: - JSONResponse: Formatted error response - """ - error_code = getattr(exc, "error_code", None) - if error_code: - status_code = StatusesModelClass.retrieve_error_by_code(error_code) - error_message = LanguageModelClass.retrieve_error_by_code( - error_code, request.headers.get("accept-language", "en") - ) - else: - status_code = exc.status_code - error_message = str(exc.detail) - - return JSONResponse( - status_code=status_code, - content={"detail": error_message, "error_code": error_code}, - ) - - async def generic_exception_handler(request: Request, exc: Exception) -> JSONResponse: """ Handle generic exceptions and return formatted error responses. @@ -89,7 +56,12 @@ def setup_exception_handlers(app: FastAPI) -> None: Args: app: FastAPI application instance """ - app.add_exception_handler(HTTPException, http_exception_handler) + from ErrorHandlers.ErrorHandlers.api_exc_handler import HTTPExceptionApiHandler + + custom_exception_handler = HTTPExceptionApiHandler(response_model=JSONResponse) + app.add_exception_handler( + HTTPExceptionApi, custom_exception_handler.handle_exception + ) app.add_exception_handler(Exception, generic_exception_handler) @@ -101,7 +73,7 @@ def setup_middleware(app: FastAPI) -> None: app: FastAPI application instance """ setup_cors_middleware(app) - app.add_middleware(MiddlewareModule.RequestTimingMiddleware) + app.add_middleware(RequestTimingMiddleware) setup_exception_handlers(app) @@ -118,4 +90,4 @@ def get_uvicorn_config() -> Dict[str, Any]: "port": 41575, "log_level": "info", "reload": True, - } \ No newline at end of file + } diff --git a/DockerApiServices/AllApiNeeds/create_file.py b/DockerApiServices/AllApiNeeds/create_file.py index b5a3cb3..9bcb4ea 100644 --- a/DockerApiServices/AllApiNeeds/create_file.py +++ b/DockerApiServices/AllApiNeeds/create_file.py @@ -8,6 +8,7 @@ This module provides functionality to create and configure a FastAPI application - Response class configuration - Security requirements for protected endpoints """ + from types import ModuleType from typing import Any, Dict, List, Optional, Union from fastapi import FastAPI, APIRouter @@ -36,10 +37,7 @@ def setup_security_schema() -> Dict[str, Any]: def configure_route_security( - path: str, - method: str, - schema: Dict[str, Any], - protected_paths: List[str] + path: str, method: str, schema: Dict[str, Any], protected_paths: List[str] ) -> None: """ Configure security requirements for a specific route. @@ -113,7 +111,7 @@ def create_app(routers: ModuleType) -> FastAPI: for route in router.routes: if isinstance(route, APIRoute): # Check if the route has auth_required decorator - if any(d.__name__ == 'auth_required' for d in route.dependencies): + if any(d.__name__ == "auth_required" for d in route.dependencies): protected_paths.append(route.path) # Include routers @@ -142,7 +140,7 @@ def create_app(routers: ModuleType) -> FastAPI: route.path, route.methods.pop().lower(), openapi_schema, - protected_paths + protected_paths, ) app.openapi_schema = openapi_schema diff --git a/DockerApiServices/AllApiNeeds/middleware/auth_middleware.py b/DockerApiServices/AllApiNeeds/middleware/auth_middleware.py index b21b054..49124a9 100644 --- a/DockerApiServices/AllApiNeeds/middleware/auth_middleware.py +++ b/DockerApiServices/AllApiNeeds/middleware/auth_middleware.py @@ -8,7 +8,7 @@ and a middleware for request timing measurements. from time import perf_counter from typing import Callable, Optional, Dict, Any, Tuple from functools import wraps -from fastapi import HTTPException, Request, Response, status +from fastapi import Request, Response from starlette.middleware.base import BaseHTTPMiddleware from AllConfigs.Token.config import Auth from ErrorHandlers.ErrorHandlers.api_exc_handler import HTTPExceptionApi @@ -21,7 +21,6 @@ class MiddlewareModule: This class provides: - Token extraction and validation - Authentication decorator for endpoints - - Request timing middleware """ @staticmethod @@ -40,23 +39,15 @@ class MiddlewareModule: """ auth_header = request.headers.get(Auth.ACCESS_TOKEN_TAG) if not auth_header: - raise HTTPExceptionApi( - status_code=status.HTTP_401_UNAUTHORIZED, - detail="No authorization header", - ) + raise HTTPExceptionApi(error_code="HTTP_401_UNAUTHORIZED", lang="tr") try: scheme, token = auth_header.split() if scheme.lower() != "bearer": - raise HTTPExceptionApi( - status_code=status.HTTP_401_UNAUTHORIZED, - detail="Invalid authentication scheme", - ) + raise HTTPExceptionApi(error_code="HTTP_401_UNAUTHORIZED", lang="tr") return scheme, token except ValueError: - raise HTTPExceptionApi( - status_code=status.HTTP_401_UNAUTHORIZED, detail="Invalid token format" - ) + raise HTTPExceptionApi(error_code="HTTP_401_UNAUTHORIZED", lang="tr") @staticmethod async def validate_token(token: str) -> Dict[str, Any]: @@ -78,10 +69,7 @@ class MiddlewareModule: # return jwt.decode(token, settings.SECRET_KEY, algorithms=["HS256"]) return {"user_id": "test", "role": "user"} # Placeholder except Exception as e: - raise HTTPExceptionApi( - status_code=status.HTTP_401_UNAUTHORIZED, - detail=f"Token validation failed: {str(e)}", - ) + raise HTTPExceptionApi(error_code="HTTP_401_UNAUTHORIZED", lang="tr") @classmethod def auth_required(cls, func: Callable) -> Callable: @@ -122,58 +110,44 @@ class MiddlewareModule: return await func(request, *args, **kwargs) except HTTPExceptionApi: - raise + raise HTTPExceptionApi(error_code="NOT_AUTHORIZED", lang="tr") except Exception as e: - raise HTTPExceptionApi( - status_code=status.HTTP_401_UNAUTHORIZED, - detail=f"Authentication failed: {str(e)}", - ) - + raise HTTPExceptionApi(error_code="NOT_AUTHORIZED", lang="tr") return wrapper - class RequestTimingMiddleware(BaseHTTPMiddleware): + +class RequestTimingMiddleware(BaseHTTPMiddleware): + """ + Middleware for measuring and logging request timing. + Only handles timing, no authentication. + """ + + async def dispatch(self, request: Request, call_next: Callable) -> Response: """ - Middleware for measuring and logging request timing. - Only handles timing, no authentication. + Process each request through the middleware. + + Args: + request: FastAPI request object + call_next: Next middleware in the chain + + Returns: + Response: Processed response with timing headers """ + start_time = perf_counter() - async def dispatch(self, request: Request, call_next: Callable) -> Response: - """ - Process each request through the middleware. + # Process the request + response = await call_next(request) - Args: - request: FastAPI request object - call_next: Next middleware in the chain + # Add timing information to response headers + end_time = perf_counter() + elapsed = (end_time - start_time) * 1000 # Convert to milliseconds - Returns: - Response: Processed response with timing headers - """ - start_time = perf_counter() + response.headers.update( + { + "request-start": f"{start_time:.6f}", + "request-end": f"{end_time:.6f}", + "request-duration": f"{elapsed:.2f}ms", + } + ) - # Process the request - response = await call_next(request) - - # Add timing information to response headers - self._add_timing_headers(response, start_time) - - return response - - @staticmethod - def _add_timing_headers(response: Response, start_time: float) -> None: - """ - Add request timing information to response headers. - - Args: - response: FastAPI response object - start_time: Time when request processing started - """ - end_time = perf_counter() - elapsed = (end_time - start_time) * 1000 # Convert to milliseconds - - response.headers.update( - { - "request-start": f"{start_time:.6f}", - "request-end": f"{end_time:.6f}", - "request-duration": f"{elapsed:.2f}ms", - } - ) + return response diff --git a/DockerApiServices/AllApiNeeds/open_api_creator.py b/DockerApiServices/AllApiNeeds/open_api_creator.py index e129066..cec5eca 100644 --- a/DockerApiServices/AllApiNeeds/open_api_creator.py +++ b/DockerApiServices/AllApiNeeds/open_api_creator.py @@ -173,15 +173,17 @@ class OpenAPISchemaCreator: # Add security schemes if "components" not in openapi_schema: openapi_schema["components"] = {} - - openapi_schema["components"]["securitySchemes"] = self._create_security_schemes() + + openapi_schema["components"][ + "securitySchemes" + ] = self._create_security_schemes() # Configure route security and responses for route in self.app.routes: if isinstance(route, APIRoute) and route.include_in_schema: path = str(route.path) methods = [method.lower() for method in route.methods] - + for method in methods: self.configure_route_security(path, method, openapi_schema) @@ -206,4 +208,4 @@ def create_openapi_schema(app: FastAPI) -> Dict[str, Any]: Dict[str, Any]: Complete OpenAPI schema """ creator = OpenAPISchemaCreator(app) - return creator.create_schema() \ No newline at end of file + return creator.create_schema() diff --git a/DockerApiServices/AllApiNeeds/routers/__init__.py b/DockerApiServices/AllApiNeeds/routers/__init__.py index e958ef0..3e0088c 100644 --- a/DockerApiServices/AllApiNeeds/routers/__init__.py +++ b/DockerApiServices/AllApiNeeds/routers/__init__.py @@ -1,5 +1,3 @@ from .base_router import test_route -__all__ = [ - "test_route" -] +__all__ = ["test_route"] diff --git a/DockerApiServices/AllApiNeeds/routers/base_router.py b/DockerApiServices/AllApiNeeds/routers/base_router.py index 3502d48..21afe00 100644 --- a/DockerApiServices/AllApiNeeds/routers/base_router.py +++ b/DockerApiServices/AllApiNeeds/routers/base_router.py @@ -7,16 +7,16 @@ from middleware.auth_middleware import MiddlewareModule # Create test router test_route = APIRouter(prefix="/test", tags=["Test"]) +test_route.include_router(test_route, include_in_schema=True) + @test_route.get("/health") @MiddlewareModule.auth_required async def health_check(request: Request): return {"status": "healthy", "message": "Service is running"} + @test_route.get("/ping") async def ping_test(): return {"ping": "pong", "service": "base-router"} -# Initialize and include test routes -def init_test_routes(): - return test_route diff --git a/DockerApiServices/AuthServiceApi/Dockerfile b/DockerApiServices/AuthServiceApi/Dockerfile index 186477a..5ddca69 100644 --- a/DockerApiServices/AuthServiceApi/Dockerfile +++ b/DockerApiServices/AuthServiceApi/Dockerfile @@ -19,7 +19,10 @@ RUN poetry config virtualenvs.create false \ && rm -rf ~/.cache/pypoetry # Copy application code + COPY DockerApiServices/AllApiNeeds /app/ +COPY ErrorHandlers /app/ErrorHandlers +COPY LanguageModels /app/LanguageModels COPY ApiLibrary /app/ApiLibrary COPY ApiValidations /app/ApiValidations COPY AllConfigs /app/AllConfigs diff --git a/DockerApiServices/README.md b/DockerApiServices/README.md index a6b91b3..5d25f28 100644 --- a/DockerApiServices/README.md +++ b/DockerApiServices/README.md @@ -6,32 +6,32 @@ This repository contains multiple microservices that can be run using Docker Com For regular development when dependencies haven't changed: ```bash # Build and run Auth Service -docker compose -f ../docker-compose-services.yml up auth-service +docker compose -f docker-compose-services.yml up auth-service # Build and run Event Service -docker compose -f ../docker-compose-services.yml up event-service +docker compose -f docker-compose-services.yml up event-service # Build and run Validation Service -docker compose -f ../docker-compose-services.yml up validation-service +docker compose -f docker-compose-services.yml up validation-service # Build and run all services -docker compose -f ../docker-compose-services.yml up +docker compose -f docker-compose-services.yml up ``` ## Clean Build (No Cache) Use these commands when changing Dockerfile or dependencies: ```bash # Auth Service -docker compose -f ../docker-compose-services.yml build --no-cache auth-service && docker compose -f ../docker-compose-services.yml up auth-service +docker compose -f docker-compose-services.yml build --no-cache auth-service && docker compose -f docker-compose-services.yml up auth-service # Event Service -docker compose -f ../docker-compose-services.yml build --no-cache event-service && docker compose -f ../docker-compose-services.yml up event-service +docker compose -f docker-compose-services.yml build --no-cache event-service && docker compose -f docker-compose-services.yml up event-service # Validation Service -docker compose -f ../docker-compose-services.yml build --no-cache validation-service && docker compose -f ../docker-compose-services.yml up validation-service +docker compose -f docker-compose-services.yml build --no-cache validation-service && docker compose -f docker-compose-services.yml up validation-service # All Services -docker compose -f ../docker-compose-services.yml build --no-cache && docker compose -f ../docker-compose-services.yml up +docker compose -f docker-compose-services.yml build --no-cache && docker compose -f docker-compose-services.yml up ``` ## Service Ports @@ -51,9 +51,9 @@ docker compose -f ../docker-compose-services.yml build --no-cache && docker comp - For faster development iterations - Run in detached mode: ```bash - docker compose -f ../docker-compose-services.yml up -d auth-service + docker compose -f docker-compose-services.yml up -d auth-service ``` - Stop services: ```bash - docker compose -f ../docker-compose-services.yml down + docker compose -f docker-compose-services.yml down ``` diff --git a/ErrorHandlers/ErrorHandlers/api_exc_handler.py b/ErrorHandlers/ErrorHandlers/api_exc_handler.py index a737fd9..277ecdf 100644 --- a/ErrorHandlers/ErrorHandlers/api_exc_handler.py +++ b/ErrorHandlers/ErrorHandlers/api_exc_handler.py @@ -1,39 +1,57 @@ -from typing import Any, Dict +from typing import Any, Dict, Union, Awaitable +from fastapi import Request, WebSocket +from fastapi.responses import Response + +from LanguageModels.Errors.merge_all_error_languages import MergedErrorLanguageModels from ErrorHandlers.Exceptions.api_exc import HTTPExceptionApi +from ErrorHandlers.bases import BaseErrorModelClass class HTTPExceptionApiHandler: def __init__( self, - **kwargs, + response_model: Any, ): - self.EXCEPTIONS = kwargs.get( - "exceptions" - ) # from fastapi.exceptions import HTTPException - self.STATUSES = kwargs.get("statuses") # from fastapi import status - self.EXCEPTION_DICTS: Dict = kwargs.get("exceptions_dict") - self.ERRORS_DICT: Dict = kwargs.get("errors_dict") - self.ERRORS_LANG: Dict = kwargs.get("error_language_dict") - self.RESPONSE_MODEL: Any = kwargs.get("response_model") + self.RESPONSE_MODEL: Any = response_model - def retrieve_error_status_code(self, exc: HTTPExceptionApi): - grab_status = self.ERRORS_DICT.get(str(exc.error_code).upper(), "") - grab_status_code = self.EXCEPTION_DICTS.get(str(grab_status).upper(), "500") - return getattr( - self.STATUSES, - str(grab_status_code), - getattr(self.STATUSES, "HTTP_500_INTERNAL_SERVER_ERROR"), + @staticmethod + def retrieve_error_status_code(exc: HTTPExceptionApi) -> int: + from ErrorHandlers import DEFAULT_ERROR + error_by_codes = BaseErrorModelClass.retrieve_error_by_codes() + grab_status_code = error_by_codes.get( + str(exc.error_code).upper(), DEFAULT_ERROR ) + return int(grab_status_code) - def retrieve_error_message(self, exc: HTTPExceptionApi): - message_by_lang = self.ERRORS_LANG.get(str(exc.lang).lower(), {}) - return message_by_lang.get(str(exc.error_code).upper(), "Unknown error") + @staticmethod + def retrieve_error_message(exc: HTTPExceptionApi, error_languages) -> str: + from ErrorHandlers import DEFAULT_ERROR + return error_languages.get(str(exc.error_code).upper(), DEFAULT_ERROR) - def handle_exception(self, request, exc: HTTPExceptionApi): - status_code = self.retrieve_error_status_code(exc) - error_message = self.retrieve_error_message(exc) + async def handle_exception( + self, request: Union[Request, WebSocket], exc: Exception + ) -> Union[Response, Awaitable[None]]: + request_string = str(request.url) if isinstance(request, Request) else request.url.path + if isinstance(exc, HTTPExceptionApi): + error_languages = MergedErrorLanguageModels.get_language_models( + language=exc.lang + ) + status_code = self.retrieve_error_status_code(exc) + error_message = self.retrieve_error_message(exc, error_languages) + return self.RESPONSE_MODEL( + status_code=int(status_code), + content={ + "message": error_message, + "lang": exc.lang, + "request": request_string, + }, + ) return self.RESPONSE_MODEL( - status_code=int(status_code), - content={"message": error_message, "lang": exc.lang, "request": request}, - ) + status_code=500, + content={ + "message": "Internal Server Error", + "lang": "def", + "request": request_string, + }, + ) # Handle other exceptions with a generic 500 error diff --git a/ErrorHandlers/__init__.py b/ErrorHandlers/__init__.py index cecfe13..f7a6b12 100644 --- a/ErrorHandlers/__init__.py +++ b/ErrorHandlers/__init__.py @@ -4,9 +4,10 @@ from ErrorHandlers.ErrorHandlers.api_exc_handler import ( from ErrorHandlers.Exceptions.api_exc import ( HTTPExceptionApi, ) - +DEFAULT_ERROR = "UNKNOWN_ERROR" __all__ = [ "HTTPExceptionApiHandler", "HTTPExceptionApi", + "DEFAULT_ERROR" ] diff --git a/ErrorHandlers/base.py b/ErrorHandlers/base.py index fdc591a..2e290ee 100644 --- a/ErrorHandlers/base.py +++ b/ErrorHandlers/base.py @@ -1,7 +1,4 @@ -from ErrorHandlers.bases import BaseErrorModelClass - - -class BaseError(BaseErrorModelClass): +class BaseError: NOT_CREATED: int = 405 NOT_DELETED: int = 405 NOT_UPDATED: int = 405 @@ -14,3 +11,4 @@ class BaseError(BaseErrorModelClass): NOT_ACCEPTABLE: int = 406 INVALID_DATA: int = 422 UNKNOWN_ERROR: int = 502 + diff --git a/ErrorHandlers/bases.py b/ErrorHandlers/bases.py index dfa07e6..587dd80 100644 --- a/ErrorHandlers/bases.py +++ b/ErrorHandlers/bases.py @@ -1,30 +1,19 @@ -from typing import Optional +from ErrorHandlers.base import BaseError +from ErrorHandlers.statuses import Statuses class BaseErrorModelClass: + list_of_statuses = [Statuses, BaseError] @classmethod - def retrieve_error_by_code(cls, error_code: str): - return getattr(cls, error_code, 502) + def retrieve_error_by_codes(cls): + language_model_status = {} + for list_of_language in cls.list_of_statuses: + clean_dict = { + key: value + for key, value in list_of_language.__dict__.items() + if "__" not in str(key)[0:3] + } + language_model_status.update(clean_dict) + return language_model_status - -class StatusesModelClass: - - @classmethod - def retrieve_error_by_code(cls, error_code: str): - return getattr(cls, error_code, 502) - - -class ErrorLanguageModelClass: - - @classmethod - def retrieve_error_header(cls, error_code: str): - return getattr(cls, error_code, "Unknown Error occured.") - - -class LanguageModelClass: - - @classmethod - def retrieve_error_by_code(cls, error_code: str, language: Optional[str] = "tr"): - language_model: ErrorLanguageModelClass = getattr(cls, language, "tr") - return language_model.retrieve_error_header(error_code) diff --git a/ErrorHandlers/statuses.py b/ErrorHandlers/statuses.py index a815e0d..df2f83b 100644 --- a/ErrorHandlers/statuses.py +++ b/ErrorHandlers/statuses.py @@ -1,7 +1,4 @@ -from ErrorHandlers.bases import StatusesModelClass - - -class Statuses(StatusesModelClass): +class Statuses: HTTP_100_CONTINUE = 100 HTTP_101_SWITCHING_PROTOCOLS = 101 HTTP_102_PROCESSING = 102 diff --git a/LanguageModels/Errors/__init__.py b/LanguageModels/Errors/__init__.py index bb27acf..3d342a5 100644 --- a/LanguageModels/Errors/__init__.py +++ b/LanguageModels/Errors/__init__.py @@ -1,3 +1,3 @@ -from LanguageModels.Errors.base_languages import BaseErrorLanguageModels +from .merge_all_error_languages import MergedErrorLanguageModels -__all__ = ["BaseErrorLanguageModels"] +__all__ = ["MergedErrorLanguageModels"] diff --git a/LanguageModels/Errors/base_languages.py b/LanguageModels/Errors/base_languages.py index 791717a..c741faf 100644 --- a/LanguageModels/Errors/base_languages.py +++ b/LanguageModels/Errors/base_languages.py @@ -1,7 +1,4 @@ -from ErrorHandlers.bases import ErrorLanguageModelClass, LanguageModelClass - - -class BaseErrorLanguageModelTurkish(ErrorLanguageModelClass): +class BaseErrorLanguageModelTurkish: NOT_CREATED: str = "Kayıt oluşturulamadı." NOT_DELETED: str = "Kayıt silinemedi." @@ -17,7 +14,7 @@ class BaseErrorLanguageModelTurkish(ErrorLanguageModelClass): UNKNOWN_ERROR: str = "Bilinmeyen bir hata oluştu." -class BaseErrorLanguageModelEnglish(ErrorLanguageModelClass): +class BaseErrorLanguageModelEnglish: NOT_CREATED: str = "Not Created." NOT_DELETED: str = "Not Deleted." @@ -33,6 +30,6 @@ class BaseErrorLanguageModelEnglish(ErrorLanguageModelClass): UNKNOWN_ERROR: str = "Unknown Error occured." -class BaseErrorLanguageModels(LanguageModelClass): +class BaseErrorLanguageModels: tr: BaseErrorLanguageModelTurkish = BaseErrorLanguageModelTurkish en: BaseErrorLanguageModelEnglish = BaseErrorLanguageModelEnglish diff --git a/LanguageModels/Errors/merge_all_error_languages.py b/LanguageModels/Errors/merge_all_error_languages.py new file mode 100644 index 0000000..5f83f27 --- /dev/null +++ b/LanguageModels/Errors/merge_all_error_languages.py @@ -0,0 +1,18 @@ +from LanguageModels.Errors.base_languages import BaseErrorLanguageModels + + +class MergedErrorLanguageModels: + list_of_languages = [BaseErrorLanguageModels] + + @classmethod + def get_language_models(cls, language: str): + language_model_keys = {} + for list_of_language in cls.list_of_languages: + language_model_class = getattr(list_of_language, language, None) + clean_dict = { + key: value + for key, value in language_model_class.__dict__.items() + if "__" not in str(key)[0:3] + } + language_model_keys.update(clean_dict) + return language_model_keys