join tested auth service login/select completed
This commit is contained in:
@@ -1,12 +1,18 @@
|
||||
import arrow
|
||||
import datetime
|
||||
|
||||
from sqlalchemy import Column, Integer, String, Float, ForeignKey, UUID, TIMESTAMP, Boolean, SmallInteger, Numeric, func, text
|
||||
from decimal import Decimal
|
||||
from typing import Any, Optional
|
||||
|
||||
from sqlalchemy import Column, Integer, String, Float, ForeignKey, UUID, TIMESTAMP, Boolean, SmallInteger, Numeric, func, text, NUMERIC
|
||||
from sqlalchemy.orm import relationship
|
||||
from sqlalchemy.orm import Mapped, mapped_column
|
||||
from sqlalchemy_mixins.serialize import SerializeMixin
|
||||
from sqlalchemy_mixins.repr import ReprMixin
|
||||
from sqlalchemy_mixins.smartquery import SmartQueryMixin
|
||||
from sqlalchemy_mixins.activerecord import ActiveRecordMixin
|
||||
from sqlalchemy.orm import InstrumentedAttribute, Mapped
|
||||
|
||||
from api_controllers.postgres.engine import get_db, Base
|
||||
|
||||
|
||||
@@ -26,6 +32,100 @@ class BasicMixin(
|
||||
"""Get database session."""
|
||||
return get_db()
|
||||
|
||||
@classmethod
|
||||
def iterate_over_variables(cls, val: Any, key: str) -> tuple[bool, Optional[Any]]:
|
||||
"""
|
||||
Process a field value based on its type and convert it to the appropriate format.
|
||||
|
||||
Args:
|
||||
val: Field value
|
||||
key: Field name
|
||||
|
||||
Returns:
|
||||
Tuple of (should_include, processed_value)
|
||||
"""
|
||||
try:
|
||||
key_ = cls.__annotations__.get(key, None)
|
||||
is_primary = key in getattr(cls, "primary_keys", [])
|
||||
row_attr = bool(getattr(getattr(cls, key), "foreign_keys", None))
|
||||
|
||||
# Skip primary keys and foreign keys
|
||||
if is_primary or row_attr:
|
||||
return False, None
|
||||
|
||||
if val is None: # Handle None values
|
||||
return True, None
|
||||
|
||||
if str(key[-5:]).lower() == "uu_id": # Special handling for UUID fields
|
||||
return True, str(val)
|
||||
|
||||
if key_: # Handle typed fields
|
||||
if key_ == Mapped[int]:
|
||||
return True, int(val)
|
||||
elif key_ == Mapped[bool]:
|
||||
return True, bool(val)
|
||||
elif key_ == Mapped[float] or key_ == Mapped[NUMERIC]:
|
||||
return True, round(float(val), 3)
|
||||
elif key_ == Mapped[TIMESTAMP]:
|
||||
return True, str(arrow.get(str(val)).format("YYYY-MM-DD HH:mm:ss"))
|
||||
elif key_ == Mapped[str]:
|
||||
return True, str(val)
|
||||
else: # Handle based on Python types
|
||||
if isinstance(val, datetime.datetime):
|
||||
return True, str(arrow.get(str(val)).format("YYYY-MM-DD HH:mm:ss"))
|
||||
elif isinstance(val, bool):
|
||||
return True, bool(val)
|
||||
elif isinstance(val, (float, Decimal)):
|
||||
return True, round(float(val), 3)
|
||||
elif isinstance(val, int):
|
||||
return True, int(val)
|
||||
elif isinstance(val, str):
|
||||
return True, str(val)
|
||||
elif val is None:
|
||||
return True, None
|
||||
return False, None
|
||||
|
||||
except Exception as e:
|
||||
err = e
|
||||
return False, None
|
||||
|
||||
def get_dict(self, exclude_list: Optional[list[InstrumentedAttribute]] = None) -> dict[str, Any]:
|
||||
"""
|
||||
Convert model instance to dictionary with customizable fields.
|
||||
|
||||
Args:
|
||||
exclude_list: List of fields to exclude from the dictionary
|
||||
|
||||
Returns:
|
||||
Dictionary representation of the model
|
||||
"""
|
||||
try:
|
||||
return_dict: Dict[str, Any] = {}
|
||||
exclude_list = exclude_list or []
|
||||
exclude_list = [exclude_arg.key for exclude_arg in exclude_list]
|
||||
|
||||
# Get all column names from the model
|
||||
columns = [col.name for col in self.__table__.columns]
|
||||
columns_set = set(columns)
|
||||
|
||||
# Filter columns
|
||||
columns_list = set([col for col in columns_set if str(col)[-2:] != "id"])
|
||||
columns_extend = set(col for col in columns_set if str(col)[-5:].lower() == "uu_id")
|
||||
columns_list = set(columns_list) | set(columns_extend)
|
||||
columns_list = list(set(columns_list) - set(exclude_list))
|
||||
|
||||
for key in columns_list:
|
||||
val = getattr(self, key)
|
||||
correct, value_of_database = self.iterate_over_variables(val, key)
|
||||
if correct:
|
||||
return_dict[key] = value_of_database
|
||||
|
||||
return return_dict
|
||||
|
||||
except Exception as e:
|
||||
err = e
|
||||
return {}
|
||||
|
||||
|
||||
class CrudMixin(BasicMixin):
|
||||
"""
|
||||
|
||||
@@ -10,9 +10,9 @@ This module provides a class for managing Redis key-value operations with suppor
|
||||
|
||||
import arrow
|
||||
import json
|
||||
from typing import Union, Dict, List, Optional, Any, TypeVar
|
||||
|
||||
from Controllers.Redis.connection import redis_cli
|
||||
from typing import Union, Dict, List, Optional, Any, TypeVar
|
||||
from .connection import redis_cli
|
||||
|
||||
|
||||
T = TypeVar("T", Dict[str, Any], List[Any])
|
||||
|
||||
@@ -2,7 +2,7 @@ import time
|
||||
|
||||
from typing import Dict, Any
|
||||
from redis import Redis, ConnectionError, TimeoutError, ConnectionPool
|
||||
from Controllers.Redis.config import redis_configs
|
||||
from .config import redis_configs
|
||||
|
||||
|
||||
class RedisConn:
|
||||
|
||||
@@ -2,9 +2,9 @@ import arrow
|
||||
|
||||
from typing import Optional, List, Dict, Union, Iterator
|
||||
|
||||
from Controllers.Redis.response import RedisResponse
|
||||
from Controllers.Redis.connection import redis_cli
|
||||
from Controllers.Redis.base import RedisRow
|
||||
from .response import RedisResponse
|
||||
from .connection import redis_cli
|
||||
from .base import RedisRow
|
||||
|
||||
|
||||
class MainConfig:
|
||||
@@ -87,9 +87,7 @@ class RedisActions:
|
||||
return bool(redis_cli.exists(key))
|
||||
|
||||
@classmethod
|
||||
def refresh_ttl(
|
||||
cls, key: Union[str, bytes], expires: Dict[str, int]
|
||||
) -> RedisResponse:
|
||||
def refresh_ttl(cls, key: Union[str, bytes], expires: Dict[str, int]) -> RedisResponse:
|
||||
"""
|
||||
Refresh TTL for an existing key.
|
||||
|
||||
@@ -160,9 +158,7 @@ class RedisActions:
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def delete(
|
||||
cls, list_keys: List[Union[Optional[str], Optional[bytes]]]
|
||||
) -> RedisResponse:
|
||||
def delete(cls, list_keys: List[Union[Optional[str], Optional[bytes]]]) -> RedisResponse:
|
||||
"""
|
||||
Delete multiple keys matching a pattern.
|
||||
|
||||
@@ -199,12 +195,7 @@ class RedisActions:
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def set_json(
|
||||
cls,
|
||||
list_keys: List[Union[str, bytes]],
|
||||
value: Optional[Union[Dict, List]],
|
||||
expires: Optional[Dict[str, int]] = None,
|
||||
) -> RedisResponse:
|
||||
def set_json(cls, list_keys: List[Union[str, bytes]], value: Optional[Union[Dict, List]], expires: Optional[Dict[str, int]] = None) -> RedisResponse:
|
||||
"""
|
||||
Set JSON value in Redis with optional expiry.
|
||||
|
||||
@@ -252,11 +243,7 @@ class RedisActions:
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def get_json(
|
||||
cls,
|
||||
list_keys: List[Union[Optional[str], Optional[bytes]]],
|
||||
limit: Optional[int] = None,
|
||||
) -> RedisResponse:
|
||||
def get_json(cls, list_keys: List[Union[Optional[str], Optional[bytes]]], limit: Optional[int] = None) -> RedisResponse:
|
||||
"""
|
||||
Get JSON values from Redis using pattern matching.
|
||||
|
||||
@@ -313,9 +300,7 @@ class RedisActions:
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def get_json_iterator(
|
||||
cls, list_keys: List[Union[Optional[str], Optional[bytes]]]
|
||||
) -> Iterator[RedisRow]:
|
||||
def get_json_iterator(cls, list_keys: List[Union[Optional[str], Optional[bytes]]]) -> Iterator[RedisRow]:
|
||||
"""
|
||||
Get JSON values from Redis as an iterator for memory-efficient processing of large datasets.
|
||||
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
from Controllers.Redis.database import RedisActions
|
||||
import threading
|
||||
import time
|
||||
import random
|
||||
import uuid
|
||||
import concurrent.futures
|
||||
|
||||
from .database import RedisActions
|
||||
|
||||
|
||||
def example_set_json() -> None:
|
||||
"""Example of setting JSON data in Redis with and without expiry."""
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
from typing import Union, Dict, Optional, Any
|
||||
from Controllers.Redis.base import RedisRow
|
||||
from .base import RedisRow
|
||||
|
||||
|
||||
class RedisResponse:
|
||||
@@ -10,13 +10,7 @@ class RedisResponse:
|
||||
with tools to convert between different data representations.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
status: bool,
|
||||
message: str,
|
||||
data: Any = None,
|
||||
error: Optional[str] = None,
|
||||
):
|
||||
def __init__(self, status: bool, message: str, data: Any = None, error: Optional[str] = None):
|
||||
"""
|
||||
Initialize a Redis response.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user