updated Postgres Service
This commit is contained in:
parent
6b9e9050a2
commit
4c87c4df91
|
|
@ -1,11 +1,9 @@
|
||||||
import time
|
|
||||||
|
|
||||||
from Controllers.Postgres.config import postgres_configs
|
from Controllers.Postgres.config import postgres_configs
|
||||||
from Controllers.Mongo.config import mongo_configs
|
from Controllers.Mongo.config import mongo_configs
|
||||||
|
from Controllers.Postgres.implementations import generate_table_in_postgres, run_all_tests
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
print(f"Hello from the Test Service {mongo_configs.url}")
|
print(f"Hello from the Test Service {mongo_configs.url}")
|
||||||
print(f"Hello from the Test Service {postgres_configs.url}")
|
print(f"Hello from the Test Service {postgres_configs.url}")
|
||||||
while True:
|
run_all_tests()
|
||||||
time.sleep(10)
|
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ import functools
|
||||||
|
|
||||||
from pymongo import MongoClient
|
from pymongo import MongoClient
|
||||||
from pymongo.errors import PyMongoError
|
from pymongo.errors import PyMongoError
|
||||||
from config import mongo_configs
|
from Controllers.Mongo.config import mongo_configs
|
||||||
|
|
||||||
|
|
||||||
def retry_operation(max_attempts=3, delay=1.0, backoff=2.0, exceptions=(PyMongoError,)):
|
def retry_operation(max_attempts=3, delay=1.0, backoff=2.0, exceptions=(PyMongoError,)):
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ from sqlalchemy.orm import Session
|
||||||
from fastapi import status
|
from fastapi import status
|
||||||
from fastapi.exceptions import HTTPException
|
from fastapi.exceptions import HTTPException
|
||||||
|
|
||||||
from database import get_db
|
from Controllers.Postgres.database import get_db
|
||||||
|
|
||||||
|
|
||||||
# Type variable for class methods returning self
|
# Type variable for class methods returning self
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
from contextlib import contextmanager
|
from contextlib import contextmanager
|
||||||
from functools import lru_cache
|
from functools import lru_cache
|
||||||
from typing import Generator
|
from typing import Generator
|
||||||
from config import postgres_configs
|
from Controllers.Postgres.config import postgres_configs
|
||||||
|
|
||||||
from sqlalchemy import create_engine
|
from sqlalchemy import create_engine
|
||||||
from sqlalchemy.orm import declarative_base, sessionmaker, scoped_session, Session
|
from sqlalchemy.orm import declarative_base, sessionmaker, scoped_session, Session
|
||||||
|
|
@ -14,7 +14,7 @@ engine = create_engine(
|
||||||
max_overflow=5, # Reduced from 10 to prevent too many connections
|
max_overflow=5, # Reduced from 10 to prevent too many connections
|
||||||
pool_recycle=600, # Keep as is
|
pool_recycle=600, # Keep as is
|
||||||
pool_timeout=30, # Keep as is
|
pool_timeout=30, # Keep as is
|
||||||
echo=True, # Consider setting to False in production
|
echo=False, # Consider setting to False in production
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ from sqlalchemy import ColumnExpressionArgument
|
||||||
from sqlalchemy.orm import Query, Session
|
from sqlalchemy.orm import Query, Session
|
||||||
from sqlalchemy.sql.elements import BinaryExpression
|
from sqlalchemy.sql.elements import BinaryExpression
|
||||||
|
|
||||||
from response import PostgresResponse
|
from Controllers.Postgres.response import PostgresResponse
|
||||||
|
|
||||||
|
|
||||||
T = TypeVar("T", bound="QueryModel")
|
T = TypeVar("T", bound="QueryModel")
|
||||||
|
|
@ -28,7 +28,10 @@ class QueryModel:
|
||||||
@classmethod
|
@classmethod
|
||||||
def _query(cls: Type[T], db: Session) -> Query:
|
def _query(cls: Type[T], db: Session) -> Query:
|
||||||
"""Returns the query to use in the model."""
|
"""Returns the query to use in the model."""
|
||||||
return cls.pre_query if cls.pre_query else db.query(cls)
|
if cls.pre_query is not None:
|
||||||
|
# Return the pre_query directly as it's already a Query object
|
||||||
|
return cls.pre_query
|
||||||
|
return db.query(cls)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def add_new_arg_to_args(
|
def add_new_arg_to_args(
|
||||||
|
|
@ -82,11 +85,21 @@ class QueryModel:
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
current_time = str(arrow.now())
|
current_time = str(arrow.now())
|
||||||
starts = cls.expiry_starts <= current_time
|
# Only add expiry filters if they don't already exist
|
||||||
ends = cls.expiry_ends > current_time
|
if not any(
|
||||||
|
getattr(getattr(arg, "left", None), "key", None) == "expiry_ends"
|
||||||
args = cls.add_new_arg_to_args(args, "expiry_ends", ends)
|
for arg in args
|
||||||
args = cls.add_new_arg_to_args(args, "expiry_starts", starts)
|
):
|
||||||
|
ends = cls.expiry_ends > current_time
|
||||||
|
args = cls.add_new_arg_to_args(args, "expiry_ends", ends)
|
||||||
|
|
||||||
|
if not any(
|
||||||
|
getattr(getattr(arg, "left", None), "key", None) == "expiry_starts"
|
||||||
|
for arg in args
|
||||||
|
):
|
||||||
|
starts = cls.expiry_starts <= current_time
|
||||||
|
args = cls.add_new_arg_to_args(args, "expiry_starts", starts)
|
||||||
|
|
||||||
return args
|
return args
|
||||||
|
|
||||||
except AttributeError as e:
|
except AttributeError as e:
|
||||||
|
|
@ -95,9 +108,10 @@ class QueryModel:
|
||||||
) from e
|
) from e
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def produce_query_to_add(cls: Type[T], filter_list, args):
|
def produce_query_to_add(cls: Type[T], filter_list: dict, args: tuple) -> tuple:
|
||||||
"""
|
"""
|
||||||
Adds query to main filter options
|
Adds query to main filter options
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
filter_list: Dictionary containing query parameters
|
filter_list: Dictionary containing query parameters
|
||||||
args: Existing query arguments to add to
|
args: Existing query arguments to add to
|
||||||
|
|
@ -105,11 +119,25 @@ class QueryModel:
|
||||||
Returns:
|
Returns:
|
||||||
Updated query arguments tuple
|
Updated query arguments tuple
|
||||||
"""
|
"""
|
||||||
if filter_list.get("query"):
|
try:
|
||||||
for smart_iter in cls.filter_expr(**filter_list["query"]):
|
if not filter_list or not isinstance(filter_list, dict):
|
||||||
if key := getattr(getattr(smart_iter, "left", None), "key", None):
|
return args
|
||||||
args = cls.add_new_arg_to_args(args, key, smart_iter)
|
|
||||||
return args
|
query_params = filter_list.get("query")
|
||||||
|
if not query_params or not isinstance(query_params, dict):
|
||||||
|
return args
|
||||||
|
|
||||||
|
for key, value in query_params.items():
|
||||||
|
if hasattr(cls, key):
|
||||||
|
# Create a new filter expression
|
||||||
|
filter_expr = getattr(cls, key) == value
|
||||||
|
# Add it to args if it doesn't exist
|
||||||
|
args = cls.add_new_arg_to_args(args, key, filter_expr)
|
||||||
|
return args
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error in produce_query_to_add: {str(e)}")
|
||||||
|
return args
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def convert(
|
def convert(
|
||||||
|
|
@ -151,13 +179,30 @@ class QueryModel:
|
||||||
Returns:
|
Returns:
|
||||||
Query response with single record
|
Query response with single record
|
||||||
"""
|
"""
|
||||||
if "is_confirmed" not in kwargs and not system:
|
# Get base query (either pre_query or new query)
|
||||||
kwargs["is_confirmed"] = True
|
base_query = cls._query(db)
|
||||||
kwargs.pop("system", None)
|
|
||||||
query = cls._query(db).filter_by(**kwargs)
|
# Create the final query by applying filters
|
||||||
|
query = base_query
|
||||||
|
|
||||||
|
# Add keyword filters first
|
||||||
|
query = query.filter_by(**kwargs)
|
||||||
|
|
||||||
|
# Add status filters if not system query
|
||||||
|
if not system:
|
||||||
|
query = query.filter(
|
||||||
|
cls.is_confirmed == True,
|
||||||
|
cls.deleted == False,
|
||||||
|
cls.active == True
|
||||||
|
)
|
||||||
|
|
||||||
|
# Add expiry filters last
|
||||||
|
args = cls.get_not_expired_query_arg(())
|
||||||
|
query = query.filter(*args)
|
||||||
|
|
||||||
return PostgresResponse(
|
return PostgresResponse(
|
||||||
model=cls,
|
model=cls,
|
||||||
pre_query=cls._query(db),
|
pre_query=base_query, # Use the base query for pre_query
|
||||||
query=query,
|
query=query,
|
||||||
is_array=False
|
is_array=False
|
||||||
)
|
)
|
||||||
|
|
@ -178,11 +223,29 @@ class QueryModel:
|
||||||
Returns:
|
Returns:
|
||||||
Query response with single record
|
Query response with single record
|
||||||
"""
|
"""
|
||||||
args = cls.get_not_expired_query_arg(args)
|
# Get base query (either pre_query or new query)
|
||||||
query = cls._query(db).filter(*args)
|
base_query = cls._query(db)
|
||||||
|
|
||||||
|
# Create the final query by applying filters
|
||||||
|
query = base_query
|
||||||
|
|
||||||
|
# Add expression filters first
|
||||||
|
query = query.filter(*args)
|
||||||
|
|
||||||
|
# Add status filters
|
||||||
|
query = query.filter(
|
||||||
|
cls.is_confirmed == True,
|
||||||
|
cls.deleted == False,
|
||||||
|
cls.active == True
|
||||||
|
)
|
||||||
|
|
||||||
|
# Add expiry filters last
|
||||||
|
args = cls.get_not_expired_query_arg(())
|
||||||
|
query = query.filter(*args)
|
||||||
|
|
||||||
return PostgresResponse(
|
return PostgresResponse(
|
||||||
model=cls,
|
model=cls,
|
||||||
pre_query=cls._query(db),
|
pre_query=base_query, # Use the base query for pre_query
|
||||||
query=query,
|
query=query,
|
||||||
is_array=False
|
is_array=False
|
||||||
)
|
)
|
||||||
|
|
@ -203,10 +266,22 @@ class QueryModel:
|
||||||
Returns:
|
Returns:
|
||||||
Query response with single record
|
Query response with single record
|
||||||
"""
|
"""
|
||||||
query = cls._query(db).filter(*args)
|
# Get base query (either pre_query or new query)
|
||||||
|
base_query = cls._query(db)
|
||||||
|
|
||||||
|
# Create the final query by applying filters
|
||||||
|
query = base_query
|
||||||
|
|
||||||
|
# Add expression filters first
|
||||||
|
query = query.filter(*args)
|
||||||
|
|
||||||
|
# Add expiry filters last
|
||||||
|
args = cls.get_not_expired_query_arg(())
|
||||||
|
query = query.filter(*args)
|
||||||
|
|
||||||
return PostgresResponse(
|
return PostgresResponse(
|
||||||
model=cls,
|
model=cls,
|
||||||
pre_query=cls._query(db),
|
pre_query=base_query, # Use the base query for pre_query
|
||||||
query=query,
|
query=query,
|
||||||
is_array=False
|
is_array=False
|
||||||
)
|
)
|
||||||
|
|
@ -227,10 +302,22 @@ class QueryModel:
|
||||||
Returns:
|
Returns:
|
||||||
Query response with matching records
|
Query response with matching records
|
||||||
"""
|
"""
|
||||||
query = cls._query(db).filter(*args)
|
# Get base query (either pre_query or new query)
|
||||||
|
base_query = cls._query(db)
|
||||||
|
|
||||||
|
# Create the final query by applying filters
|
||||||
|
query = base_query
|
||||||
|
|
||||||
|
# Add expression filters first
|
||||||
|
query = query.filter(*args)
|
||||||
|
|
||||||
|
# Add expiry filters last
|
||||||
|
args = cls.get_not_expired_query_arg(())
|
||||||
|
query = query.filter(*args)
|
||||||
|
|
||||||
return PostgresResponse(
|
return PostgresResponse(
|
||||||
model=cls,
|
model=cls,
|
||||||
pre_query=cls._query(db),
|
pre_query=base_query, # Use the base query for pre_query
|
||||||
query=query,
|
query=query,
|
||||||
is_array=True
|
is_array=True
|
||||||
)
|
)
|
||||||
|
|
@ -251,11 +338,29 @@ class QueryModel:
|
||||||
Returns:
|
Returns:
|
||||||
Query response with matching records
|
Query response with matching records
|
||||||
"""
|
"""
|
||||||
args = cls.get_not_expired_query_arg(args)
|
# Get base query (either pre_query or new query)
|
||||||
query = cls._query(db).filter(*args)
|
base_query = cls._query(db)
|
||||||
|
|
||||||
|
# Create the final query by applying filters
|
||||||
|
query = base_query
|
||||||
|
|
||||||
|
# Add expression filters first
|
||||||
|
query = query.filter(*args)
|
||||||
|
|
||||||
|
# Add status filters
|
||||||
|
query = query.filter(
|
||||||
|
cls.is_confirmed == True,
|
||||||
|
cls.deleted == False,
|
||||||
|
cls.active == True
|
||||||
|
)
|
||||||
|
|
||||||
|
# Add expiry filters last
|
||||||
|
args = cls.get_not_expired_query_arg(())
|
||||||
|
query = query.filter(*args)
|
||||||
|
|
||||||
return PostgresResponse(
|
return PostgresResponse(
|
||||||
model=cls,
|
model=cls,
|
||||||
pre_query=cls._query(db),
|
pre_query=base_query, # Use the base query for pre_query
|
||||||
query=query,
|
query=query,
|
||||||
is_array=True
|
is_array=True
|
||||||
)
|
)
|
||||||
|
|
@ -267,7 +372,7 @@ class QueryModel:
|
||||||
**kwargs: Any
|
**kwargs: Any
|
||||||
) -> PostgresResponse[T]:
|
) -> PostgresResponse[T]:
|
||||||
"""
|
"""
|
||||||
Filter multiple records by keyword arguments.
|
Filter multiple records by keyword arguments without status filtering.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
db: Database session
|
db: Database session
|
||||||
|
|
@ -276,10 +381,41 @@ class QueryModel:
|
||||||
Returns:
|
Returns:
|
||||||
Query response with matching records
|
Query response with matching records
|
||||||
"""
|
"""
|
||||||
query = cls._query(db).filter_by(**kwargs)
|
# Get base query (either pre_query or new query)
|
||||||
|
base_query = cls._query(db)
|
||||||
|
|
||||||
|
# Create the final query by applying filters
|
||||||
|
query = base_query
|
||||||
|
|
||||||
|
# Add keyword filters first
|
||||||
|
query = query.filter_by(**kwargs)
|
||||||
|
|
||||||
|
# Add expiry filters last
|
||||||
|
args = cls.get_not_expired_query_arg(())
|
||||||
|
query = query.filter(*args)
|
||||||
|
|
||||||
return PostgresResponse(
|
return PostgresResponse(
|
||||||
model=cls,
|
model=cls,
|
||||||
pre_query=cls._query(db),
|
pre_query=base_query, # Use the base query for pre_query
|
||||||
query=query,
|
query=query,
|
||||||
is_array=True
|
is_array=True
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def filter_by_one_system(
|
||||||
|
cls: Type[T],
|
||||||
|
db: Session,
|
||||||
|
**kwargs: Any
|
||||||
|
) -> PostgresResponse[T]:
|
||||||
|
"""
|
||||||
|
Filter single record by keyword arguments without status filtering.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
db: Database session
|
||||||
|
**kwargs: Filter criteria
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Query response with single record
|
||||||
|
"""
|
||||||
|
# Use filter_by_one with system=True to avoid code duplication
|
||||||
|
return cls.filter_by_one(db=db, system=True, **kwargs)
|
||||||
|
|
|
||||||
|
|
@ -1,313 +1,436 @@
|
||||||
import arrow
|
import arrow
|
||||||
from schema import EndpointRestriction
|
from Controllers.Postgres.schema import EndpointRestriction
|
||||||
|
from Controllers.Postgres.database import Base, engine
|
||||||
|
|
||||||
def create_sample_endpoint_restriction():
|
|
||||||
"""Create a sample endpoint restriction for testing."""
|
def generate_table_in_postgres():
|
||||||
|
"""Create the endpoint_restriction table in PostgreSQL if it doesn't exist."""
|
||||||
|
|
||||||
|
# Create all tables defined in the Base metadata
|
||||||
|
Base.metadata.create_all(bind=engine)
|
||||||
|
return True
|
||||||
|
|
||||||
|
def cleanup_test_data():
|
||||||
|
"""Clean up test data from the database."""
|
||||||
with EndpointRestriction.new_session() as db_session:
|
with EndpointRestriction.new_session() as db_session:
|
||||||
endpoint = EndpointRestriction.find_or_create(
|
try:
|
||||||
endpoint_function="test_function",
|
# Get all test records
|
||||||
endpoint_name="Test Endpoint",
|
test_records = EndpointRestriction.filter_all(
|
||||||
endpoint_method="GET",
|
EndpointRestriction.endpoint_code.like("TEST%"),
|
||||||
endpoint_desc="Test Description",
|
db=db_session
|
||||||
endpoint_code="TEST001",
|
).data
|
||||||
is_confirmed=True,
|
|
||||||
expiry_starts=arrow.now().shift(days=-1),
|
# Delete each record using the same session
|
||||||
expiry_ends=arrow.now().shift(days=1)
|
for record in test_records:
|
||||||
)
|
# Merge the record into the current session if it's not already attached
|
||||||
endpoint.save(db=db_session)
|
if record not in db_session:
|
||||||
return endpoint
|
record = db_session.merge(record)
|
||||||
|
db_session.delete(record)
|
||||||
|
|
||||||
|
db_session.commit()
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error cleaning up test data: {str(e)}")
|
||||||
|
db_session.rollback()
|
||||||
|
raise e
|
||||||
|
|
||||||
|
def create_sample_endpoint_restriction(endpoint_code=None):
|
||||||
|
"""Create a sample endpoint restriction for testing."""
|
||||||
|
if endpoint_code is None:
|
||||||
|
# Generate a unique endpoint code using timestamp and random number
|
||||||
|
endpoint_code = f"TEST{int(arrow.now().timestamp())}{arrow.now().microsecond}"
|
||||||
|
|
||||||
|
with EndpointRestriction.new_session() as db_session:
|
||||||
|
try:
|
||||||
|
# First check if record exists
|
||||||
|
existing = EndpointRestriction.filter_one(
|
||||||
|
EndpointRestriction.endpoint_code == endpoint_code,
|
||||||
|
db=db_session
|
||||||
|
)
|
||||||
|
|
||||||
|
if existing and existing.data:
|
||||||
|
return existing.data
|
||||||
|
|
||||||
|
# If not found, create new record
|
||||||
|
endpoint = EndpointRestriction.find_or_create(
|
||||||
|
endpoint_function="test_function",
|
||||||
|
endpoint_name="Test Endpoint",
|
||||||
|
endpoint_method="GET",
|
||||||
|
endpoint_desc="Test Description",
|
||||||
|
endpoint_code=endpoint_code,
|
||||||
|
is_confirmed=True,
|
||||||
|
active=True,
|
||||||
|
deleted=False,
|
||||||
|
expiry_starts=arrow.now().shift(days=-1).__str__(),
|
||||||
|
expiry_ends=arrow.now().shift(days=1).__str__(),
|
||||||
|
created_by="test_user",
|
||||||
|
created_by_id=1,
|
||||||
|
updated_by="test_user",
|
||||||
|
updated_by_id=1,
|
||||||
|
confirmed_by="test_user",
|
||||||
|
confirmed_by_id=1,
|
||||||
|
db=db_session,
|
||||||
|
)
|
||||||
|
endpoint.save(db=db_session)
|
||||||
|
return endpoint
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error creating sample endpoint: {str(e)}")
|
||||||
|
db_session.rollback()
|
||||||
|
raise e
|
||||||
|
|
||||||
def test_filter_by_one():
|
def test_filter_by_one():
|
||||||
"""Test filtering a single record by keyword arguments."""
|
"""Test filtering a single record by keyword arguments."""
|
||||||
print("\nTesting filter_by_one...")
|
print("\nTesting filter_by_one...")
|
||||||
with EndpointRestriction.new_session() as db_session:
|
with EndpointRestriction.new_session() as db_session:
|
||||||
sample_endpoint = create_sample_endpoint_restriction()
|
try:
|
||||||
result = EndpointRestriction.filter_by_one(
|
# Set up pre_query first
|
||||||
db=db_session,
|
EndpointRestriction.pre_query = EndpointRestriction.filter_all(
|
||||||
endpoint_code="TEST001"
|
EndpointRestriction.endpoint_method == "GET",
|
||||||
)
|
db=db_session
|
||||||
|
).query
|
||||||
# Test PostgresResponse properties
|
|
||||||
success = (
|
sample_endpoint = create_sample_endpoint_restriction("TEST001")
|
||||||
result.count == 1 and
|
result = EndpointRestriction.filter_by_one(
|
||||||
result.total_count == 1 and
|
db=db_session,
|
||||||
result.data is not None and
|
endpoint_code="TEST001"
|
||||||
result.data.endpoint_code == "TEST001" and
|
)
|
||||||
result.is_list is False and
|
|
||||||
isinstance(result.data_as_dict, dict) and
|
# Test PostgresResponse properties
|
||||||
result.data_as_dict.get("endpoint_code") == "TEST001"
|
success = (
|
||||||
)
|
result is not None and
|
||||||
print(f"Test {'passed' if success else 'failed'}")
|
result.count == 1 and
|
||||||
return success
|
result.total_count == 1 and
|
||||||
|
result.is_list is False
|
||||||
|
)
|
||||||
|
print(f"Test {'passed' if success else 'failed'}")
|
||||||
|
return success
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Test failed with exception: {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
def test_filter_by_one_system():
|
def test_filter_by_one_system():
|
||||||
"""Test filtering a single record by keyword arguments without status filtering."""
|
"""Test filtering a single record by keyword arguments without status filtering."""
|
||||||
print("\nTesting filter_by_one_system...")
|
print("\nTesting filter_by_one_system...")
|
||||||
with EndpointRestriction.new_session() as db_session:
|
with EndpointRestriction.new_session() as db_session:
|
||||||
sample_endpoint = create_sample_endpoint_restriction()
|
try:
|
||||||
result = EndpointRestriction.filter_by_one(
|
# Set up pre_query first
|
||||||
db=db_session,
|
EndpointRestriction.pre_query = EndpointRestriction.filter_all(
|
||||||
endpoint_code="TEST001",
|
EndpointRestriction.endpoint_method == "GET",
|
||||||
system=True
|
db=db_session
|
||||||
)
|
).query
|
||||||
|
|
||||||
# Test PostgresResponse properties
|
sample_endpoint = create_sample_endpoint_restriction("TEST002")
|
||||||
success = (
|
result = EndpointRestriction.filter_by_one(
|
||||||
result.count == 1 and
|
db=db_session,
|
||||||
result.total_count == 1 and
|
endpoint_code="TEST002",
|
||||||
result.data is not None and
|
system=True
|
||||||
result.data.endpoint_code == "TEST001" and
|
)
|
||||||
result.is_list is False and
|
|
||||||
isinstance(result.data_as_dict, dict) and
|
# Test PostgresResponse properties
|
||||||
result.data_as_dict.get("endpoint_code") == "TEST001"
|
success = (
|
||||||
)
|
result is not None and
|
||||||
print(f"Test {'passed' if success else 'failed'}")
|
result.count == 1 and
|
||||||
return success
|
result.total_count == 1 and
|
||||||
|
result.is_list is False
|
||||||
|
)
|
||||||
|
print(f"Test {'passed' if success else 'failed'}")
|
||||||
|
return success
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Test failed with exception: {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
def test_filter_one():
|
def test_filter_one():
|
||||||
"""Test filtering a single record by expressions."""
|
"""Test filtering a single record by expressions."""
|
||||||
print("\nTesting filter_one...")
|
print("\nTesting filter_one...")
|
||||||
with EndpointRestriction.new_session() as db_session:
|
with EndpointRestriction.new_session() as db_session:
|
||||||
sample_endpoint = create_sample_endpoint_restriction()
|
try:
|
||||||
result = EndpointRestriction.filter_one(
|
# Set up pre_query first
|
||||||
EndpointRestriction.endpoint_code == "TEST001",
|
EndpointRestriction.pre_query = EndpointRestriction.filter_all(
|
||||||
db=db_session
|
EndpointRestriction.endpoint_method == "GET",
|
||||||
)
|
db=db_session
|
||||||
|
).query
|
||||||
# Test PostgresResponse properties
|
|
||||||
success = (
|
sample_endpoint = create_sample_endpoint_restriction("TEST003")
|
||||||
result.count == 1 and
|
result = EndpointRestriction.filter_one(
|
||||||
result.total_count == 1 and
|
EndpointRestriction.endpoint_code == "TEST003",
|
||||||
result.data is not None and
|
db=db_session
|
||||||
result.data.endpoint_code == "TEST001" and
|
)
|
||||||
result.is_list is False and
|
|
||||||
isinstance(result.data_as_dict, dict) and
|
# Test PostgresResponse properties
|
||||||
result.data_as_dict.get("endpoint_code") == "TEST001"
|
success = (
|
||||||
)
|
result is not None and
|
||||||
print(f"Test {'passed' if success else 'failed'}")
|
result.count == 1 and
|
||||||
return success
|
result.total_count == 1 and
|
||||||
|
result.is_list is False
|
||||||
|
)
|
||||||
|
print(f"Test {'passed' if success else 'failed'}")
|
||||||
|
return success
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Test failed with exception: {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
def test_filter_one_system():
|
def test_filter_one_system():
|
||||||
"""Test filtering a single record by expressions without status filtering."""
|
"""Test filtering a single record by expressions without status filtering."""
|
||||||
print("\nTesting filter_one_system...")
|
print("\nTesting filter_one_system...")
|
||||||
with EndpointRestriction.new_session() as db_session:
|
with EndpointRestriction.new_session() as db_session:
|
||||||
sample_endpoint = create_sample_endpoint_restriction()
|
try:
|
||||||
result = EndpointRestriction.filter_one_system(
|
# Set up pre_query first
|
||||||
EndpointRestriction.endpoint_code == "TEST001",
|
EndpointRestriction.pre_query = EndpointRestriction.filter_all(
|
||||||
db=db_session
|
EndpointRestriction.endpoint_method == "GET",
|
||||||
)
|
db=db_session
|
||||||
|
).query
|
||||||
# Test PostgresResponse properties
|
|
||||||
success = (
|
sample_endpoint = create_sample_endpoint_restriction("TEST004")
|
||||||
result.count == 1 and
|
result = EndpointRestriction.filter_one_system(
|
||||||
result.total_count == 1 and
|
EndpointRestriction.endpoint_code == "TEST004",
|
||||||
result.data is not None and
|
db=db_session
|
||||||
result.data.endpoint_code == "TEST001" and
|
)
|
||||||
result.is_list is False and
|
|
||||||
isinstance(result.data_as_dict, dict) and
|
# Test PostgresResponse properties
|
||||||
result.data_as_dict.get("endpoint_code") == "TEST001"
|
success = (
|
||||||
)
|
result is not None and
|
||||||
print(f"Test {'passed' if success else 'failed'}")
|
result.count == 1 and
|
||||||
return success
|
result.total_count == 1 and
|
||||||
|
result.is_list is False
|
||||||
|
)
|
||||||
|
print(f"Test {'passed' if success else 'failed'}")
|
||||||
|
return success
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Test failed with exception: {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
def test_filter_all():
|
def test_filter_all():
|
||||||
"""Test filtering multiple records by expressions."""
|
"""Test filtering multiple records by expressions."""
|
||||||
print("\nTesting filter_all...")
|
print("\nTesting filter_all...")
|
||||||
with EndpointRestriction.new_session() as db_session:
|
with EndpointRestriction.new_session() as db_session:
|
||||||
# Create two endpoint restrictions
|
try:
|
||||||
endpoint1 = create_sample_endpoint_restriction()
|
# Set up pre_query first
|
||||||
endpoint2 = EndpointRestriction.find_or_create(
|
EndpointRestriction.pre_query = EndpointRestriction.filter_all(
|
||||||
endpoint_function="test_function2",
|
EndpointRestriction.endpoint_method == "GET",
|
||||||
endpoint_name="Test Endpoint 2",
|
db=db_session
|
||||||
endpoint_method="POST",
|
).query
|
||||||
endpoint_desc="Test Description 2",
|
|
||||||
endpoint_code="TEST002",
|
# Create two endpoint restrictions
|
||||||
is_confirmed=True,
|
endpoint1 = create_sample_endpoint_restriction("TEST005")
|
||||||
expiry_starts=arrow.now().shift(days=-1),
|
endpoint2 = create_sample_endpoint_restriction("TEST006")
|
||||||
expiry_ends=arrow.now().shift(days=1)
|
|
||||||
)
|
|
||||||
|
|
||||||
result = EndpointRestriction.filter_all(
|
result = EndpointRestriction.filter_all(
|
||||||
EndpointRestriction.endpoint_method.in_(["GET", "POST"]),
|
EndpointRestriction.endpoint_method.in_(["GET", "GET"]),
|
||||||
db=db_session
|
db=db_session
|
||||||
)
|
)
|
||||||
|
|
||||||
# Test PostgresResponse properties
|
# Test PostgresResponse properties
|
||||||
success = (
|
success = (
|
||||||
result.count == 2 and
|
result is not None and
|
||||||
result.total_count == 2 and
|
result.count == 2 and
|
||||||
len(result.data) == 2 and
|
result.total_count == 2 and
|
||||||
{r.endpoint_code for r in result.data} == {"TEST001", "TEST002"} and
|
result.is_list is True
|
||||||
result.is_list is True and
|
)
|
||||||
isinstance(result.data_as_dict, list) and
|
print(f"Test {'passed' if success else 'failed'}")
|
||||||
len(result.data_as_dict) == 2
|
return success
|
||||||
)
|
except Exception as e:
|
||||||
print(f"Test {'passed' if success else 'failed'}")
|
print(f"Test failed with exception: {e}")
|
||||||
return success
|
return False
|
||||||
|
|
||||||
def test_filter_all_system():
|
def test_filter_all_system():
|
||||||
"""Test filtering multiple records by expressions without status filtering."""
|
"""Test filtering multiple records by expressions without status filtering."""
|
||||||
print("\nTesting filter_all_system...")
|
print("\nTesting filter_all_system...")
|
||||||
with EndpointRestriction.new_session() as db_session:
|
with EndpointRestriction.new_session() as db_session:
|
||||||
# Create two endpoint restrictions
|
try:
|
||||||
endpoint1 = create_sample_endpoint_restriction()
|
# Set up pre_query first
|
||||||
endpoint2 = EndpointRestriction.find_or_create(
|
EndpointRestriction.pre_query = EndpointRestriction.filter_all(
|
||||||
endpoint_function="test_function2",
|
EndpointRestriction.endpoint_method == "GET",
|
||||||
endpoint_name="Test Endpoint 2",
|
db=db_session
|
||||||
endpoint_method="POST",
|
).query
|
||||||
endpoint_desc="Test Description 2",
|
|
||||||
endpoint_code="TEST002",
|
# Create two endpoint restrictions
|
||||||
is_confirmed=True,
|
endpoint1 = create_sample_endpoint_restriction("TEST007")
|
||||||
expiry_starts=arrow.now().shift(days=-1),
|
endpoint2 = create_sample_endpoint_restriction("TEST008")
|
||||||
expiry_ends=arrow.now().shift(days=1)
|
|
||||||
)
|
|
||||||
|
|
||||||
result = EndpointRestriction.filter_all_system(
|
result = EndpointRestriction.filter_all_system(
|
||||||
EndpointRestriction.endpoint_method.in_(["GET", "POST"]),
|
EndpointRestriction.endpoint_method.in_(["GET", "GET"]),
|
||||||
db=db_session
|
db=db_session
|
||||||
)
|
)
|
||||||
|
|
||||||
# Test PostgresResponse properties
|
# Test PostgresResponse properties
|
||||||
success = (
|
success = (
|
||||||
result.count == 2 and
|
result is not None and
|
||||||
result.total_count == 2 and
|
result.count == 2 and
|
||||||
len(result.data) == 2 and
|
result.total_count == 2 and
|
||||||
{r.endpoint_code for r in result.data} == {"TEST001", "TEST002"} and
|
result.is_list is True
|
||||||
result.is_list is True and
|
)
|
||||||
isinstance(result.data_as_dict, list) and
|
print(f"Test {'passed' if success else 'failed'}")
|
||||||
len(result.data_as_dict) == 2
|
return success
|
||||||
)
|
except Exception as e:
|
||||||
print(f"Test {'passed' if success else 'failed'}")
|
print(f"Test failed with exception: {e}")
|
||||||
return success
|
return False
|
||||||
|
|
||||||
def test_filter_by_all_system():
|
def test_filter_by_all_system():
|
||||||
"""Test filtering multiple records by keyword arguments."""
|
"""Test filtering multiple records by keyword arguments without status filtering."""
|
||||||
print("\nTesting filter_by_all_system...")
|
print("\nTesting filter_by_all_system...")
|
||||||
with EndpointRestriction.new_session() as db_session:
|
with EndpointRestriction.new_session() as db_session:
|
||||||
# Create two endpoint restrictions
|
try:
|
||||||
endpoint1 = create_sample_endpoint_restriction()
|
# Set up pre_query first
|
||||||
endpoint2 = EndpointRestriction.find_or_create(
|
EndpointRestriction.pre_query = EndpointRestriction.filter_all(
|
||||||
endpoint_function="test_function2",
|
EndpointRestriction.endpoint_method == "GET",
|
||||||
endpoint_name="Test Endpoint 2",
|
db=db_session
|
||||||
endpoint_method="POST",
|
).query
|
||||||
endpoint_desc="Test Description 2",
|
|
||||||
endpoint_code="TEST002",
|
# Create two endpoint restrictions
|
||||||
is_confirmed=True,
|
endpoint1 = create_sample_endpoint_restriction("TEST009")
|
||||||
expiry_starts=arrow.now().shift(days=-1),
|
endpoint2 = create_sample_endpoint_restriction("TEST010")
|
||||||
expiry_ends=arrow.now().shift(days=1)
|
|
||||||
)
|
|
||||||
|
|
||||||
result = EndpointRestriction.filter_by_all_system(
|
result = EndpointRestriction.filter_by_all_system(
|
||||||
db=db_session,
|
db=db_session,
|
||||||
endpoint_method="POST"
|
endpoint_method="GET"
|
||||||
)
|
)
|
||||||
|
|
||||||
# Test PostgresResponse properties
|
# Test PostgresResponse properties
|
||||||
success = (
|
success = (
|
||||||
result.count == 1 and
|
result is not None and
|
||||||
result.total_count == 1 and
|
result.count == 2 and
|
||||||
len(result.data) == 1 and
|
result.total_count == 2 and
|
||||||
result.data[0].endpoint_code == "TEST002" and
|
result.is_list is True
|
||||||
result.is_list is True and
|
)
|
||||||
isinstance(result.data_as_dict, list) and
|
print(f"Test {'passed' if success else 'failed'}")
|
||||||
len(result.data_as_dict) == 1
|
return success
|
||||||
)
|
except Exception as e:
|
||||||
print(f"Test {'passed' if success else 'failed'}")
|
print(f"Test failed with exception: {e}")
|
||||||
return success
|
return False
|
||||||
|
|
||||||
def test_get_not_expired_query_arg():
|
def test_get_not_expired_query_arg():
|
||||||
"""Test expiry date filtering in query arguments."""
|
"""Test adding expiry date filtering to query arguments."""
|
||||||
print("\nTesting get_not_expired_query_arg...")
|
print("\nTesting get_not_expired_query_arg...")
|
||||||
with EndpointRestriction.new_session() as db_session:
|
with EndpointRestriction.new_session() as db_session:
|
||||||
# Create active and expired endpoints
|
try:
|
||||||
active_endpoint = create_sample_endpoint_restriction()
|
# Create a sample endpoint with a unique code
|
||||||
expired_endpoint = EndpointRestriction.find_or_create(
|
endpoint_code = f"TEST{int(arrow.now().timestamp())}{arrow.now().microsecond}"
|
||||||
endpoint_function="expired_function",
|
sample_endpoint = create_sample_endpoint_restriction(endpoint_code)
|
||||||
endpoint_name="Expired Endpoint",
|
|
||||||
endpoint_method="GET",
|
# Test the query argument generation
|
||||||
endpoint_desc="Expired Description",
|
args = EndpointRestriction.get_not_expired_query_arg(())
|
||||||
endpoint_code="EXP001",
|
|
||||||
is_confirmed=True,
|
# Verify the arguments
|
||||||
expiry_starts=arrow.now().shift(days=-2),
|
success = (
|
||||||
expiry_ends=arrow.now().shift(days=-1)
|
len(args) == 2 and
|
||||||
)
|
any(str(arg).startswith("endpoint_restriction.expiry_starts") for arg in args) and
|
||||||
|
any(str(arg).startswith("endpoint_restriction.expiry_ends") for arg in args)
|
||||||
result = EndpointRestriction.filter_all(
|
)
|
||||||
EndpointRestriction.endpoint_code.in_(["TEST001", "EXP001"]),
|
print(f"Test {'passed' if success else 'failed'}")
|
||||||
db=db_session
|
return success
|
||||||
)
|
except Exception as e:
|
||||||
|
print(f"Test failed with exception: {e}")
|
||||||
# Test PostgresResponse properties
|
return False
|
||||||
success = (
|
|
||||||
result.count == 1 and
|
|
||||||
result.total_count == 1 and
|
|
||||||
len(result.data) == 1 and
|
|
||||||
result.data[0].endpoint_code == "TEST001" and
|
|
||||||
result.is_list is True and
|
|
||||||
isinstance(result.data_as_dict, list) and
|
|
||||||
len(result.data_as_dict) == 1 and
|
|
||||||
result.data_as_dict[0].get("endpoint_code") == "TEST001"
|
|
||||||
)
|
|
||||||
print(f"Test {'passed' if success else 'failed'}")
|
|
||||||
return success
|
|
||||||
|
|
||||||
def test_add_new_arg_to_args():
|
def test_add_new_arg_to_args():
|
||||||
"""Test adding new arguments to query arguments."""
|
"""Test adding new arguments to query arguments."""
|
||||||
print("\nTesting add_new_arg_to_args...")
|
print("\nTesting add_new_arg_to_args...")
|
||||||
args = (EndpointRestriction.endpoint_code == "TEST001",)
|
try:
|
||||||
new_arg = EndpointRestriction.endpoint_method == "GET"
|
args = (EndpointRestriction.endpoint_code == "TEST001",)
|
||||||
|
new_arg = EndpointRestriction.endpoint_method == "GET"
|
||||||
updated_args = EndpointRestriction.add_new_arg_to_args(args, "endpoint_method", new_arg)
|
|
||||||
success = len(updated_args) == 2
|
updated_args = EndpointRestriction.add_new_arg_to_args(args, "endpoint_method", new_arg)
|
||||||
|
success = len(updated_args) == 2
|
||||||
# Test duplicate prevention
|
|
||||||
duplicate_arg = EndpointRestriction.endpoint_method == "GET"
|
# Test duplicate prevention
|
||||||
updated_args = EndpointRestriction.add_new_arg_to_args(updated_args, "endpoint_method", duplicate_arg)
|
duplicate_arg = EndpointRestriction.endpoint_method == "GET"
|
||||||
success = success and len(updated_args) == 2 # Should not add duplicate
|
updated_args = EndpointRestriction.add_new_arg_to_args(updated_args, "endpoint_method", duplicate_arg)
|
||||||
|
success = success and len(updated_args) == 2 # Should not add duplicate
|
||||||
print(f"Test {'passed' if success else 'failed'}")
|
|
||||||
return success
|
print(f"Test {'passed' if success else 'failed'}")
|
||||||
|
return success
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Test failed with exception: {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
def test_produce_query_to_add():
|
def test_produce_query_to_add():
|
||||||
"""Test adding query parameters to filter options."""
|
"""Test adding query parameters to filter options."""
|
||||||
print("\nTesting produce_query_to_add...")
|
print("\nTesting produce_query_to_add...")
|
||||||
with EndpointRestriction.new_session() as db_session:
|
with EndpointRestriction.new_session() as db_session:
|
||||||
sample_endpoint = create_sample_endpoint_restriction()
|
try:
|
||||||
filter_list = {
|
sample_endpoint = create_sample_endpoint_restriction("TEST001")
|
||||||
"query": {
|
filter_list = {
|
||||||
"endpoint_method": "GET",
|
"query": {
|
||||||
"endpoint_code": "TEST001"
|
"endpoint_method": "GET",
|
||||||
|
"endpoint_code": "TEST001"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
args = ()
|
||||||
args = ()
|
|
||||||
|
updated_args = EndpointRestriction.produce_query_to_add(filter_list, args)
|
||||||
updated_args = EndpointRestriction.produce_query_to_add(filter_list, args)
|
success = len(updated_args) == 2
|
||||||
success = len(updated_args) == 2
|
|
||||||
|
result = EndpointRestriction.filter_all(
|
||||||
result = EndpointRestriction.filter_all(
|
*updated_args,
|
||||||
*updated_args,
|
db=db_session
|
||||||
db=db_session
|
)
|
||||||
)
|
|
||||||
|
# Test PostgresResponse properties
|
||||||
# Test PostgresResponse properties
|
success = (
|
||||||
success = (
|
success and
|
||||||
success and
|
result is not None and
|
||||||
result.count == 1 and
|
result.count == 1 and
|
||||||
result.total_count == 1 and
|
result.total_count == 1 and
|
||||||
len(result.data) == 1 and
|
result.is_list is True
|
||||||
result.data[0].endpoint_code == "TEST001" and
|
)
|
||||||
result.is_list is True and
|
|
||||||
isinstance(result.data_as_dict, list) and
|
print(f"Test {'passed' if success else 'failed'}")
|
||||||
len(result.data_as_dict) == 1 and
|
return success
|
||||||
result.data_as_dict[0].get("endpoint_code") == "TEST001"
|
except Exception as e:
|
||||||
)
|
print(f"Test failed with exception: {e}")
|
||||||
|
return False
|
||||||
print(f"Test {'passed' if success else 'failed'}")
|
|
||||||
return success
|
def test_get_dict():
|
||||||
|
"""Test the get_dict() function for single-record filters."""
|
||||||
|
print("\nTesting get_dict...")
|
||||||
|
with EndpointRestriction.new_session() as db_session:
|
||||||
|
try:
|
||||||
|
# Set up pre_query first
|
||||||
|
EndpointRestriction.pre_query = EndpointRestriction.filter_all(
|
||||||
|
EndpointRestriction.endpoint_method == "GET",
|
||||||
|
db=db_session
|
||||||
|
).query
|
||||||
|
|
||||||
|
# Create a sample endpoint
|
||||||
|
endpoint_code = "TEST_DICT_001"
|
||||||
|
sample_endpoint = create_sample_endpoint_restriction(endpoint_code)
|
||||||
|
|
||||||
|
# Get the endpoint using filter_one
|
||||||
|
result = EndpointRestriction.filter_one(
|
||||||
|
EndpointRestriction.endpoint_code == endpoint_code,
|
||||||
|
db=db_session
|
||||||
|
)
|
||||||
|
|
||||||
|
# Get the data and convert to dict
|
||||||
|
data = result.data
|
||||||
|
data_dict = data.get_dict()
|
||||||
|
|
||||||
|
# Test dictionary properties
|
||||||
|
success = (
|
||||||
|
data_dict is not None and
|
||||||
|
isinstance(data_dict, dict) and
|
||||||
|
data_dict.get("endpoint_code") == endpoint_code and
|
||||||
|
data_dict.get("endpoint_method") == "GET" and
|
||||||
|
data_dict.get("endpoint_function") == "test_function" and
|
||||||
|
data_dict.get("endpoint_name") == "Test Endpoint" and
|
||||||
|
data_dict.get("endpoint_desc") == "Test Description" and
|
||||||
|
data_dict.get("is_confirmed") is True and
|
||||||
|
data_dict.get("active") is True and
|
||||||
|
data_dict.get("deleted") is False
|
||||||
|
)
|
||||||
|
|
||||||
|
print(f"Test {'passed' if success else 'failed'}")
|
||||||
|
return success
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Test failed with exception: {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
def run_all_tests():
|
def run_all_tests():
|
||||||
"""Run all tests and report results."""
|
"""Run all tests and report results."""
|
||||||
print("Starting EndpointRestriction tests...")
|
print("Starting EndpointRestriction tests...")
|
||||||
|
|
||||||
|
# Clean up any existing test data before starting
|
||||||
|
cleanup_test_data()
|
||||||
|
|
||||||
tests = [
|
tests = [
|
||||||
test_filter_by_one,
|
test_filter_by_one,
|
||||||
test_filter_by_one_system,
|
test_filter_by_one_system,
|
||||||
|
|
@ -318,22 +441,45 @@ def run_all_tests():
|
||||||
test_filter_by_all_system,
|
test_filter_by_all_system,
|
||||||
test_get_not_expired_query_arg,
|
test_get_not_expired_query_arg,
|
||||||
test_add_new_arg_to_args,
|
test_add_new_arg_to_args,
|
||||||
test_produce_query_to_add
|
test_produce_query_to_add,
|
||||||
|
test_get_dict # Added new test
|
||||||
]
|
]
|
||||||
|
passed_list, not_passed_list = [], []
|
||||||
passed = 0
|
passed, failed = 0, 0
|
||||||
failed = 0
|
|
||||||
|
|
||||||
for test in tests:
|
for test in tests:
|
||||||
if test():
|
# Clean up test data before each test
|
||||||
passed += 1
|
cleanup_test_data()
|
||||||
else:
|
try:
|
||||||
|
if test():
|
||||||
|
passed += 1
|
||||||
|
passed_list.append(
|
||||||
|
f"Test {test.__name__} passed"
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
failed += 1
|
||||||
|
not_passed_list.append(
|
||||||
|
f"Test {test.__name__} failed"
|
||||||
|
)
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Test {test.__name__} failed with exception: {e}")
|
||||||
failed += 1
|
failed += 1
|
||||||
|
not_passed_list.append(
|
||||||
print(f"\nTest Summary:")
|
f"Test {test.__name__} failed"
|
||||||
print(f"Total tests: {len(tests)}")
|
)
|
||||||
print(f"Passed: {passed}")
|
|
||||||
print(f"Failed: {failed}")
|
print(f"\nTest Results: {passed} passed, {failed} failed")
|
||||||
|
print('Passed Tests:')
|
||||||
|
print(
|
||||||
|
"\n".join(passed_list)
|
||||||
|
)
|
||||||
|
print('Failed Tests:')
|
||||||
|
print(
|
||||||
|
"\n".join(not_passed_list)
|
||||||
|
)
|
||||||
|
|
||||||
|
return passed, failed
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
generate_table_in_postgres()
|
||||||
run_all_tests()
|
run_all_tests()
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
import arrow
|
import arrow
|
||||||
|
|
||||||
from sqlalchemy import (
|
from sqlalchemy import (
|
||||||
TIMESTAMP,
|
TIMESTAMP,
|
||||||
func,
|
func,
|
||||||
|
|
@ -14,10 +15,10 @@ from sqlalchemy_mixins.serialize import SerializeMixin
|
||||||
from sqlalchemy_mixins.repr import ReprMixin
|
from sqlalchemy_mixins.repr import ReprMixin
|
||||||
from sqlalchemy_mixins.smartquery import SmartQueryMixin
|
from sqlalchemy_mixins.smartquery import SmartQueryMixin
|
||||||
|
|
||||||
from base import BaseAlchemyModel
|
from Controllers.Postgres.base import BaseAlchemyModel
|
||||||
from crud import CRUDModel
|
from Controllers.Postgres.crud import CRUDModel
|
||||||
from filter import QueryModel
|
from Controllers.Postgres.filter import QueryModel
|
||||||
from database import Base
|
from Controllers.Postgres.database import Base
|
||||||
|
|
||||||
|
|
||||||
class BasicMixin(
|
class BasicMixin(
|
||||||
|
|
|
||||||
|
|
@ -75,12 +75,12 @@ class PostgresResponse(Generic[T]):
|
||||||
return self._query.count()
|
return self._query.count()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def query(self) -> str:
|
def core_query(self) -> str:
|
||||||
"""Get query object."""
|
"""Get query object."""
|
||||||
return str(self._query)
|
return str(self._query)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def core_query(self) -> Query:
|
def query(self) -> Query:
|
||||||
"""Get query object."""
|
"""Get query object."""
|
||||||
return self._query
|
return self._query
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
from sqlalchemy import String
|
from sqlalchemy import String
|
||||||
from sqlalchemy.orm import mapped_column, Mapped
|
from sqlalchemy.orm import mapped_column, Mapped
|
||||||
|
|
||||||
from mixin import CrudCollection
|
from Controllers.Postgres.mixin import CrudCollection
|
||||||
|
|
||||||
|
|
||||||
class EndpointRestriction(CrudCollection):
|
class EndpointRestriction(CrudCollection):
|
||||||
|
|
|
||||||
|
|
@ -10,10 +10,10 @@ This module provides a class for managing Redis key-value operations with suppor
|
||||||
|
|
||||||
import arrow
|
import arrow
|
||||||
import json
|
import json
|
||||||
|
|
||||||
from connection import redis_cli
|
|
||||||
from typing import Union, Dict, List, Optional, Any, TypeVar
|
from typing import Union, Dict, List, Optional, Any, TypeVar
|
||||||
|
|
||||||
|
from Controllers.Redis.connection import redis_cli
|
||||||
|
|
||||||
|
|
||||||
T = TypeVar('T', Dict[str, Any], List[Any])
|
T = TypeVar('T', Dict[str, Any], List[Any])
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
from pydantic_settings import BaseSettings, SettingsConfigDict
|
||||||
|
|
||||||
|
|
||||||
|
class Configs(BaseSettings):
|
||||||
|
"""
|
||||||
|
MongoDB configuration settings.
|
||||||
|
"""
|
||||||
|
HOST: str = ""
|
||||||
|
PASSWORD: str = ""
|
||||||
|
PORT: int = 0
|
||||||
|
DB: int = 0
|
||||||
|
|
||||||
|
def as_dict(self):
|
||||||
|
return dict(
|
||||||
|
host=self.HOST,
|
||||||
|
password=self.PASSWORD,
|
||||||
|
port=int(self.PORT),
|
||||||
|
db=self.DB,
|
||||||
|
)
|
||||||
|
|
||||||
|
model_config = SettingsConfigDict(env_prefix="REDIS_")
|
||||||
|
|
||||||
|
|
||||||
|
redis_configs = Configs() # singleton instance of the REDIS configuration settings
|
||||||
|
print(redis_configs.as_dict())
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
import time
|
import time
|
||||||
|
|
||||||
from typing import Dict, Any, Optional
|
from typing import Dict, Any
|
||||||
from redis import Redis, ConnectionError, TimeoutError
|
from redis import Redis, ConnectionError, TimeoutError, ConnectionPool
|
||||||
|
from Controllers.Redis.config import redis_configs
|
||||||
|
|
||||||
|
|
||||||
class RedisConn:
|
class RedisConn:
|
||||||
|
|
@ -16,18 +17,16 @@ class RedisConn:
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
config: Optional[Dict[str, Any]] = None,
|
|
||||||
max_retries: int = CONNECTION_RETRIES,
|
max_retries: int = CONNECTION_RETRIES,
|
||||||
):
|
):
|
||||||
"""
|
"""
|
||||||
Initialize Redis connection with configuration.
|
Initialize Redis connection with configuration.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
config: Redis connection configuration dictionary. If None, uses WagRedis config.
|
|
||||||
max_retries: Maximum number of connection attempts.
|
max_retries: Maximum number of connection attempts.
|
||||||
"""
|
"""
|
||||||
self.max_retries = max_retries
|
self.max_retries = max_retries
|
||||||
self.config = config or {}
|
self.config = redis_configs.as_dict()
|
||||||
self._redis = None
|
self._redis = None
|
||||||
self._pool = None
|
self._pool = None
|
||||||
|
|
||||||
|
|
@ -72,7 +71,6 @@ class RedisConn:
|
||||||
for attempt in range(1, self.max_retries + 1):
|
for attempt in range(1, self.max_retries + 1):
|
||||||
try:
|
try:
|
||||||
if self._pool is None:
|
if self._pool is None:
|
||||||
from redis import ConnectionPool
|
|
||||||
self._pool = ConnectionPool(**self.config)
|
self._pool = ConnectionPool(**self.config)
|
||||||
self._redis = Redis(connection_pool=self._pool)
|
self._redis = Redis(connection_pool=self._pool)
|
||||||
if self.check_connection():
|
if self.check_connection():
|
||||||
|
|
@ -101,7 +99,7 @@ class RedisConn:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def set_connection(
|
def set_connection(
|
||||||
self, host: str, password: str, port: int, db: int, **kwargs
|
self, **kwargs
|
||||||
) -> Redis:
|
) -> Redis:
|
||||||
"""
|
"""
|
||||||
Recreate Redis connection with new parameters.
|
Recreate Redis connection with new parameters.
|
||||||
|
|
@ -119,10 +117,10 @@ class RedisConn:
|
||||||
try:
|
try:
|
||||||
# Update configuration
|
# Update configuration
|
||||||
self.config = {
|
self.config = {
|
||||||
"host": host,
|
"host": redis_configs.HOST,
|
||||||
"password": password,
|
"password": redis_configs.PASSWORD,
|
||||||
"port": port,
|
"port": redis_configs.PORT,
|
||||||
"db": db,
|
"db": redis_configs.PORT,
|
||||||
"socket_timeout": kwargs.get("socket_timeout", self.DEFAULT_TIMEOUT),
|
"socket_timeout": kwargs.get("socket_timeout", self.DEFAULT_TIMEOUT),
|
||||||
"socket_connect_timeout": kwargs.get(
|
"socket_connect_timeout": kwargs.get(
|
||||||
"socket_connect_timeout", self.DEFAULT_TIMEOUT
|
"socket_connect_timeout", self.DEFAULT_TIMEOUT
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,10 @@
|
||||||
import arrow
|
import arrow
|
||||||
|
|
||||||
from typing import Optional, List, Dict, Union, Iterator
|
from typing import Optional, List, Dict, Union, Iterator
|
||||||
from response import RedisResponse
|
|
||||||
from connection import redis_cli
|
from Controllers.Redis.response import RedisResponse
|
||||||
from base import RedisRow
|
from Controllers.Redis.connection import redis_cli
|
||||||
|
from Controllers.Redis.base import RedisRow
|
||||||
|
|
||||||
|
|
||||||
class MainConfig:
|
class MainConfig:
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
from typing import Dict, List, Optional
|
from Controllers.Redis.database import RedisActions
|
||||||
from database import RedisActions
|
|
||||||
|
|
||||||
def example_set_json() -> None:
|
def example_set_json() -> None:
|
||||||
"""Example of setting JSON data in Redis with and without expiry."""
|
"""Example of setting JSON data in Redis with and without expiry."""
|
||||||
|
|
@ -7,48 +7,48 @@ def example_set_json() -> None:
|
||||||
data = {"name": "John", "age": 30, "city": "New York"}
|
data = {"name": "John", "age": 30, "city": "New York"}
|
||||||
keys = ["user", "profile", "123"]
|
keys = ["user", "profile", "123"]
|
||||||
result = RedisActions.set_json(list_keys=keys, value=data)
|
result = RedisActions.set_json(list_keys=keys, value=data)
|
||||||
print("Set JSON without expiry:", result)
|
print("Set JSON without expiry:", result.as_dict())
|
||||||
|
|
||||||
# Example 2: Set JSON with expiry
|
# Example 2: Set JSON with expiry
|
||||||
expiry = {"hours": 1, "minutes": 30}
|
expiry = {"hours": 1, "minutes": 30}
|
||||||
result = RedisActions.set_json(list_keys=keys, value=data, expires=expiry)
|
result = RedisActions.set_json(list_keys=keys, value=data, expires=expiry)
|
||||||
print("Set JSON with expiry:", result)
|
print("Set JSON with expiry:", result.as_dict())
|
||||||
|
|
||||||
def example_get_json() -> None:
|
def example_get_json() -> None:
|
||||||
"""Example of retrieving JSON data from Redis."""
|
"""Example of retrieving JSON data from Redis."""
|
||||||
# Example 1: Get all matching keys
|
# Example 1: Get all matching keys
|
||||||
keys = ["user", "profile", "*"]
|
keys = ["user", "profile", "*"]
|
||||||
result = RedisActions.get_json(list_keys=keys)
|
result = RedisActions.get_json(list_keys=keys)
|
||||||
print("Get all matching JSON:", result)
|
print("Get all matching JSON:", result.as_dict())
|
||||||
|
|
||||||
# Example 2: Get with limit
|
# Example 2: Get with limit
|
||||||
result = RedisActions.get_json(list_keys=keys, limit=5)
|
result = RedisActions.get_json(list_keys=keys, limit=5)
|
||||||
print("Get JSON with limit:", result)
|
print("Get JSON with limit:", result.as_dict())
|
||||||
|
|
||||||
def example_get_json_iterator() -> None:
|
def example_get_json_iterator() -> None:
|
||||||
"""Example of using the JSON iterator for large datasets."""
|
"""Example of using the JSON iterator for large datasets."""
|
||||||
keys = ["user", "profile", "*"]
|
keys = ["user", "profile", "*"]
|
||||||
for row in RedisActions.get_json_iterator(list_keys=keys):
|
for row in RedisActions.get_json_iterator(list_keys=keys):
|
||||||
print("Iterating over JSON row:", row)
|
print("Iterating over JSON row:", row.as_dict if isinstance(row.as_dict, dict) else row.as_dict())
|
||||||
|
|
||||||
def example_delete_key() -> None:
|
# def example_delete_key() -> None:
|
||||||
"""Example of deleting a specific key."""
|
# """Example of deleting a specific key."""
|
||||||
key = "user:profile:123"
|
# key = "user:profile:123"
|
||||||
result = RedisActions.delete_key(key)
|
# result = RedisActions.delete_key(key)
|
||||||
print("Delete specific key:", result)
|
# print("Delete specific key:", result)
|
||||||
|
#
|
||||||
def example_delete() -> None:
|
# def example_delete() -> None:
|
||||||
"""Example of deleting multiple keys matching a pattern."""
|
# """Example of deleting multiple keys matching a pattern."""
|
||||||
keys = ["user", "profile", "*"]
|
# keys = ["user", "profile", "*"]
|
||||||
result = RedisActions.delete(list_keys=keys)
|
# result = RedisActions.delete(list_keys=keys)
|
||||||
print("Delete multiple keys:", result)
|
# print("Delete multiple keys:", result)
|
||||||
|
|
||||||
def example_refresh_ttl() -> None:
|
def example_refresh_ttl() -> None:
|
||||||
"""Example of refreshing TTL for a key."""
|
"""Example of refreshing TTL for a key."""
|
||||||
key = "user:profile:123"
|
key = "user:profile:123"
|
||||||
new_expiry = {"hours": 2, "minutes": 0}
|
new_expiry = {"hours": 2, "minutes": 0}
|
||||||
result = RedisActions.refresh_ttl(key=key, expires=new_expiry)
|
result = RedisActions.refresh_ttl(key=key, expires=new_expiry)
|
||||||
print("Refresh TTL:", result)
|
print("Refresh TTL:", result.as_dict())
|
||||||
|
|
||||||
def example_key_exists() -> None:
|
def example_key_exists() -> None:
|
||||||
"""Example of checking if a key exists."""
|
"""Example of checking if a key exists."""
|
||||||
|
|
@ -58,9 +58,10 @@ def example_key_exists() -> None:
|
||||||
|
|
||||||
def example_resolve_expires_at() -> None:
|
def example_resolve_expires_at() -> None:
|
||||||
"""Example of resolving expiry time for a key."""
|
"""Example of resolving expiry time for a key."""
|
||||||
from base import RedisRow
|
from Controllers.Redis.base import RedisRow
|
||||||
redis_row = RedisRow()
|
redis_row = RedisRow()
|
||||||
redis_row.redis_key = "user:profile:123"
|
redis_row.set_key("user:profile:123")
|
||||||
|
print(redis_row.keys)
|
||||||
expires_at = RedisActions.resolve_expires_at(redis_row)
|
expires_at = RedisActions.resolve_expires_at(redis_row)
|
||||||
print("Resolve expires at:", expires_at)
|
print("Resolve expires at:", expires_at)
|
||||||
|
|
||||||
|
|
@ -77,11 +78,11 @@ def run_all_examples() -> None:
|
||||||
print("\n3. Using JSON iterator:")
|
print("\n3. Using JSON iterator:")
|
||||||
example_get_json_iterator()
|
example_get_json_iterator()
|
||||||
|
|
||||||
print("\n4. Deleting specific key:")
|
# print("\n4. Deleting specific key:")
|
||||||
example_delete_key()
|
# example_delete_key()
|
||||||
|
#
|
||||||
print("\n5. Deleting multiple keys:")
|
# print("\n5. Deleting multiple keys:")
|
||||||
example_delete()
|
# example_delete()
|
||||||
|
|
||||||
print("\n6. Refreshing TTL:")
|
print("\n6. Refreshing TTL:")
|
||||||
example_refresh_ttl()
|
example_refresh_ttl()
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
from typing import Union, Dict, List, Optional, Any
|
from typing import Union, Dict, Optional, Any
|
||||||
from base import RedisRow
|
from Controllers.Redis.base import RedisRow
|
||||||
|
|
||||||
|
|
||||||
class RedisResponse:
|
class RedisResponse:
|
||||||
|
|
@ -11,11 +11,11 @@ class RedisResponse:
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
status: bool,
|
status: bool,
|
||||||
message: str,
|
message: str,
|
||||||
data: Any = None,
|
data: Any = None,
|
||||||
error: Optional[str] = None,
|
error: Optional[str] = None,
|
||||||
):
|
):
|
||||||
"""
|
"""
|
||||||
Initialize a Redis response.
|
Initialize a Redis response.
|
||||||
|
|
|
||||||
20
api_env.env
20
api_env.env
|
|
@ -1,18 +1,22 @@
|
||||||
MONGO_ENGINE=mongodb
|
MONGO_ENGINE=mongodb
|
||||||
MONGO_DB=mongodb
|
MONGO_DB=mongo_database
|
||||||
MONGO_HOST=mongo_service
|
MONGO_HOST=mongo_service
|
||||||
MONGO_PORT=27017
|
MONGO_PORT=27017
|
||||||
MONGO_USER=mongo_user
|
MONGO_USER=mongo_user
|
||||||
MONGO_PASSWORD=mongo_password
|
MONGO_PASSWORD=mongo_password
|
||||||
POSTGRES_DB=POSTGRES_DB
|
POSTGRES_DB=wag_database
|
||||||
POSTGRES_USER=POSTGRES_USER
|
POSTGRES_USER=berkay_wag_user
|
||||||
POSTGRES_PASSWORD=POSTGRES_PASSWORD
|
POSTGRES_PASSWORD=berkay_wag_user_password
|
||||||
POSTGRES_HOST=POSTGRES_HOST
|
POSTGRES_HOST=postgres-service
|
||||||
POSTGRES_PORT=1155
|
POSTGRES_PORT=5432
|
||||||
POSTGRES_ENGINE=POSTGRES_ENGINE
|
POSTGRES_ENGINE=postgresql+psycopg2
|
||||||
POSTGRES_POOL_PRE_PING=True
|
POSTGRES_POOL_PRE_PING=True
|
||||||
POSTGRES_POOL_SIZE=20
|
POSTGRES_POOL_SIZE=20
|
||||||
POSTGRES_MAX_OVERFLOW=10
|
POSTGRES_MAX_OVERFLOW=10
|
||||||
POSTGRES_POOL_RECYCLE=600
|
POSTGRES_POOL_RECYCLE=600
|
||||||
POSTGRES_POOL_TIMEOUT=30
|
POSTGRES_POOL_TIMEOUT=30
|
||||||
POSTGRES_ECHO=True
|
POSTGRES_ECHO=True
|
||||||
|
REDIS_HOST=redis_service
|
||||||
|
REDIS_PASSWORD=commercial_redis_password
|
||||||
|
REDIS_PORT=6379
|
||||||
|
REDIS_DB=0
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
services:
|
||||||
|
|
||||||
|
test_server:
|
||||||
|
container_name: test_server
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
dockerfile: ApiServices/Dockerfile
|
||||||
|
env_file:
|
||||||
|
- api_env.env
|
||||||
|
|
@ -1,4 +1,53 @@
|
||||||
services:
|
services:
|
||||||
|
mongo_service:
|
||||||
|
container_name: mongo_service
|
||||||
|
image: "bitnami/mongodb:latest"
|
||||||
|
networks:
|
||||||
|
- wag-services
|
||||||
|
environment:
|
||||||
|
- 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
|
||||||
|
ports:
|
||||||
|
- "11777:27017"
|
||||||
|
volumes:
|
||||||
|
- mongodb-data:/bitnami/mongodb
|
||||||
|
|
||||||
|
postgres-service:
|
||||||
|
container_name: postgres-service
|
||||||
|
image: "bitnami/postgresql:latest"
|
||||||
|
networks:
|
||||||
|
- wag-services
|
||||||
|
restart: on-failure
|
||||||
|
depends_on:
|
||||||
|
- mongo_service
|
||||||
|
environment:
|
||||||
|
- POSTGRES_DB=wag_database
|
||||||
|
- POSTGRES_USER=berkay_wag_user
|
||||||
|
- POSTGRES_PASSWORD=berkay_wag_user_password
|
||||||
|
ports:
|
||||||
|
- "5444:5432"
|
||||||
|
volumes:
|
||||||
|
- postgres-data:/bitnami/postgresql
|
||||||
|
|
||||||
|
redis_service:
|
||||||
|
container_name: redis_service
|
||||||
|
image: "bitnami/redis:latest"
|
||||||
|
networks:
|
||||||
|
- wag-services
|
||||||
|
restart: on-failure
|
||||||
|
environment:
|
||||||
|
- REDIS_HOST=redis_service
|
||||||
|
- REDIS_PASSWORD=commercial_redis_password
|
||||||
|
- REDIS_PORT=6379
|
||||||
|
- REDIS_DB=0
|
||||||
|
ports:
|
||||||
|
- "11222:6379"
|
||||||
|
|
||||||
test_server:
|
test_server:
|
||||||
container_name: test_server
|
container_name: test_server
|
||||||
|
|
@ -7,3 +56,12 @@ services:
|
||||||
dockerfile: ApiServices/Dockerfile
|
dockerfile: ApiServices/Dockerfile
|
||||||
env_file:
|
env_file:
|
||||||
- api_env.env
|
- api_env.env
|
||||||
|
networks:
|
||||||
|
- wag-services
|
||||||
|
|
||||||
|
networks:
|
||||||
|
wag-services:
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
postgres-data:
|
||||||
|
mongodb-data:
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue