Files
amq-adapter-python/cleverbrag/clever_brag_adapter.py
T
2025-05-29 01:05:05 +01:00

126 lines
4.5 KiB
Python

"""
This module provides the CleverBRAG AMQP Adapter for handling API requests via AMQP.
The code IS MEANT to be part of CleverBRAG codebase, and has direct dependencies on the CleverBRAG codebase.
It is NOT MEANT to be used as a standalone module. It WILL NOT run outside the CleverBRAG context.
"""
from threading import Thread
from typing import Any, List
from uuid import UUID
# CleverBrag specific imports
import core
from fastapi.routing import APIRoute
from fastapi.security.http import HTTPAuthorizationCredentials
from pydantic import BaseModel
from shared.abstractions import R2RSerializable, User
# AMQP specific imports
from amqp.adapter.cleverthis_service_adapter import CleverThisServiceAdapter
from amqp.config.amq_configuration import AMQConfiguration
from amqp.service.amq_service import AMQService
class BRAGArgument:
"""
This class is used to represent a BRAG API input argument. It is uses FastAPI annotation to define the arguments
(the argument type) that are passed as input arguments to the BRAG endpoint.
"""
def __init__(self, arg: Any):
self.arg = arg
self.module = arg.__module__
self.cls = arg.__name__ if hasattr(arg, "__name__") else str(arg)
self.is_r2r_serializable = issubclass(arg, R2RSerializable)
self.is_builtin = self.module == "builtins"
self.is_uuid = self.cls == "UUID"
self.is_optional = self.cls == "Optional"
self.is_list = self.cls == "list"
self.is_dict = self.cls == "dict"
self.is_base_model = issubclass(arg, BaseModel)
self.is_nested = self.is_list or self.is_optional or self.is_dict
if self.is_nested and hasattr(arg, "__args__"):
self.nested = BRAGArgument(getattr(arg, "__args__")[0])
if self.is_dict:
self.nested = (self.nested, BRAGArgument(getattr(arg, "__args__")[1]))
else:
self.nested = None
self.is_nested = False
def __repr__(self):
return f"{self.module}.{self.cls}" + (f"[{self.nested}]" if self.is_nested else "")
def convert_to_argument(arg: BRAGArgument, value: str) -> Any:
"""
Converts the argument to a string representation.
"""
try:
if arg.cls == "str":
return value
elif arg.cls == "bool":
return str(value).lower() == "true"
elif arg.cls == "float":
return float(value)
elif arg.cls == "int":
return int(value)
elif arg.is_uuid:
return UUID(value)
elif arg.is_optional:
return convert_to_argument(arg.nested, value) if arg.nested else None
elif arg.is_list:
return (
[convert_to_argument(arg.nested, v.strip()) for v in value.split(",")]
if arg.nested
else value.split()
)
elif arg.is_dict:
return (
{
convert_to_argument(arg.nested[0], k.strip()): convert_to_argument(
arg.nested[1], v.strip()
)
for k, v in (item.split(":") for item in value.split(","))
}
if arg.nested
else dict(item.split(":") for item in value.split(","))
)
elif arg.is_base_model:
return arg.arg.parse_raw(value)
else:
print(f"Unsupported argument type: {type(arg)}")
except Exception as e:
print(f"Error converting argument {arg}: {e}")
return None
class CleverBragAmqpAdapter(CleverThisServiceAdapter):
"""
CleverBRAG AMQP Adapter for CleverBRAG API. Implements the interface to CleverBRAG API.
"""
def __init__(
self,
amq_configuration: AMQConfiguration,
routes: List[APIRoute],
auth_provider: core.base.providers.auth.AuthProvider,
extra_init_data: dict,
):
super().__init__(
amq_configuration, routes, None, "auth_user", extra_init_data=extra_init_data
)
self.auth_provider = auth_provider
_amq_service: AMQService = AMQService(amq_configuration, self)
self.thread = Thread(target=_amq_service.run)
self.thread.start()
async def get_current_user(self, token: str) -> User:
"""
Overrides the default get_current_user method to use the token from the AMQP message.
:param token: JWT token from the AMQP message
:return: User object
"""
return await self.auth_provider.auth_wrapper(
HTTPAuthorizationCredentials(scheme="Bearer", credentials=token)
)