SIENTIAPDE-1646
Update project configuration and dependencies - Added .mypy_cache and .cursor to .gitignore. - Changed asyncio_default_fixture_loop_scope and asyncio_default_test_loop_scope to "session" in pyproject.toml. - Updated e2e testing dependencies in requirements-dev.txt, replacing fakeredis and mongomock with pytest-httpserver. - Updated requirements.txt to use sientia_do instead of a specific git commit. - Modified sonar-project.properties to remove a file from coverage exclusions. - Enhanced E2E test fixtures in e2e/conftest.py for better container management. - Cleaned up e2e test files related to CoreScouter and PIWebAPIScouter workflows.
This commit is contained in:
@@ -1,241 +0,0 @@
|
||||
"""
|
||||
Fake MongoDB Repository adapter for testing.
|
||||
|
||||
This adapter implements the MongoDBRepository interface using mongomock
|
||||
to provide an in-memory MongoDB server for testing.
|
||||
"""
|
||||
|
||||
import time
|
||||
from typing import Any
|
||||
|
||||
from mongomock import MongoClient
|
||||
from sientia_do.notifications.handlers import CoreNotificationHandler as NotificationHandler
|
||||
from sientia_do.observability.logger import Logger
|
||||
from sientia_do.observability.metrics_controller import MetricsController
|
||||
from sientia_do.observability.sientia_monitoring import SientiaMonitoring
|
||||
|
||||
|
||||
def clear_mongo_id(docs: list) -> list:
|
||||
"""
|
||||
Remove MongoDB internal `_id` fields from nested structures.
|
||||
|
||||
Same implementation as in the real MongoDBRepository.
|
||||
|
||||
Args:
|
||||
docs: The list of documents or nested structures to clean.
|
||||
|
||||
Returns:
|
||||
The cleaned documents with `_id` fields removed wherever present.
|
||||
"""
|
||||
for doc in docs:
|
||||
if isinstance(doc, list):
|
||||
clear_mongo_id(doc)
|
||||
elif isinstance(doc, dict):
|
||||
if '_id' in doc:
|
||||
del doc['_id']
|
||||
for _key, value in doc.items():
|
||||
if isinstance(value, list):
|
||||
clear_mongo_id(value)
|
||||
elif isinstance(value, dict):
|
||||
clear_mongo_id([value])
|
||||
return docs
|
||||
|
||||
|
||||
class FakeMongoDBRepository(SientiaMonitoring):
|
||||
"""
|
||||
Fake MongoDB Repository that uses mongomock for testing.
|
||||
|
||||
Implements the same interface as MongoDBRepository but uses
|
||||
mongomock for in-memory MongoDB operations.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
connection_string: str,
|
||||
database_name: str,
|
||||
logger: Logger,
|
||||
notification_handler: NotificationHandler,
|
||||
metrics_controller: MetricsController,
|
||||
):
|
||||
"""
|
||||
Initialize fake MongoDB repository with mongomock.
|
||||
|
||||
Args:
|
||||
connection_string: MongoDB connection string (ignored in fake mode)
|
||||
database_name: Target database name
|
||||
logger: Logger instance
|
||||
notification_handler: Notification handler
|
||||
metrics_controller: Metrics controller
|
||||
"""
|
||||
SientiaMonitoring.__init__(
|
||||
self,
|
||||
logger=logger,
|
||||
notification_handler=notification_handler,
|
||||
metrics_controller=metrics_controller,
|
||||
)
|
||||
|
||||
self.database_name = database_name
|
||||
# Use mongomock instead of real MongoDB
|
||||
self.mongo_client = MongoClient()
|
||||
self.database = self.mongo_client[self.database_name]
|
||||
logger.info('Fake MongoDB connection initialized')
|
||||
|
||||
def close(self):
|
||||
"""
|
||||
Closes fake MongoDB connection and shuts down monitoring.
|
||||
"""
|
||||
try:
|
||||
if self.mongo_client:
|
||||
self.logger.info('Closing fake MongoDB connection...')
|
||||
self.mongo_client.close()
|
||||
self.logger.info('Fake MongoDB connection closed successfully')
|
||||
except Exception as e:
|
||||
self.logger.error(f'Failed to close fake MongoDB connection: {e}')
|
||||
SientiaMonitoring.shutdown(self)
|
||||
|
||||
def __del__(self):
|
||||
"""
|
||||
Destructor that closes the connection when destroying the instance.
|
||||
"""
|
||||
self.close()
|
||||
|
||||
async def find(
|
||||
self,
|
||||
collection_name: str,
|
||||
filters: dict[str, Any],
|
||||
metadata: dict[str, Any],
|
||||
) -> list[dict[str, Any]]:
|
||||
"""
|
||||
Finds documents in a MongoDB collection based on provided filters.
|
||||
|
||||
Args:
|
||||
collection_name: Name of the collection to search
|
||||
filters: Query filters to apply
|
||||
metadata: Dictionary with additional metadata
|
||||
|
||||
Return:
|
||||
List of documents matching the filters (with `_id` removed)
|
||||
"""
|
||||
try:
|
||||
start_time = time.time()
|
||||
collection = self.database[collection_name]
|
||||
documents = list(collection.find(filters, {'_id': 0}))
|
||||
except Exception as e:
|
||||
self.logger.error(f'Failed to find documents in fake MongoDB: {e}')
|
||||
raise e
|
||||
|
||||
return clear_mongo_id(documents)
|
||||
|
||||
async def aggregate(
|
||||
self,
|
||||
collection_name: str,
|
||||
pipeline: list[dict[str, Any]],
|
||||
metadata: dict[str, Any],
|
||||
) -> list[dict[str, Any]]:
|
||||
"""
|
||||
Executes an aggregation on a MongoDB collection.
|
||||
|
||||
Args:
|
||||
collection_name: Name of the collection to aggregate
|
||||
pipeline: MongoDB aggregation pipeline
|
||||
metadata: Dictionary with additional metadata
|
||||
|
||||
Return:
|
||||
List of documents resulting from aggregation (with `_id` removed)
|
||||
"""
|
||||
try:
|
||||
start_time = time.time()
|
||||
collection = self.database[collection_name]
|
||||
documents = list(collection.aggregate(pipeline))
|
||||
except Exception as e:
|
||||
self.logger.error(f'Failed to aggregate documents in fake MongoDB: {e}')
|
||||
raise e
|
||||
|
||||
return clear_mongo_id(documents)
|
||||
|
||||
async def update_many(
|
||||
self,
|
||||
collection_name: str,
|
||||
filters: dict[str, Any],
|
||||
update: dict[str, Any],
|
||||
metadata: dict[str, Any],
|
||||
) -> None:
|
||||
"""
|
||||
Updates multiple documents in a MongoDB collection.
|
||||
|
||||
Args:
|
||||
collection_name: Collection name
|
||||
filters: Filters to identify documents to update
|
||||
update: Update operations to apply
|
||||
metadata: Dictionary with additional metadata
|
||||
"""
|
||||
try:
|
||||
collection = self.database[collection_name]
|
||||
collection.update_many(filters, update)
|
||||
except Exception as e:
|
||||
self.logger.error(f'Failed to update documents in fake MongoDB: {e}')
|
||||
raise e
|
||||
|
||||
async def insert_many(
|
||||
self,
|
||||
collection_name: str,
|
||||
documents: list[dict[str, Any]],
|
||||
metadata: dict[str, Any],
|
||||
) -> None:
|
||||
"""
|
||||
Inserts multiple documents into a MongoDB collection.
|
||||
|
||||
Args:
|
||||
collection_name: Collection name
|
||||
documents: List of documents to insert
|
||||
metadata: Dictionary with additional metadata
|
||||
"""
|
||||
try:
|
||||
collection = self.database[collection_name]
|
||||
collection.insert_many(documents)
|
||||
except Exception as e:
|
||||
self.logger.error(f'Failed to insert documents in fake MongoDB: {e}')
|
||||
raise e
|
||||
|
||||
async def insert(
|
||||
self,
|
||||
collection_name: str,
|
||||
document: dict[str, Any],
|
||||
metadata: dict[str, Any],
|
||||
) -> None:
|
||||
"""
|
||||
Inserts a document into a MongoDB collection.
|
||||
|
||||
Args:
|
||||
collection_name: Collection name
|
||||
document: Document to insert
|
||||
metadata: Dictionary with additional metadata
|
||||
"""
|
||||
try:
|
||||
collection = self.database[collection_name]
|
||||
collection.insert_one(document)
|
||||
except Exception as e:
|
||||
self.logger.error(f'Failed to insert document in fake MongoDB: {e}')
|
||||
raise e
|
||||
|
||||
async def delete_many(
|
||||
self,
|
||||
collection_name: str,
|
||||
filters: dict[str, Any],
|
||||
metadata: dict[str, Any],
|
||||
) -> None:
|
||||
"""
|
||||
Removes multiple documents from a MongoDB collection.
|
||||
|
||||
Args:
|
||||
collection_name: Collection name
|
||||
filters: Filters to identify documents to remove
|
||||
metadata: Dictionary with additional metadata
|
||||
"""
|
||||
try:
|
||||
collection = self.database[collection_name]
|
||||
collection.delete_many(filters)
|
||||
except Exception as e:
|
||||
self.logger.error(f'Failed to delete documents in fake MongoDB: {e}')
|
||||
raise e
|
||||
|
||||
@@ -1,170 +0,0 @@
|
||||
"""
|
||||
Fake Redis Repository adapter for testing.
|
||||
|
||||
This adapter implements the RedisRepository interface using fakeredis
|
||||
to provide an in-memory Redis server for testing.
|
||||
"""
|
||||
|
||||
import json
|
||||
from typing import Any
|
||||
|
||||
import fakeredis
|
||||
from sientia_do.notifications.handlers import CoreNotificationHandler as NotificationHandler
|
||||
from sientia_do.observability.logger import Logger
|
||||
from sientia_do.observability.metrics_controller import MetricsController
|
||||
from sientia_do.observability.sientia_monitoring import SientiaMonitoring
|
||||
|
||||
|
||||
class FakeRedisRepository(SientiaMonitoring):
|
||||
"""
|
||||
Fake Redis Repository that uses fakeredis for testing.
|
||||
|
||||
Implements the same interface as RedisRepository but uses
|
||||
fakeredis for in-memory Redis operations.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
host: str,
|
||||
port: int,
|
||||
username: str,
|
||||
password: str,
|
||||
logger: Logger,
|
||||
notification_handler: NotificationHandler,
|
||||
metrics_controller: MetricsController,
|
||||
):
|
||||
"""
|
||||
Initialize fake Redis repository with fakeredis.
|
||||
|
||||
Args:
|
||||
host: Redis server address (ignored in fake mode)
|
||||
port: Redis server port (ignored in fake mode)
|
||||
username: Username (ignored in fake mode)
|
||||
password: Password (ignored in fake mode)
|
||||
logger: Logger instance
|
||||
notification_handler: Notification handler
|
||||
metrics_controller: Metrics controller
|
||||
"""
|
||||
SientiaMonitoring.__init__(
|
||||
self,
|
||||
logger=logger,
|
||||
notification_handler=notification_handler,
|
||||
metrics_controller=metrics_controller,
|
||||
)
|
||||
# Create fake Redis server
|
||||
self.redis_client = fakeredis.FakeStrictRedis(
|
||||
decode_responses=True
|
||||
)
|
||||
|
||||
def _get_redis(self):
|
||||
"""Get fakeredis connection."""
|
||||
return self.redis_client
|
||||
|
||||
async def get(self, key: str, metadata: dict | None = None):
|
||||
"""
|
||||
Gets a value from fake Redis by key.
|
||||
|
||||
Args:
|
||||
key: Key of the value to retrieve
|
||||
metadata: Optional dictionary with additional metadata
|
||||
|
||||
Return:
|
||||
Deserialized value from Redis or None if not found
|
||||
"""
|
||||
redis = self._get_redis()
|
||||
try:
|
||||
history = redis.get(key)
|
||||
return json.loads(history) if history else None
|
||||
except Exception as e:
|
||||
self.error(f'Error getting data from fake redis: {e}', metadata or {})
|
||||
raise e
|
||||
|
||||
async def set(
|
||||
self,
|
||||
key: str,
|
||||
data: dict,
|
||||
ttl: int = 600,
|
||||
nx: bool = False,
|
||||
metadata: dict | None = None,
|
||||
) -> bool:
|
||||
"""
|
||||
Sets a value in fake Redis with optional TTL.
|
||||
|
||||
Args:
|
||||
key: Key of the value to set
|
||||
data: Dictionary with data to store
|
||||
ttl: Time to live in seconds (default: 600)
|
||||
nx: If True, only sets if key doesn't exist (default: False)
|
||||
metadata: Optional dictionary with additional metadata
|
||||
|
||||
Return:
|
||||
True if value was set, False otherwise
|
||||
"""
|
||||
redis = self._get_redis()
|
||||
try:
|
||||
result = redis.set(
|
||||
key, json.dumps(data), ex=ttl, nx=nx
|
||||
)
|
||||
return bool(result)
|
||||
except Exception as e:
|
||||
self.error(f'Error setting data in fake redis: {e}', metadata or {})
|
||||
raise e
|
||||
|
||||
async def delete(self, key: str, metadata: dict | None = None):
|
||||
"""
|
||||
Removes a key from fake Redis.
|
||||
|
||||
Args:
|
||||
key: Key to be removed
|
||||
metadata: Optional dictionary with additional metadata
|
||||
"""
|
||||
redis = self._get_redis()
|
||||
try:
|
||||
redis.delete(key)
|
||||
except Exception as e:
|
||||
self.error(f'Error deleting data from fake redis: {e}', metadata or {})
|
||||
raise e
|
||||
|
||||
async def expire(self, key: str, ttl: int, metadata: dict | None = None):
|
||||
"""
|
||||
Sets the time to live (TTL) of an existing Redis key.
|
||||
|
||||
Args:
|
||||
key: Key whose TTL will be set
|
||||
ttl: Time to live in seconds
|
||||
metadata: Optional dictionary with additional metadata
|
||||
"""
|
||||
redis = self._get_redis()
|
||||
try:
|
||||
redis.expire(key, ttl)
|
||||
except Exception as e:
|
||||
self.error(f'Error expiring data from fake redis: {e}', metadata or {})
|
||||
raise e
|
||||
|
||||
async def keys(self, pattern: str, metadata: dict | None = None):
|
||||
"""
|
||||
Gets all keys matching the specified pattern.
|
||||
|
||||
Args:
|
||||
pattern: Search pattern for keys
|
||||
metadata: Optional dictionary with additional metadata
|
||||
|
||||
Return:
|
||||
List of keys matching the pattern
|
||||
"""
|
||||
redis = self._get_redis()
|
||||
try:
|
||||
keys = redis.keys(pattern)
|
||||
return keys
|
||||
except Exception as e:
|
||||
self.error(f'Error getting keys from fake redis: {e}', metadata or {})
|
||||
raise e
|
||||
|
||||
def close(self):
|
||||
"""
|
||||
Closes fake Redis connection and shuts down monitoring.
|
||||
"""
|
||||
if self.redis_client:
|
||||
self.redis_client.close()
|
||||
SientiaMonitoring.shutdown(self)
|
||||
|
||||
Reference in New Issue
Block a user