201 lines
5.8 KiB
Python
201 lines
5.8 KiB
Python
from typing import Union, Dict, Optional, Any
|
|
from Controllers.Redis.base import RedisRow
|
|
|
|
|
|
class RedisResponse:
|
|
"""
|
|
Base class for Redis response handling.
|
|
|
|
Provides a standardized way to return and process Redis operation results,
|
|
with tools to convert between different data representations.
|
|
"""
|
|
|
|
def __init__(
|
|
self,
|
|
status: bool,
|
|
message: str,
|
|
data: Any = None,
|
|
error: Optional[str] = None,
|
|
):
|
|
"""
|
|
Initialize a Redis response.
|
|
|
|
Args:
|
|
status: Operation success status
|
|
message: Human-readable message about the operation
|
|
data: Response data (can be None, RedisRow, list, or dict)
|
|
error: Optional error message if operation failed
|
|
"""
|
|
self.status = status
|
|
self.message = message
|
|
self.data = data
|
|
self.error = error
|
|
|
|
# Determine the data type
|
|
if isinstance(data, dict):
|
|
self.data_type = "dict"
|
|
elif isinstance(data, list):
|
|
self.data_type = "list"
|
|
elif isinstance(data, RedisRow):
|
|
self.data_type = "row"
|
|
elif isinstance(data, (int, float, str, bool)):
|
|
self.data_type = "primitive"
|
|
else:
|
|
self.data_type = None
|
|
|
|
def as_dict(self) -> Dict:
|
|
"""
|
|
Convert the response to a dictionary format suitable for serialization.
|
|
|
|
Returns:
|
|
Dictionary representation of the response
|
|
"""
|
|
# Base response fields
|
|
main_dict = {
|
|
"status": self.status,
|
|
"message": self.message,
|
|
"count": self.count,
|
|
"dataType": self.data_type,
|
|
}
|
|
|
|
# Add error if present
|
|
if self.error:
|
|
main_dict["error"] = self.error
|
|
|
|
data = self.all
|
|
|
|
# Process single RedisRow
|
|
if isinstance(data, RedisRow):
|
|
result = {**main_dict}
|
|
if hasattr(data, "keys") and hasattr(data, "row"):
|
|
if not isinstance(data.keys, str):
|
|
raise ValueError("RedisRow keys must be string type")
|
|
result[data.keys] = data.row
|
|
return result
|
|
|
|
# Process list of RedisRows
|
|
elif isinstance(data, list):
|
|
result = {**main_dict}
|
|
|
|
# Handle list of RedisRow objects
|
|
rows_dict = {}
|
|
for row in data:
|
|
if (
|
|
isinstance(row, RedisRow)
|
|
and hasattr(row, "keys")
|
|
and hasattr(row, "row")
|
|
):
|
|
if not isinstance(row.keys, str):
|
|
raise ValueError("RedisRow keys must be string type")
|
|
rows_dict[row.keys] = row.row
|
|
|
|
if rows_dict:
|
|
result["data"] = rows_dict
|
|
elif data: # If it's just a regular list with items
|
|
result["data"] = data
|
|
|
|
return result
|
|
|
|
# Process dictionary
|
|
elif isinstance(data, dict):
|
|
return {**main_dict, "data": data}
|
|
|
|
return main_dict
|
|
|
|
@property
|
|
def all(self) -> Any:
|
|
"""
|
|
Get all data from the response.
|
|
|
|
Returns:
|
|
All data or empty list if None
|
|
"""
|
|
return self.data if self.data is not None else []
|
|
|
|
@property
|
|
def count(self) -> int:
|
|
"""
|
|
Count the number of items in the response data.
|
|
|
|
Returns:
|
|
Number of items (0 if no data)
|
|
"""
|
|
data = self.all
|
|
|
|
if isinstance(data, list):
|
|
return len(data)
|
|
elif isinstance(data, (RedisRow, dict)):
|
|
return 1
|
|
return 0
|
|
|
|
@property
|
|
def first(self) -> Union[Dict, None]:
|
|
"""
|
|
Get the first item from the response data.
|
|
|
|
Returns:
|
|
First item as a dictionary or None if no data
|
|
"""
|
|
if not self.data:
|
|
return None
|
|
|
|
if isinstance(self.data, list) and self.data:
|
|
item = self.data[0]
|
|
if isinstance(item, RedisRow) and hasattr(item, "row"):
|
|
return item.row
|
|
return item
|
|
elif isinstance(self.data, RedisRow) and hasattr(self.data, "row"):
|
|
return self.data.row
|
|
elif isinstance(self.data, dict):
|
|
return self.data
|
|
|
|
return None
|
|
|
|
def is_successful(self) -> bool:
|
|
"""
|
|
Check if the operation was successful.
|
|
|
|
Returns:
|
|
Boolean indicating success status
|
|
"""
|
|
return self.status
|
|
|
|
def to_api_response(self) -> Dict:
|
|
"""
|
|
Format the response for API consumption.
|
|
|
|
Returns:
|
|
API-friendly response dictionary
|
|
"""
|
|
try:
|
|
response = {
|
|
"success": self.status,
|
|
"message": self.message,
|
|
}
|
|
|
|
if self.error:
|
|
response["error"] = self.error
|
|
|
|
if self.data is not None:
|
|
if self.data_type == "row" and hasattr(self.data, "to_dict"):
|
|
response["data"] = self.data.to_dict()
|
|
elif self.data_type == "list":
|
|
try:
|
|
if all(hasattr(item, "to_dict") for item in self.data):
|
|
response["data"] = [item.to_dict() for item in self.data]
|
|
else:
|
|
response["data"] = self.data
|
|
except Exception as e:
|
|
response["error"] = f"Error converting list items: {str(e)}"
|
|
else:
|
|
response["data"] = self.data
|
|
|
|
response["count"] = self.count
|
|
return response
|
|
except Exception as e:
|
|
return {
|
|
"success": False,
|
|
"message": "Error formatting response",
|
|
"error": str(e),
|
|
}
|