validations updated & Error Handlers updated & token config added
This commit is contained in:
parent
f21c92cb27
commit
69883d3120
|
|
@ -0,0 +1,107 @@
|
||||||
|
import enum
|
||||||
|
from typing import Optional, List, Any
|
||||||
|
from pydantic import BaseModel
|
||||||
|
|
||||||
|
|
||||||
|
# Company / Priority / Department / Duty / Employee / Occupant / Module / Endpoint are changeable dynamics
|
||||||
|
|
||||||
|
|
||||||
|
class UserType(enum.Enum):
|
||||||
|
|
||||||
|
employee = 1
|
||||||
|
occupant = 2
|
||||||
|
|
||||||
|
|
||||||
|
class Credentials(BaseModel):
|
||||||
|
|
||||||
|
person_id: int
|
||||||
|
person_name: str
|
||||||
|
|
||||||
|
|
||||||
|
class ApplicationToken(BaseModel):
|
||||||
|
# Application Token Object -> is the main object for the user
|
||||||
|
|
||||||
|
domain: Optional[str] = "app.evyos.com.tr"
|
||||||
|
lang: Optional[str] = "TR"
|
||||||
|
timezone: Optional[str] = "GMT+3"
|
||||||
|
|
||||||
|
user_type: int = UserType.occupant.value
|
||||||
|
credentials: dict = None
|
||||||
|
|
||||||
|
user_uu_id: str
|
||||||
|
user_id: int
|
||||||
|
|
||||||
|
person_id: int
|
||||||
|
person_uu_id: str
|
||||||
|
|
||||||
|
request: Optional[dict] = None # Request Info of Client
|
||||||
|
expires_at: Optional[float] = None # Expiry timestamp
|
||||||
|
|
||||||
|
|
||||||
|
class OccupantToken(BaseModel):
|
||||||
|
# Selection of the occupant type for a build part is made by the user
|
||||||
|
|
||||||
|
living_space_id: int # Internal use
|
||||||
|
living_space_uu_id: str # Outer use
|
||||||
|
|
||||||
|
occupant_type_id: int
|
||||||
|
occupant_type_uu_id: str
|
||||||
|
occupant_type: str
|
||||||
|
|
||||||
|
build_id: int
|
||||||
|
build_uuid: str
|
||||||
|
build_part_id: int
|
||||||
|
build_part_uuid: str
|
||||||
|
|
||||||
|
responsible_company_id: Optional[int] = None
|
||||||
|
responsible_company_uuid: Optional[str] = None
|
||||||
|
responsible_employee_id: Optional[int] = None
|
||||||
|
responsible_employee_uuid: Optional[str] = None
|
||||||
|
|
||||||
|
reachable_event_list_id: Optional[list] = None # ID list of reachable modules
|
||||||
|
# reachable_event_list_uu_id: Optional[list] = None # UUID list of reachable modules
|
||||||
|
|
||||||
|
|
||||||
|
class CompanyToken(BaseModel): # Required Company Object for an employee
|
||||||
|
|
||||||
|
company_id: int
|
||||||
|
company_uu_id: str
|
||||||
|
|
||||||
|
department_id: int # ID list of departments
|
||||||
|
department_uu_id: str # ID list of departments
|
||||||
|
|
||||||
|
duty_id: int
|
||||||
|
duty_uu_id: str
|
||||||
|
|
||||||
|
staff_id: int
|
||||||
|
staff_uu_id: str
|
||||||
|
|
||||||
|
employee_id: int
|
||||||
|
employee_uu_id: str
|
||||||
|
|
||||||
|
bulk_duties_id: int
|
||||||
|
|
||||||
|
reachable_event_list_id: Optional[list] = None # ID list of reachable modules
|
||||||
|
# reachable_event_list_uu_id: Optional[list] = None # UUID list of reachable modules
|
||||||
|
|
||||||
|
|
||||||
|
class OccupantTokenObject(ApplicationToken):
|
||||||
|
# Occupant Token Object -> Requires selection of the occupant type for a specific build part
|
||||||
|
|
||||||
|
available_occupants: dict = None
|
||||||
|
|
||||||
|
selected_occupant: Optional[OccupantToken] = None # Selected Occupant Type
|
||||||
|
available_event: Optional[Any] = None
|
||||||
|
|
||||||
|
|
||||||
|
class EmployeeTokenObject(ApplicationToken):
|
||||||
|
# Full hierarchy Employee[staff_id] -> Staff -> Duty -> Department -> Company
|
||||||
|
|
||||||
|
companies_id_list: List[int] # List of company objects
|
||||||
|
companies_uu_id_list: List[str] # List of company objects
|
||||||
|
|
||||||
|
duty_id_list: List[int] # List of duty objects
|
||||||
|
duty_uu_id_list: List[str] # List of duty objects
|
||||||
|
|
||||||
|
selected_company: Optional[CompanyToken] = None # Selected Company Object
|
||||||
|
available_event: Optional[Any] = None
|
||||||
|
|
@ -0,0 +1,93 @@
|
||||||
|
# Git
|
||||||
|
.git
|
||||||
|
.gitignore
|
||||||
|
.gitattributes
|
||||||
|
|
||||||
|
|
||||||
|
# CI
|
||||||
|
.codeclimate.yml
|
||||||
|
.travis.yml
|
||||||
|
.taskcluster.yml
|
||||||
|
|
||||||
|
# Docker
|
||||||
|
docker-compose.yml
|
||||||
|
service_app/Dockerfile
|
||||||
|
.docker
|
||||||
|
.dockerignore
|
||||||
|
|
||||||
|
# Byte-compiled / optimized / DLL files
|
||||||
|
**/__pycache__/
|
||||||
|
**/*.py[cod]
|
||||||
|
|
||||||
|
# C extensions
|
||||||
|
*.so
|
||||||
|
|
||||||
|
# Distribution / packaging
|
||||||
|
.Python
|
||||||
|
service_app/env/
|
||||||
|
build/
|
||||||
|
develop-eggs/
|
||||||
|
dist/
|
||||||
|
downloads/
|
||||||
|
eggs/
|
||||||
|
lib/
|
||||||
|
lib64/
|
||||||
|
parts/
|
||||||
|
sdist/
|
||||||
|
var/
|
||||||
|
*.egg-info/
|
||||||
|
.installed.cfg
|
||||||
|
*.egg
|
||||||
|
|
||||||
|
# PyInstaller
|
||||||
|
# Usually these files are written by a python script from a template
|
||||||
|
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||||
|
*.manifest
|
||||||
|
*.spec
|
||||||
|
|
||||||
|
# Installer logs
|
||||||
|
pip-log.txt
|
||||||
|
pip-delete-this-directory.txt
|
||||||
|
|
||||||
|
# Unit test / coverage reports
|
||||||
|
htmlcov/
|
||||||
|
.tox/
|
||||||
|
.coverage
|
||||||
|
.cache
|
||||||
|
nosetests.xml
|
||||||
|
coverage.xml
|
||||||
|
|
||||||
|
# Translations
|
||||||
|
*.mo
|
||||||
|
*.pot
|
||||||
|
|
||||||
|
# Django stuff:
|
||||||
|
*.log
|
||||||
|
|
||||||
|
# Sphinx documentation
|
||||||
|
docs/_build/
|
||||||
|
|
||||||
|
# PyBuilder
|
||||||
|
target/
|
||||||
|
|
||||||
|
# Virtual environment
|
||||||
|
service_app/.env
|
||||||
|
.venv/
|
||||||
|
venv/
|
||||||
|
|
||||||
|
# PyCharm
|
||||||
|
.idea
|
||||||
|
|
||||||
|
# Python mode for VIM
|
||||||
|
.ropeproject
|
||||||
|
**/.ropeproject
|
||||||
|
|
||||||
|
# Vim swap files
|
||||||
|
**/*.swp
|
||||||
|
|
||||||
|
# VS Code
|
||||||
|
.vscode/
|
||||||
|
|
||||||
|
test_application/
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
REDIS_HOST=commercial_redis_service
|
||||||
|
REDIS_PASSWORD=commercial_redis_password
|
||||||
|
REDIS_PORT=6379
|
||||||
|
REDIS_DB=0
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
MONGODB_DISABLE_ENFORCE_AUTH=true
|
||||||
|
MONGODB_ROOT_PASSWORD=root
|
||||||
|
MONGODB_DATABASE=mongo_database
|
||||||
|
MONGODB_USERNAME=mongo_user
|
||||||
|
MONGODB_PASSWORD=mongo_password
|
||||||
|
MONGO_INITDB_ROOT_USERNAME=mongo_user
|
||||||
|
MONGO_INITDB_ROOT_PASSWORD=mongo_password
|
||||||
|
MONGO_INITDB_DATABASE=mongo_database
|
||||||
|
|
@ -0,0 +1,48 @@
|
||||||
|
services:
|
||||||
|
|
||||||
|
commercial_main_mongo_service:
|
||||||
|
container_name: commercial_main_mongo_service
|
||||||
|
# image: "bitnami/mongodb:latest"
|
||||||
|
image: "bitnami/mongodb:4.4.1-debian-10-r3"
|
||||||
|
networks:
|
||||||
|
- network_store_services
|
||||||
|
restart: on-failure
|
||||||
|
env_file:
|
||||||
|
- commercial_main_mongo_service.env
|
||||||
|
volumes:
|
||||||
|
- wag_commercial_mongodb_main_data:/bitnami/mongodb
|
||||||
|
ports:
|
||||||
|
- "11777:27017"
|
||||||
|
|
||||||
|
commercial_main_memory_service:
|
||||||
|
container_name: commercial_main_memory_service
|
||||||
|
image: 'bitnami/redis:latest'
|
||||||
|
networks:
|
||||||
|
- network_store_services
|
||||||
|
restart: on-failure
|
||||||
|
env_file:
|
||||||
|
- commercial_main_memory_service.env
|
||||||
|
ports:
|
||||||
|
- "11222:6379"
|
||||||
|
|
||||||
|
postgres_main_commercial:
|
||||||
|
image: 'bitnami/postgresql:latest'
|
||||||
|
container_name: postgres_main_commercial
|
||||||
|
networks:
|
||||||
|
- network_store_services
|
||||||
|
restart: on-failure
|
||||||
|
env_file:
|
||||||
|
- postgres_main_commercial.env
|
||||||
|
depends_on:
|
||||||
|
- commercial_main_mongo_service
|
||||||
|
ports:
|
||||||
|
- "5444:5432"
|
||||||
|
volumes:
|
||||||
|
- wag_postgres_main_commercial_data:/bitnami/postgresql
|
||||||
|
|
||||||
|
networks:
|
||||||
|
network_store_services:
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
wag_postgres_main_commercial_data:
|
||||||
|
wag_commercial_mongodb_main_data:
|
||||||
|
|
@ -0,0 +1,48 @@
|
||||||
|
services:
|
||||||
|
|
||||||
|
commercial_main_mongo_service:
|
||||||
|
container_name: commercial_main_mongo_service
|
||||||
|
image: "bitnami/mongodb:latest"
|
||||||
|
# image: "bitnami/mongodb:4.4.1-debian-10-r3"
|
||||||
|
networks:
|
||||||
|
- network_store_services
|
||||||
|
restart: on-failure
|
||||||
|
env_file:
|
||||||
|
- commercial_main_mongo_service.env
|
||||||
|
volumes:
|
||||||
|
- wag_commercial_mongodb_main_data:/bitnami/mongodb
|
||||||
|
ports:
|
||||||
|
- "11777:27017"
|
||||||
|
|
||||||
|
commercial_main_memory_service:
|
||||||
|
container_name: commercial_main_memory_service
|
||||||
|
image: 'bitnami/redis:latest'
|
||||||
|
networks:
|
||||||
|
- network_store_services
|
||||||
|
restart: on-failure
|
||||||
|
env_file:
|
||||||
|
- commercial_main_memory_service.env
|
||||||
|
ports:
|
||||||
|
- "11222:6379"
|
||||||
|
|
||||||
|
postgres_main_commercial:
|
||||||
|
image: 'bitnami/postgresql:latest'
|
||||||
|
container_name: postgres_main_commercial
|
||||||
|
networks:
|
||||||
|
- network_store_services
|
||||||
|
restart: on-failure
|
||||||
|
env_file:
|
||||||
|
- postgres_main_commercial.env
|
||||||
|
depends_on:
|
||||||
|
- commercial_mongo_service
|
||||||
|
ports:
|
||||||
|
- "5444:5432"
|
||||||
|
volumes:
|
||||||
|
- wag_postgres_main_commercial_data:/bitnami/postgresql
|
||||||
|
|
||||||
|
networks:
|
||||||
|
network_store_services:
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
wag_postgres_main_commercial_data:
|
||||||
|
wag_commercial_mongodb_main_data:
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
POSTGRES_DB=wag_database
|
||||||
|
POSTGRES_USER=berkay_wag_user
|
||||||
|
POSTGRES_PASSWORD=berkay_wag_user_password
|
||||||
|
|
@ -1,114 +1,259 @@
|
||||||
|
"""
|
||||||
|
Redis key-value operations with structured data handling.
|
||||||
|
|
||||||
|
This module provides a class for managing Redis key-value operations with support for:
|
||||||
|
- Structured data storage and retrieval
|
||||||
|
- Key pattern generation for searches
|
||||||
|
- JSON serialization/deserialization
|
||||||
|
- Type-safe value handling
|
||||||
|
"""
|
||||||
|
|
||||||
import json
|
import json
|
||||||
from typing import Union, Dict, List, Optional, Any
|
from typing import Union, Dict, List, Optional, Any, ClassVar
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
|
||||||
|
class RedisKeyError(Exception):
|
||||||
|
"""Exception raised for Redis key-related errors."""
|
||||||
|
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class RedisValueError(Exception):
|
||||||
|
"""Exception raised for Redis value-related errors."""
|
||||||
|
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class RedisRow:
|
class RedisRow:
|
||||||
"""Class for handling Redis key-value operations with structured data."""
|
"""
|
||||||
|
Handles Redis key-value operations with structured data.
|
||||||
|
|
||||||
key: Union[str, bytes]
|
This class provides methods for:
|
||||||
value: Any
|
- Managing compound keys with delimiters
|
||||||
delimiter: str = ":"
|
- Converting between bytes and string formats
|
||||||
expires_at: Optional[str] = None
|
- JSON serialization/deserialization of values
|
||||||
|
- Pattern generation for Redis key searches
|
||||||
|
|
||||||
|
Attributes:
|
||||||
|
key: The Redis key in bytes or string format
|
||||||
|
value: The stored value (will be JSON serialized)
|
||||||
|
delimiter: Character used to separate compound key parts
|
||||||
|
expires_at: Optional expiration timestamp
|
||||||
|
"""
|
||||||
|
|
||||||
|
key: ClassVar[Union[str, bytes]]
|
||||||
|
value: ClassVar[Any]
|
||||||
|
delimiter: ClassVar[str] = ":"
|
||||||
|
expires_at: ClassVar[Optional[str]] = None
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def merge(cls, set_values: List[Union[str, bytes]]) -> None:
|
def merge(cls, set_values: List[Union[str, bytes]]) -> None:
|
||||||
"""Merge list of values into a single delimited key."""
|
"""
|
||||||
cls.key = ""
|
Merge list of values into a single delimited key.
|
||||||
for key, set_value in enumerate(set_values):
|
|
||||||
set_value = (
|
|
||||||
set_value.decode() if isinstance(set_value, bytes) else str(set_value)
|
|
||||||
)
|
|
||||||
cls.key += (
|
|
||||||
f"{set_value}"
|
|
||||||
if key == len(set_values) - 1
|
|
||||||
else f"{set_value}{cls.delimiter}"
|
|
||||||
)
|
|
||||||
cls.key = cls.key.encode()
|
|
||||||
|
|
||||||
@classmethod
|
Args:
|
||||||
def regex(cls, list_keys: List[Union[str, bytes]]) -> str:
|
set_values: List of values to merge into key
|
||||||
"""Generate Redis search pattern from list of keys.
|
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
list_keys = [None, "example1", "example2"]
|
>>> RedisRow.merge(["users", "123", "profile"])
|
||||||
Result: "*:example1:example2"
|
>>> print(RedisRow.key)
|
||||||
|
b'users:123:profile'
|
||||||
"""
|
"""
|
||||||
# First create string with dash separators
|
if not set_values:
|
||||||
temp_str = "-"
|
raise RedisKeyError("Cannot merge empty list of values")
|
||||||
for list_key in list_keys:
|
|
||||||
if list_key:
|
|
||||||
list_key = (
|
|
||||||
list_key.decode() if isinstance(list_key, bytes) else str(list_key)
|
|
||||||
)
|
|
||||||
temp_str += f"{list_key}-"
|
|
||||||
|
|
||||||
# Remove redundant dashes
|
merged = []
|
||||||
temp_str = temp_str.strip("-")
|
for value in set_values:
|
||||||
|
if value is None:
|
||||||
|
continue
|
||||||
|
if isinstance(value, bytes):
|
||||||
|
value = value.decode()
|
||||||
|
merged.append(str(value))
|
||||||
|
|
||||||
# If no valid keys, return empty string
|
cls.key = cls.delimiter.join(merged).encode()
|
||||||
if not temp_str:
|
|
||||||
|
@classmethod
|
||||||
|
def regex(cls, list_keys: List[Union[str, bytes, None]]) -> str:
|
||||||
|
"""
|
||||||
|
Generate Redis search pattern from list of keys.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
list_keys: List of key parts, can include None for wildcards
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
str: Redis key pattern with wildcards
|
||||||
|
|
||||||
|
Example:
|
||||||
|
>>> RedisRow.regex([None, "users", "active"])
|
||||||
|
'*:users:active'
|
||||||
|
"""
|
||||||
|
if not list_keys:
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
# Replace dashes with delimiter
|
# Filter and convert valid keys
|
||||||
result = temp_str.replace("-", cls.delimiter)
|
valid_keys = []
|
||||||
|
for key in list_keys:
|
||||||
|
if key is None:
|
||||||
|
continue
|
||||||
|
if isinstance(key, bytes):
|
||||||
|
key = key.decode()
|
||||||
|
valid_keys.append(str(key))
|
||||||
|
|
||||||
# Add wildcard at start if first item was None
|
# Build pattern
|
||||||
if list_keys and list_keys[0] is None:
|
pattern = cls.delimiter.join(valid_keys)
|
||||||
result = f"*{cls.delimiter}{result}"
|
if not pattern:
|
||||||
else:
|
return ""
|
||||||
result = f"{result}"
|
|
||||||
|
|
||||||
return result
|
# Add wildcard if first key was None
|
||||||
|
if list_keys[0] is None:
|
||||||
|
pattern = f"*{cls.delimiter}{pattern}"
|
||||||
|
|
||||||
|
return pattern
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def parse(cls) -> List[str]:
|
def parse(cls) -> List[str]:
|
||||||
"""Parse the key into its component parts."""
|
"""
|
||||||
return cls.key.split(cls.delimiter) if cls.key else []
|
Parse the key into its component parts.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
List[str]: Key parts split by delimiter
|
||||||
|
|
||||||
|
Example:
|
||||||
|
>>> RedisRow.key = b'users:123:profile'
|
||||||
|
>>> RedisRow.parse()
|
||||||
|
['users', '123', 'profile']
|
||||||
|
"""
|
||||||
|
if not cls.key:
|
||||||
|
return []
|
||||||
|
|
||||||
|
key_str = cls.key.decode() if isinstance(cls.key, bytes) else cls.key
|
||||||
|
return key_str.split(cls.delimiter)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def feed(cls, value: Union[bytes, Dict, List]) -> None:
|
def feed(cls, value: Union[bytes, Dict, List]) -> None:
|
||||||
"""Convert and store value in JSON format."""
|
"""
|
||||||
if isinstance(value, (dict, list)):
|
Convert and store value in JSON format.
|
||||||
cls.value = json.dumps(value)
|
|
||||||
else:
|
Args:
|
||||||
cls.value = json.dumps(json.loads(value.decode()))
|
value: Value to store (bytes, dict, or list)
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
RedisValueError: If value type is not supported
|
||||||
|
|
||||||
|
Example:
|
||||||
|
>>> RedisRow.feed({"name": "John", "age": 30})
|
||||||
|
>>> print(RedisRow.value)
|
||||||
|
'{"name": "John", "age": 30}'
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
if isinstance(value, (dict, list)):
|
||||||
|
cls.value = json.dumps(value)
|
||||||
|
elif isinstance(value, bytes):
|
||||||
|
cls.value = json.dumps(json.loads(value.decode()))
|
||||||
|
else:
|
||||||
|
raise RedisValueError(f"Unsupported value type: {type(value)}")
|
||||||
|
except json.JSONDecodeError as e:
|
||||||
|
raise RedisValueError(f"Invalid JSON format: {str(e)}")
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def modify(cls, add_dict: Dict) -> None:
|
def modify(cls, add_dict: Dict) -> None:
|
||||||
"""Modify existing data by merging with new dictionary."""
|
"""
|
||||||
value = cls.data or {}
|
Modify existing data by merging with new dictionary.
|
||||||
cls.feed({**value, **add_dict})
|
|
||||||
|
Args:
|
||||||
|
add_dict: Dictionary to merge with existing data
|
||||||
|
|
||||||
|
Example:
|
||||||
|
>>> RedisRow.feed({"name": "John"})
|
||||||
|
>>> RedisRow.modify({"age": 30})
|
||||||
|
>>> print(RedisRow.data)
|
||||||
|
{"name": "John", "age": 30}
|
||||||
|
"""
|
||||||
|
if not isinstance(add_dict, dict):
|
||||||
|
raise RedisValueError("modify() requires a dictionary argument")
|
||||||
|
|
||||||
|
current_data = cls.data if cls.data else {}
|
||||||
|
if not isinstance(current_data, dict):
|
||||||
|
raise RedisValueError("Cannot modify non-dictionary data")
|
||||||
|
|
||||||
|
cls.feed({**current_data, **add_dict})
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def remove(cls, key: str) -> None:
|
def remove(cls, key: str) -> None:
|
||||||
"""Remove a key from the stored dictionary."""
|
"""
|
||||||
value = cls.data or {}
|
Remove a key from the stored dictionary.
|
||||||
value.pop(key)
|
|
||||||
cls.feed(value)
|
Args:
|
||||||
|
key: Key to remove from stored dictionary
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
KeyError: If key doesn't exist
|
||||||
|
RedisValueError: If stored value is not a dictionary
|
||||||
|
"""
|
||||||
|
current_data = cls.data
|
||||||
|
if not isinstance(current_data, dict):
|
||||||
|
raise RedisValueError("Cannot remove key from non-dictionary data")
|
||||||
|
|
||||||
|
try:
|
||||||
|
current_data.pop(key)
|
||||||
|
cls.feed(current_data)
|
||||||
|
except KeyError:
|
||||||
|
raise KeyError(f"Key '{key}' not found in stored data")
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def keys(self) -> str:
|
def keys(self) -> str:
|
||||||
"""Get key as string."""
|
"""
|
||||||
|
Get key as string.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
str: Key in string format
|
||||||
|
"""
|
||||||
return self.key.decode() if isinstance(self.key, bytes) else self.key
|
return self.key.decode() if isinstance(self.key, bytes) else self.key
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def set_key(cls, key: Union[str, bytes]) -> None:
|
def set_key(cls, key: Union[str, bytes]) -> None:
|
||||||
"""Set key ensuring bytes format."""
|
"""
|
||||||
cls.key = key if isinstance(key, bytes) else key.encode()
|
Set key ensuring bytes format.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
key: Key in string or bytes format
|
||||||
|
"""
|
||||||
|
if not key:
|
||||||
|
raise RedisKeyError("Cannot set empty key")
|
||||||
|
cls.key = key if isinstance(key, bytes) else str(key).encode()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def redis_key(self) -> bytes:
|
def redis_key(self) -> bytes:
|
||||||
"""Get key in bytes format for Redis operations."""
|
"""
|
||||||
return self.key if isinstance(self.key, bytes) else self.key.encode()
|
Get key in bytes format for Redis operations.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bytes: Key in bytes format
|
||||||
|
"""
|
||||||
|
return self.key if isinstance(self.key, bytes) else str(self.key).encode()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def data(self) -> Union[Dict, List]:
|
def data(self) -> Union[Dict, List]:
|
||||||
"""Get stored value as Python object."""
|
"""
|
||||||
return json.loads(self.value)
|
Get stored value as Python object.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Union[Dict, List]: Deserialized JSON data
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
return json.loads(self.value)
|
||||||
|
except json.JSONDecodeError as e:
|
||||||
|
raise RedisValueError(f"Invalid JSON format in stored value: {str(e)}")
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def as_dict(self) -> Dict:
|
def as_dict(self) -> Dict[str, Any]:
|
||||||
"""Get row data as dictionary."""
|
"""
|
||||||
|
Get row data as dictionary.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Dict[str, Any]: Dictionary with keys and value
|
||||||
|
"""
|
||||||
return {
|
return {
|
||||||
"keys": self.keys,
|
"keys": self.keys,
|
||||||
"value": self.data,
|
"value": self.data,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue