From b791c561d5e63e00a644a34a3efb094f59f2cbdb Mon Sep 17 00:00:00 2001 From: ZoranPandovski Date: Fri, 19 Dec 2025 15:50:47 +0100 Subject: [PATCH 1/4] Rmv unused tests --- tests/unused/integration/a2a/__init__.py | 0 .../integration/a2a/test_a2a_streaming.py | 436 ------------------ .../integration/flows/test_ml_task_queue.py | 142 ------ .../integration/knowledge_bases/data/seed.sql | 14 - ...sdb_langchain_pgvector_integration_test.py | 64 --- .../knowledge_bases/test_knowledge_bases.py | 337 -------------- .../integration/metrics/test_metrics.py | 68 --- .../integration/rag/test_rag_search_kwargs.py | 271 ----------- .../rag/rerankers/test_openai_reranker.py | 47 -- .../retrievers/test_multi_hop_retriever.py | 127 ----- .../utilities/rag/test_file_loader.py | 41 -- .../utilities/rag/test_file_splitter.py | 164 ------- .../agents/test_agents_controller.py | 43 -- .../interfaces/agents/test_sql_agent_cache.py | 28 -- 14 files changed, 1782 deletions(-) delete mode 100644 tests/unused/integration/a2a/__init__.py delete mode 100644 tests/unused/integration/a2a/test_a2a_streaming.py delete mode 100644 tests/unused/integration/flows/test_ml_task_queue.py delete mode 100644 tests/unused/integration/knowledge_bases/data/seed.sql delete mode 100644 tests/unused/integration/knowledge_bases/mindsdb_langchain_pgvector_integration_test.py delete mode 100644 tests/unused/integration/knowledge_bases/test_knowledge_bases.py delete mode 100644 tests/unused/integration/metrics/test_metrics.py delete mode 100644 tests/unused/integration/rag/test_rag_search_kwargs.py delete mode 100644 tests/unused/integrations/utilities/rag/rerankers/test_openai_reranker.py delete mode 100644 tests/unused/integrations/utilities/rag/retrievers/test_multi_hop_retriever.py delete mode 100644 tests/unused/integrations/utilities/rag/test_file_loader.py delete mode 100644 tests/unused/integrations/utilities/rag/test_file_splitter.py delete mode 100644 tests/unused/interfaces/agents/test_agents_controller.py delete mode 100644 tests/unused/interfaces/agents/test_sql_agent_cache.py diff --git a/tests/unused/integration/a2a/__init__.py b/tests/unused/integration/a2a/__init__.py deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/tests/unused/integration/a2a/test_a2a_streaming.py b/tests/unused/integration/a2a/test_a2a_streaming.py deleted file mode 100644 index 71032a7e679..00000000000 --- a/tests/unused/integration/a2a/test_a2a_streaming.py +++ /dev/null @@ -1,436 +0,0 @@ -#!/usr/bin/env python -import sys -import json -import time -import requests -import uuid -import argparse -import pytest -import os -from typing import Dict, List, Set - -# Default test configuration -DEFAULT_HOST = "0.0.0.0" -DEFAULT_PORT = 10002 -DEFAULT_TIMEOUT = 120 # seconds -DEFAULT_QUERY = "What's the average price for a one bed?" -DEFAULT_AGENT_NAME = "my_agent" # Default agent name to use for requests - -""" -Run instructions: - -start A2A server and mindsdb - -You should have an agent created in MindsDB (this script does NOT create the agent) - -By default the agent is named "my_agent" - -e.g. - -CREATE AGENT my_agent -USING - - model='gemini-2.0-flash', - include_knowledge_bases=['mindsdb.kb_test'], - include_tables=['postgresql_conn.home_rentals', 'postgresql_conn2.car_info'], - prompt_template=' - mindsdb.kb_test knowledge base has info about cities - postgresql_conn.home_rentals database tables has rental data - postgresql_conn2.car_info contains info on cars specs - '; - -source .venv/bin/activate -python test_a2a_streaming.py --host 0.0.0.0 --port 10002 --timeout 180 "What's the average price of homes in berkeley_hills?" -""" - - -def generate_uuid() -> str: - """Generate a random UUID string.""" - return str(uuid.uuid4()).replace("-", "") - - -def stream_a2a_query( - query: str, - host: str = DEFAULT_HOST, - port: int = DEFAULT_PORT, - timeout: int = DEFAULT_TIMEOUT, - verbose: bool = False, - agent_name: str = DEFAULT_AGENT_NAME, # Added agent_name parameter with default -): - """ - Stream a query to the A2A server and yield the responses incrementally. - - Args: - query: The text query to send to the agent - host: A2A server host - port: A2A server port - timeout: Maximum time to wait for responses (seconds) - verbose: Whether to print responses to stdout - agent_name: Name of the agent to use (REQUIRED - the A2A API requires an explicit agent name) - - Yields: - Dict: Response messages from the A2A server - """ - # Generate unique IDs for the request - task_id = generate_uuid() - session_id = generate_uuid() - request_id = generate_uuid() - - # Prepare the request payload - payload = { - "jsonrpc": "2.0", - "id": request_id, - "method": "tasks/sendSubscribe", - "params": { - "id": task_id, - "sessionId": session_id, - "message": { - "role": "user", - "parts": [ - {"type": "text", "text": query}, - ], - "metadata": {"agent_name": agent_name}, # Using the provided agent_name - }, - "acceptedOutputModes": ["text/plain"], - }, - } - - url = f"http://{host}:{port}/a2a" - if verbose: - print(f"Sending streaming request to {url}") - print(f"Query: {query}") - print("Streaming responses:") - print("-" * 60) - - # Set up headers for SSE - headers = { - "Content-Type": "application/json", - "Accept": "text/event-stream", - "Cache-Control": "no-cache", - "Connection": "keep-alive", - } - - # Track seen messages to avoid duplicates - seen_messages: Set[str] = set() - all_responses: List[Dict] = [] - start_time = time.time() - - try: - # Make the streaming request - with requests.post(url, json=payload, headers=headers, stream=True) as response: - if not response.ok: - error_msg = f"Error: HTTP {response.status_code} - {response.text}" - if verbose: - print(error_msg) - yield {"error": error_msg} - return - - # Process the SSE stream - buffer = "" - for chunk in response.iter_content(chunk_size=1): - # Check timeout - if time.time() - start_time > timeout: - error_msg = f"Timeout after {timeout} seconds" - if verbose: - print(error_msg) - yield {"error": error_msg, "timeout": True} - return - - if not chunk: - continue - - # Decode the chunk and add to buffer - buffer += chunk.decode("utf-8") - - # Process complete lines - while "\n" in buffer: - line, buffer = buffer.split("\n", 1) - line = line.rstrip() - - # Skip empty lines - if not line: - continue - - # Process data lines - if line.startswith("data:"): - data_str = line[5:].strip() - if not data_str: - continue - - try: - # Parse the JSON data - data = json.loads(data_str) - - # Extract and display content - if "result" in data: - result = data["result"] - - # Handle status updates - if "status" in result: - message = result["status"].get("message", {}) - parts = message.get("parts", []) - - for part in parts: - # Get content and metadata - content = part.get("text", "") - metadata = part.get("metadata", {}) - thought_type = metadata.get("thought_type", "") - - # Create a unique key for deduplication - message_key = f"{thought_type}:{content}" - - # Skip if we've seen this message before - if message_key in seen_messages: - continue - - # Add to seen messages - seen_messages.add(message_key) - - # Create response object - response_obj = { - "type": thought_type - or part.get("type", "text"), - "content": content, - "metadata": metadata, - } - - # Display based on thought type - if verbose: - if thought_type == "thought": - print(f"Thought: {content}") - elif thought_type == "observation": - print(f"Observation: {content}") - elif thought_type == "sql": - print(f"SQL Query: {content}") - elif part.get("type") == "text": - print(content) - sys.stdout.flush() - - # Yield the response - yield response_obj - all_responses.append(response_obj) - - # Handle artifact updates - if "artifact" in result: - artifact = result["artifact"] - parts = artifact.get("parts", []) - - for part in parts: - content = part.get("text", "") - if content: - response_obj = { - "type": "answer", - "content": content, - } - if verbose: - print(content) - sys.stdout.flush() - yield response_obj - all_responses.append(response_obj) - - # Handle completion - if result.get("final"): - response_obj = {"type": "completion", "final": True} - if verbose: - print("\n[Completed]") - sys.stdout.flush() - yield response_obj - all_responses.append(response_obj) - - # Handle errors - elif "error" in data: - error_msg = data["error"].get("message", "") - response_obj = {"error": error_msg} - if verbose: - print(f"Error: {error_msg}") - sys.stdout.flush() - yield response_obj - all_responses.append(response_obj) - - except json.JSONDecodeError: - if verbose: - print(f"Warning: Invalid JSON: {data_str[:50]}...") - sys.stdout.flush() - - # Process event end - elif line == "": - # Event boundary - process the event - pass - - except KeyboardInterrupt: - if verbose: - print("\nInterrupted by user") - yield {"error": "Interrupted by user"} - except Exception as e: - error_msg = f"Error: {str(e)}" - if verbose: - print(error_msg) - yield {"error": error_msg} - - # Return all collected responses - return all_responses - - -def run_manual_test(): - """Run a manual test with command line arguments.""" - parser = argparse.ArgumentParser( - description="Test A2A streaming with direct requests" - ) - parser.add_argument("--host", default=DEFAULT_HOST, help="A2A server host") - parser.add_argument( - "--port", type=int, default=DEFAULT_PORT, help="A2A server port" - ) - parser.add_argument( - "--timeout", type=int, default=DEFAULT_TIMEOUT, help="Timeout in seconds" - ) - parser.add_argument( - "--agent-name", default=DEFAULT_AGENT_NAME, help="Name of the agent to use" - ) - parser.add_argument( - "query", nargs="?", default=DEFAULT_QUERY, help="Query to send to the agent" - ) - - args = parser.parse_args() - - # Run with verbose output for manual testing - for _ in stream_a2a_query( - args.query, - args.host, - args.port, - args.timeout, - verbose=True, - agent_name=args.agent_name, - ): - pass # Just consume the generator to display output - - -@pytest.mark.integration -def test_a2a_streaming_integration(): - """ - Integration test for A2A streaming functionality. - - This test requires a running A2A server. It can be configured with environment variables: - - A2A_TEST_HOST: A2A server host (default: 0.0.0.0) - - A2A_TEST_PORT: A2A server port (default: 10002) - - A2A_TEST_QUERY: Query to send (default: "What's the average price for a one bed?") - - A2A_TEST_TIMEOUT: Timeout in seconds (default: 120) - - A2A_TEST_AGENT_NAME: Agent name to use (default: my_agent) - - IMPORTANT: You must create the agent in MindsDB before running this test. - """ - # Get configuration from environment variables - host = os.environ.get("A2A_TEST_HOST", DEFAULT_HOST) - port = int(os.environ.get("A2A_TEST_PORT", DEFAULT_PORT)) - query = os.environ.get("A2A_TEST_QUERY", DEFAULT_QUERY) - timeout = int(os.environ.get("A2A_TEST_TIMEOUT", DEFAULT_TIMEOUT)) - agent_name = os.environ.get("A2A_TEST_AGENT_NAME", DEFAULT_AGENT_NAME) - - # Check if we should skip the test - skip_test = os.environ.get("SKIP_A2A_TEST", "false").lower() == "true" - if skip_test: - pytest.skip( - "Skipping A2A test as requested by SKIP_A2A_TEST environment variable" - ) - - # First, check if the agent exists by making a simple request - try: - # Make a simple request to check if the agent exists - url = f"http://{host}:{port}/a2a" - check_payload = { - "jsonrpc": "2.0", - "id": generate_uuid(), - "method": "tasks/send", - "params": { - "id": generate_uuid(), - "sessionId": generate_uuid(), - "message": { - "role": "user", - "parts": [{"type": "text", "text": "test"}], - "metadata": {"agent_name": agent_name}, - }, - }, - } - - response = requests.post(url, json=check_payload, timeout=10) - if response.status_code == 404 or "not found" in response.text.lower(): - pytest.skip( - f"Agent '{agent_name}' not found. Please create the agent before running this test." - ) - except Exception as e: - pytest.skip(f"Error checking if agent exists: {str(e)}") - - # Collect all responses - responses = list( - stream_a2a_query( - query, host, port, timeout, verbose=False, agent_name=agent_name - ) - ) - - # Basic assertions - assert len(responses) > 0, "No responses received from A2A server" - - # Check for error responses, but be more tolerant of task tracking errors and validation errors - errors = [r for r in responses if "error" in r] - - # Identify different types of non-critical errors - task_tracking_errors = [ - e - for e in errors - if "Task" in e.get("error", "") and "not found" in e.get("error", "") - ] - validation_errors = [e for e in errors if "validation error" in e.get("error", "")] - non_critical_errors = task_tracking_errors + validation_errors - - # If all errors are non-critical, we can consider the test passed - if len(errors) > 0 and len(non_critical_errors) == len(errors): - print(f"Ignoring non-critical errors: {non_critical_errors}") - else: - # If there are other types of errors, fail the test - real_errors = [e for e in errors if e not in non_critical_errors] - assert len(real_errors) == 0, f"Errors in responses: {real_errors}" - - # Print response types for debugging - response_types = set(r.get("type", "") for r in responses) - print(f"Response types found: {response_types}") - - # Verify we have different types of responses (thoughts, observations, etc.) - assert len(response_types) > 1, f"Only found response types: {response_types}" - - # Look for any kind of final/completion message - # More flexible approach - check for any of these indicators - final_messages = [ - r - for r in responses - if ( - # Original strict check - (r.get("type") == "completion" and r.get("final")) - or r.get("final") is True - or r.get("type") == "answer" - or ( - r.get("type") == "text" - and r.get("content", "").strip() - and len(r.get("content", "")) > 20 - ) - ) - ] - - print(f"Found {len(final_messages)} potential final/completion messages") - if len(final_messages) == 0: - # Print the last few responses for debugging - print("Last 5 responses for debugging:") - for r in responses[-5:]: - print(f" {r}") - - # More lenient assertion - just check if we got any responses at all - assert len(responses) > 5, "Not enough responses received" - - # Skip the completion check for now as the format may vary - # assert len(final_messages) > 0, "No completion or final message received" - - print(f"✅ Integration test passed with {len(responses)} responses") - return responses - - -if __name__ == "__main__": - # If run directly, use the manual test mode - run_manual_test() diff --git a/tests/unused/integration/flows/test_ml_task_queue.py b/tests/unused/integration/flows/test_ml_task_queue.py deleted file mode 100644 index 8e17fca4d08..00000000000 --- a/tests/unused/integration/flows/test_ml_task_queue.py +++ /dev/null @@ -1,142 +0,0 @@ -import json -import os - -import pytest -from walrus import Database - -from mindsdb.api.executor.data_types.response_type import RESPONSE_TYPE -from mindsdb.utilities.ml_task_queue.const import TASKS_STREAM_NAME - -from tests.integration.utils.http_test_helpers import HTTPHelperMixin -from tests.integration.conftest import HTTP_API_ROOT - -REDIS_HOST = os.environ.get("INTERNAL_URL", "").replace("mindsdb", "redis-master") - - -@pytest.mark.skipif("localhost" in HTTP_API_ROOT or "127.0.0.1" in HTTP_API_ROOT, reason="Requires redis") -class TestMLTaskQueue(HTTPHelperMixin): - - def test_redis_connection(self): - db = Database(protocol=3, host=REDIS_HOST) - db.ping() - - def test_create_model(self, train_finetune_lock): - """ 1. create db connection - 2. create test dataset - 3. start to train model in 'async' mode: check status - 4. start to train model in 'sync' mode: check status - 5. await model 2 is finished - 6. 2 messages in redis stream - """ - - db_details = { - "type": "postgres", - "connection_data": { - "type": "postgres", - "host": "samples.mindsdb.com", - "port": "5432", - "user": "demo_user", - "password": "demo_password", - "database": "demo" - } - } - - self.sql_via_http("DROP MODEL IF EXISTS p_test_queue_async;", RESPONSE_TYPE.OK) - self.sql_via_http("DROP MODEL IF EXISTS p_test_queue_sync;", RESPONSE_TYPE.OK) - - query = f""" - CREATE DATABASE IF NOT EXISTS test_demo_queue - WITH ENGINE = 'postgres', - PARAMETERS = {json.dumps(db_details['connection_data'])}; - """ - self.sql_via_http(query, RESPONSE_TYPE.OK) - - with train_finetune_lock.acquire(timeout=600): - query = """ - create predictor p_test_queue_async - from test_demo_queue (select sqft, location, rental_price from demo_data.home_rentals limit 30) - predict rental_price; - """ - response = self.sql_via_http(query, RESPONSE_TYPE.TABLE) - status = response['data'][0][response['column_names'].index('STATUS')] - assert status in ('generating', 'training') - - query = """ - create predictor p_test_queue_sync - from test_demo_queue (select sqft, location, rental_price from demo_data.home_rentals limit 30) - predict rental_price - USING join_learn_process=true; - """ - response = self.sql_via_http(query, RESPONSE_TYPE.TABLE) - status = response['data'][0][response['column_names'].index('STATUS')] - assert status == 'complete' - - status = self.await_model('p_test_queue_async') - assert status == 'complete' - - db = Database(protocol=3, host=REDIS_HOST) - assert TASKS_STREAM_NAME in db.keys() - - assert db.type(TASKS_STREAM_NAME) == b'stream' - xlen = db.xlen(TASKS_STREAM_NAME) - if xlen != 0: - lol = db.xrange(TASKS_STREAM_NAME) - assert False, "Caught non-zero length ml queue: " + str(lol) - assert db.xlen(TASKS_STREAM_NAME) == 0 - - def test_predict(self): - """ make predict queries to both trained models - """ - - query = """ - SELECT rental_price, - rental_price_explain - FROM mindsdb.p_test_queue_async - WHERE b = 10; - """ - response = self.sql_via_http(query, RESPONSE_TYPE.TABLE) - assert len(response['data']) == 1 - assert len(response['data'][0]) == 2 - - query = """ - SELECT rental_price, - rental_price_explain - FROM test_demo_queue.demo_data.home_rentals - JOIN mindsdb.p_test_queue_async - LIMIT 3; - """ - response = self.sql_via_http(query, RESPONSE_TYPE.TABLE) - assert len(response['data']) == 3 - assert len(response['data'][0]) == 2 - - db = Database(protocol=3, host=REDIS_HOST) - assert db.xlen(TASKS_STREAM_NAME) == 0 - - def test_finetune(self, train_finetune_lock): - """ check that finetune is working - """ - - with train_finetune_lock.acquire(timeout=600): - query = """ - FINETUNE p_test_queue_sync - FROM test_demo_queue (SELECT * FROM demo_data.home_rentals LIMIT 10) - USING join_learn_process=true; - """ - response = self.sql_via_http(query, RESPONSE_TYPE.TABLE) - status = response['data'][0][response['column_names'].index('STATUS')] - assert status == 'complete' - - query = """ - FINETUNE p_test_queue_async - FROM test_demo_queue (SELECT * FROM demo_data.home_rentals LIMIT 10); - """ - response = self.sql_via_http(query, RESPONSE_TYPE.TABLE) - status = response['data'][0][response['column_names'].index('STATUS')] - # FINETUNE in this case may be very fast, so add 'complete' to check - assert status in ('generating', 'training', 'complete') - - status = self.await_model('p_test_queue_async', version_number=2) - assert status == 'complete' - - db = Database(protocol=3, host=REDIS_HOST) - assert db.xlen(TASKS_STREAM_NAME) == 0 diff --git a/tests/unused/integration/knowledge_bases/data/seed.sql b/tests/unused/integration/knowledge_bases/data/seed.sql deleted file mode 100644 index 69fe7847fc2..00000000000 --- a/tests/unused/integration/knowledge_bases/data/seed.sql +++ /dev/null @@ -1,14 +0,0 @@ --- Make sure pgvector extension is enabled -DROP EXTENSION IF EXISTS vector; -CREATE EXTENSION vector; - --- Create the table -CREATE TABLE IF NOT EXISTS items ( - id text PRIMARY KEY, - content text NOT NULL, - embeddings vector NOT NULL, - metadata jsonb -); - --- Dummy data will be handled in tests themselves. Leave it empty. -COMMIT; diff --git a/tests/unused/integration/knowledge_bases/mindsdb_langchain_pgvector_integration_test.py b/tests/unused/integration/knowledge_bases/mindsdb_langchain_pgvector_integration_test.py deleted file mode 100644 index 3a16dac44d0..00000000000 --- a/tests/unused/integration/knowledge_bases/mindsdb_langchain_pgvector_integration_test.py +++ /dev/null @@ -1,64 +0,0 @@ -from mindsdb.integrations.utilities.rag.loaders.vector_store_loader.pgvector import PGVectorMDB -from mindsdb.integrations.handlers.langchain_embedding_handler.fastapi_embeddings import FastAPIEmbeddings - - -def setup_pgvector_database(): - """Setup pgvector database""" - # Using port 15432 to avoid conflicts with local PostgreSQL - connection_string = "postgresql://gateway:gateway@localhost:15432/gateway" - - print(f"Connecting to: {connection_string}") - - # Initialize FastAPI embeddings - embeddings = FastAPIEmbeddings( - api_base="http://localhost:8043/v1/embeddings", - model="sparse_model" - ) - - # Initialize PGVectorMDB - vector_db = PGVectorMDB( - connection_string=connection_string, - collection_name="test_dev_doc_vectors", - embedding_function=embeddings, - is_sparse=True, # Using sparse vectors - vector_size=30522 # Size for sparse vectors - ) - - return vector_db - - -def test_vector_queries(vector_db): - """Test various vector queries""" - print("\nTesting vector queries...") - - # Test text to be embedded - test_text = "For the Bsecondaryl containment" - - # Get embeddings for the test text - embedding = vector_db.embedding_function.embed_query(test_text) - - # Query similar vectors - results = vector_db._query_collection( - embedding=embedding, - k=5 - ) - - print("\nVector similarity search results:") - for item, distance in results: - print(f"Content: {item.content}") - print(f"Metadata: {item.metadata}") - print(f"Distance: {distance}") - print("---") - - -def main(): - # Setup vector database - print("\nSetting up pgvector database...") - vector_db = setup_pgvector_database() - - # Run tests - test_vector_queries(vector_db) - - -if __name__ == "__main__": - main() diff --git a/tests/unused/integration/knowledge_bases/test_knowledge_bases.py b/tests/unused/integration/knowledge_bases/test_knowledge_bases.py deleted file mode 100644 index a43c1a77ce5..00000000000 --- a/tests/unused/integration/knowledge_bases/test_knowledge_bases.py +++ /dev/null @@ -1,337 +0,0 @@ -from http import HTTPStatus -from tempfile import TemporaryDirectory -from time import perf_counter, sleep -from uuid import uuid4 - -import os -import psycopg2 -import pytest - -from mindsdb.api.http.initialize import initialize_app -from mindsdb.migrations import migrate -from mindsdb.interfaces.storage import db -from mindsdb.utilities.config import config - -# Should match table name in data/seed.sql -TEST_TABLE_NAME = 'items' -# Should match column names in data/seed.sql -COLUMN_NAMES = ['id', 'content', 'embeddings', 'metadata'] - -CONNECTION_KWARGS = { - 'connection_data': { - 'host': os.environ.get('MDB_TEST_PGVECTOR_HOST', '127.0.0.1'), - 'port': os.environ.get('MDB_TEST_PGVECTOR_PORT', '5432'), - 'user': os.environ.get('MDB_TEST_PGVECTOR_USER', 'postgres'), - 'password': os.environ.get('MDB_TEST_PGVECTOR_PASSWORD', 'supersecret'), - 'database': None # Different for each test. - } -} - -MODEL_WAIT_DURATION_SECONDS = 5 -MODEL_WAIT_SLEEP_INTERVAL_SECONDS = 0.2 - - -@pytest.fixture(scope="session", autouse=True) -def app(): - old_minds_db_con = '' - if 'MINDSDB_DB_CON' in os.environ: - old_minds_db_con = os.environ['MINDSDB_DB_CON'] - with TemporaryDirectory(prefix='knowledge_bases_integration_test_') as temp_dir: - db_path = 'sqlite:///' + os.path.join(temp_dir, 'mindsdb.sqlite3.db') - # Need to change env variable for migrate module, since it calls db.init(). - os.environ['MINDSDB_DB_CON'] = db_path - db.init() - migrate.migrate_to_head() - config["gui"]["open_on_start"] = False - config["gui"]["autoupdate"] = False - app = initialize_app() - - test_client = app.test_client() - - # Create langchain embedding model to use in all tests. - create_ml_engine_query = 'CREATE ML_ENGINE langchain_embedding FROM langchain_embedding;' - create_ml_engine_data = { - 'query': create_ml_engine_query - } - response = test_client.post('/api/sql/query', json=create_ml_engine_data, follow_redirects=True) - assert '200' in response.status - - # Create model to use in all tests. Use OpenAI for embeddings. - create_query = ''' - CREATE MODEL mindsdb.test_embedding_model - PREDICT embeddings - USING - engine='langchain_embedding', - class = 'OpenAIEmbeddings', - input_columns = ['content']; - ''' - train_data = { - 'query': create_query - } - response = test_client.post('/api/projects/mindsdb/models', json=train_data, follow_redirects=True) - assert '201' in response.status - - # Wait for model to complete. - model_complete = False - model_start_time = perf_counter() - while not model_complete: - if (perf_counter() - model_start_time) > MODEL_WAIT_DURATION_SECONDS: - pytest.fail('Model test_embedding_model did not finish training in time') - response = test_client.get('/api/projects/mindsdb/models/test_embedding_model') - model_status = response.get_json().get('status', 'error') - if model_status == 'complete': - model_complete = True - continue - if model_status == 'error': - pytest.fail('Model test_embedding_model encountered an error while training') - sleep(MODEL_WAIT_SLEEP_INTERVAL_SECONDS) - yield app - os.environ['MINDSDB_DB_CON'] = old_minds_db_con - - -@pytest.fixture() -def client(app): - return app.test_client() - - -def init_db(): - '''Initialize a new DB for every test.''' - conn_info = CONNECTION_KWARGS['connection_data'].copy() - conn_info['database'] = 'postgres' - db = psycopg2.connect(**conn_info) - db.autocommit = True - cursor = db.cursor() - - try: - new_db_name = f'test_pgvector_{uuid4().hex}' - # Create the test database if it does not exist. - cursor.execute(f'DROP DATABASE IF EXISTS {new_db_name}') - db.commit() - cursor.execute(f'CREATE DATABASE {new_db_name};') - db.commit() - - # Reconnect to the new database - conn_info['database'] = new_db_name - db = psycopg2.connect(**conn_info) - db.autocommit = True - cursor = db.cursor() - - # Seed the database with data - curr_dir = os.path.dirname(os.path.realpath(__file__)) - seed_sql_path = os.path.join(curr_dir, 'data', 'seed.sql') - with open(seed_sql_path, 'r') as sql_seed_file: - cursor.execute(sql_seed_file.read()) - db.commit() - - finally: - # Close the cursor and the connection - cursor.close() - db.close() - - return new_db_name - - -@pytest.fixture(autouse=True) -def pgvector_database_name(client): - # Initialize a fresh DB for each test. - new_db_name = init_db() - # Connect new DB to MindsDB. - conn_info = CONNECTION_KWARGS['connection_data'].copy() - conn_info['database'] = new_db_name - example_db_data = { - 'database': { - 'name': new_db_name, - 'engine': 'pgvector', - 'parameters': conn_info - } - } - response = client.post('/api/databases', json=example_db_data, follow_redirects=True) - assert '201' in response.status - return new_db_name - - -@pytest.mark.skipif(os.environ.get('MDB_TEST_PGVECTOR_HOST') is None, reason='MDB_TEST_PGVECTOR_HOST environment variable not set') -@pytest.mark.skipif(os.environ.get('OPENAI_API_KEY') is None, reason='OPENAI_API_KEY environment variable not set') -class TestKnowledgeBaseCompletion: - def test_chat_completion(self, client, pgvector_database_name): - test_kb_name = 'test_chat_completion_kb' - create_request = { - 'knowledge_base': { - 'name': test_kb_name, - 'model': 'test_embedding_model', - 'storage': { - 'table': TEST_TABLE_NAME, - 'database': pgvector_database_name - } - } - } - create_kb_response = client.post('/api/projects/mindsdb/knowledge_bases', json=create_request, follow_redirects=True) - assert create_kb_response.status_code == HTTPStatus.CREATED - - # Insert documents to help answer the question. - rows_to_insert = [ - {'content': 'The capital of Tyler Fantasy RAG Land is MindsDB'} - ] - update_request = { - 'knowledge_base': { - 'rows': rows_to_insert - } - } - update_kb_response = client.put(f'/api/projects/mindsdb/knowledge_bases/{test_kb_name}', - json=update_request, follow_redirects=True) - assert update_kb_response.status_code == HTTPStatus.OK - - completion_request = { - 'query': 'What is the capital of Tyler Fantasy RAG Land?', - 'llm_model': 'gpt-4o' - } - response = client.post(f'/api/projects/mindsdb/knowledge_bases/{test_kb_name}/completions', - json=completion_request, follow_redirects=True) - assert response.status_code == HTTPStatus.OK - response_data = response.get_json() - assert 'message' in response_data - assert 'content' in response_data['message'] - assert 'context' in response_data['message'] - assert response_data['message']['role'] == 'assistant' - # Should get the right answer. - assert 'mindsdb' in response_data['message']['content'].lower() - - def test_context_completion_with_keywords(self, client, pgvector_database_name): - test_kb_name = 'test_context_completion_with_keywords' - create_request = { - 'knowledge_base': { - 'name': test_kb_name, - 'model': 'test_embedding_model', - 'storage': { - 'table': TEST_TABLE_NAME, - 'database': pgvector_database_name - } - } - } - create_kb_response = client.post('/api/projects/mindsdb/knowledge_bases', json=create_request, follow_redirects=True) - assert create_kb_response.status_code == HTTPStatus.CREATED - - # Insert documents for context. - rows_to_insert = [ - {'content': 'The capital of Tyler Fantasy RAG Land is MindsDB'}, - {'content': 'The population of Tyler Fantasy RAG Land is 6'} - ] - update_request = { - 'knowledge_base': { - 'rows': rows_to_insert - } - } - update_kb_response = client.put(f'/api/projects/mindsdb/knowledge_bases/{test_kb_name}', - json=update_request, follow_redirects=True) - assert update_kb_response.status_code == HTTPStatus.OK - - completion_request = { - 'query': 'Population of rag land', - 'keywords': 'population rag land', - 'type': 'context' - } - response = client.post(f'/api/projects/mindsdb/knowledge_bases/{test_kb_name}/completions', - json=completion_request, follow_redirects=True) - assert response.status_code == HTTPStatus.OK - response_data = response.get_json() - # Should have the most relevant document first. - assert 'documents' in response_data - assert len(response_data['documents']) == 2 - assert 'population' in response_data['documents'][0]['content'] - - def test_context_completion_with_metadata(self, client, pgvector_database_name): - test_kb_name = 'test_context_completion_with_metadata' - create_request = { - 'knowledge_base': { - 'name': test_kb_name, - 'model': 'test_embedding_model', - 'storage': { - 'table': TEST_TABLE_NAME, - 'database': pgvector_database_name - } - } - } - create_kb_response = client.post('/api/projects/mindsdb/knowledge_bases', json=create_request, follow_redirects=True) - assert create_kb_response.status_code == HTTPStatus.CREATED - - # Insert documents for context. - rows_to_insert = [ - {'content': 'The capital of Tyler Fantasy RAG Land is MindsDB', 'author': 'Danya'}, - {'content': 'The population of Tyler Fantasy RAG Land is 6', 'author': 'Tyler'}, - {'content': 'Totally unrelated', 'author': 'Tyler'} - - ] - update_request = { - 'knowledge_base': { - 'rows': rows_to_insert - } - } - update_kb_response = client.put(f'/api/projects/mindsdb/knowledge_bases/{test_kb_name}', - json=update_request, follow_redirects=True) - assert update_kb_response.status_code == HTTPStatus.OK - - completion_request = { - 'query': 'Population of rag land', - 'metadata': { - 'author': 'Tyler' - }, - 'type': 'context' - } - response = client.post(f'/api/projects/mindsdb/knowledge_bases/{test_kb_name}/completions', - json=completion_request, follow_redirects=True) - assert response.status_code == HTTPStatus.OK - response_data = response.get_json() - assert 'documents' in response_data - # Only 2 have matching metadata. - assert len(response_data['documents']) == 2 - # Should have the most relevant document first. - assert 'population' in response_data['documents'][0]['content'] - - def test_context_completion_with_keywords_and_metadata(self, client, pgvector_database_name): - test_kb_name = 'test_context_completion_with_keywords_and_metadata' - create_request = { - 'knowledge_base': { - 'name': test_kb_name, - 'model': 'test_embedding_model', - 'storage': { - 'table': TEST_TABLE_NAME, - 'database': pgvector_database_name - } - } - } - create_kb_response = client.post('/api/projects/mindsdb/knowledge_bases', json=create_request, follow_redirects=True) - assert create_kb_response.status_code == HTTPStatus.CREATED - - # Insert documents for context. - rows_to_insert = [ - {'content': 'The capital of Tyler Fantasy RAG Land is MindsDB', 'author': 'Danya'}, - {'content': 'The population of Tyler Fantasy RAG Land is 6', 'author': 'Tyler'}, - {'content': 'Totally unrelated', 'author': 'Tyler'} - - ] - update_request = { - 'knowledge_base': { - 'rows': rows_to_insert - } - } - update_kb_response = client.put(f'/api/projects/mindsdb/knowledge_bases/{test_kb_name}', - json=update_request, follow_redirects=True) - assert update_kb_response.status_code == HTTPStatus.OK - - completion_request = { - 'query': 'Population of rag land', - 'metadata': { - 'author': 'Tyler' - }, - 'keywords': 'rag land population', - 'type': 'context' - } - response = client.post(f'/api/projects/mindsdb/knowledge_bases/{test_kb_name}/completions', - json=completion_request, follow_redirects=True) - assert response.status_code == HTTPStatus.OK - response_data = response.get_json() - assert 'documents' in response_data - # Only 2 have matching metadata. - assert len(response_data['documents']) == 2 - # Should have the most relevant document first. - assert 'population' in response_data['documents'][0]['content'] diff --git a/tests/unused/integration/metrics/test_metrics.py b/tests/unused/integration/metrics/test_metrics.py deleted file mode 100644 index 970b592d834..00000000000 --- a/tests/unused/integration/metrics/test_metrics.py +++ /dev/null @@ -1,68 +0,0 @@ -import datetime -import os -import pytest -import requests -import time -from typing import Dict - -from tests.integration.utils.http_test_helpers import HTTPHelperMixin -from tests.integration.conftest import HTTP_API_ROOT - - -def _get_metrics(): - url = HTTP_API_ROOT.rstrip("api") + "metrics" - print(f"Getting metrics from {url}") - resp = requests.get(url).text - print(f"Metrics response: {resp}") - return resp - - -def _wait_for_metric(name: str, labels: Dict[str, str], timeout: datetime.timedelta = None): - if timeout is None: - timeout = datetime.timedelta(seconds=30) - start_time = datetime.datetime.now() - while datetime.datetime.now() - start_time < timeout: - metrics = _get_metrics() - for metrics_line in metrics.split('\n'): - if name not in metrics_line: - continue - # Check labels match metric. - found = True - for label_name, label_value in labels.items(): - if f'{label_name}="{label_value}"' not in metrics_line: - found = False - break - if found: - print(f"Found metric: {metrics_line}") - metrics_value = metrics_line.split()[-1] - return float(metrics_value) - time.sleep(0.5) - return -1 - - -class TestMetrics(HTTPHelperMixin): - @pytest.mark.skipif(("localhost" in HTTP_API_ROOT or "127.0.0.1" in HTTP_API_ROOT) and os.getenv('PROMETHEUS_MULTIPROC_DIR') is None, reason="PROMETHEUS_MULTIPROC_DIR environment variable is not set") - def test_http_metrics(self): - # Make an HTTP request and check for updated metrics. - api_metric_labels = { - 'endpoint': '/util/ping_native', - 'method': 'GET', - 'status': '200' - } - - before_metric = _wait_for_metric( - 'mindsdb_rest_api_latency_seconds_count', - api_metric_labels, - ) - print(f"Before metric: {before_metric}") - _ = self.api_request('get', '/util/ping_native') - assert _wait_for_metric( - 'mindsdb_rest_api_latency_seconds_count', - api_metric_labels, - ) == before_metric + 1 - # Check multiproc dir is populated. - multiproc_dir = os.getenv('PROMETHEUS_MULTIPROC_DIR') - # We can't check this dir if we're running against a remote env. - if multiproc_dir is not None: - assert os.path.isdir(multiproc_dir) - assert len(os.listdir(os.getenv('PROMETHEUS_MULTIPROC_DIR'))) > 0 diff --git a/tests/unused/integration/rag/test_rag_search_kwargs.py b/tests/unused/integration/rag/test_rag_search_kwargs.py deleted file mode 100644 index 7ee668790fd..00000000000 --- a/tests/unused/integration/rag/test_rag_search_kwargs.py +++ /dev/null @@ -1,271 +0,0 @@ -import os -import uuid -import pytest -from unittest.mock import Mock, patch -from langchain_openai import ChatOpenAI, OpenAIEmbeddings -from langchain_core.documents import Document -from langchain.vectorstores.base import VectorStore -import tempfile -import shutil -from langchain_community.vectorstores import Chroma -from langchain_text_splitters import RecursiveCharacterTextSplitter - -from mindsdb.integrations.utilities.rag.settings import ( - RAGPipelineModel, - RetrieverType, - SearchKwargs, - SearchType, - MultiVectorRetrieverMode, - DEFAULT_LLM_MODEL, - DEFAULT_LLM_ENDPOINT -) -from mindsdb.integrations.utilities.rag.pipelines.rag import LangChainRAGPipeline - -requires_openai = pytest.mark.skipif( - not os.getenv("OPENAI_API_KEY"), - reason="OPENAI_API_KEY environment variable not set" -) - - -@pytest.fixture -def chat_llm(): - api_key = os.getenv("OPENAI_API_KEY") - if not api_key: - pytest.skip("OPENAI_API_KEY environment variable not set") - return ChatOpenAI( - model=DEFAULT_LLM_MODEL, - openai_api_base=DEFAULT_LLM_ENDPOINT, - api_key=api_key - ) - - -@pytest.fixture -def embeddings(): - api_key = os.getenv("OPENAI_API_KEY") - if not api_key: - pytest.skip("OPENAI_API_KEY environment variable not set") - return OpenAIEmbeddings(api_key=api_key) - - -class MockVectorStore(VectorStore): - def add_texts(self, *args, **kwargs): - pass - - def similarity_search(self, *args, **kwargs): - pass - - def as_retriever(self, **kwargs): - return Mock() - - -@pytest.fixture -def sample_documents(): - return [ - Document(page_content="Test document 1", metadata={"source": "test1"}), - Document(page_content="Test document 2", metadata={"source": "test2"}) - ] - - -@pytest.fixture -def vector_store_path(): - temp_dir = tempfile.mkdtemp() - yield temp_dir - shutil.rmtree(temp_dir) - - -@pytest.fixture -def vector_store(embeddings, vector_store_path): - return Chroma( - embedding_function=embeddings, - persist_directory=vector_store_path - ) - - -@pytest.fixture -def base_config(sample_documents, chat_llm, embeddings, vector_store): - return RAGPipelineModel( - documents=sample_documents, - vector_store=vector_store, - embedding_model=embeddings, - llm=chat_llm - ) - - -class TestRAGSearchKwargs: - @pytest.fixture(autouse=True) - def setup(self, base_config, sample_documents, chat_llm, embeddings, vector_store): - """Setup test configuration with fixtures""" - self.base_config = base_config - self.sample_documents = sample_documents - self.chat_llm = chat_llm - self.embeddings = embeddings - self.vector_store = vector_store - self.base_dict = { - 'documents': self.sample_documents, - 'vector_store': self.vector_store, - 'embedding_model': self.embeddings, - 'llm': self.chat_llm - } - - @requires_openai - def test_vector_store_retriever_search_kwargs(self): - config = RAGPipelineModel( - **self.base_dict, - search_type=SearchType.SIMILARITY_SCORE_THRESHOLD, - search_kwargs=SearchKwargs( - k=3, - score_threshold=0.5 - ), - retriever_type=RetrieverType.VECTOR_STORE - ) - mock_retriever = Mock() - mock_retriever.search_kwargs = {"k": 3, "score_threshold": 0.5} - with patch('mindsdb.integrations.utilities.rag.vector_store.VectorStoreOperator') as mock_vs_op: - mock_vs_op.return_value.vector_store.as_retriever.return_value = mock_retriever - _ = LangChainRAGPipeline.from_retriever(config) - assert mock_retriever.search_kwargs == {"k": 3, "score_threshold": 0.5} - - def test_auto_retriever_search_kwargs(self): - config = RAGPipelineModel( - **self.base_dict, - search_type=SearchType.MMR, - search_kwargs=SearchKwargs( - k=2, - fetch_k=4, - lambda_mult=0.7 - ), - retriever_type=RetrieverType.AUTO - ) - mock_retriever = Mock() - mock_retriever.search_kwargs = {"k": 2, "fetch_k": 4, "lambda_mult": 0.7} - mock_llm_response = Mock() - mock_llm_response.content = '[{"name": "source", "description": "Source field", "type": "string"}]' - with patch('mindsdb.integrations.utilities.rag.retrievers.auto_retriever.AutoRetriever') as MockAutoRetriever, \ - patch('langchain_openai.chat_models.ChatOpenAI.invoke', return_value=mock_llm_response): - mock_auto = Mock() - mock_auto.as_runnable.return_value = mock_retriever - MockAutoRetriever.return_value = mock_auto - _ = LangChainRAGPipeline.from_auto_retriever(config) - assert mock_retriever.search_kwargs == {"k": 2, "fetch_k": 4, "lambda_mult": 0.7} - - def test_search_kwargs_validation(self): - """Test the validation rules for SearchKwargs""" - # Test fetch_k validation for MMR search type - with pytest.raises(ValueError, match="fetch_k must be greater than k"): - RAGPipelineModel( - **self.base_dict, - search_type=SearchType.MMR, - search_kwargs=SearchKwargs( - k=5, - fetch_k=3, - lambda_mult=0.7 - ) - ) - - # Test MMR parameter requirements - with pytest.raises(ValueError, match="lambda_mult is required when using fetch_k"): - RAGPipelineModel( - **self.base_dict, - search_type=SearchType.MMR, - search_kwargs=SearchKwargs( - k=3, - fetch_k=5 - ) - ) - - with pytest.raises(ValueError, match="fetch_k is required when using lambda_mult"): - RAGPipelineModel( - **self.base_dict, - search_type=SearchType.MMR, - search_kwargs=SearchKwargs( - k=3, - lambda_mult=0.7 - ) - ) - - # Test score_threshold requirement for SIMILARITY_SCORE_THRESHOLD - with pytest.raises(ValueError, match="score_threshold is required"): - RAGPipelineModel( - **self.base_dict, - search_type=SearchType.SIMILARITY_SCORE_THRESHOLD, - search_kwargs=SearchKwargs( - k=3 - ) - ) - - def test_search_type_compatibility(self): - """Test that search kwargs match the search type""" - # Test MMR search configuration - config = RAGPipelineModel( - **self.base_dict, - search_type=SearchType.MMR, - search_kwargs=SearchKwargs( - k=3, - fetch_k=6, - lambda_mult=0.7 - ) - ) - assert config.search_kwargs.fetch_k == 6 - assert config.search_kwargs.lambda_mult == 0.7 - - # Test similarity_score_threshold configuration - config = RAGPipelineModel( - **self.base_dict, - search_type=SearchType.SIMILARITY_SCORE_THRESHOLD, - search_kwargs=SearchKwargs( - k=3, - score_threshold=0.5 - ) - ) - assert config.search_kwargs.score_threshold == 0.5 - - # Test basic similarity configuration - config = RAGPipelineModel( - **self.base_dict, - search_type=SearchType.SIMILARITY, - search_kwargs=SearchKwargs( - k=3, - filter={"source": "test1"} - ) - ) - assert config.search_kwargs.filter == {"source": "test1"} - - def test_multi_vector_retriever_search_kwargs(self): - """Test search kwargs for multi vector retriever""" - config = RAGPipelineModel( - **self.base_dict, - search_type=SearchType.SIMILARITY, - search_kwargs=SearchKwargs( - k=5, - filter={"source": "test1"} - ), - retriever_type=RetrieverType.MULTI, - multi_retriever_mode=MultiVectorRetrieverMode.BOTH - ) - - mock_retriever = Mock() - mock_retriever.search_kwargs = {"k": 5, "filter": {"source": "test1"}} - - with patch('mindsdb.integrations.utilities.rag.pipelines.rag.MultiVectorRetriever') as MockMultiRetrieverClass: - class MockMultiRetriever: - def __init__(self, config): - self.text_splitter = RecursiveCharacterTextSplitter( - chunk_size=config.chunk_size, - chunk_overlap=config.chunk_overlap - ) - self.documents = config.documents - self.config = config - - def as_runnable(self): - return mock_retriever - - def _split_documents(self): - return [], [] - - def _generate_id_and_split_document(self, doc): - return str(uuid.uuid4()), [doc] - - MockMultiRetrieverClass.side_effect = MockMultiRetriever - - _ = LangChainRAGPipeline.from_multi_vector_retriever(config) - assert mock_retriever.search_kwargs == {"k": 5, "filter": {"source": "test1"}} diff --git a/tests/unused/integrations/utilities/rag/rerankers/test_openai_reranker.py b/tests/unused/integrations/utilities/rag/rerankers/test_openai_reranker.py deleted file mode 100644 index 7b0c5cafa91..00000000000 --- a/tests/unused/integrations/utilities/rag/rerankers/test_openai_reranker.py +++ /dev/null @@ -1,47 +0,0 @@ -from langchain.schema import Document -import pytest - -from mindsdb.integrations.utilities.rag.rerankers.reranker_compressor import LLMReranker -from mindsdb.integrations.utilities.rag.settings import RerankerConfig - - -@pytest.mark.asyncio -async def test_openai_reranker(): - openai_reranker = LLMReranker() - results = await openai_reranker.compress_documents( - documents=[Document(page_content="Jack declared that he likes cats more than dogs"), - Document(page_content="Jack declared that he likes AI")], - query="Jack's opinion on animals", - ) - assert len(results) == 1 - assert "cats" in results[0].page_content - - -@pytest.mark.asyncio -async def test_openai_reranker_diff_threshold(): - openai_reranker = LLMReranker(filtering_threshold=0.6) - assert openai_reranker.filtering_threshold == 0.6 - results = await openai_reranker.compress_documents( - documents=[Document(page_content="Jack declared that he likes cats more than dogs"), - Document(page_content="Jack declared that he likes AI")], - query="Jack's opinion on animals", - ) - assert len(results) == 1 - assert "cats" in results[0].page_content - assert openai_reranker.filtering_threshold == 0.6 - - -@pytest.mark.asyncio -async def test_openai_reranker_config(): - config = RerankerConfig(filtering_threshold=0.6, model="gpt-3.5-turbo", base_url="https://api.openai.com/v1") - openai_reranker = LLMReranker(filtering_threshold=config.filtering_threshold, model=config.model, - base_url=config.base_url) - assert openai_reranker.filtering_threshold == 0.6 - results = await openai_reranker.compress_documents( - documents=[Document(page_content="Jack declared that he likes cats more than dogs"), - Document(page_content="Jack declared that he likes AI")], - query="Jack's opinion on animals", - ) - assert len(results) == 1 - assert "cats" in results[0].page_content - assert openai_reranker.filtering_threshold == 0.6 diff --git a/tests/unused/integrations/utilities/rag/retrievers/test_multi_hop_retriever.py b/tests/unused/integrations/utilities/rag/retrievers/test_multi_hop_retriever.py deleted file mode 100644 index 9cbb199f966..00000000000 --- a/tests/unused/integrations/utilities/rag/retrievers/test_multi_hop_retriever.py +++ /dev/null @@ -1,127 +0,0 @@ -from typing import List, Any, Optional - -import pytest -from langchain_core.documents import Document -from langchain_core.retrievers import BaseRetriever -from langchain_core.language_models import BaseChatModel -from langchain_core.messages import BaseMessage - -from mindsdb.integrations.utilities.rag.retrievers import MultiHopRetriever - - -# Simple template for testing -TEST_TEMPLATE = """Question: {question} -Context: {context} -Generate follow-up questions:""" - - -class MockRetriever(BaseRetriever): - """Simple mock retriever that returns predefined documents""" - def _get_relevant_documents(self, query: str, **kwargs) -> List[Document]: - if "Wright brothers" in query: - return [Document(page_content="The Wright brothers invented the airplane.")] - if "World War 1" in query: - return [Document(page_content="Airplanes were used extensively in WWI.")] - return [] - - -class MockLLM(BaseChatModel): - """Simple mock LLM that returns predefined responses""" - @property - def _llm_type(self) -> str: - return "mock" - - def _generate(self, messages: List[BaseMessage], stop: Optional[List[str]] = None, run_manager: Optional[Any] = None, **kwargs) -> Any: - raise NotImplementedError("Not needed for tests") - - def invoke(self, input_str: str, **kwargs) -> str: - if "Wright brothers" in str(input_str): - return '["How were airplanes used in World War 1?"]' - return "[]" - - -class InvalidOutputLLM(BaseChatModel): - """Mock LLM that always returns invalid JSON""" - @property - def _llm_type(self) -> str: - return "mock" - - def _generate(self, messages: List[BaseMessage], stop: Optional[List[str]] = None, run_manager: Optional[Any] = None, **kwargs) -> Any: - raise NotImplementedError("Not needed for tests") - - def invoke(self, input_str: str, **kwargs) -> str: - return "invalid json" - - -@pytest.fixture -def mock_retriever(): - return MockRetriever() - - -@pytest.fixture -def mock_llm(): - return MockLLM() - - -def test_multi_hop_retriever_basic_functionality(mock_retriever, mock_llm): - """Test the basic functionality of MultiHopRetriever""" - retriever = MultiHopRetriever( - base_retriever=mock_retriever, - llm=mock_llm, - max_hops=2, - reformulation_template=TEST_TEMPLATE - ) - - # Test with a query that should trigger follow-up - docs = retriever._get_relevant_documents("Tell me about the Wright brothers") - - # Should have documents from both queries - assert len(docs) == 2 - assert any("Wright brothers" in doc.page_content for doc in docs) - assert any("WWI" in doc.page_content for doc in docs) - - -def test_multi_hop_retriever_no_results(mock_retriever, mock_llm): - """Test behavior when no documents are found""" - retriever = MultiHopRetriever( - base_retriever=mock_retriever, - llm=mock_llm, - max_hops=2, - reformulation_template=TEST_TEMPLATE - ) - - # Test with a query that won't find any documents - docs = retriever._get_relevant_documents("Something unrelated") - - # Should have no documents - assert len(docs) == 0 - - -def test_multi_hop_retriever_invalid_llm_output(mock_retriever): - """Test handling of invalid LLM output""" - retriever = MultiHopRetriever( - base_retriever=mock_retriever, - llm=InvalidOutputLLM(), - max_hops=2, - reformulation_template=TEST_TEMPLATE - ) - - # Should still work and return initial results - docs = retriever._get_relevant_documents("Tell me about the Wright brothers") - assert len(docs) == 1 - assert "Wright brothers" in docs[0].page_content - - -def test_multi_hop_retriever_max_hops(mock_retriever, mock_llm): - """Test that max_hops is respected""" - retriever = MultiHopRetriever( - base_retriever=mock_retriever, - llm=mock_llm, - max_hops=1, # Only allow 1 hop - reformulation_template=TEST_TEMPLATE - ) - - # Should only get initial documents - docs = retriever._get_relevant_documents("Tell me about the Wright brothers") - assert len(docs) == 1 - assert "Wright brothers" in docs[0].page_content diff --git a/tests/unused/integrations/utilities/rag/test_file_loader.py b/tests/unused/integrations/utilities/rag/test_file_loader.py deleted file mode 100644 index 092ca0936f2..00000000000 --- a/tests/unused/integrations/utilities/rag/test_file_loader.py +++ /dev/null @@ -1,41 +0,0 @@ -from mindsdb.integrations.utilities.rag.loaders.file_loader import FileLoader - - -def test_load_pdf(): - loader = FileLoader('./tests/data/test.pdf') - docs = loader.load() - # Each page is a doc. - assert len(docs) == 3 - assert 'THE CASE FOR MACHINE LEARNING' in docs[0].page_content - assert 'INTRODUCTION' in docs[1].page_content - assert 'THE CASE FOR \nDEMOCRATIZING \nMACHINE LEARNING' in docs[2].page_content - - -def test_load_csv(): - loader = FileLoader('./tests/data/movies.csv') - docs = loader.load() - # Each row is a doc. - assert len(docs) == 10 - assert 'Toy Story' in docs[0].page_content - assert 'GoldenEye' in docs[9].page_content - - -def test_load_html(): - loader = FileLoader('./tests/data/test.html') - docs = loader.load() - assert len(docs) == 1 - assert 'Some intro text about Foo' in docs[0].page_content - - -def test_load_md(): - loader = FileLoader('./mindsdb/integrations/handlers/langchain_handler/README.md') - docs = loader.load() - assert len(docs) == 1 - assert 'This documentation describes the integration of MindsDB with LangChain' in docs[0].page_content - - -def test_load_text(): - loader = FileLoader('./tests/data/test.txt') - docs = loader.load() - assert len(docs) == 1 - assert 'This is a test plaintext file' in docs[0].page_content diff --git a/tests/unused/integrations/utilities/rag/test_file_splitter.py b/tests/unused/integrations/utilities/rag/test_file_splitter.py deleted file mode 100644 index ce757284b4b..00000000000 --- a/tests/unused/integrations/utilities/rag/test_file_splitter.py +++ /dev/null @@ -1,164 +0,0 @@ -from unittest.mock import patch - -from langchain_core.documents import Document -from langchain_text_splitters import MarkdownHeaderTextSplitter, HTMLHeaderTextSplitter, RecursiveCharacterTextSplitter -from mindsdb.integrations.utilities.rag.splitters.file_splitter import FileSplitter, FileSplitterConfig - - -def test_split_documents_pdf(): - pdf_doc = Document( - page_content='This is a test PDF file. Let us try to do some splitting!', - metadata={'extension': '.pdf'} - ) - recursive_splitter = RecursiveCharacterTextSplitter() - file_splitter = FileSplitter(FileSplitterConfig( - recursive_splitter=recursive_splitter - )) - split_pdf_docs = file_splitter.split_documents([pdf_doc]) - assert len(split_pdf_docs) > 0 - - -def test_split_documents_md(): - md_content = ''' - # Unit Testing for Dummies - This MD document covers how to write basic unit tests. - ## Introduction - Unit testing helps ensure code works as expected and prevents regressions. Time to dive in! - ## How to Write Tests - To be continued! -''' - md_doc = Document( - page_content=md_content, - metadata={'extension': '.md'} - ) - headers_to_split_on = [ - ('#', 'Header 1'), - ('##', 'Header 2'), - ] - md_text_splitter = MarkdownHeaderTextSplitter(headers_to_split_on=headers_to_split_on) - file_splitter = FileSplitter(FileSplitterConfig( - markdown_splitter=md_text_splitter - )) - split_md_docs = file_splitter.split_documents([md_doc]) - assert len(split_md_docs) == 3 - # Check we actually split on headers. - assert 'This MD document covers how to write basic unit tests.' in split_md_docs[0].page_content - assert 'Unit testing helps ensure code works as expected and prevents regressions. Time to dive in!' in split_md_docs[1].page_content - assert 'To be continued!' in split_md_docs[2].page_content - - -def test_split_documents_html(): - html_content = ''' - - - -
-

Foo

-

Some intro text about Foo.

-
-

Bar main section

-

Some intro text about Bar.

-

Bar subsection 1

-

Some text about the first subtopic of Bar.

-

Bar subsection 2

-

Some text about the second subtopic of Bar.

-
-
-

Baz

-

Some text about Baz

-
-
-

Some concluding text about Foo

-
- - -''' - headers_to_split_on = [ - ('h1', 'Header 1'), - ('h2', 'Header 2'), - ('h3', 'Header 3') - ] - html_text_splitter = HTMLHeaderTextSplitter(headers_to_split_on=headers_to_split_on) - file_splitter = FileSplitter(FileSplitterConfig( - html_splitter=html_text_splitter - )) - html_doc = Document( - page_content=html_content, - metadata={'extension': '.html'} - ) - split_html_docs = file_splitter.split_documents([html_doc]) - assert len(split_html_docs) == 8 - # # Check we actually split on headers. - assert 'Foo' in split_html_docs[0].page_content - assert 'Some intro text about Foo' in split_html_docs[1].page_content - assert 'Some intro text about Bar' in split_html_docs[2].page_content - assert 'Some text about the first subtopic of Bar' in split_html_docs[3].page_content - assert 'Some text about the second subtopic of Bar' in split_html_docs[4].page_content - assert 'Baz' in split_html_docs[5].page_content - assert 'Some text about Baz' in split_html_docs[6].page_content - assert 'Some concluding text about Foo' in split_html_docs[7].page_content - - -def test_split_documents_default(): - recursive_splitter = RecursiveCharacterTextSplitter() - file_splitter = FileSplitter(FileSplitterConfig( - recursive_splitter=recursive_splitter - )) - txt_doc = Document( - page_content='This is a text file!', - metadata={'extension': '.txt'} - ) - split_txt_docs = file_splitter.split_documents([txt_doc]) - assert len(split_txt_docs) == 1 - assert 'This is a text file!' in split_txt_docs[0].page_content - - -@patch('mindsdb.integrations.utilities.rag.splitters.file_splitter.MarkdownHeaderTextSplitter') -def test_split_documents_failover(mock_md_splitter): - md_content = ''' - # Unit Testing for Dummies - This MD document covers how to write basic unit tests. - ## Introduction - Unit testing helps ensure code works as expected and prevents regressions. Time to dive in! - ## How to Write Tests - To be continued! -''' - mock_md_splitter.split_text.side_effect = Exception('Something went wrong!') - file_splitter = FileSplitter(FileSplitterConfig( - markdown_splitter=mock_md_splitter - )) - md_doc = Document( - page_content=md_content, - metadata={'extension': '.md'} - ) - - # Should throw an exception and go to default. - split_md_docs = file_splitter.split_documents([md_doc]) - assert len(split_md_docs) > 0 - - -@patch('mindsdb.integrations.utilities.rag.splitters.file_splitter.MarkdownHeaderTextSplitter') -def test_split_documents_no_failover(mock_md_splitter): - md_content = ''' - # Unit Testing for Dummies - This MD document covers how to write basic unit tests. - ## Introduction - Unit testing helps ensure code works as expected and prevents regressions. Time to dive in! - ## How to Write Tests - To be continued! -''' - mock_md_splitter.split_text.side_effect = Exception('Something went wrong!') - file_splitter = FileSplitter(FileSplitterConfig( - markdown_splitter=mock_md_splitter - )) - md_doc = Document( - page_content=md_content, - metadata={'extension': '.md'} - ) - - # Should throw an exception. - try: - _ = file_splitter.split_documents([md_doc], default_failover=False) - except Exception: - return - assert False diff --git a/tests/unused/interfaces/agents/test_agents_controller.py b/tests/unused/interfaces/agents/test_agents_controller.py deleted file mode 100644 index ba5c4b41028..00000000000 --- a/tests/unused/interfaces/agents/test_agents_controller.py +++ /dev/null @@ -1,43 +0,0 @@ -from unittest.mock import patch - -import pandas as pd - -from mindsdb.interfaces.storage import db -from mindsdb.interfaces.agents.agents_controller import AgentsController - - -@patch('mindsdb.api.executor.datahub.datanodes.project_datanode.ProjectDataNode') -@patch('mindsdb.api.executor.datahub.datahub.InformationSchemaDataNode') -@patch('mindsdb.interfaces.model.model_controller.ModelController') -def test_get_completion(mock_model_controller, mock_schema_datanode, mock_project_datanode): - mock_project_datanode_instance = mock_project_datanode.return_value - mock_datanode_instance = mock_schema_datanode.return_value - mock_datanode_instance.get.return_value = mock_project_datanode_instance - mock_model_controller_instance = mock_model_controller.return_value - mock_model_controller_instance.get_model.return_value = { - 'model_name': 'test_model', - 'predict': 'answer', - 'problem_definition': { - 'using': - { - 'prompt_template': 'What is the meaning of life?' - } - } - } - agents_controller = AgentsController( - mock_datanode_instance, - model_controller=mock_model_controller_instance) - - completion_response = {'answer': '42'} - df = pd.DataFrame.from_records([completion_response]) - mock_project_datanode_instance.predict.return_value = df - agent = db.Agents() - agent.model_name = 'test_model' - agent.provider = 'mindsdb' - agent.params = {} - messages = [{'question': 'What is the meaning of life?', 'answer': None}] - completion_df = agents_controller.get_completion(agent, messages) - - assert not completion_df.empty - assert 'answer' in completion_df.columns - assert completion_df['answer'].loc[0] == '42' diff --git a/tests/unused/interfaces/agents/test_sql_agent_cache.py b/tests/unused/interfaces/agents/test_sql_agent_cache.py deleted file mode 100644 index 3241f2b9b2c..00000000000 --- a/tests/unused/interfaces/agents/test_sql_agent_cache.py +++ /dev/null @@ -1,28 +0,0 @@ -import pytest -from unittest.mock import MagicMock, patch - -from mindsdb.interfaces.skills.sql_agent import SQLAgent - - -@pytest.fixture -def sql_agent_setup(): - command_executor = MagicMock() - cache_mock = MagicMock() - sql_agent = SQLAgent(command_executor=command_executor, database='test_db', cache=cache_mock) - return sql_agent, cache_mock - - -def test_get_table_info_cache_miss(sql_agent_setup): - sql_agent, cache_mock = sql_agent_setup - cache_mock.get.return_value = None - with patch.object(SQLAgent, '_fetch_table_info') as mock_fetch_table_info: - sql_agent.get_table_info(['test_table']) - mock_fetch_table_info.assert_called_once() - - -def test_get_table_info_cache_hit(sql_agent_setup): - sql_agent, cache_mock = sql_agent_setup - cache_mock.get.return_value = {'test_table': 'table_info'} - with patch.object(SQLAgent, '_fetch_table_info') as mock_fetch_table_info: - sql_agent.get_table_info(['test_table']) - assert not mock_fetch_table_info.called From 49cfe5da62f0d0a394d285b15395a70ac59359ca Mon Sep 17 00:00:00 2001 From: ZoranPandovski Date: Fri, 19 Dec 2025 15:50:53 +0100 Subject: [PATCH 2/4] Rmv unused tests --- tests/unused/load/__init__.py | 0 tests/unused/load/tasks.py | 49 - tests/unused/load/test_postgresql.py | 15 - tests/unused/load/tests_start.py | 25 - .../unit/api/http/knowledge_bases_test.py | 1049 ----------------- .../unused/unit/broken/test_knowledge_base.py | 452 ------- .../test_map_reduce_summarizer_chain.py | 76 -- .../unused/unit/broken/test_sql_retriever.py | 313 ----- tests/unused/unit/executor/test_udf.py | 117 -- tests/unused/unit/handler_tests/__init__.py | 0 .../unit/handler_tests/data/pgvector/seed.sql | 20 - .../data/rag_pipelines/auto_retriever.yml | 1 - .../rag_pipelines/multi_retriever_both.yml | 3 - .../rag_pipelines/multi_retriever_split.yml | 3 - .../multi_retriever_summarize.yml | 3 - .../rag_pipelines/vector_retriever_chroma.yml | 3 - .../vector_retriever_pgvector.yml | 3 - .../test_apache_doris_handler.py | 104 -- .../unit/handler_tests/test_aqicn_handler.py | 50 - 19 files changed, 2286 deletions(-) delete mode 100644 tests/unused/load/__init__.py delete mode 100644 tests/unused/load/tasks.py delete mode 100644 tests/unused/load/test_postgresql.py delete mode 100644 tests/unused/load/tests_start.py delete mode 100644 tests/unused/unit/api/http/knowledge_bases_test.py delete mode 100644 tests/unused/unit/broken/test_knowledge_base.py delete mode 100644 tests/unused/unit/broken/test_map_reduce_summarizer_chain.py delete mode 100644 tests/unused/unit/broken/test_sql_retriever.py delete mode 100644 tests/unused/unit/executor/test_udf.py delete mode 100644 tests/unused/unit/handler_tests/__init__.py delete mode 100644 tests/unused/unit/handler_tests/data/pgvector/seed.sql delete mode 100644 tests/unused/unit/handler_tests/data/rag_pipelines/auto_retriever.yml delete mode 100644 tests/unused/unit/handler_tests/data/rag_pipelines/multi_retriever_both.yml delete mode 100644 tests/unused/unit/handler_tests/data/rag_pipelines/multi_retriever_split.yml delete mode 100644 tests/unused/unit/handler_tests/data/rag_pipelines/multi_retriever_summarize.yml delete mode 100644 tests/unused/unit/handler_tests/data/rag_pipelines/vector_retriever_chroma.yml delete mode 100644 tests/unused/unit/handler_tests/data/rag_pipelines/vector_retriever_pgvector.yml delete mode 100644 tests/unused/unit/handler_tests/test_apache_doris_handler.py delete mode 100644 tests/unused/unit/handler_tests/test_aqicn_handler.py diff --git a/tests/unused/load/__init__.py b/tests/unused/load/__init__.py deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/tests/unused/load/tasks.py b/tests/unused/load/tasks.py deleted file mode 100644 index 9a4e364e9c2..00000000000 --- a/tests/unused/load/tasks.py +++ /dev/null @@ -1,49 +0,0 @@ -from locust import SequentialTaskSet, task, events -from tests.utils.query_generator import QueryGenerator as query -from tests.utils.config import get_value_from_json_env_var, generate_random_db_name - -from mindsdb.utilities import log - -logger = log.getLogger(__name__) - - -class BaseDBConnectionBehavior(SequentialTaskSet): - def on_start(self): - """This method is called once for each user when they start.""" - self.query_generator = query() - self.random_db_name = generate_random_db_name(f"{self.db_type}_datasource") - self.create_new_datasource() - - def __post_query(self, query): - try: - response = self.client.post('/api/sql/query', json={'query': query}) - response.raise_for_status() - assert response.json()['type'] != 'error' - return response - except Exception as e: - logger.error(f'Error running {query}: {e}') - events.request.fire(request_type="POST", name="/api/sql/query", response_time=0, response_length=0, exception=e) - self.interrupt(reschedule=True) - - def create_new_datasource(self): - """This method creates a new data source.""" - db_config = get_value_from_json_env_var("INTEGRATIONS_CONFIG", self.db_type) - query = self.query_generator.create_database_query( - self.random_db_name, - self.db_type, - db_config - ) - self.__post_query(query) - - @task - def select_integration_query(self): - """This task performs a SELECT query from integration.""" - query = f'SELECT * FROM {self.random_db_name}.{self.table_name} LIMIT 10' - self.__post_query(query) - - @task - def run_native_query(self): - """This task runs a native DB select query.""" - for n_query in self.native_queries: - query = f'SELECT * FROM {self.random_db_name}( {n_query})' - self.__post_query(query) diff --git a/tests/unused/load/test_postgresql.py b/tests/unused/load/test_postgresql.py deleted file mode 100644 index d7e137ab5c8..00000000000 --- a/tests/unused/load/test_postgresql.py +++ /dev/null @@ -1,15 +0,0 @@ -from tests.load.tasks import BaseDBConnectionBehavior - - -class PostgreSQLConnectionBehavior(BaseDBConnectionBehavior): - """ - This class defines the behavior of a PostgreSQL connection. - @TODO: Read query values from sql_queries.json file - """ - db_type = "postgres" - table_name = "solar_flare_data" - native_queries = ["native_query_average", "native_query_aggregation", "native_query_max", "native_query_grouping"] - native_query_aggregation = f"SELECT COUNT(*) AS total_flares FROM tests.{table_name};" - native_query_average = f"SELECT AVG(peak_c_per_s) AS avg_peak_counts FROM tests.{table_name};" - native_query_max = f"SELECT MAX(energy_kev) AS max_energy FROM tests.{table_name};" - native_query_grouping = f"SELECT active_region_ar, COUNT(*) AS flare_count FROM tests.{table_name} GROUP BY active_region_ar;" diff --git a/tests/unused/load/tests_start.py b/tests/unused/load/tests_start.py deleted file mode 100644 index 3eaed9bf111..00000000000 --- a/tests/unused/load/tests_start.py +++ /dev/null @@ -1,25 +0,0 @@ -from locust import between, HttpUser -from tests.load.test_postgresql import PostgreSQLConnectionBehavior -from tests.utils.config import get_value_from_json_env_var - -from mindsdb.utilities import log - -logger = log.getLogger(__name__) - - -class DBConnectionUser(HttpUser): - tasks = [PostgreSQLConnectionBehavior] - wait_time = between(5, 15) - config = get_value_from_json_env_var("INTEGRATIONS_CONFIG", "mindsdb_cloud") - host = config['host'] - - def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) - try: - response = self.client.post('/cloud/login', json={ - 'email': self.config['user'], - 'password': self.config['password'] - }) - response.raise_for_status() - except Exception as e: - logger.error(f'Logging to MindsDB failed: {e}') diff --git a/tests/unused/unit/api/http/knowledge_bases_test.py b/tests/unused/unit/api/http/knowledge_bases_test.py deleted file mode 100644 index 0e0f65b1fd7..00000000000 --- a/tests/unused/unit/api/http/knowledge_bases_test.py +++ /dev/null @@ -1,1049 +0,0 @@ -from http import HTTPStatus - -import pytest -from unittest.mock import patch, MagicMock - -from mindsdb.api.mysql.mysql_proxy.mysql_proxy import SQLAnswer -from mindsdb.api.executor.data_types.response_type import RESPONSE_TYPE - - -def test_prepare(client): - # Create langchain embedding model to use in all tests. - create_ml_engine_query = 'CREATE ML_ENGINE langchain_embedding FROM langchain_embedding;' - create_ml_engine_data = { - 'query': create_ml_engine_query - } - response = client.post('/api/sql/query', json=create_ml_engine_data, follow_redirects=True) - assert response.status_code == HTTPStatus.OK - - # Create model to use in all tests. - create_query = ''' - CREATE MODEL mindsdb.test_embedding_model - PREDICT embeddings - USING - engine='langchain_embedding', - class = 'FakeEmbeddings', - size = 512, - input_columns = ['content']; - ''' - train_data = { - 'query': create_query - } - response = client.post('/api/projects/mindsdb/models', json=train_data, follow_redirects=True) - assert response.status_code == HTTPStatus.CREATED - - -def test_get_knowledge_base(client): - get_knowledge_bases_response = client.get('/api/projects/mindsdb/knowledge_bases') - - assert len(get_knowledge_bases_response.get_json()) == 0 - - create_request = { - 'knowledge_base': { - 'name': 'test_get_kb', - 'model': 'test_embedding_model' - } - } - - create_response = client.post('/api/projects/mindsdb/knowledge_bases', json=create_request, follow_redirects=True) - assert create_response.status_code == HTTPStatus.CREATED - - get_knowledge_bases_response = client.get('/api/projects/mindsdb/knowledge_bases') - assert get_knowledge_bases_response.status_code == HTTPStatus.OK - - all_knowledge_bases = get_knowledge_bases_response.get_json() - assert len(all_knowledge_bases) == 1 - - get_knowledge_base_response = client.get('/api/projects/mindsdb/knowledge_bases/test_get_kb') - assert get_knowledge_base_response.status_code == HTTPStatus.OK - - created_knowledge_base = create_response.get_json() - test_get_kb = get_knowledge_base_response.get_json() - expected_create_knowledge_base = { - 'name': 'test_get_kb', - 'embedding_model': 'test_embedding_model', - 'vector_database': 'test_get_kb_chromadb', - 'vector_database_table': 'default_collection', - 'id': created_knowledge_base['id'], - 'project_id': created_knowledge_base['project_id'], - 'params': created_knowledge_base['params'], - 'created_at': created_knowledge_base['created_at'], - 'updated_at': created_knowledge_base['updated_at'] - } - assert created_knowledge_base == expected_create_knowledge_base - assert test_get_kb == expected_create_knowledge_base - - # Returned fields are slightly different for GET all vs POST. - fetched_knowledge_base = all_knowledge_bases[0] - expected_get_knowledge_base = { - 'name': 'test_get_kb', - 'embedding_model': 'test_embedding_model', - 'vector_database': 'test_get_kb_chromadb', - 'vector_database_table': 'default_collection', - 'id': created_knowledge_base['id'], - 'project_name': 'mindsdb', - 'project_id': created_knowledge_base['project_id'], - 'params': created_knowledge_base['params'] - } - assert fetched_knowledge_base == expected_get_knowledge_base - - -def test_create_knowledge_base_no_storage(client): - create_request = { - 'knowledge_base': { - 'name': 'test_kb', - 'model': 'test_embedding_model' - } - } - - create_response = client.post('/api/projects/mindsdb/knowledge_bases', json=create_request, follow_redirects=True) - assert create_response.status_code == HTTPStatus.CREATED - - created_knowledge_base = create_response.get_json() - expected_knowledge_base = { - 'name': 'test_kb', - 'embedding_model': 'test_embedding_model', - 'vector_database': 'test_kb_chromadb', - 'vector_database_table': 'default_collection', - 'id': created_knowledge_base['id'], - 'project_id': created_knowledge_base['project_id'], - 'params': created_knowledge_base['params'], - 'created_at': created_knowledge_base['created_at'], - 'updated_at': created_knowledge_base['updated_at'] - } - assert created_knowledge_base == expected_knowledge_base - - -def test_create_knowledge_base_no_knowledge_base_param(client): - create_request = { - 'name': 'test_kb', - 'model': 'test_embedding_model' - } - - create_response = client.post('/api/projects/mindsdb/knowledge_bases', json=create_request, follow_redirects=True) - assert create_response.status_code == HTTPStatus.BAD_REQUEST - - -def test_create_knowledge_base_no_name(client): - create_request = { - 'knowledge_base': { - 'model': 'test_embedding_model' - } - } - - create_response = client.post('/api/projects/mindsdb/knowledge_bases', json=create_request, follow_redirects=True) - assert create_response.status_code == HTTPStatus.BAD_REQUEST - - -def test_create_knowledge_base_no_model(client): - create_request = { - 'knowledge_base': { - 'name': 'test_kb' - } - } - - create_response = client.post('/api/projects/mindsdb/knowledge_bases', json=create_request, follow_redirects=True) - assert create_response.status_code == HTTPStatus.BAD_REQUEST - - -def test_create_knowledge_base_no_storage_database(client): - create_request = { - 'knowledge_base': { - 'name': 'test_kb', - 'model': 'test_embedding_model', - 'storage': { - 'table': 'vector_db_table' - } - } - } - - create_response = client.post('/api/projects/mindsdb/knowledge_bases', json=create_request, follow_redirects=True) - assert create_response.status_code == HTTPStatus.BAD_REQUEST - - -def test_create_knowledge_base_no_storage_table(client): - create_request = { - 'knowledge_base': { - 'name': 'test_kb', - 'model': 'test_embedding_model', - 'storage': { - 'database': 'vector_db' - } - } - } - - create_response = client.post('/api/projects/mindsdb/knowledge_bases', json=create_request, follow_redirects=True) - assert create_response.status_code == HTTPStatus.BAD_REQUEST - - -def test_create_knowledge_base_project_not_found(client): - create_request = { - 'knowledge_base': { - 'name': 'test_kb', - 'model': 'test_embedding_model' - } - } - - create_response = client.post('/api/projects/buoluobao/knowledge_bases', json=create_request, follow_redirects=True) - assert create_response.status_code == HTTPStatus.NOT_FOUND - - -def test_create_knowledge_base_already_exists(client): - create_request = { - 'knowledge_base': { - 'name': 'test_kb_already_exists', - 'model': 'test_embedding_model' - } - } - - create_response = client.post('/api/projects/mindsdb/knowledge_bases', json=create_request, follow_redirects=True) - assert create_response.status_code == HTTPStatus.CREATED - - create_response = client.post('/api/projects/mindsdb/knowledge_bases', json=create_request, follow_redirects=True) - assert create_response.status_code == HTTPStatus.CONFLICT - - -def test_delete_knowledge_base(client): - create_request = { - 'knowledge_base': { - 'name': 'test_delete_kb', - 'model': 'test_embedding_model' - } - } - - create_response = client.post('/api/projects/mindsdb/knowledge_bases', json=create_request, follow_redirects=True) - assert create_response.status_code == HTTPStatus.CREATED - - delete_response = client.delete('/api/projects/mindsdb/knowledge_bases/test_delete_kb', follow_redirects=True) - assert delete_response.status_code == HTTPStatus.NO_CONTENT - - get_response = client.get('/api/projects/mindsdb/knowledge_bases/test_delete_kb', follow_redirects=True) - assert get_response.status_code == HTTPStatus.NOT_FOUND - - -def test_delete_knowledge_base_project_not_found(client): - delete_response = client.delete('/api/projects/chasiubao/knowledge_bases/test_kb', follow_redirects=True) - assert delete_response.status_code == HTTPStatus.NOT_FOUND - - -def test_delete_knowledge_base_not_found(client): - delete_response = client.delete('/api/projects/mindsdb/knowledge_bases/xiaolongbao_kb', follow_redirects=True) - assert delete_response.status_code == HTTPStatus.NOT_FOUND - - -def test_put_knowledge_base_rows(client): - create_request = { - 'knowledge_base': { - 'name': 'test_kb_update_rows', - 'model': 'test_embedding_model' - } - } - - create_response = client.post('/api/projects/mindsdb/knowledge_bases', json=create_request, follow_redirects=True) - assert create_response.status_code == HTTPStatus.CREATED - - content_to_embed = '''To begin with a perfect Peking duck recipe at home, firstly choose head on (easy to hang for air drying out), clean and leaner ducks. - Add around 1 teaspoon of white vinegar in clean water and soak the duck for 1 hour. Then prepare lines and tie the ducks from the top of the neck. - Hang them on hooks. I hang the ducks on the top of kitchen pool. - Please note: I make this peking duck in March when the room temperature is around 13-15 degree C, you will need to hang the duck in fridge or in a room with air conditioner in hot summer days. - ''' - - test_id = 0 - rows_to_insert = [ - {'id': test_id, 'content': content_to_embed} - ] - update_request = { - 'knowledge_base': { - 'rows': rows_to_insert - } - } - - with patch('mindsdb.interfaces.knowledge_base.controller.KnowledgeBaseTable') as mock_kb_table: - # Create a mock KB instance - mock_table_instance = MagicMock() - mock_kb_table.return_value = mock_table_instance - - # Setup the _kb attribute with required params - mock_kb = MagicMock() - mock_kb.params = {'preprocessing': None} # Initial state - mock_table_instance._kb = mock_kb - - update_response = client.put( - '/api/projects/mindsdb/knowledge_bases/test_kb_update_rows', - json=update_request, - follow_redirects=True - ) - - assert update_response.status_code == HTTPStatus.OK - - # Verify insert_rows was called with correct data - mock_table_instance.insert_rows.assert_called_once() - actual_rows = mock_table_instance.insert_rows.call_args[0][0] - assert len(actual_rows) == 1 - assert actual_rows[0]['id'] == test_id - assert actual_rows[0]['content'] == content_to_embed - - -def test_put_knowledge_base_query(client): - create_request = { - 'knowledge_base': { - 'name': 'test_kb_update_query', - 'model': 'test_embedding_model' - } - } - create_response = client.post('/api/projects/mindsdb/knowledge_bases', json=create_request, follow_redirects=True) - assert create_response.status_code == HTTPStatus.CREATED - - content_to_embed = '''To begin with a perfect Peking duck recipe at home, firstly choose head on (easy to hang for air drying out), clean and leaner ducks. - Add around 1 teaspoon of white vinegar in clean water and soak the duck for 1 hour. Then prepare lines and tie the ducks from the top of the neck. - Hang them on hooks. I hang the ducks on the top of kitchen pool. - Please note: I make this peking duck in March when the room temperature is around 13-15 degree C, you will need to hang the duck in fridge or in a room with air conditioner in hot summer days. - ''' - update_request = { - 'knowledge_base': { - 'query': 'SELECT * FROM mock_db.recipes' - } - } - - # Mock the FakeMysqlProxy - mock_proxy = MagicMock() - mock_proxy.process_query.return_value = SQLAnswer( - resp_type=RESPONSE_TYPE.TABLE, - columns=[{'alias': 'id'}, {'name': 'content'}], - data=[(0, content_to_embed)] - ) - - with patch('mindsdb.interfaces.knowledge_base.controller.KnowledgeBaseTable') as mock_kb_table: - mock_table_instance = MagicMock() - mock_kb_table.return_value = mock_table_instance - - # Setup the mock table - mock_kb = MagicMock() - mock_kb.params = {'preprocessing': None} - mock_table_instance._kb = mock_kb - mock_table_instance.mysql_proxy = mock_proxy - - update_response = client.put( - '/api/projects/mindsdb/knowledge_bases/test_kb_update_query', - json=update_request, - follow_redirects=True - ) - - assert update_response.status_code == HTTPStatus.OK - - # Verify insert was called with correct data - mock_table_instance.insert_query_result.assert_called_once_with( - 'SELECT * FROM mock_db.recipes', - 'mindsdb' - ) - - -@pytest.fixture -def create_test_kb(client): - kb_name = 'test_completions_kb' - - # First, try to delete the existing knowledge base if it exists - client.delete(f'/api/projects/mindsdb/knowledge_bases/{kb_name}', follow_redirects=True) - create_kb_request = { - 'knowledge_base': { - 'name': kb_name, - 'model': 'test_embedding_model' - } - } - create_response = client.post('/api/projects/mindsdb/knowledge_bases', json=create_kb_request, - follow_redirects=True) - - # Check if creation was successful - assert create_response.status_code in [ - HTTPStatus.CREATED, - HTTPStatus.OK - ], f"Failed to create knowledge base. Status: {create_response.status}" - - return kb_name - - -def test_successful_completion(client, create_test_kb): - kb_name = create_test_kb - completion_request = { - 'query': 'What is the capital of France?', - } - response = client.post(f'/api/projects/mindsdb/knowledge_bases/{kb_name}/completions', - json=completion_request, follow_redirects=True) - assert response.status_code == HTTPStatus.OK - response_data = response.get_json() - assert 'message' in response_data - assert 'content' in response_data['message'] - assert 'context' in response_data['message'] - assert response_data['message']['role'] == 'assistant' - - -def test_completion_missing_query_parameter(client, create_test_kb): - kb_name = create_test_kb - invalid_request = { - 'knowledge_base': kb_name - } - response = client.post(f'/api/projects/mindsdb/knowledge_bases/{kb_name}/completions', - json=invalid_request, follow_redirects=True) - assert response.status_code == HTTPStatus.BAD_REQUEST - - -def test_completion_non_existent_project(client, create_test_kb): - kb_name = create_test_kb - completion_request = { - 'query': 'What is the capital of France?', - } - response = client.post(f'/api/projects/nonexistent/knowledge_bases/{kb_name}/completions', - json=completion_request, follow_redirects=True) - assert response.status_code == HTTPStatus.NOT_FOUND - - -def test_completion_non_existent_knowledge_base(client): - completion_request = { - 'query': 'What is the capital of France?', - } - response = client.post('/api/projects/mindsdb/knowledge_bases/nonexistent_kb/completions', - json=completion_request, follow_redirects=True) - assert response.status_code == HTTPStatus.NOT_FOUND - - -def test_create_knowledge_base_with_preprocessing(client): - """Test creating a knowledge base with preprocessing configuration""" - create_request = { - 'knowledge_base': { - 'name': 'test_kb_preprocess', - 'model': 'test_embedding_model', - 'preprocessing': { - 'type': 'contextual', - 'contextual_config': { - 'chunk_size': 1000, - 'chunk_overlap': 200, - 'llm_model': 'gpt-4' - } - } - } - } - - create_response = client.post('/api/projects/mindsdb/knowledge_bases', json=create_request, follow_redirects=True) - assert create_response.status_code == HTTPStatus.CREATED - - created_knowledge_base = create_response.get_json() - assert 'preprocessing' in created_knowledge_base['params'] - assert created_knowledge_base['params']['preprocessing']['type'] == 'contextual' - - # Verify preprocessing config is preserved in GET - get_response = client.get('/api/projects/mindsdb/knowledge_bases/test_kb_preprocess') - assert get_response.status_code == HTTPStatus.OK - kb_data = get_response.get_json() - assert 'preprocessing' in kb_data['params'] - assert kb_data['params']['preprocessing'] == create_request['knowledge_base']['preprocessing'] - - -def test_create_knowledge_base_invalid_preprocessing(client): - """Test creating a knowledge base with invalid preprocessing configuration""" - create_request = { - 'knowledge_base': { - 'name': 'test_kb_invalid_preprocess', - 'model': 'test_embedding_model', - 'preprocessing': { - 'type': 'invalid_type', - 'contextual_config': { - 'chunk_size': 'invalid' - } - } - } - } - - create_response = client.post('/api/projects/mindsdb/knowledge_bases', json=create_request, follow_redirects=True) - assert create_response.status_code == HTTPStatus.BAD_REQUEST - - -def test_put_knowledge_base_with_preprocessing(client): - """Test updating knowledge base with preprocessing""" - # First create a KB - create_request = { - 'knowledge_base': { - 'name': 'test_kb_update_preprocess', - 'model': 'test_embedding_model' - } - } - - create_response = client.post('/api/projects/mindsdb/knowledge_bases', json=create_request, follow_redirects=True) - assert create_response.status_code == HTTPStatus.CREATED - - # Update with content and preprocessing - content_to_embed = [ - "First document to be processed and chunked.", - "Second document with different content for testing.", - ] - rows_to_insert = [ - {'content': content_to_embed[0]}, - {'content': content_to_embed[1]} - ] - - update_request = { - 'knowledge_base': { - 'rows': rows_to_insert, - 'preprocessing': { - 'type': 'contextual', - 'contextual_config': { - 'chunk_size': 500, - 'chunk_overlap': 100, - 'llm_model': 'gpt-4' - } - } - } - } - - with patch('mindsdb.interfaces.knowledge_base.controller.KnowledgeBaseTable') as mock_kb_table: - # Create a mock KB instance - mock_table_instance = MagicMock() - mock_kb_table.return_value = mock_table_instance - - # Setup the _kb attribute with required params - mock_kb = MagicMock() - mock_kb.params = {'preprocessing': None} # Initial state - mock_table_instance._kb = mock_kb - - update_response = client.put( - '/api/projects/mindsdb/knowledge_bases/test_kb_update_preprocess', - json=update_request, - follow_redirects=True - ) - - assert update_response.status_code == HTTPStatus.OK - - # Verify preprocessing was configured - mock_table_instance.configure_preprocessing.assert_called_with({ - 'type': 'contextual', - 'contextual_config': { - 'chunk_size': 500, - 'chunk_overlap': 100, - 'llm_model': 'gpt-4' - } - }) - - # Verify rows were inserted - mock_table_instance.insert_rows.assert_called_once() - inserted_rows = mock_table_instance.insert_rows.call_args[0][0] - assert len(inserted_rows) == 2 - assert inserted_rows[0]['content'] == content_to_embed[0] - assert inserted_rows[1]['content'] == content_to_embed[1] - - -def test_put_knowledge_base_invalid_preprocessing(client): - """Test updating knowledge base with invalid preprocessing config""" - # First create a KB - create_request = { - 'knowledge_base': { - 'name': 'test_kb_invalid_update_preprocess', - 'model': 'test_embedding_model' - } - } - - create_response = client.post('/api/projects/mindsdb/knowledge_bases', json=create_request, follow_redirects=True) - assert create_response.status_code == HTTPStatus.CREATED - - # Update with invalid preprocessing config - update_request = { - 'knowledge_base': { - 'rows': [{'content': 'test content'}], - 'preprocessing': { - 'type': 'invalid_type', - 'invalid_config': { - 'invalid_param': 'invalid_value' - } - } - } - } - - with patch('mindsdb.interfaces.knowledge_base.controller.KnowledgeBaseTable') as mock_kb_table: - # Create a mock KB instance - mock_table_instance = MagicMock() - mock_kb_table.return_value = mock_table_instance - - # Setup the _kb attribute with required params - mock_kb = MagicMock() - mock_kb.params = {'preprocessing': None} - mock_table_instance._kb = mock_kb - - # Configure the mock to raise an error when invalid preprocessing config is provided - mock_table_instance.configure_preprocessing.side_effect = ValueError("Invalid preprocessing type") - - update_response = client.put( - '/api/projects/mindsdb/knowledge_bases/test_kb_invalid_update_preprocess', - json=update_request, - follow_redirects=True - ) - - assert update_response.status_code == HTTPStatus.BAD_REQUEST - - -def test_put_knowledge_base_with_documents(client): - """Test updating knowledge base with Document objects""" - create_request = { - 'knowledge_base': { - 'name': 'test_kb_documents', - 'model': 'test_embedding_model' - } - } - - create_response = client.post('/api/projects/mindsdb/knowledge_bases', json=create_request, follow_redirects=True) - assert create_response.status_code == HTTPStatus.CREATED - - # Test data - test_documents = [ - { - 'content': 'First test document content', - 'metadata': {'source': 'test1', 'category': 'A'} - }, - { - 'content': 'Second test document content', - 'metadata': {'source': 'test2', 'category': 'B'} - } - ] - - update_request = { - 'knowledge_base': { - 'rows': test_documents - } - } - - with patch('mindsdb.interfaces.knowledge_base.controller.KnowledgeBaseTable') as mock_kb_table: - mock_table_instance = MagicMock() - mock_kb_table.return_value = mock_table_instance - - # Mock the dependencies - mock_kb = MagicMock() - mock_kb.params = {'preprocessing': None} - mock_table_instance._kb = mock_kb - - update_response = client.put( - '/api/projects/mindsdb/knowledge_bases/test_kb_documents', - json=update_request, - follow_redirects=True - ) - - assert update_response.status_code == HTTPStatus.OK - - # Verify insert_rows was called with correct Document objects - mock_table_instance.insert_rows.assert_called_once() - inserted_rows = mock_table_instance.insert_rows.call_args[0][0] - assert len(inserted_rows) == 2 - assert all(isinstance(row, dict) for row in inserted_rows) - assert inserted_rows[0]['content'] == test_documents[0]['content'] - assert inserted_rows[0]['metadata'] == test_documents[0]['metadata'] - - -def test_put_knowledge_base_mixed_content(client): - """Test updating knowledge base with multiple content types""" - create_request = { - 'knowledge_base': { - 'name': 'test_kb_mixed', - 'model': 'test_embedding_model' - } - } - - create_response = client.post('/api/projects/mindsdb/knowledge_bases', json=create_request, follow_redirects=True) - assert create_response.status_code == HTTPStatus.CREATED - - update_request = { - 'knowledge_base': { - 'rows': [{'content': 'Test content', 'metadata': {'source': 'manual'}}], - 'files': ['test_file.txt'], - 'urls': ['http: //example.com'], - 'query': 'SELECT * FROM test_table', - 'preprocessing': { - 'type': 'contextual', - 'contextual_config': { - 'chunk_size': 500, - 'chunk_overlap': 50 - } - } - } - } - - with patch('mindsdb.interfaces.knowledge_base.controller.KnowledgeBaseTable') as mock_kb_table: - mock_table_instance = MagicMock() - mock_kb_table.return_value = mock_table_instance - - # Mock the dependencies - mock_kb = MagicMock() - mock_kb.params = {'preprocessing': None} - mock_table_instance._kb = mock_kb - - update_response = client.put( - '/api/projects/mindsdb/knowledge_bases/test_kb_mixed', - json=update_request, - follow_redirects=True - ) - - assert update_response.status_code == HTTPStatus.OK - - -def test_create_knowledge_base_with_text_chunking(client): - """Test creating a knowledge base with text chunking preprocessing configuration""" - create_request = { - 'knowledge_base': { - 'name': 'test_kb_text_chunking', - 'model': 'test_embedding_model', - 'preprocessing': { - 'type': 'text_chunking', - 'text_chunking_config': { - 'chunk_size': 500, - 'chunk_overlap': 50, - 'separators': ["\n\n", "\n", ".", " "] - } - } - } - } - - create_response = client.post('/api/projects/mindsdb/knowledge_bases', json=create_request, follow_redirects=True) - assert create_response.status_code == HTTPStatus.CREATED - - created_knowledge_base = create_response.get_json() - assert 'preprocessing' in created_knowledge_base['params'] - assert created_knowledge_base['params']['preprocessing']['type'] == 'text_chunking' - - # Verify preprocessing config is preserved in GET - get_response = client.get('/api/projects/mindsdb/knowledge_bases/test_kb_text_chunking') - assert get_response.status_code == HTTPStatus.OK - kb_data = get_response.get_json() - assert 'preprocessing' in kb_data['params'] - assert kb_data['params']['preprocessing'] == create_request['knowledge_base']['preprocessing'] - - -def test_create_knowledge_base_invalid_text_chunking(client): - """Test creating a knowledge base with invalid text chunking configuration""" - create_request = { - 'knowledge_base': { - 'name': 'test_kb_invalid_chunking', - 'model': 'test_embedding_model', - 'preprocessing': { - 'type': 'text_chunking', - 'text_chunking_config': { - 'chunk_size': -100, # Invalid negative size - 'chunk_overlap': "invalid", # Invalid type - } - } - } - } - - create_response = client.post('/api/projects/mindsdb/knowledge_bases', json=create_request, follow_redirects=True) - assert create_response.status_code == HTTPStatus.BAD_REQUEST - - -def test_put_knowledge_base_default_preprocessing(client): - """Test that text chunking is used as default preprocessing when none specified""" - create_request = { - 'knowledge_base': { - 'name': 'test_kb_default_preprocess', - 'model': 'test_embedding_model' - } - } - - create_response = client.post('/api/projects/mindsdb/knowledge_bases', json=create_request, follow_redirects=True) - assert create_response.status_code == HTTPStatus.CREATED - - update_request = { - 'knowledge_base': { - 'rows': [{ - 'content': 'Test content for default preprocessing', - 'source': 'test' # Flat metadata instead of nested - }] - } - } - - # Send update request directly - update_response = client.put( - '/api/projects/mindsdb/knowledge_bases/test_kb_default_preprocess', - json=update_request, - follow_redirects=True - ) - - assert update_response.status_code == HTTPStatus.OK - - -def test_put_knowledge_base_missing_metadata(client): - """Test proper error handling when metadata is missing""" - create_request = { - 'knowledge_base': { - 'name': 'test_kb_metadata', - 'model': 'test_embedding_model' - } - } - - create_response = client.post('/api/projects/mindsdb/knowledge_bases', json=create_request, follow_redirects=True) - assert create_response.status_code == HTTPStatus.CREATED - - # Request with missing source - update_request = { - 'knowledge_base': { - 'rows': [{ - 'content': 'Test content without metadata' - }] - } - } - - update_response = client.put( - '/api/projects/mindsdb/knowledge_bases/test_kb_metadata', - json=update_request, - follow_redirects=True - ) - - assert update_response.status_code == HTTPStatus.OK # Should succeed with default metadata - - -def test_document_processing_with_valid_metadata(client): - """Test document processing with valid metadata configuration""" - create_request = { - 'knowledge_base': { - 'name': 'test_kb_valid_metadata', - 'model': 'test_embedding_model', - 'preprocessing': { - 'type': 'text_chunking', - 'text_chunking_config': { - 'chunk_size': 100, - 'chunk_overlap': 20 - } - } - } - } - - create_response = client.post('/api/projects/mindsdb/knowledge_bases', json=create_request, follow_redirects=True) - assert create_response.status_code == HTTPStatus.CREATED - - # Various valid metadata configurations as flat key-value pairs - test_rows = [ - { - 'content': 'First test content', - 'source': 'test1', - 'category': 'A' - }, - { - 'content': 'Second test content', - 'source': 'test2', - 'doc_type': 'document' - }, - { - 'content': 'Third test content', - 'source': 'test3', - 'tag': 'tag1' - } - ] - - update_request = { - 'knowledge_base': { - 'rows': test_rows - } - } - - update_response = client.put( - '/api/projects/mindsdb/knowledge_bases/test_kb_valid_metadata', - json=update_request, - follow_redirects=True - ) - - assert update_response.status_code == HTTPStatus.OK - - -def test_document_processing_with_default_metadata(client): - """Test document processing where system adds default metadata""" - create_request = { - 'knowledge_base': { - 'name': 'test_kb_default_metadata', - 'model': 'test_embedding_model' - } - } - - create_response = client.post('/api/projects/mindsdb/knowledge_bases', json=create_request, follow_redirects=True) - assert create_response.status_code == HTTPStatus.CREATED - - # Only provide content, system should add default metadata - update_request = { - 'knowledge_base': { - 'rows': [{ - 'content': 'Test content with system metadata', - 'source': 'api' # This will be moved to metadata - }] - } - } - - # Need to patch both controller and preprocessor - with patch('mindsdb.interfaces.knowledge_base.controller.KnowledgeBaseTable') as mock_kb_table: - mock_instance = MagicMock() - mock_kb_table.return_value = mock_instance - - # Mock KB params - mock_kb = MagicMock() - mock_kb.params = {} - mock_instance._kb = mock_kb - - update_response = client.put( - '/api/projects/mindsdb/knowledge_bases/test_kb_default_metadata', - json=update_request, - follow_redirects=True - ) - - assert update_response.status_code == HTTPStatus.OK - - # Verify that insert_rows was called with the correct data - mock_instance.insert_rows.assert_called_once() - inserted_rows = mock_instance.insert_rows.call_args[0][0] - assert len(inserted_rows) == 1 - assert inserted_rows[0]['content'] == 'Test content with system metadata' - assert inserted_rows[0]['source'] == 'api' - - -def test_document_loader_with_file_extensions(client): - """Test document loader handling different file extensions""" - create_request = { - 'knowledge_base': { - 'name': 'test_kb_file_extensions', - 'model': 'test_embedding_model' - } - } - - create_response = client.post('/api/projects/mindsdb/knowledge_bases', json=create_request, follow_redirects=True) - assert create_response.status_code == HTTPStatus.CREATED - - # Create test files - with patch('mindsdb.interfaces.file.file_controller.FileController') as mock_file_controller: - # Mock file existence checks - mock_file_controller.return_value.get_file_path.return_value = MagicMock() - - update_request = { - 'knowledge_base': { - 'files': ['test.md', 'test.html', 'test.pdf'] - } - } - - with patch('mindsdb.interfaces.knowledge_base.controller.KnowledgeBaseTable') as mock_kb_table: - mock_table_instance = MagicMock() - mock_kb_table.return_value = mock_table_instance - - # Mock KB params - mock_kb = MagicMock() - mock_kb.params = {} - mock_table_instance._kb = mock_kb - - update_response = client.put( - '/api/projects/mindsdb/knowledge_bases/test_kb_file_extensions', - json=update_request, - follow_redirects=True - ) - - assert update_response.status_code == HTTPStatus.OK - - # Verify document loader was used - mock_table_instance.insert_files.assert_called_once_with(['test.md', 'test.html', 'test.pdf']) - - -def test_document_loader_sql_error_handling(client): - """Test document loader handling SQL query errors""" - create_request = { - 'knowledge_base': { - 'name': 'test_kb_sql_errors', - 'model': 'test_embedding_model' - } - } - - create_response = client.post('/api/projects/mindsdb/knowledge_bases', json=create_request, follow_redirects=True) - assert create_response.status_code == HTTPStatus.CREATED - - # This will not use the document loader. - update_request = { - 'knowledge_base': { - 'query': 'INVALID SQL QUERY' - } - } - - update_response = client.put( - '/api/projects/mindsdb/knowledge_bases/test_kb_sql_errors', - json=update_request, - follow_redirects=True - ) - - assert update_response.status_code == HTTPStatus.BAD_REQUEST - - -def test_preprocessing_update(client): - """Test updating preprocessing configuration""" - initial_request = { - 'knowledge_base': { - 'name': 'test_kb_preprocess_update', - 'model': 'test_embedding_model' - } - } - - # First try to delete if exists - client.delete( - f'/api/projects/mindsdb/knowledge_bases/{initial_request["knowledge_base"]["name"]}', - follow_redirects=True - ) - - with patch('mindsdb.api.http.namespaces.knowledge_bases.SessionController') as mock_session_class: - mock_session = MagicMock() - mock_session_class.return_value = mock_session - - # Setup KB controller mock - mock_kb_controller = MagicMock() - mock_session.kb_controller = mock_kb_controller - - # Setup table mock - mock_table = MagicMock() - mock_kb_controller.get_table.return_value = mock_table - - # Setup KB object mock - mock_kb = MagicMock() - mock_kb.params = {} - mock_kb.id = 1 - mock_kb.name = initial_request['knowledge_base']['name'] - mock_kb.as_dict.return_value = { - 'id': 1, - 'name': initial_request['knowledge_base']['name'], - 'params': mock_kb.params, - 'created_at': '2024-11-07T12: 13: 46', - 'updated_at': '2024-11-07T12: 13: 46' - } - - # Setup controller methods - mock_kb_controller.get.side_effect = [None, mock_kb] - mock_kb_controller.add.return_value = mock_kb - - create_response = client.post( - '/api/projects/mindsdb/knowledge_bases', - json=initial_request, - follow_redirects=True - ) - - assert create_response.status_code == HTTPStatus.CREATED - - # Now update with preprocessing config - update_request = { - 'knowledge_base': { - 'preprocessing': { - 'type': 'text_chunking', - 'text_chunking_config': { - 'chunk_size': 300, - 'chunk_overlap': 30 - } - } - } - } - - # Reset get to always return the KB now that it exists - mock_kb_controller.get.reset_mock() - mock_kb_controller.get.return_value = mock_kb - - update_response = client.put( - f'/api/projects/mindsdb/knowledge_bases/{initial_request["knowledge_base"]["name"]}', - json=update_request, - follow_redirects=True - ) - - assert update_response.status_code == HTTPStatus.OK - - # Verify preprocessing was updated - mock_table.configure_preprocessing.assert_called_with( - update_request['knowledge_base']['preprocessing'] - ) diff --git a/tests/unused/unit/broken/test_knowledge_base.py b/tests/unused/unit/broken/test_knowledge_base.py deleted file mode 100644 index 02e224003c6..00000000000 --- a/tests/unused/unit/broken/test_knowledge_base.py +++ /dev/null @@ -1,452 +0,0 @@ -import tempfile -import time -from unittest.mock import patch - -import pandas as pd -import pytest -from mindsdb_sql_parser import parse_sql - -from mindsdb.interfaces.storage.db import KnowledgeBase - -from tests.unit.executor_test_base import BaseExecutorTest - - -class TestKnowledgeBase(BaseExecutorTest): - def run_sql(self, sql): - ret = self.command_executor.execute_command(parse_sql(sql)) - assert ret.error_code is None - if ret.data is not None: - return ret.data.to_df() - - def wait_predictor(self, project, name): - # wait - done = False - for _ in range(200): - ret = self.run_sql(f"select * from {project}.models where name='{name}'") - if not ret.empty: - if ret["STATUS"][0] == "complete": - done = True - break - elif ret["STATUS"][0] == "error": - break - time.sleep(0.5) - if not done: - raise RuntimeError("predictor wasn't created") - - @patch("mindsdb.integrations.handlers.postgres_handler.Handler") - def setup_method(self, method, mock_handler): - super().setup_method() - - vectordatabase_name = "chroma_test" - - # create a vector database table - tmp_directory = tempfile.mkdtemp() - self.run_sql( - f""" - CREATE DATABASE {vectordatabase_name} - WITH ENGINE = "chromadb", - PARAMETERS = {{ - "persist_directory" : "{tmp_directory}" - }} - """ - ) - - # mock the data - df = pd.DataFrame( - { - "id": ["id1", "id2", "id3"], - "content": ["content1", "content2", "content3"], - "metadata": [ - '{"datasource": "web", "some_field": "some_value"}', - '{"datasource": "web"}', - '{"datasource": "web"}', - ], - "embeddings": [[1, 2, 3], [4, 5, 6], [7, 8, 9]], - } - ) - - self.save_file("df", df) - - # create the table - vectordatabase_table_name = "test_table" - sql = f""" - CREATE TABLE chroma_test.{vectordatabase_table_name} - ( - SELECT * FROM files.df - ) - """ - self.run_sql(sql) - - # create an embedding model - embedding_model_name = "test_dummy_embedding" - self.run_sql( - f""" - CREATE MODEL {embedding_model_name} - PREDICT embeddings - USING - engine='langchain_embedding', - class = 'FakeEmbeddings', - size = 3, - input_columns = ['content'] - """ - ) - - self.wait_predictor("mindsdb", embedding_model_name) - self.vector_database_table_name = vectordatabase_table_name - self.vector_database_name = vectordatabase_name - self.embedding_model_name = embedding_model_name - self.database_path = tmp_directory - - def teardown_method(self, method): - # drop the vector database - self.run_sql("DROP KNOWLEDGE_BASE IF EXISTS test_kb") - self.run_sql(f"DROP TABLE {self.vector_database_name}.{self.vector_database_table_name}") - self.run_sql(f"DROP DATABASE {self.vector_database_name}") - - def test_create_kb(self): - # create knowledge base - sql = f""" - CREATE KNOWLEDGE BASE test_kb - USING - MODEL = {self.embedding_model_name}, - STORAGE = {self.vector_database_name}.{self.vector_database_table_name} - """ - self.run_sql(sql) - - # verify the knowledge base is created - kb_obj = self.db.session.query(KnowledgeBase).filter_by(name="test_kb").first() - assert kb_obj is not None - - # create a knowledge base from select - # todo this should be supported but isn't yet - - # sql = f""" - # CREATE KNOWLEDGE BASE test_kb2 - # FROM ( - # SELECT content, embeddings, metadata - # FROM {self.vector_database_name}.{self.vector_database_table_name} - # ) - # USING - # MODEL = {self.embedding_model_name}, - # STORAGE = {self.vector_database_name}.{self.vector_database_table_name} - # """ - # - # self.run_sql(sql) - # - # # verify the knowledge base is created - # kb_obj = self.db.session.query(KnowledgeBase).filter_by(name="test_kb2").first() - # assert kb_obj is not None - - # create a knowledge base with invalid model and storage name should throw an exception - sql = f""" - CREATE KNOWLEDGE BASE test_kb3 - USING - MODEL = invalid_model_name, - STORAGE = {self.vector_database_name}.{self.vector_database_table_name} - """ - with pytest.raises(Exception): - self.run_sql(sql) - - sql = f""" - CREATE KNOWLEDGE BASE test_kb4 - USING - MODEL = {self.embedding_model_name}, - STORAGE = invalid_storage_name - """ - with pytest.raises(Exception): - self.run_sql(sql) - - # create a knowledge base without a storage name, default should be used - - sql = f""" - CREATE KNOWLEDGE BASE test_kb5 - USING - MODEL = {self.embedding_model_name} - """ - - self.run_sql(sql) - - # verify the knowledge base is created - kb_obj = self.db.session.query(KnowledgeBase).filter_by(name="test_kb5").first() - assert kb_obj is not None - assert kb_obj.vector_database.name == "test_kb5_chromadb" - - # create a knowledge base without a model name, default should be used - sql = f""" - CREATE KNOWLEDGE BASE test_kb6 - USING - STORAGE = {self.vector_database_name}.{self.vector_database_table_name} - """ - - self.run_sql(sql) - - # verify the knowledge base is created - kb_obj = self.db.session.query(KnowledgeBase).filter_by(name="test_kb6").first() - assert kb_obj is not None - assert kb_obj.embedding_model.name == "kb_default_embedding_model" - # clean up - self.run_sql("DROP KNOWLEDGE BASE test_kb6") - - def test_drop_kb(self): - # create a knowledge base - sql = f""" - CREATE KNOWLEDGE BASE test_kb_delete - USING - MODEL = {self.embedding_model_name}, - STORAGE = {self.vector_database_name}.{self.vector_database_table_name} - """ - self.run_sql(sql) - - # verify the knowledge base is created - kb_obj = self.db.session.query(KnowledgeBase).filter_by(name="test_kb_delete").first() - assert kb_obj is not None - - # drop a knowledge base - sql = """ - DROP KNOWLEDGE BASE test_kb_delete - """ - self.run_sql(sql) - - # verify the knowledge base is dropped - kb_obj = self.db.session.query(KnowledgeBase).filter_by(name="test_kb").first() - assert kb_obj is None - - def test_select_from_kb(self): - # create the knowledge base - sql = f""" - CREATE KNOWLEDGE BASE test_kb - USING - MODEL = {self.embedding_model_name}, - STORAGE = {self.vector_database_name}.{self.vector_database_table_name} - """ - self.run_sql(sql) - - # select from the knowledge base without any filters - sql = """ - SELECT * - FROM test_kb - """ - df = self.run_sql(sql) - assert df.shape[0] == 3 - - # select from the knowledge base with an id filter - sql = """ - SELECT * - FROM test_kb - WHERE id = 'id1' - """ - df = self.run_sql(sql) - assert df.shape[0] == 1 - - # select from the knowledge base with a metadata filter - sql = """ - SELECT * - FROM test_kb - WHERE - `metadata.some_field` = 'some_value' - """ - df = self.run_sql(sql) - assert df.shape[0] == 1 - - # select with a search query - sql = """ - SELECT * - FROM test_kb - WHERE - content = 'some query' - LIMIT 1 - """ - df = self.run_sql(sql) - assert df.shape[0] == 1 - - @pytest.mark.skip(reason="need to cleanly mock embedding model predict") - def test_insert_into_kb(self): - # create the knowledge base - sql = f""" - CREATE KNOWLEDGE BASE test_kb - USING - MODEL = {self.embedding_model_name}, - STORAGE = {self.vector_database_name}.{self.vector_database_table_name} - """ - self.run_sql(sql) - - # insert into the knowledge base using values - sql = """ - INSERT INTO test_kb (id, content, embeddings, metadata) - VALUES ( - 'id4', - 'content4', - '[4, 5, 6]', - '{"d": 4}' - ) - - """ - self.run_sql(sql) - - # verify the knowledge base is updated - sql = """ - SELECT * - FROM test_kb - WHERE id = 'id4' - """ - df = self.run_sql(sql) - assert df.shape[0] == 1 - - # insert into the knowledge base using a select - sql = """ - INSERT INTO test_kb - SELECT - content, metadata - FROM files.df - """ - self.run_sql(sql) - - # verify the knowledge base is updated - sql = """ - SELECT * - FROM test_kb - """ - - df = self.run_sql(sql) - assert df.shape[0] == 7 - - @pytest.mark.skip(reason="Not implemented") - def test_update_kb(self): - ... - - def test_delete_from_kb(self): - # create the knowledge base - sql = f""" - CREATE KNOWLEDGE BASE test_kb - USING - MODEL = {self.embedding_model_name}, - STORAGE = {self.vector_database_name}.{self.vector_database_table_name} - """ - - self.run_sql(sql) - - # delete with id filter - sql = """ - DELETE FROM test_kb - WHERE id = 'id1' - """ - self.run_sql(sql) - - # verify the knowledge base is updated - sql = """ - SELECT * - FROM test_kb - WHERE id = 'id1' - """ - df = self.run_sql(sql) - assert df.shape[0] == 0 - - # delete with metadata filter - sql = """ - DELETE FROM test_kb - WHERE `metadata.datasource` = 'web' - """ - self.run_sql(sql) - - # verify the knowledge base is updated - sql = """ - SELECT * - FROM test_kb - WHERE id = 'id2' - """ - df = self.run_sql(sql) - assert df.shape[0] == 0 - - # delete from the knowledge base without any filters is not allowed - sql = """ - DELETE FROM test_kb - """ - with pytest.raises(Exception): - self.run_sql(sql) - - def test_show_knowledge_bases(self): - # create the knowledge base - sql = f""" - CREATE KNOWLEDGE BASE test_kb - USING - MODEL = {self.embedding_model_name}, - STORAGE = {self.vector_database_name}.{self.vector_database_table_name} - """ - self.run_sql(sql) - - # show knowledge bases - sql = """ - SHOW KNOWLEDGE BASES - """ - df = self.run_sql(sql) - assert df.shape[0] == 1 - - @pytest.mark.skip(reason="need to cleanly mock embedding model predict") - def test_kb_params(self): - - df = pd.DataFrame([ - {'id': 1, 'ticket': 'NFLX', 'value': 532, 'created_at': '2020-01-01', 'ma': 100}, - {'id': 2, 'ticket': 'MSFT', 'value': 311, 'created_at': '2020-01-02', 'ma': 200}, - ]) - - self.save_file('stock', df) - - # ---- default ---- - self.run_sql(f'create knowledge base kb_test USING MODEL = {self.embedding_model_name}') - self.run_sql('INSERT INTO kb_test select * from files.stock') - ret = self.run_sql("select * from kb_test where content='msft'") - self.run_sql('drop knowledge base kb_test') # have to drop KB with model and vector sore before assertions - - # second row is the result, all columns in content - content = ret.content[0] - assert 'MSFT' in content and 'created_at' in content and '311' in content and '200' in content - - # metadata is empty - assert ret.metadata[0] is None - - # id = 2 - assert ret.id[0] == '2' - - # ---- choose content ---- - self.run_sql(''' - create knowledge base kb_test - using content_columns = ['ticket', 'value'] - ''') - self.run_sql('INSERT INTO kb_test select * from files.stock') - ret = self.run_sql("select * from kb_test where content='msft'") - self.run_sql('drop knowledge base kb_test') - - metadata = ret.metadata[0] - content = ret.content[0] - # ticket and value in content - assert 'MSFT' in content and '311' in content - # created and ma in metadata - assert 'created_at' in metadata and 'ma' in metadata - - # ---- choose metadata ---- - self.run_sql(''' - create knowledge base kb_test - using metadata_columns = ['created_at', 'value'] - ''') - self.run_sql('INSERT INTO kb_test select * from files.stock') - ret = self.run_sql("select * from kb_test where content='msft'") - self.run_sql('drop knowledge base kb_test') - - metadata = ret.metadata[0] - content = ret.content[0] - # ticket and ma in content - assert 'MSFT' in content and '200' in content - # created and value in metadata - assert 'created_at' in metadata and 'value' in metadata - - # ---- choose id ---- - self.run_sql(''' - create knowledge base kb_test - using id_column='ma' - ''') - self.run_sql('INSERT INTO kb_test select * from files.stock') - ret = self.run_sql("select * from kb_test where content='msft'") - self.run_sql('drop knowledge base kb_test') - - # id = 200 - assert ret.id[0] == '200' diff --git a/tests/unused/unit/broken/test_map_reduce_summarizer_chain.py b/tests/unused/unit/broken/test_map_reduce_summarizer_chain.py deleted file mode 100644 index 2953a94ad6f..00000000000 --- a/tests/unused/unit/broken/test_map_reduce_summarizer_chain.py +++ /dev/null @@ -1,76 +0,0 @@ -from unittest.mock import AsyncMock, MagicMock - -import pandas as pd -from langchain.chains.combine_documents.map_reduce import MapReduceDocumentsChain -from langchain_core.documents import Document - -from mindsdb.integrations.libs.vectordatabase_handler import VectorStoreHandler -from mindsdb.integrations.utilities.rag.chains.map_reduce_summarizer_chain import MapReduceSummarizerChain -from mindsdb.integrations.utilities.rag.settings import SummarizationConfig -from mindsdb.integrations.utilities.sql_utils import FilterCondition, FilterOperator - - -class TestMapReduceSummarizerChain: - def test_summarizes_documents(self): - mock_vector_store_handler = MagicMock(spec=VectorStoreHandler, wraps=VectorStoreHandler) - mock_vector_store_handler.select.side_effect = [ - pd.DataFrame.from_records([ - {'content': 'Chunk 1'}, - {'content': 'Chunk 2'}, - ]), - pd.DataFrame.from_records([ - {'content': 'Chunk 3'} - ]) - ] - mock_map_reduce_documents_chain = AsyncMock(spec=MapReduceDocumentsChain, wraps=MapReduceDocumentsChain) - mock_map_reduce_documents_chain.ainvoke.side_effect = [{'output_text': 'Final summary 1'}, {'output_text': 'Final summary 2'}] - test_summarizer_chain = MapReduceSummarizerChain( - vector_store_handler=mock_vector_store_handler, - map_reduce_documents_chain=mock_map_reduce_documents_chain, - summarization_config=SummarizationConfig() - ) - - chain_input = { - 'context': [ - Document(page_content='Chunk 1', metadata={'original_row_id': '1'}), - Document(page_content='Chunk 2', metadata={'original_row_id': '1'}), - Document(page_content='Chunk 3', metadata={'original_row_id': '2'}) - ], - 'question': 'What is the answer to life?', - } - actual_chain_output = test_summarizer_chain.invoke(chain_input) - - # Make sure we select from the vector store correctly. - mock_vector_store_handler.select.assert_any_call( - 'embeddings', - columns=['content', 'metadata'], - conditions=[FilterCondition( - "metadata->>'original_row_id'", - FilterOperator.EQUAL, - '1' - )] - ) - mock_vector_store_handler.select.assert_any_call( - 'embeddings', - columns=['content', 'metadata'], - conditions=[FilterCondition( - "metadata->>'original_row_id'", - FilterOperator.EQUAL, - '2' - )] - ) - - # Make sure we are calling the summarization chain with the right chunks. - mock_map_reduce_documents_chain.ainvoke.assert_awaited() - - # Make sure the summary is actually added to the context. - expected_chain_output = { - 'context': [ - Document(page_content='Chunk 1', metadata={'original_row_id': '1', 'summary': 'Final summary 1'}), - Document(page_content='Chunk 2', metadata={'original_row_id': '1', 'summary': 'Final summary 1'}), - Document(page_content='Chunk 3', metadata={'original_row_id': '2', 'summary': 'Final summary 2'}) - ], - 'question': 'What is the answer to life?', - } - - assert actual_chain_output == expected_chain_output diff --git a/tests/unused/unit/broken/test_sql_retriever.py b/tests/unused/unit/broken/test_sql_retriever.py deleted file mode 100644 index 7734739540b..00000000000 --- a/tests/unused/unit/broken/test_sql_retriever.py +++ /dev/null @@ -1,313 +0,0 @@ -from unittest.mock import MagicMock - -import pandas as pd -from langchain_core.documents import Document -from langchain_core.embeddings import Embeddings -from langchain_core.outputs.generation import Generation -from langchain_core.outputs.llm_result import LLMResult -from langchain_core.retrievers import BaseRetriever -from langchain_openai.chat_models.base import ChatOpenAI - -from mindsdb.api.executor.data_types.response_type import RESPONSE_TYPE -from mindsdb.integrations.libs.response import HandlerResponse -from mindsdb.integrations.libs.vectordatabase_handler import DistanceFunction, VectorStoreHandler -from mindsdb.integrations.utilities.rag.retrievers.sql_retriever import SQLRetriever -from mindsdb.integrations.utilities.rag.settings import DEFAULT_METADATA_FILTERS_PROMPT_TEMPLATE, DEFAULT_SEMANTIC_PROMPT_TEMPLATE, ColumnSchema, MetadataSchema, SearchKwargs - - -class TestSQLRetriever: - def test_basic(self): - llm = MagicMock(spec=ChatOpenAI, wraps=ChatOpenAI) - llm_result = MagicMock(spec=LLMResult, wraps=LLMResult) - llm_result.generations = [ - [ - Generation( - text='''```json -{ - "filters": [ - { - "attribute": "ContributorName", - "comparator": "=", - "value": "Alfred" - } - ] -} -```''' - ) - ] - ] - llm.generate_prompt.return_value = llm_result - vector_db_mock = MagicMock(spec=VectorStoreHandler, wraps=VectorStoreHandler) - series = pd.Series( - [0, 'Chunk1', '[1.0, 2.0, 3.0]', {'key1': 'value1'}, 0, 1], - index=['id', 'content', 'embeddings', 'metadata', 'Id', 'Type'] - ) - df = pd.DataFrame([series]) - vector_db_mock.native_query.return_value = HandlerResponse( - RESPONSE_TYPE.TABLE, - data_frame=df - ) - embeddings_mock = MagicMock(spec=Embeddings, wraps=Embeddings) - embeddings_mock.embed_query.return_value = list(range(768)) - - source_schema = MetadataSchema( - table='test_source_table', - description='Contains source documents', - columns=[ - ColumnSchema(name='Id', type='int', description='Unique ID as primary key of doc'), - ColumnSchema(name='Type', type='int', description='Document Type', values={1: 'Unknown', 2: 'Site Audit'}) - ] - ) - unit_schema = MetadataSchema( - table='unit', - description='Contains information about specific units of power plants. Several units can be part of a single plant.', - columns=[ - ColumnSchema(name='UnitKey', type='int', description='Unique ID of the unit'), - ColumnSchema(name='PlantKey', type='int', description='ID of the plant the unit belongs to') - ] - ) - plant_schema = MetadataSchema( - table='plant', - description='Contains information about specific power plants', - columns=[ - ColumnSchema(name='PlantKey', type='int', description='The unique ID of the plant'), - ColumnSchema(name='PlantName', type='str', description='The name of the plant') - ] - ) - document_unit_schema = MetadataSchema( - table='document_unit', - description='Links documents to the power plant they are relevant to', - columns=[ - ColumnSchema(name='DocumentId', type='int', description='The ID of the document associated with the unit'), - ColumnSchema(name='UnitKey', type='int', description='The ID of the unit the documnet is associated with') - ] - ) - all_schemas = [source_schema, unit_schema, plant_schema, document_unit_schema] - fallback_retriever = MagicMock(spec=BaseRetriever, wraps=BaseRetriever) - sql_retriever = SQLRetriever( - fallback_retriever=fallback_retriever, - vector_store_handler=vector_db_mock, - metadata_schemas=all_schemas, - embeddings_model=embeddings_mock, - metadata_filters_prompt_template=DEFAULT_METADATA_FILTERS_PROMPT_TEMPLATE, - rewrite_prompt_template=DEFAULT_SEMANTIC_PROMPT_TEMPLATE, - num_retries=2, - embeddings_table='test_embeddings_table', - source_table='test_source_table', - distance_function=DistanceFunction.SQUARED_EUCLIDEAN_DISTANCE, - search_kwargs=SearchKwargs(k=5), - llm=llm - ) - - docs = sql_retriever.invoke('What are Beaver Valley plant documents for nuclear fuel waste?') - # Make sure right doc was retrieved. - assert len(docs) == 1 - assert docs[0].page_content == 'Chunk1' - assert docs[0].metadata == {'key1': 'value1'} - - def test_retries(self): - llm = MagicMock(spec=ChatOpenAI, wraps=ChatOpenAI) - llm_result = MagicMock(spec=LLMResult, wraps=LLMResult) - llm_result.generations = [ - [ - Generation( - text='''```json -{ - "filters": [ - { - "attribute": "ContributorName", - "comparator": "=", - "value": "Alfred" - } - ] -} -```''' - ) - ] - ] - llm.generate_prompt.return_value = llm_result - vector_db_mock = MagicMock(spec=VectorStoreHandler, wraps=VectorStoreHandler) - series = pd.Series( - [0, 'Chunk1', '[1.0, 2.0, 3.0]', {'key1': 'value1'}, 0, 1], - index=['id', 'content', 'embeddings', 'metadata', 'Id', 'Type'] - ) - df = pd.DataFrame([series]) - vector_db_mock.native_query.side_effect = [ - HandlerResponse( - RESPONSE_TYPE.ERROR, - error_message='Something went wrong I am in absolute shambles' - ), - HandlerResponse( - RESPONSE_TYPE.ERROR, - error_message='Something went wrong I am in absolute shambles' - ), - HandlerResponse( - RESPONSE_TYPE.TABLE, - data_frame=df - ) - ] - embeddings_mock = MagicMock(spec=Embeddings, wraps=Embeddings) - embeddings_mock.embed_query.return_value = list(range(768)) - - source_schema = MetadataSchema( - table='test_source_table', - description='Contains source documents', - columns=[ - ColumnSchema(name='Id', type='int', description='Unique ID as primary key of doc'), - ColumnSchema(name='Type', type='int', description='Document Type', values={1: 'Unknown', 2: 'Site Audit'}) - ] - ) - unit_schema = MetadataSchema( - table='unit', - description='Contains information about specific units of power plants. Several units can be part of a single plant.', - columns=[ - ColumnSchema(name='UnitKey', type='int', description='Unique ID of the unit'), - ColumnSchema(name='PlantKey', type='int', description='ID of the plant the unit belongs to') - ] - ) - plant_schema = MetadataSchema( - table='plant', - description='Contains information about specific power plants', - columns=[ - ColumnSchema(name='PlantKey', type='int', description='The unique ID of the plant'), - ColumnSchema(name='PlantName', type='str', description='The name of the plant') - ] - ) - document_unit_schema = MetadataSchema( - table='document_unit', - description='Links documents to the power plant they are relevant to', - columns=[ - ColumnSchema(name='DocumentId', type='int', description='The ID of the document associated with the unit'), - ColumnSchema(name='UnitKey', type='int', description='The ID of the unit the documnet is associated with') - ] - ) - all_schemas = [source_schema, unit_schema, plant_schema, document_unit_schema] - fallback_retriever = MagicMock(spec=BaseRetriever, wraps=BaseRetriever) - sql_retriever = SQLRetriever( - fallback_retriever=fallback_retriever, - vector_store_handler=vector_db_mock, - metadata_schemas=all_schemas, - embeddings_model=embeddings_mock, - metadata_filters_prompt_template=DEFAULT_METADATA_FILTERS_PROMPT_TEMPLATE, - rewrite_prompt_template=DEFAULT_SEMANTIC_PROMPT_TEMPLATE, - num_retries=3, - embeddings_table='test_embeddings_table', - source_table='test_source_table', - distance_function=DistanceFunction.SQUARED_EUCLIDEAN_DISTANCE, - search_kwargs=SearchKwargs(k=5), - llm=llm - ) - - docs = sql_retriever.invoke('What are Beaver Valley plant documents for nuclear fuel waste?') - # Make sure we retried. - assert len(vector_db_mock.native_query.mock_calls) == 3 - # Make sure right doc was retrieved. - assert len(docs) == 1 - assert docs[0].page_content == 'Chunk1' - assert docs[0].metadata == {'key1': 'value1'} - - def test_fallback(self): - llm = MagicMock(spec=ChatOpenAI, wraps=ChatOpenAI) - llm_result = MagicMock(spec=LLMResult, wraps=LLMResult) - llm_result.generations = [ - [ - Generation( - text='''```json -{ - "filters": [ - { - "attribute": "ContributorName", - "comparator": "=", - "value": "Alfred" - } - ] -} -```''' - ) - ] - ] - llm.generate_prompt.return_value = llm_result - vector_db_mock = MagicMock(spec=VectorStoreHandler, wraps=VectorStoreHandler) - vector_db_mock.native_query.side_effect = [ - HandlerResponse( - RESPONSE_TYPE.ERROR, - error_message='Something went wrong I am in absolute shambles' - ), - HandlerResponse( - RESPONSE_TYPE.ERROR, - error_message='Something went wrong I am in absolute shambles' - ), - HandlerResponse( - RESPONSE_TYPE.ERROR, - error_message='Something went wrong I am in absolute shambles' - ), - ] - embeddings_mock = MagicMock(spec=Embeddings, wraps=Embeddings) - embeddings_mock.embed_query.return_value = list(range(768)) - - source_schema = MetadataSchema( - table='test_source_table', - description='Contains source documents', - columns=[ - ColumnSchema(name='Id', type='int', description='Unique ID as primary key of doc'), - ColumnSchema(name='Type', type='int', description='Document Type', values={1: 'Unknown', 2: 'Site Audit'}) - ] - ) - unit_schema = MetadataSchema( - table='unit', - description='Contains information about specific units of power plants. Several units can be part of a single plant.', - columns=[ - ColumnSchema(name='UnitKey', type='int', description='Unique ID of the unit'), - ColumnSchema(name='PlantKey', type='int', description='ID of the plant the unit belongs to') - ] - ) - plant_schema = MetadataSchema( - table='plant', - description='Contains information about specific power plants', - columns=[ - ColumnSchema(name='PlantKey', type='int', description='The unique ID of the plant'), - ColumnSchema(name='PlantName', type='str', description='The name of the plant') - ] - ) - document_unit_schema = MetadataSchema( - table='document_unit', - description='Links documents to the power plant they are relevant to', - columns=[ - ColumnSchema(name='DocumentId', type='int', description='The ID of the document associated with the unit'), - ColumnSchema(name='UnitKey', type='int', description='The ID of the unit the documnet is associated with') - ] - ) - all_schemas = [source_schema, unit_schema, plant_schema, document_unit_schema] - fallback_retriever = MagicMock(spec=BaseRetriever, wraps=BaseRetriever) - fallback_retriever._get_relevant_documents.return_value = [ - Document( - page_content='Chunk1', - metadata={ - 'key1': 'value1' - } - ) - ] - sql_retriever = SQLRetriever( - fallback_retriever=fallback_retriever, - vector_store_handler=vector_db_mock, - metadata_schemas=all_schemas, - embeddings_model=embeddings_mock, - metadata_filters_prompt_template=DEFAULT_METADATA_FILTERS_PROMPT_TEMPLATE, - rewrite_prompt_template=DEFAULT_SEMANTIC_PROMPT_TEMPLATE, - num_retries=2, - embeddings_table='test_embeddings_table', - source_table='test_source_table', - distance_function=DistanceFunction.SQUARED_EUCLIDEAN_DISTANCE, - search_kwargs=SearchKwargs(k=5), - llm=llm - ) - - docs = sql_retriever.invoke('What are Beaver Valley plant documents for nuclear fuel waste?') - # Make sure we retried. - assert len(vector_db_mock.native_query.mock_calls) == 3 - # Make sure we falled back. - assert len(fallback_retriever._get_relevant_documents.mock_calls) == 1 - # Make sure right doc was retrieved. - assert len(docs) == 1 - assert docs[0].page_content == 'Chunk1' - assert docs[0].metadata == {'key1': 'value1'} diff --git a/tests/unused/unit/executor/test_udf.py b/tests/unused/unit/executor/test_udf.py deleted file mode 100644 index 95a8ea7be0d..00000000000 --- a/tests/unused/unit/executor/test_udf.py +++ /dev/null @@ -1,117 +0,0 @@ -import os -from textwrap import dedent -from tempfile import TemporaryDirectory - -from unittest.mock import patch - -import pandas as pd -import pytest - -from mindsdb_sql_parser.ast.mindsdb import CreateMLEngine -from mindsdb_sql_parser.ast import Identifier - -from tests.unit.executor_test_base import BaseExecutorDummyML - - -@pytest.mark.parametrize('byom_type', ['inhouse', 'venv']) -class TestBYOM(BaseExecutorDummyML): - - def _create_engine(self, name, code, **kwargs): - with TemporaryDirectory(prefix='udf_test_') as temp_dir: - code_path = os.path.join(temp_dir, 'code.py') - reqs_path = os.path.join(temp_dir, 'reqs.py') - - open(code_path, 'w').write(code) - open(reqs_path, 'w').write('') - - params = { - 'code': code_path, - 'modules': reqs_path, - } - params.update(kwargs) - - ret = self.command_executor.execute_command( - CreateMLEngine( - name=Identifier(name), - handler='byom', - params=params - ) - ) - assert ret.error_code is None - - @patch('mindsdb.integrations.handlers.postgres_handler.Handler') - def test_udf(self, data_handler, byom_type): - - df = pd.DataFrame([ - {'a': 3, 'b': 4, 'c': 'a', 'd': 'b'}, - ]) - self.set_handler(data_handler, name='pg', tables={'sample': df}) - - code = dedent(""" - from os import listdir # imported function - - def fibo(num: int) -> int: - if num < 2: - return num - return fibo(num - 1) + fibo(num - 2) - - # not annotated - def add1(a, b): - return a + b - - # annotated - def add2(a: int, b: int) -> int: - return a + b - """) - - self._create_engine(name='myml', code=code, - type=byom_type, mode='custom_function') - # convert to explicit types, because duckdb doesn't convert it and fails - ret = self.run_sql(''' - select myml.fibo(b) x, - myml.add1(a::char,b::char) y, - myml.add2(a,b) z - from pg.sample - ''') - assert ret['x'][0] == 3 - assert ret['y'][0] == '34' - assert ret['z'][0] == 7 - - # test without table - ret = self.run_sql(''' - select myml.fibo(4) x - ''') - assert ret['x'][0] == 3 - - def test_byom(self, byom_type): - - code = dedent(""" - from datetime import datetime - import pandas as pd - - class MyBYOM(): - - def train(self, df, target_col, args=None): - self.target_col = target_col - self.value = '>my_response' - - def predict(self, df): - df[self.target_col] = df['input_col'] + self.value - - return df[[self.target_col]] - """) - - self._create_engine(name='myml', code=code, type=byom_type) - - self.run_sql(''' - create model m1 - predict output_col - using engine='myml', - join_learn_process=true - ''') - - ret = self.run_sql(''' - select * from m1 - where input_col = 'my_input' - ''') - assert ret['output_col'][0] == 'my_input>my_response' diff --git a/tests/unused/unit/handler_tests/__init__.py b/tests/unused/unit/handler_tests/__init__.py deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/tests/unused/unit/handler_tests/data/pgvector/seed.sql b/tests/unused/unit/handler_tests/data/pgvector/seed.sql deleted file mode 100644 index 0b1739b555d..00000000000 --- a/tests/unused/unit/handler_tests/data/pgvector/seed.sql +++ /dev/null @@ -1,20 +0,0 @@ --- Make sure pgvector extension is enabled -DROP EXTENSION IF EXISTS vector; -CREATE EXTENSION vector; - --- Create the table -CREATE TABLE items ( - id bigserial PRIMARY KEY, - content text NOT NULL, - embeddings vector(3) NOT NULL, -- 3 dimensions - metadata jsonb -); - --- Dummy data -INSERT INTO items (content, embeddings, metadata) VALUES - ('a fat cat sat on a mat and ate a fat rat', '[1, 2, 3]', '{"location": "Wonderland", "author": "Taishan"}'), - ('a fat dog sat on a mat and ate a fat rat', '[4, 5, 6]', '{"location": "Wonderland", "author": "Taishan"}'), - ('a thin cat sat on a mat and ate a thin rat', '[7, 8, 9]', '{"location": "Zimbabwe", "author": "Taishan"}'), - ('a thin dog sat on a mat and ate a thin rat', '[10, 11, 12]', '{"location": "Springfield", "author": "Muhammad"}'); - -COMMIT; diff --git a/tests/unused/unit/handler_tests/data/rag_pipelines/auto_retriever.yml b/tests/unused/unit/handler_tests/data/rag_pipelines/auto_retriever.yml deleted file mode 100644 index c3dada1b80b..00000000000 --- a/tests/unused/unit/handler_tests/data/rag_pipelines/auto_retriever.yml +++ /dev/null @@ -1 +0,0 @@ -retriever_type: auto diff --git a/tests/unused/unit/handler_tests/data/rag_pipelines/multi_retriever_both.yml b/tests/unused/unit/handler_tests/data/rag_pipelines/multi_retriever_both.yml deleted file mode 100644 index 0974bdc14de..00000000000 --- a/tests/unused/unit/handler_tests/data/rag_pipelines/multi_retriever_both.yml +++ /dev/null @@ -1,3 +0,0 @@ -retriever_type: multi -multi_retriever_mode: both - diff --git a/tests/unused/unit/handler_tests/data/rag_pipelines/multi_retriever_split.yml b/tests/unused/unit/handler_tests/data/rag_pipelines/multi_retriever_split.yml deleted file mode 100644 index 9daf6c19f88..00000000000 --- a/tests/unused/unit/handler_tests/data/rag_pipelines/multi_retriever_split.yml +++ /dev/null @@ -1,3 +0,0 @@ -retriever_type: multi -multi_retriever_mode: split - diff --git a/tests/unused/unit/handler_tests/data/rag_pipelines/multi_retriever_summarize.yml b/tests/unused/unit/handler_tests/data/rag_pipelines/multi_retriever_summarize.yml deleted file mode 100644 index 9379c365ec2..00000000000 --- a/tests/unused/unit/handler_tests/data/rag_pipelines/multi_retriever_summarize.yml +++ /dev/null @@ -1,3 +0,0 @@ -retriever_type: multi -multi_retriever_mode: summarize - diff --git a/tests/unused/unit/handler_tests/data/rag_pipelines/vector_retriever_chroma.yml b/tests/unused/unit/handler_tests/data/rag_pipelines/vector_retriever_chroma.yml deleted file mode 100644 index bc35cd3e998..00000000000 --- a/tests/unused/unit/handler_tests/data/rag_pipelines/vector_retriever_chroma.yml +++ /dev/null @@ -1,3 +0,0 @@ -retriever_type: vector_store -vector_store_config: - vector_store_type: chroma diff --git a/tests/unused/unit/handler_tests/data/rag_pipelines/vector_retriever_pgvector.yml b/tests/unused/unit/handler_tests/data/rag_pipelines/vector_retriever_pgvector.yml deleted file mode 100644 index a75a9b33b71..00000000000 --- a/tests/unused/unit/handler_tests/data/rag_pipelines/vector_retriever_pgvector.yml +++ /dev/null @@ -1,3 +0,0 @@ -retriever_type: vector_store -vector_store_config: - vector_store_type: pgvector \ No newline at end of file diff --git a/tests/unused/unit/handler_tests/test_apache_doris_handler.py b/tests/unused/unit/handler_tests/test_apache_doris_handler.py deleted file mode 100644 index f4b1f3ac861..00000000000 --- a/tests/unused/unit/handler_tests/test_apache_doris_handler.py +++ /dev/null @@ -1,104 +0,0 @@ -import pytest - -from mindsdb.integrations.handlers.apache_doris_handler.apache_doris_handler import ApacheDorisHandler -from mindsdb.api.executor.data_types.response_type import RESPONSE_TYPE - -HANDLER_KWARGS = { - "connection_data": { - "host": "127.0.0.1", - "port": 9030, - "user": "root", - "password": "password", - "database": "mindstest" - } -} - -HANDLER_NAME = 'test_doris_handler' - - -@pytest.fixture(scope="module") -def handler(request): - handler = ApacheDorisHandler(HANDLER_NAME, **HANDLER_KWARGS) - yield handler - - -class TestMySQLHandler: - - def check_valid_response(self, res): - if res.resp_type == RESPONSE_TYPE.TABLE: - assert res.data_frame is not None, "expected to have some data, but got None" - assert res.error_code == 0, f"expected to have zero error_code, but got {res.error_code}" - assert res.error_message is None, f"expected to have None in error message, but got {res.error_message}" - - def get_table_names(self, handler): - res = handler.get_tables() - tables = res.data_frame - assert tables is not None, "expected to have some tables in the db, but got None" - assert 'table_name' in tables, f"expected to get 'table_name' column in the response:\n{tables}" - return list(tables['table_name']) - - def test_connect(self, handler): - handler.connect() - assert handler.is_connected, "connection error" - - def test_check_connection(self, handler): - res = handler.check_connection() - assert res.success, res.error_message - - def test_native_query_show_dbs(self, handler): - dbs = handler.native_query("SHOW DATABASES;") - dbs = dbs.data_frame - assert dbs is not None, "expected to get some data, but got None" - assert 'Database' in dbs, f"expected to get 'Database' column in response:\n{dbs}" - dbs = list(dbs["Database"]) - expected_db = HANDLER_KWARGS["connection_data"]["database"] - assert expected_db in dbs, f"expected to have {expected_db} db in response: {dbs}" - - def test_get_tables(self, handler): - tables = self.get_table_names(handler) - assert "example_tbl" in tables, f"expected to have 'example_tbl' table in the db but got: {tables}" - - def test_describe_table(self, handler): - described = handler.get_columns("example_tbl") - describe_data = described.data_frame - self.check_valid_response(described) - got_columns = list(describe_data.iloc[:, 0]) - want_columns = ["user_id", "date", "city", "age", "sex", "last_visit_date", "cost", "max_dwell_time", "min_dwell_time"] - assert got_columns == want_columns, f"expected to have next columns in table:\n{want_columns}\nbut got:\n{got_columns}" - - def test_create_table(self, handler): - new_table = "test_mdb" - res = handler.native_query(f""" - CREATE TABLE IF NOT EXISTS {new_table} (test_col INT) - DISTRIBUTED BY HASH(test_col) BUCKETS 1 - PROPERTIES ( - "replication_allocation" = "tag.location.default: 1" - ); - """) - self.check_valid_response(res) - tables = self.get_table_names(handler) - assert new_table in tables, f"expected to have {new_table} in database, but got: {tables}" - - def test_drop_table(self, handler): - drop_table = "test_mdb" - res = handler.native_query(f"DROP TABLE IF EXISTS {drop_table}") - self.check_valid_response(res) - tables = self.get_table_names(handler) - assert drop_table not in tables - - def test_select_query(self, handler): - limit = 3 - query = f"SELECT * FROM example_tbl LIMIT {limit}" - res = handler.query(query) - self.check_valid_response(res) - got_rows = res.data_frame.shape[0] - want_rows = limit - assert got_rows == want_rows, f"expected to have {want_rows} rows in response but got: {got_rows}" - - def test_select_where_query(self, handler): - want_rows = 5 - query = "SELECT * FROM example_tbl WHERE sex = 0" - res = handler.query(query) - self.check_valid_response(res) - got_rows = res.data_frame.shape[0] - assert got_rows == want_rows, f"expected to have {want_rows} rows in response but got: {got_rows}" diff --git a/tests/unused/unit/handler_tests/test_aqicn_handler.py b/tests/unused/unit/handler_tests/test_aqicn_handler.py deleted file mode 100644 index 674e4f04799..00000000000 --- a/tests/unused/unit/handler_tests/test_aqicn_handler.py +++ /dev/null @@ -1,50 +0,0 @@ -import importlib -import os -import pytest -from mindsdb_sql_parser import parse_sql - -from ..unit.executor_test_base import BaseExecutorTest - -try: - importlib.import_module("requests") - REQUESTS_INSTALLED = True -except ImportError: - REQUESTS_INSTALLED = False - - -@pytest.mark.skipif(not REQUESTS_INSTALLED, reason="requests package is not installed") -class TestAQICNHandler(BaseExecutorTest): - - def run_sql(self, sql): - ret = self.command_executor.execute_command(parse_sql(sql)) - assert ret.error_code is None - if ret.data is not None: - return ret.data.to_df() - - def setup_method(self): - super().setup_method() - self.api_key = os.environ.get("AQICN_KEY") - self.run_sql(f""" - CREATE DATABASE mindsdb_aqicn - WITH ENGINE = 'aqicn', - PARAMETERS = { - "api_key": '{self.api_key}' - }; - """) - - def test_basic_select_from(self): - sql = 'SELECT * FROM mindsdb_aqicn.air_quality_city where city="Bangalore";' - assert self.run_sql(sql).shape[0] == 1 - - sql = 'SELECT * FROM mindsdb_aqicn.air_quality_lat_lng where lat="12.938539" AND lng="77.5901";' - assert self.run_sql(sql).shape[0] == 1 - - sql = 'SELECT * FROM mindsdb_aqicn.air_quality_user_location;' - assert self.run_sql(sql).shape[0] == 1 - - def test_complex_select(self): - sql = 'SELECT data.city.url, data.city.name FROM mindsdb_aqicn.air_quality_lat_lng where lat="12.938539" AND lng="77.5901";' - assert self.run_sql(sql).shape[1] == 2 - - sql = 'SELECT * FROM mindsdb_aqicn.air_quality_user_location LIMIT 1;' - assert self.run_sql(sql).shape[0] == 1 From 7ff0d26ebea5905d60e901dfa007c1fd90d88842 Mon Sep 17 00:00:00 2001 From: ZoranPandovski Date: Fri, 19 Dec 2025 15:51:02 +0100 Subject: [PATCH 3/4] Rmv unused tests --- .../handler_tests/test_binance_handler.py | 110 -- .../handler_tests/test_coinbase_handler.py | 94 -- .../unit/handler_tests/test_email_handler.py | 138 --- .../handler_tests/test_eventbrite_handler.py | 405 ------- .../unit/handler_tests/test_gmail_handler.py | 240 ---- .../handler_tests/test_handler_metrics.py | 52 - .../handler_tests/test_hubspot_handler.py | 39 - .../handler_tests/test_instatus_handler.py | 144 --- .../handler_tests/test_intercom_handler.py | 62 - .../handler_tests/test_lightdash_handler.py | 146 --- .../unit/handler_tests/test_luma_handler.py | 40 - .../handler_tests/test_mariadb_handler.py | 169 --- .../unit/handler_tests/test_milvus_handler.py | 460 -------- .../handler_tests/test_ms_teams_handler.py | 1050 ----------------- .../unit/handler_tests/test_npm_handler.py | 86 -- .../handler_tests/test_oilpriceapi_handler.py | 47 - .../unit/handler_tests/test_paypal_handler.py | 46 - .../handler_tests/test_pgvector_handler.py | 134 --- .../handler_tests/test_pinecone_handler.py | 274 ----- .../unit/handler_tests/test_qdrant_handler.py | 442 ------- 20 files changed, 4178 deletions(-) delete mode 100644 tests/unused/unit/handler_tests/test_binance_handler.py delete mode 100644 tests/unused/unit/handler_tests/test_coinbase_handler.py delete mode 100644 tests/unused/unit/handler_tests/test_email_handler.py delete mode 100644 tests/unused/unit/handler_tests/test_eventbrite_handler.py delete mode 100644 tests/unused/unit/handler_tests/test_gmail_handler.py delete mode 100644 tests/unused/unit/handler_tests/test_handler_metrics.py delete mode 100644 tests/unused/unit/handler_tests/test_hubspot_handler.py delete mode 100644 tests/unused/unit/handler_tests/test_instatus_handler.py delete mode 100644 tests/unused/unit/handler_tests/test_intercom_handler.py delete mode 100644 tests/unused/unit/handler_tests/test_lightdash_handler.py delete mode 100644 tests/unused/unit/handler_tests/test_luma_handler.py delete mode 100644 tests/unused/unit/handler_tests/test_mariadb_handler.py delete mode 100644 tests/unused/unit/handler_tests/test_milvus_handler.py delete mode 100644 tests/unused/unit/handler_tests/test_ms_teams_handler.py delete mode 100644 tests/unused/unit/handler_tests/test_npm_handler.py delete mode 100644 tests/unused/unit/handler_tests/test_oilpriceapi_handler.py delete mode 100644 tests/unused/unit/handler_tests/test_paypal_handler.py delete mode 100644 tests/unused/unit/handler_tests/test_pgvector_handler.py delete mode 100644 tests/unused/unit/handler_tests/test_pinecone_handler.py delete mode 100644 tests/unused/unit/handler_tests/test_qdrant_handler.py diff --git a/tests/unused/unit/handler_tests/test_binance_handler.py b/tests/unused/unit/handler_tests/test_binance_handler.py deleted file mode 100644 index 456b9d7345b..00000000000 --- a/tests/unused/unit/handler_tests/test_binance_handler.py +++ /dev/null @@ -1,110 +0,0 @@ -from mindsdb.integrations.handlers.binance_handler.binance_tables import BinanceAggregatedTradesTable -from mindsdb.integrations.handlers.binance_handler.binance_handler import BinanceHandler -from mindsdb_sql_parser import ast -from mindsdb_sql_parser.ast.select.star import Star -from mindsdb_sql_parser.ast.select.identifier import Identifier - -from unittest.mock import Mock - -import pandas as pd -import unittest - - -class BinanceAggregatedTradesTableTest(unittest.TestCase): - def test_get_columns_returns_all_columns(self): - api_handler = Mock(BinanceHandler) - trades_table = BinanceAggregatedTradesTable(api_handler) - # Order matters. - expected_columns = [ - 'symbol', - 'open_time', - 'open_price', - 'high_price', - 'low_price', - 'close_price', - 'volume', - 'close_time', - 'quote_asset_volume', - 'number_of_trades', - 'taker_buy_base_asset_volume', - 'taker_buy_quote_asset_volume' - ] - self.assertListEqual(trades_table.get_columns(), expected_columns) - - def test_select_returns_all_columns(self): - api_handler = Mock(BinanceHandler) - api_handler.call_binance_api.return_value = pd.DataFrame([ - [ - 'symbol', # Symbol - 1499040000000, # Kline open time - '0.01634790', # Open price - '0.80000000', # High price - '0.01575800', # Low price - '0.01577100', # Close price - '148976.11427815', # Volume - 1499644799999, # Kline Close time - '2434.19055334', # Quote asset volume - 308, # Number of trades - '1756.87402397', # Taker buy base asset volume - '28.46694368', # Taker buy quote asset volume - ] - ]) - trades_table = BinanceAggregatedTradesTable(api_handler) - - select_all = ast.Select( - targets=[Star()], - from_table='aggregated_trade_data', - where='aggregated_trade_data.symbol = "symbol"' - ) - - all_trade_data = trades_table.select(select_all) - first_trade_data = all_trade_data.iloc[0] - - self.assertEqual(all_trade_data.shape[1], 12) - self.assertEqual(first_trade_data['symbol'], 'symbol') - self.assertEqual(first_trade_data['open_time'], 1499040000000) - self.assertEqual(first_trade_data['open_price'], '0.01634790') - self.assertEqual(first_trade_data['high_price'], '0.80000000') - self.assertEqual(first_trade_data['low_price'], '0.01575800') - self.assertEqual(first_trade_data['close_price'], '0.01577100') - self.assertEqual(first_trade_data['volume'], '148976.11427815') - self.assertEqual(first_trade_data['close_time'], 1499644799999) - self.assertEqual(first_trade_data['quote_asset_volume'], '2434.19055334') - self.assertEqual(first_trade_data['number_of_trades'], 308) - self.assertEqual(first_trade_data['taker_buy_base_asset_volume'], '1756.87402397') - self.assertEqual(first_trade_data['taker_buy_quote_asset_volume'], '28.46694368') - - def test_select_returns_only_selected_columns(self): - api_handler = Mock(BinanceHandler) - api_handler.call_binance_api.return_value = pd.DataFrame([ - [ - 'symbol', # Symbol - 1499040000000, # Kline open time - '0.01634790', # Open price - '0.80000000', # High price - '0.01575800', # Low price - '0.01577100', # Close price - '148976.11427815', # Volume - 1499644799999, # Kline Close time - '2434.19055334', # Quote asset volume - 308, # Number of trades - '1756.87402397', # Taker buy base asset volume - '28.46694368', # Taker buy quote asset volume - ] - ]) - trades_table = BinanceAggregatedTradesTable(api_handler) - - open_time_identifier = Identifier(path_str='open_time') - close_time_identifier = Identifier(path_str='close_time') - select_times = ast.Select( - targets=[open_time_identifier, close_time_identifier], - from_table='aggregated_trade_data', - where='aggregated_trade_data.symbol = "symbol"' - ) - - all_trade_data = trades_table.select(select_times) - first_trade_data = all_trade_data.iloc[0] - - self.assertEqual(all_trade_data.shape[1], 2) - self.assertEqual(first_trade_data['open_time'], 1499040000000) - self.assertEqual(first_trade_data['close_time'], 1499644799999) diff --git a/tests/unused/unit/handler_tests/test_coinbase_handler.py b/tests/unused/unit/handler_tests/test_coinbase_handler.py deleted file mode 100644 index 0a7b3067b82..00000000000 --- a/tests/unused/unit/handler_tests/test_coinbase_handler.py +++ /dev/null @@ -1,94 +0,0 @@ -from mindsdb.integrations.handlers.coinbase_handler.coinbase_tables import CoinBaseAggregatedTradesTable -from mindsdb.integrations.handlers.coinbase_handler.coinbase_handler import CoinBaseHandler -from mindsdb_sql_parser import ast -from mindsdb_sql_parser.ast.select.star import Star -from mindsdb_sql_parser.ast.select.identifier import Identifier - -from unittest.mock import Mock - -import pandas as pd -import unittest - - -class CoinBaseAggregatedTradesTableTest(unittest.TestCase): - def test_get_columns_returns_all_columns(self): - api_handler = Mock(CoinBaseHandler) - trades_table = CoinBaseAggregatedTradesTable(api_handler) - # Order matters. - expected_columns = [ - 'symbol', - 'low', - 'high', - 'open', - 'close', - 'volume', - 'timestamp', - 'timestamp_iso' - ] - self.assertListEqual(trades_table.get_columns(), expected_columns) - - def test_select_returns_all_columns(self): - api_handler = Mock(CoinBaseHandler) - api_handler.call_coinbase_api.return_value = pd.DataFrame([ - [ - 'BTC-USD', # symbol - 34330.01, # low - 34623.21, # high - 34493.51, # open - 34349.16, # close - 719.064133, # volume - 1698710400, # timestamp - "2023-10-30T20:00:00-04:00" # timestamp_iso - ] - ]) - trades_table = CoinBaseAggregatedTradesTable(api_handler) - - select_all = ast.Select( - targets=[Star()], - from_table='coinbase_candle_data', - where='coinbase_candle_data.symbol = "BTC-USD"' - ) - - all_trade_data = trades_table.select(select_all) - first_trade_data = all_trade_data.iloc[0] - - self.assertEqual(all_trade_data.shape[1], 8) - self.assertEqual(first_trade_data['symbol'], 'BTC-USD') - self.assertEqual(first_trade_data['low'], 34330.01) - self.assertEqual(first_trade_data['high'], 34623.21) - self.assertEqual(first_trade_data['open'], 34493.51) - self.assertEqual(first_trade_data['close'], 34349.16) - self.assertEqual(first_trade_data['volume'], 719.064133) - self.assertEqual(first_trade_data['timestamp'], 1698710400) - self.assertEqual(first_trade_data['timestamp_iso'], '2023-10-30T20:00:00-04:00') - - def test_select_returns_only_selected_columns(self): - api_handler = Mock(CoinBaseHandler) - api_handler.call_coinbase_api.return_value = pd.DataFrame([ - [ - 'BTC-USD', # symbol - 34330.01, # low - 34623.21, # high - 34493.51, # open - 34349.16, # close - 719.064133, # volume - 1698710400, # timestamp - "2023-10-30T20:00:00-04:00" # timestamp_iso - ] - ]) - trades_table = CoinBaseAggregatedTradesTable(api_handler) - - open_time_identifier = Identifier(path_str='open') - close_time_identifier = Identifier(path_str='close') - select_times = ast.Select( - targets=[open_time_identifier, close_time_identifier], - from_table='coinbase_candle_data', - where='coinbase_candle_data.symbol = "BTC-USD"' - ) - - all_trade_data = trades_table.select(select_times) - first_trade_data = all_trade_data.iloc[0] - - self.assertEqual(all_trade_data.shape[1], 2) - self.assertEqual(first_trade_data['open'], 34493.51) - self.assertEqual(first_trade_data['close'], 34349.16) diff --git a/tests/unused/unit/handler_tests/test_email_handler.py b/tests/unused/unit/handler_tests/test_email_handler.py deleted file mode 100644 index 6bd96b68e53..00000000000 --- a/tests/unused/unit/handler_tests/test_email_handler.py +++ /dev/null @@ -1,138 +0,0 @@ -import os - -import pandas as pd -import pytest -from unittest.mock import MagicMock - -from mindsdb_sql_parser import parse_sql -from mindsdb.integrations.handlers.email_handler.email_tables import EmailsTable -from mindsdb.integrations.handlers.email_handler.email_handler import EmailHandler - - -class TestEmailHandler: - def setup_class(self): - # Check if env variables exist, if not fail the test - email = os.getenv("EMAIL_USERNAME") - password = os.getenv("EMAIL_PASSWORD") - assert email is not None, "EMAIL_USERNAME environment variable not found e.g. example@gmail.com" - assert password is not None, "EMAIL_PASSWORD environment variable not found" - - self.connection_data = {"email": email, "password": password} - self.email_handler = EmailHandler(connection_data=self.connection_data) - self.email_handler.connect() - self.emails_table_instance = EmailsTable(self.email_handler) - - def test_connect_already_connected(self): - self.email_handler.is_connected = True - connection = self.email_handler.connect() - assert connection is self.email_handler.connection, "The connection must be the same as the one in the handler." - - def test_check_connection(self): - response = self.email_handler.check_connection() - assert response.success is True, "The response success must be True." - - def test_select(self): - """ - Test the select method of EmailsTable Class - """ - - mock_df = pd.DataFrame( - { - "date": [ - "Wed, 02 Feb 2022 15:30:00 +0000", - "Thu, 10 Mar 2022 10:45:15 +0530", - "Fri, 16 Dec 2022 20:15:30 -0400", - ], - "body_content_type": ["html", "html", "text"], - "body": [ - "

Hello, World!

", - "

Hello, World!

", - "Hello, World!", - ], - "from_field": ["", "", ""], - "id": ["", "", ""], - "to_field": ["", "", ""], - "subject": ["", "", ""], - } - ) - - self.emails_table_instance.handler.connection.search_email = MagicMock(return_value=mock_df) - - query = parse_sql("SELECT * FROM emails limit 1") - - self.emails_table_instance.select(query) - - assert self.emails_table_instance.handler.connection.search_email.called, ( - "The search_email method must be called." - ) - - # select using invalid column should raise Exception - query = parse_sql("SELECT invalid_column FROM emails limit 1") - - with pytest.raises(Exception): - self.emails_table_instance.select(query) - - def test_insert(self): - """ - Test the insert method of EmailsTable Class - """ - - self.emails_table_instance.handler.connection.send_email = MagicMock() - - query = parse_sql( - "INSERT INTO email_datasource.emails(to_field, subject, body) " - 'VALUES ("toemail@email.com", "MindsDB", "Hello from MindsDB!")' - ) - - self.emails_table_instance.insert(query) - assert self.emails_table_instance.handler.connection.send_email.called, "The send_email method must be called." - - # insert using invalid column should raise Exception - query = parse_sql( - "INSERT INTO email_datasource.emails(to_field, subject, body, invalid_column) " - 'VALUES ("toemail@email.com", "MindsDB", "blaha" , "invalid")' - ) - - with pytest.raises(Exception): - self.emails_table_instance.insert(query) - - def test_get_columns(self): - """ - Test the get_columns method of EmailsTable Class - """ - - columns = self.emails_table_instance.get_columns() - assert isinstance(columns, list), "The returned value must be a list." - assert "id" in columns, "Column 'id' must be in the columns list." - assert "body" in columns, "Column 'body' must be in the columns list." - assert "subject" in columns, "Column 'subject' must be in the columns list." - assert "to_field" in columns, "Column 'to_field' must be in the columns list." - assert "from_field" in columns, "Column 'from_field' must be in the columns list." - assert "datetime" in columns, "Column 'datetime' must be in the columns list." - - def test_undetectable_encoding_handling(self): - """ - Test that the email handler can process emails with undetectable encodings - without raising exceptions. - """ - - undetectable_content = b"\x80\x81\x82\x83\x84\x85\x86\x87" - mock_df = pd.DataFrame( - { - "date": ["Wed, 02 Feb 2022 15:30:00 +0000"], - "body_content_type": ["text"], - "body": [undetectable_content], - "from_field": ["test@example.com"], - "id": ["test1"], - "to_field": ["recipient@example.com"], - "subject": ["Test email with undetectable encoding"], - } - ) - - self.emails_table_instance.handler.connection.search_email = MagicMock(return_value=mock_df) - query = parse_sql("SELECT * FROM emails limit 1") - result = self.emails_table_instance.select(query) - - assert result is not None, "The result must not be None." - assert "body" in result.columns, "The body should be in the result columns." - assert len(result) > 0, "The result should not be empty." diff --git a/tests/unused/unit/handler_tests/test_eventbrite_handler.py b/tests/unused/unit/handler_tests/test_eventbrite_handler.py deleted file mode 100644 index b07e3f09cdd..00000000000 --- a/tests/unused/unit/handler_tests/test_eventbrite_handler.py +++ /dev/null @@ -1,405 +0,0 @@ -from mindsdb.integrations.handlers.eventbrite_handler.eventbrite_handler import ( - EventbriteHandler, -) - -from mindsdb.integrations.handlers.eventbrite_handler.eventbrite_handler import ( - CategoryInfoTable, - EventDetailsTable, -) - -from mindsdb_sql_parser import ast -from mindsdb_sql_parser.ast.select.identifier import Identifier - -from unittest.mock import Mock - -import pandas as pd -import unittest - - -class CategoryInfoTableTest(unittest.TestCase): - def test_get_columns_returns_all_columns(self): - api_handler = Mock(EventbriteHandler) - trades_table = CategoryInfoTable(api_handler) - # Order matters. - expected_columns = [ - "resource_uri", - "id", - "name", - "name_localized", - "short_name", - "short_name_localized", - ] - self.assertListEqual(trades_table.get_columns(), expected_columns) - - def test_select_returns_some_columns(self): - api_handler = Mock() - api_handler.api.list_categories.return_value = pd.DataFrame( - { - "locale": "en_US", - "categories": [ - { - "resource_uri": "https://www.eventbriteapi.com/v3/categories/103/", - "id": "103", - "name": "Music", - "name_localized": "Music", - "short_name": "Music", - "short_name_localized": "Music", - }, - { - "resource_uri": "https://www.eventbriteapi.com/v3/categories/101/", - "id": "101", - "name": "Business & Professional", - "name_localized": "Business & Professional", - "short_name": "Business", - "short_name_localized": "Business", - }, - { - "resource_uri": "https://www.eventbriteapi.com/v3/categories/110/", - "id": "110", - "name": "Food & Drink", - "name_localized": "Food & Drink", - "short_name": "Food & Drink", - "short_name_localized": "Food & Drink", - }, - { - "resource_uri": "https://www.eventbriteapi.com/v3/categories/113/", - "id": "113", - "name": "Community & Culture", - "name_localized": "Community & Culture", - "short_name": "Community", - "short_name_localized": "Community", - }, - { - "resource_uri": "https://www.eventbriteapi.com/v3/categories/105/", - "id": "105", - "name": "Performing & Visual Arts", - "name_localized": "Performing & Visual Arts", - "short_name": "Arts", - "short_name_localized": "Arts", - }, - { - "resource_uri": "https://www.eventbriteapi.com/v3/categories/104/", - "id": "104", - "name": "Film, Media & Entertainment", - "name_localized": "Film, Media & Entertainment", - "short_name": "Film & Media", - "short_name_localized": "Film & Media", - }, - { - "resource_uri": "https://www.eventbriteapi.com/v3/categories/108/", - "id": "108", - "name": "Sports & Fitness", - "name_localized": "Sports & Fitness", - "short_name": "Sports & Fitness", - "short_name_localized": "Sports & Fitness", - }, - { - "resource_uri": "https://www.eventbriteapi.com/v3/categories/107/", - "id": "107", - "name": "Health & Wellness", - "name_localized": "Health & Wellness", - "short_name": "Health", - "short_name_localized": "Health", - }, - { - "resource_uri": "https://www.eventbriteapi.com/v3/categories/102/", - "id": "102", - "name": "Science & Technology", - "name_localized": "Science & Technology", - "short_name": "Science & Tech", - "short_name_localized": "Science & Tech", - }, - { - "resource_uri": "https://www.eventbriteapi.com/v3/categories/109/", - "id": "109", - "name": "Travel & Outdoor", - "name_localized": "Travel & Outdoor", - "short_name": "Travel & Outdoor", - "short_name_localized": "Travel & Outdoor", - }, - { - "resource_uri": "https://www.eventbriteapi.com/v3/categories/111/", - "id": "111", - "name": "Charity & Causes", - "name_localized": "Charity & Causes", - "short_name": "Charity & Causes", - "short_name_localized": "Charity & Causes", - }, - { - "resource_uri": "https://www.eventbriteapi.com/v3/categories/114/", - "id": "114", - "name": "Religion & Spirituality", - "name_localized": "Religion & Spirituality", - "short_name": "Spirituality", - "short_name_localized": "Spirituality", - }, - { - "resource_uri": "https://www.eventbriteapi.com/v3/categories/115/", - "id": "115", - "name": "Family & Education", - "name_localized": "Family & Education", - "short_name": "Family & Education", - "short_name_localized": "Family & Education", - }, - { - "resource_uri": "https://www.eventbriteapi.com/v3/categories/116/", - "id": "116", - "name": "Seasonal & Holiday", - "name_localized": "Seasonal & Holiday", - "short_name": "Holiday", - "short_name_localized": "Holiday", - }, - { - "resource_uri": "https://www.eventbriteapi.com/v3/categories/112/", - "id": "112", - "name": "Government & Politics", - "name_localized": "Government & Politics", - "short_name": "Government", - "short_name_localized": "Government", - }, - { - "resource_uri": "https://www.eventbriteapi.com/v3/categories/106/", - "id": "106", - "name": "Fashion & Beauty", - "name_localized": "Fashion & Beauty", - "short_name": "Fashion", - "short_name_localized": "Fashion", - }, - { - "resource_uri": "https://www.eventbriteapi.com/v3/categories/117/", - "id": "117", - "name": "Home & Lifestyle", - "name_localized": "Home & Lifestyle", - "short_name": "Home & Lifestyle", - "short_name_localized": "Home & Lifestyle", - }, - { - "resource_uri": "https://www.eventbriteapi.com/v3/categories/118/", - "id": "118", - "name": "Auto, Boat & Air", - "name_localized": "Auto, Boat & Air", - "short_name": "Auto, Boat & Air", - "short_name_localized": "Auto, Boat & Air", - }, - { - "resource_uri": "https://www.eventbriteapi.com/v3/categories/119/", - "id": "119", - "name": "Hobbies & Special Interest", - "name_localized": "Hobbies & Special Interest", - "short_name": "Hobbies", - "short_name_localized": "Hobbies", - }, - { - "resource_uri": "https://www.eventbriteapi.com/v3/categories/199/", - "id": "199", - "name": "Other", - "name_localized": "Other", - "short_name": "Other", - "short_name_localized": "Other", - }, - { - "resource_uri": "https://www.eventbriteapi.com/v3/categories/120/", - "id": "120", - "name": "School Activities", - "name_localized": "School Activities", - "short_name": "School Activities", - "short_name_localized": "School Activities", - }, - ], - } - ) - eventbrite_table = CategoryInfoTable(api_handler) - - resource_uri_identifier = Identifier(path_str="resource_uri") - id_identifier = Identifier(path_str="id") - name_identifier = Identifier(path_str="name") - name_localized_identifier = Identifier(path_str="name_localized") - - select_all = ast.Select( - targets=[ - resource_uri_identifier, - id_identifier, - name_identifier, - name_localized_identifier, - ], - from_table="categoryInfoTable", - ) - - all_category_data = eventbrite_table.select(select_all) - - self.assertEqual(all_category_data.shape[0], 20) - self.assertEqual(all_category_data.shape[1], 4) - - -class EventDetailsTableTest(unittest.TestCase): - def test_get_columns_returns_all_columns(self): - api_handler = Mock(EventbriteHandler) - trades_table = EventDetailsTable(api_handler) - # Order matters. - expected_columns = [ - "name_text", - "name_html", - "description_text", - "description_html", - "url", - "start_timezone", - "start_local", - "start_utc", - "end_timezone", - "end_local", - "end_utc", - "organization_id", - "created", - "changed", - "published", - "capacity", - "capacity_is_custom", - "status", - "currency", - "listed", - "shareable", - "online_event", - "tx_time_limit", - "hide_start_date", - "hide_end_date", - "locale", - "is_locked", - "privacy_setting", - "is_series", - "is_series_parent", - "inventory_type", - "is_reserved_seating", - "show_pick_a_seat", - "show_seatmap_thumbnail", - "show_colors_in_seatmap_thumbnail", - "source", - "is_free", - "version", - "summary", - "facebook_event_id", - "logo_id", - "organizer_id", - "venue_id", - "category_id", - "subcategory_id", - "format_id", - "id", - "resource_uri", - "is_externally_ticketed", - "logo_crop_mask", - "logo_original", - "logo_id", - "logo_url", - "logo_aspect_ratio", - "logo_edge_color", - "logo_edge_color_set", - ] - self.assertListEqual(trades_table.get_columns(), expected_columns) - - def test_select_returns_some_columns(self): - api_handler = Mock() - api_handler.api.get_event.return_value = pd.DataFrame( - { - "name": { - "text": "AI Forum: Can AI Fix Climate Change?", - "html": "AI Forum: Can AI Fix Climate Change?", - }, - "description": { - "text": "The third in a series of lunchtime presentations by King's researchers at Science Gallery London", - "html": "The third in a series of lunchtime presentations by King's researchers at Science Gallery London", - }, - "url": "https://www.eventbrite.co.uk/e/ai-forum-can-ai-fix-climate-change-tickets-717926867587", - "start": { - "timezone": "Europe/London", - "local": "2023-11-01T13:15:00", - "utc": "2023-11-01T13:15:00Z", - }, - "end": { - "timezone": "Europe/London", - "local": "2023-11-01T14:00:00", - "utc": "2023-11-01T14:00:00Z", - }, - "organization_id": "112948679745", - "created": "2023-09-12T15:38:12Z", - "changed": "2023-10-11T20:01:50Z", - "published": "2023-09-12T15:44:26Z", - "capacity": None, - "capacity_is_custom": None, - "status": "live", - "currency": "GBP", - "listed": True, - "shareable": True, - "online_event": False, - "tx_time_limit": 1200, - "hide_start_date": False, - "hide_end_date": False, - "locale": "en_GB", - "is_locked": False, - "privacy_setting": "unlocked", - "is_series": False, - "is_series_parent": False, - "inventory_type": "limited", - "is_reserved_seating": False, - "show_pick_a_seat": False, - "show_seatmap_thumbnail": False, - "show_colors_in_seatmap_thumbnail": False, - "source": "coyote", - "is_free": True, - "version": None, - "summary": "The third in a series of lunchtime presentations by King's researchers at Science Gallery London", - "facebook_event_id": None, - "logo_id": "596060689", - "organizer_id": "7201076133", - "venue_id": "173614819", - "category_id": "102", - "subcategory_id": None, - "format_id": "2", - "id": "717926867587", - "resource_uri": "https://www.eventbriteapi.com/v3/events/717926867587/", - "is_externally_ticketed": False, - "logo": { - "crop_mask": { - "top_left": {"x": 0, "y": 0}, - "width": 2160, - "height": 1080, - }, - "original": { - "url": "https://img.evbuc.com/https%3A%2F%2Fcdn.evbuc.com%2Fimages%2F596060689%2F112948679745%2F1%2Foriginal.20230912-154003?auto=format%2Ccompress&q=75&sharp=10&s=0bb5e81d009275e956f98c418a9a3025", - "width": 2160, - "height": 1080, - }, - "id": "596060689", - "url": "https://img.evbuc.com/https%3A%2F%2Fcdn.evbuc.com%2Fimages%2F596060689%2F112948679745%2F1%2Foriginal.20230912-154003?h=200&w=450&auto=format%2Ccompress&q=75&sharp=10&rect=0%2C0%2C2160%2C1080&s=282ef80475d468edff954cb243435432", - "aspect_ratio": "2", - "edge_color": "#d6b4be", - "edge_color_set": True, - }, - } - ) - eventbrite_table = EventDetailsTable(api_handler) - - name_text_identifier = Identifier(path_str="name_text") - description_text_identifier = Identifier(path_str="description_text") - url_identifier = Identifier(path_str="url") - - select_all = ast.Select( - targets=[name_text_identifier, description_text_identifier, url_identifier], - from_table="eventDetailsTable", - where='locationId = "717926867587"', - ) - - review_data = eventbrite_table.select(select_all) - first_data = review_data.iloc[0] - - self.assertEqual(review_data.shape[1], 3) - self.assertEqual( - first_data["name_text"], "AI Forum: Can AI Fix Climate Change?" - ) - self.assertEqual( - first_data["description_text"], - "The third in a series of lunchtime presentations by King's researchers at Science Gallery London", - ) - - -if __name__ == "__main__": - unittest.main() diff --git a/tests/unused/unit/handler_tests/test_gmail_handler.py b/tests/unused/unit/handler_tests/test_gmail_handler.py deleted file mode 100644 index 7e8fe86758d..00000000000 --- a/tests/unused/unit/handler_tests/test_gmail_handler.py +++ /dev/null @@ -1,240 +0,0 @@ -from mindsdb.api.executor.data_types.response_type import RESPONSE_TYPE -from mindsdb.integrations.handlers.gmail_handler.gmail_handler import GmailHandler -from mindsdb.integrations.handlers.gmail_handler.gmail_handler import EmailsTable -from google.oauth2.credentials import Credentials -from mindsdb_sql_parser import parse_sql -import unittest -from unittest.mock import Mock, patch -from unittest import mock - - -class GmailHandlerTest(unittest.TestCase): - def setUp(self) -> None: - self.credentials_file = 'test1_credentials.json' - self.credentials_url = 's3://your-bucket/test_credentials.json' - self.handler = GmailHandler(connection_data={ - 'credentials_file': self.credentials_file, - 'credentials_url': self.credentials_url - }) - - @patch('mindsdb.integrations.handlers.gmail_handler.gmail_handler.requests.get') # Patching the requests.get method - def test_has_creds_file_with_valid_s3_link(self, mock_get): - # Configure the mock behavior - mock_response = mock_get.return_value - mock_response.status_code = 200 - mock_response.text = 'Mocked credentials file content' - - result = self.handler._has_creds_file(self.credentials_file) - # Assert that the requests.get method was called with the correct URL - mock_get.assert_called_once_with(self.credentials_url) - # Assert that the method returns True - self.assertTrue(result) - - @patch('mindsdb.integrations.handlers.gmail_handler.gmail_handler.requests.get') # Patching the requests.get method - def test_has_creds_file_with_invalid_s3_link(self, mock_get): - # Test when invalid S3 credentials file is provided - mock_response = mock.Mock() - mock_response.status_code = 404 - mock_get.return_value = mock_response - - # TODO this will be broken now that we don't use global loggers anymore - with patch('mindsdb.utilities.log.logger') as mock_logger: - result = self.handler._has_creds_file(self.credentials_file) - # Assert that the requests.get method was called with the correct URL - self.assertFalse(result) - # Assert that the error message is logged - mock_logger.error.assert_called_once_with("Failed to get credentials from S3", 404) - - def test_create_connection_with_mocked_token(self): - with mock.patch('google.oauth2.credentials.Credentials.from_authorized_user_file') as mock_credentials: - mock_credentials.return_value = Credentials('token.json') - with mock.patch('os.path.isfile') as mock_isfile: - mock_isfile.return_value = True - result = self.handler.create_connection() - self.assertIsNotNone(result) - - def test_create_connection_with_mocked_credentials_file(self): - with mock.patch('google.oauth2.credentials.Credentials.from_authorized_user_file') as mock_credentials: - mock_credentials.is_valid.return_value = False - with mock.patch('os.path.isfile') as mock_isfile: - mock_isfile.return_value = True - result = self.handler.create_connection() - self.assertIsNotNone(result) - - def test_create_connection_with_mocked_credentials_file_and_s3(self): - with mock.patch('google.oauth2.credentials.Credentials.from_authorized_user_file') as mock_credentials: - mock_credentials.is_valid.return_value = False - with mock.patch('os.path.isfile') as mock_isfile: - mock_isfile.return_value = True - with mock.patch( - 'mindsdb.integrations.handlers.gmail_handler.gmail_handler.GmailHandler._has_creds_file') \ - as mock_has_creds_file: - mock_has_creds_file.return_value = True - result = self.handler.create_connection() - self.assertIsNotNone(result) - - def test_parse_parts_with_multipart_mime_type(self): - email_parts = [ - { - 'mimeType': 'multipart/mixed', - 'parts': [ - { - 'mimeType': 'multipart/alternative', - 'parts': [ - { - 'mimeType': 'text/plain', - 'body': { - 'data': 'VGhpcyBpcyB0aGUgcGxhaW4gdGV4dCBib2R5IG9mIHRoZSBlbWFpbC4=' - } - }, - { - 'mimeType': 'text/html', - 'body': { - 'data': 'PGh0bWw+CiAgICA8Ym9keT4KICAgICAgPHA+V' - 'GhpcyBpcyB0aGUgSFRNTCBib2R5IG9mIHRoZSBlbWFpbC4' - 'gPC9wPgogICAgPC9ib2R5PjwvaHRtbD4=' - } - } - ] - }, - { - 'mimeType': 'application/pdf', - 'filename': 'example.pdf', - 'body': { - 'attachmentId': '<>' - } - } - ] - } - - ] - attachments = [] - email_body = self.handler._parse_parts(email_parts, attachments) - expected_body = "This is the plain text body of the email." - expected_attachments = [ - { - 'filename': 'example.pdf', - 'mimeType': 'application/pdf', - 'attachmentId': '<>' - } - ] - self.assertEqual(email_body, expected_body) - self.assertEqual(attachments, expected_attachments) - - def test_parse_parts_with_multipart_mime_type_and_no_parts(self): - email_parts = [ - { - 'mimeType': 'multipart/mixed', - 'parts': [] - } - ] - attachments = [] - email_body = self.handler._parse_parts(email_parts, attachments) - expected_body = "" - expected_attachments = [] - self.assertEqual(email_body, expected_body) - self.assertEqual(attachments, expected_attachments) - - def test_parse_parts_with_multiple_attachments(self): - email_parts = [ - { - 'mimeType': 'multipart/mixed', - 'parts': [ - { - 'mimeType': 'multipart/alternative', - 'parts': [ - { - 'mimeType': 'text/plain', - 'body': { - 'data': 'VGhpcyBpcyB0aGUgcGxhaW4gdGV4dCBib2R5IG9mIHRoZSBlbWFpbC4=' - } - }, - { - 'mimeType': 'text/html', - 'body': { - 'data': 'PGh0bWw+CiAgICA8Ym9keT4KICAgICAgPHA+' - 'VGhpcyBpcyB0aGUgSFRNTCBib2R5IG9mIHRoZSBlbWFpb' - 'C4gPC9wPgogICAgPC9ib2R5PjwvaHRtbD4=' - } - } - ] - }, - { - 'mimeType': 'application/pdf', - 'filename': 'example.pdf', - 'body': { - 'attachmentId': '<>' - } - }, - { - 'mimeType': 'application/pdf', - 'filename': 'example2.pdf', - 'body': { - 'attachmentId': '<>' - } - } - ] - } - ] - attachments = [] - email_body = self.handler._parse_parts(email_parts, attachments) - expected_body = "This is the plain text body of the email." - expected_attachments = [ - { - 'filename': 'example.pdf', - 'mimeType': 'application/pdf', - 'attachmentId': '<>' - }, - { - 'filename': 'example2.pdf', - 'mimeType': 'application/pdf', - 'attachmentId': '<>' - } - ] - self.assertEqual(email_body, expected_body) - self.assertEqual(attachments, expected_attachments) - - -class EmailsTableTest(unittest.TestCase): - - def test_get_tables(self): - handler = Mock(GmailHandler) - tables = handler.get_tables() - assert tables.type is not RESPONSE_TYPE.ERROR - - def test_get_columns_returns_all_columns(self): - gmail_handler = Mock(GmailHandler) - gmail_table = EmailsTable(gmail_handler) - expected_columns = [ - 'id', - 'message_id', - 'thread_id', - 'label_ids', - 'sender', - 'to', - 'date', - 'subject', - 'snippet', - 'history_id', - 'size_estimate', - 'body', - 'attachments' - - ] - self.assertListEqual(gmail_table.get_columns(), expected_columns) - - def test_delete_method(self): - gmail_handler = Mock(GmailHandler) - gmail_table = EmailsTable(gmail_handler) - query = parse_sql('delete from gmail where id=1') - gmail_table.delete(query) - gmail_handler.call_gmail_api.assert_called_once_with('delete_message', {'id': 1}) - - def test_update_method(self): - gmail_handler = Mock(GmailHandler) - gmail_table = EmailsTable(gmail_handler) - query = parse_sql('update gmail set addLabel="test1",removeLabel = "test" where id=1') - gmail_table.update(query) - gmail_handler.call_gmail_api.assert_called_once_with('modify_message', {'id': 1, - 'body': {'addLabelIds': ['test1'], - 'removeLabelIds': ['test']}}) diff --git a/tests/unused/unit/handler_tests/test_handler_metrics.py b/tests/unused/unit/handler_tests/test_handler_metrics.py deleted file mode 100644 index 26ee07040ed..00000000000 --- a/tests/unused/unit/handler_tests/test_handler_metrics.py +++ /dev/null @@ -1,52 +0,0 @@ -import datetime -import pandas as pd -from unit.executor_test_base import BaseExecutorDummyML - - -class TestHandlerMetrics(BaseExecutorDummyML): - def test_handler_query_time(self): - self.set_data('tasks', pd.DataFrame([ - {'a': 1, 'b': datetime.datetime(2020, 1, 1)}, - {'a': 2, 'b': datetime.datetime(2020, 1, 2)}, - {'a': 1, 'b': datetime.datetime(2020, 1, 3)}, - ])) - # Create & predict a simple model. - self.run_sql('create database proj') - self.run_sql( - ''' - CREATE model proj.task_model - from dummy_data (select * from tasks) - PREDICT a - using engine='dummy_ml', - tag = 'first', - join_learn_process=true - ''' - ) - self.wait_predictor('proj', 'task_model') - self.run_sql(''' - SELECT m.* - FROM dummy_data.tasks as t - JOIN proj.task_model as m - ''') - # Import here so we don't reuse registry across test functions. - from mindsdb.metrics import metrics - query_time_metric = list(metrics.INTEGRATION_HANDLER_QUERY_TIME.collect())[0] - query_size_metric = list(metrics.INTEGRATION_HANDLER_RESPONSE_SIZE.collect())[0] - assert len(query_time_metric.samples) == 3 - assert len(query_size_metric.samples) == 3 - for sample in query_time_metric.samples: - assert sample.name.startswith('mindsdb_integration_handler_query_seconds') - if sample.name.endswith('count'): - assert sample.value == 1.0 - elif sample.name.endswith('sum'): - assert sample.value > 0.0 - elif sample.name.endswith('created'): - assert sample.value > 0.0 - for sample in query_size_metric.samples: - assert sample.name.startswith('mindsdb_integration_handler_response_size') - if sample.name.endswith('count'): - assert sample.value == 1.0 - elif sample.name.endswith('sum'): - assert sample.value > 0.0 - elif sample.name.endswith('created'): - assert sample.value > 0.0 diff --git a/tests/unused/unit/handler_tests/test_hubspot_handler.py b/tests/unused/unit/handler_tests/test_hubspot_handler.py deleted file mode 100644 index 6c78f9a047c..00000000000 --- a/tests/unused/unit/handler_tests/test_hubspot_handler.py +++ /dev/null @@ -1,39 +0,0 @@ -import os -import unittest - -from mindsdb.integrations.handlers.hubspot_handler.hubspot_handler import HubspotHandler -from mindsdb.api.executor.data_types.response_type import RESPONSE_TYPE - - -class HubSpotHandlerTest(unittest.TestCase): - - @classmethod - def setUpClass(cls): - cls.kwargs = { - "connection_data": { - "access_token": os.environ.get('ACCESS_TOKEN') - } - } - cls.handler = HubspotHandler('test_hubspot_handler', **cls.kwargs) - - def test_0_check_connection(self): - assert self.handler.check_connection() - - def test_1_get_tables(self): - tables = self.handler.get_tables() - assert tables.type is not RESPONSE_TYPE.ERROR - - def test_2_select_companies_query(self): - query = "SELECT * FROM test_hubspot_handler.companies" - result = self.handler.native_query(query) - assert result.type is RESPONSE_TYPE.TABLE - - def test_3_select_contacts_query(self): - query = "SELECT * FROM test_hubspot_handler.contacts" - result = self.handler.native_query(query) - assert result.type is RESPONSE_TYPE.TABLE - - def test_4_select_deals_query(self): - query = "SELECT * FROM test_hubspot_handler.deals" - result = self.handler.native_query(query) - assert result.type is RESPONSE_TYPE.TABLE diff --git a/tests/unused/unit/handler_tests/test_instatus_handler.py b/tests/unused/unit/handler_tests/test_instatus_handler.py deleted file mode 100644 index f42932f281d..00000000000 --- a/tests/unused/unit/handler_tests/test_instatus_handler.py +++ /dev/null @@ -1,144 +0,0 @@ -import unittest -from mindsdb.integrations.handlers.instatus_handler.instatus_handler import InstatusHandler -from mindsdb.api.executor.data_types.response_type import RESPONSE_TYPE -import pandas as pd -import os - - -class InstatusHandlerTest(unittest.TestCase): - - @classmethod - def setUpClass(cls): - cls.handler = InstatusHandler(name='mindsdb_instatus', connection_data={'api_key': os.environ.get('INSTATUS_API_KEY')}) - - def setUp(self): - self.pageId = self.handler.call_instatus_api(endpoint='/v2/pages')['id'][0] - self.componentId = self.handler.call_instatus_api(endpoint=f'/v1/{self.pageId}/components')['id'][0] - - def test_0_check_connection(self): - assert self.handler.check_connection() - - def test_1_call_instatus_api(self): - self.assertIsInstance(self.handler.call_instatus_api(endpoint='/v2/pages'), pd.DataFrame) - - def test_2_get_tables(self): - tables = self.handler.get_tables() - assert tables.type is not RESPONSE_TYPE.ERROR - - def test_3_get_columns(self): - status_pages_columns = self.handler.get_columns(table_name='status_pages') - components_columns = self.handler.get_columns(table_name='components') - assert type(status_pages_columns) is not RESPONSE_TYPE.ERROR - assert type(components_columns) is not RESPONSE_TYPE.ERROR - - def test_4_select_status_pages(self): - query = '''SELECT * - FROM mindsdb_instatus.status_pages''' - self.assertTrue(self.handler.native_query(query)) - - def test_5_select_status_pages_by_conditions(self): - query = '''SELECT name, status, subdomain - FROM mindsdb_instatus.status_pages - WHERE id = "clo3xshsk1114842hkn377y3lrap"''' - self.assertTrue(self.handler.native_query(query)) - - def test_6_insert_status_pages(self): - query = f'''INSERT INTO mindsdb_instatus.status_pages (email, name, subdomain, components, logoUrl) VALUES ('{os.environ.get('EMAIL_ID')}', 'mindsdb', 'somtirtha-roy', '["Website", "App", "API"]', 'https://instatus.com/sample.png')''' - try: - self.assertTrue(self.handler.native_query(query)) - except Exception as e: - error_message = str(e) - if "This subdomain is taken by another status page" in error_message: - print("Subdomain is already taken. Choose a different one.") - - def test_7_update_status_pages(self): - # update the row with the id obtained - query = f'''UPDATE mindsdb_instatus.status_pages - SET logoUrl = 'https://instatus.com/sample.png', - faviconUrl = 'https://instatus.com/favicon-32x32.png', - websiteUrl = 'https://instatus.com', - language = 'en', - useLargeHeader = true, - brandColor = '#111', - okColor = '#33B17E', - disruptedColor = '#FF8C03', - degradedColor = '#ECC94B', - downColor = '#DC123D', - noticeColor = '#70808F', - unknownColor = '#DFE0E1', - googleAnalytics = 'UA-00000000-1', - subscribeBySms = true, - smsService = 'twilio', - twilioSid = 'YOUR_TWILIO_SID', - twilioToken = 'YOUR_TWILIO_TOKEN', - twilioSender = 'YOUR_TWILIO_SENDER', - nexmoKey = null, - nexmoSecret = null, - nexmoSender = null, - htmlInMeta = null, - htmlAboveHeader = null, - htmlBelowHeader = null, - htmlAboveFooter = null, - htmlBelowFooter = null, - htmlBelowSummary = null, - cssGlobal = null, - launchDate = null, - dateFormat = 'MMMMMM d, yyyy', - dateFormatShort = 'MMM yyyy', - timeFormat = 'p', - private = false, - useAllowList = false, - translations = '{{ - "name": {{ - "fr": "nasa" - }} - }}' - WHERE id = "{self.pageId}"''' - self.assertTrue(self.handler.native_query(query)) - - def test_8_select_components(self): - query = f'''SELECT * - FROM mindsdb_instatus.components - WHERE page_id = '{self.pageId}';''' - self.assertTrue(self.handler.native_query(query)) - - def test_9_select_components_by_conditions(self): - query = f'''SELECT * - FROM mindsdb_instatus.components - WHERE page_id = '{self.pageId}' - AND component_id = '{self.componentId}';''' - self.assertTrue(self.handler.native_query(query)) - - def test_10_insert_components(self): - query = f'''INSERT INTO mindsdb_instatus.components (page_id, name, description, status, order, showUptime, grouped, translations_name_in_fr, translations_desc_in_fr) - VALUES ( - '{self.pageId}', - 'Test component', - 'Testing', - 'OPERATIONAL', - 6, - true, - false, - "Composant de test", - "En test" - );''' - self.assertTrue(self.handler.native_query(query)) - - def test_11_update_components(self): - query = f'''UPDATE mindsdb_instatus.components - SET - name = 'Test component 4', - description = 'Test test test', - status = 'OPERATIONAL', - order = 6, - showUptime = true, - grouped = false, - translations_name_in_fr = "Composant de test 4", - translations_desc_in_fr = "Test test test" - WHERE page_id = '{self.pageId}' - AND component_id = '{self.componentId}';''' - self.assertTrue(self.handler.native_query(query)) - - -if __name__ == '__main__': - unittest.main() diff --git a/tests/unused/unit/handler_tests/test_intercom_handler.py b/tests/unused/unit/handler_tests/test_intercom_handler.py deleted file mode 100644 index cee50735d13..00000000000 --- a/tests/unused/unit/handler_tests/test_intercom_handler.py +++ /dev/null @@ -1,62 +0,0 @@ -import unittest -from mindsdb.integrations.handlers.intercom_handler.intercom_handler import IntercomHandler -from mindsdb.api.executor.data_types.response_type import RESPONSE_TYPE -import pandas as pd -import os - - -class InstatusHandlerTest(unittest.TestCase): - - @classmethod - def setUpClass(cls): - cls.handler = IntercomHandler(name="mindsdb_intercon", connection_data={'access_token': os.environ.get('INTERCOM_ACCESS_TOKEN')}) - - def test_0_check_connection(self): - assert self.handler.check_connection() - - def test_1_connect(self): - assert self.handler.connect() - - def test_2_call_instatus_api(self): - self.assertIsInstance(self.handler.call_intercom_api(endpoint='/articles'), pd.DataFrame) - - def test_3_get_tables(self): - tables = self.handler.get_tables() - assert tables.type is not RESPONSE_TYPE.ERROR - - def test_4_get_columns(self): - columns = self.handler.get_columns(table_name='articles') - assert type(columns) is not RESPONSE_TYPE.ERROR - - def test_5_select_articles(self): - query = "SELECT * FROM articles" - self.assertTrue(self.handler.native_query(query=query)) - - def test_6_select_articles_by_condition(self): - query = "SELECT * FROM articles WHERE id = '8553922'" - self.assertTrue(self.handler.native_query(query=query)) - - def test_7_insert_article(self): - query = '''INSERT INTO myintercom.articles (title, description, body, author_id, state, parent_id, parent_type) - VALUES ('Thanks for everything', - 'Description of the Article', - 'Body of the Article', - 6840572, - 'published', - 6801839, - 'collection' - );''' - self.assertTrue(self.handler.native_query(query=query)) - - def test_8_update_article(self): - df = pd.DataFrame(self.handler.call_intercom_api(endpoint='/articles', params={'page': 1, 'per_page': 1})['data'][0]) - _id = df['id'][0] - query = f'''UPDATE myintercom.articles - SET title = 'Christmas is here!', - body = '

New gifts in store for the jolly season

' - WHERE id = {_id};''' - self.assertTrue(self.handler.native_query(query=query)) - - -if __name__ == '__main__': - unittest.main() diff --git a/tests/unused/unit/handler_tests/test_lightdash_handler.py b/tests/unused/unit/handler_tests/test_lightdash_handler.py deleted file mode 100644 index 84cba655bd4..00000000000 --- a/tests/unused/unit/handler_tests/test_lightdash_handler.py +++ /dev/null @@ -1,146 +0,0 @@ -import importlib -import os - -import pytest -from mindsdb_sql_parser import parse_sql - -from ..unit.executor_test_base import BaseExecutorTest - -try: - importlib.import_module("requests") - REQUESTS_INSTALLED = True -except ImportError: - REQUESTS_INSTALLED = False - - -@pytest.mark.skipif(not REQUESTS_INSTALLED, reason="requests package is not installed") -class TestLightdashHandler(BaseExecutorTest): - - def run_sql(self, sql): - ret = self.command_executor.execute_command(parse_sql(sql)) - assert ret.error_code is None - if ret.data is not None: - return ret.data.to_df() - - def setup_method(self): - super().setup_method() - self.api_key = os.environ.get("LIGHTDASH_API_KEY") - self.base_url = os.environ.get("LIGHTDASH_BASE_URL") - self.project_uuid = os.environ.get("LIGHTDASH_PROJECT_UUID") - self.space_uuid = os.environ.get("LIGHTDASH_SPACE_UUID") - self.chart_uuid = os.environ.get("LIGHTDASH_CHART_UUID") - self.chart_version_uuid = os.environ.get("LIGHTDASH_CHART_VERSION_UUID") - self.scheduler_uuid = os.environ.get("LIGHTDASH_SCHEDULER_UUID") - self.job_id = os.environ.get("LIGHTDASH_JOB_ID") - self.run_sql(f""" - CREATE DATABASE lightdash_datasource - WITH ENGINE = "lightdash", - PARAMETERS = {{ - "api_key": '{self.api_key}', - "base_url": '{self.base_url}' - }}; - """) - - def test_basic_select_from(self): - sql = """ - SELECT * FROM lightdash_datasource.user; - """ - self.run_sql(sql) - sql = """ - SELECT * FROM lightdash_datasource.user_ability; - """ - self.run_sql(sql) - sql = """ - SELECT * FROM lightdash_datasource.org; - """ - self.run_sql(sql) - sql = """ - SELECT * FROM lightdash_datasource.org_projects; - """ - self.run_sql(sql) - sql = """ - SELECT * FROM lightdash_datasource.org_members; - """ - self.run_sql(sql) - sql = f""" - SELECT * FROM lightdash_datasource.project_table WHERE project_uuid='{self.project_uuid}'; - """ - self.run_sql(sql) - sql = f""" - SELECT * FROM lightdash_datasource.warehouse_connection WHERE project_uuid='{self.project_uuid}'; - """ - self.run_sql(sql) - sql = f""" - SELECT * FROM lightdash_datasource.dbt_connection WHERE project_uuid='{self.project_uuid}'; - """ - self.run_sql(sql) - sql = f""" - SELECT * FROM lightdash_datasource.dbt_env_vars WHERE project_uuid='{self.project_uuid}'; - """ - self.run_sql(sql) - sql = f""" - SELECT * FROM lightdash_datasource.charts WHERE project_uuid='{self.project_uuid}'; - """ - self.run_sql(sql) - sql = f""" - SELECT * FROM lightdash_datasource.spaces WHERE project_uuid='{self.project_uuid}'; - """ - self.run_sql(sql) - sql = f""" - SELECT * FROM lightdash_datasource.access WHERE project_uuid='{self.project_uuid}'; - """ - self.run_sql(sql) - sql = f""" - SELECT * FROM lightdash_datasource.validation WHERE project_uuid='{self.project_uuid}'; - """ - self.run_sql(sql) - sql = f""" - SELECT * FROM lightdash_datasource.dashboards WHERE project_uuid='{self.project_uuid}' AND space_uuid='{self.space_uuid}'; - """ - self.run_sql(sql) - sql = f""" - SELECT * FROM lightdash_datasource.queries WHERE project_uuid='{self.project_uuid}' AND space_uuid='{self.space_uuid}'; - """ - self.run_sql(sql) - sql = f""" - SELECT * FROM lightdash_datasource.chart_history WHERE chart_uuid='{self.chart_uuid}'; - """ - self.run_sql(sql) - sql = f""" - SELECT * FROM lightdash_datasource.chart_config WHERE chart_uuid='{self.chart_uuid}' AND version_uuid='{self.chart_version_uuid}'; - """ - self.run_sql(sql) - sql = f""" - SELECT * FROM lightdash_datasource.chart_additional_metrics WHERE chart_uuid='{self.chart_uuid}' AND version_uuid='{self.chart_version_uuid}'; - """ - self.run_sql(sql) - sql = f""" - SELECT * FROM lightdash_datasource.chart_table_calculations WHERE chart_uuid='{self.chart_uuid}' AND version_uuid='{self.chart_version_uuid}'; - """ - self.run_sql(sql) - sql = f""" - SELECT * FROM lightdash_datasource.scheduler_logs WHERE project_uuid='{self.project_uuid}'; - """ - self.run_sql(sql) - sql = f""" - SELECT * FROM lightdash_datasource.scheduler WHERE scheduler_uuid='{self.scheduler_uuid}'; - """ - self.run_sql(sql) - sql = f""" - SELECT * FROM lightdash_datasource.scheduler_jobs WHERE scheduler_uuid='{self.scheduler_uuid}'; - """ - self.run_sql(sql) - sql = f""" - SELECT * FROM lightdash_datasource.scheduler_job_status WHERE job_id='{self.job_id}'; - """ - self.run_sql(sql) - - def test_complex_select(self): - sql = """ - SELECT firstName, lastName FROM lightdash_datasource.user; - """ - assert self.run_sql(sql).shape[1] == 2 - sql = f""" - SELECT name FROM lightdash_datasource.project_table WHERE project_uuid='{self.project_uuid}'; - """ - assert self.run_sql(sql).shape[1] == 1 diff --git a/tests/unused/unit/handler_tests/test_luma_handler.py b/tests/unused/unit/handler_tests/test_luma_handler.py deleted file mode 100644 index 9bf31289dc9..00000000000 --- a/tests/unused/unit/handler_tests/test_luma_handler.py +++ /dev/null @@ -1,40 +0,0 @@ -import importlib -import os -import pytest -from mindsdb_sql_parser import parse_sql - -from ..unit.executor_test_base import BaseExecutorTest - -try: - importlib.import_module("requests") - REQUESTS_INSTALLED = True -except ImportError: - REQUESTS_INSTALLED = False - - -@pytest.mark.skipif(not REQUESTS_INSTALLED, reason="requests package is not installed") -class TestLumaHandler(BaseExecutorTest): - - def run_sql(self, sql): - ret = self.command_executor.execute_command(parse_sql(sql)) - assert ret.error_code is None - if ret.data is not None: - return ret.data.to_df() - - def setup_method(self): - super().setup_method() - self.api_key = os.environ.get("LUMA_API_KEY") - self.run_sql(f""" - CREATE DATABASE mindsdb_luma - WITH ENGINE = 'luma', - PARAMETERS = { - "api_key": '{self.api_key}' - }; - """) - - def test_basic_select_from(self): - sql = "SELECT * FROM mindsdb_luma.events;" - self.run_sql(sql) - - sql = 'SELECT * FROM mindsdb_luma.events where event_id = "evt-HQ36IFDwncocuGy";' - assert self.run_sql(sql).shape[0] == 1 diff --git a/tests/unused/unit/handler_tests/test_mariadb_handler.py b/tests/unused/unit/handler_tests/test_mariadb_handler.py deleted file mode 100644 index fd3db056f7e..00000000000 --- a/tests/unused/unit/handler_tests/test_mariadb_handler.py +++ /dev/null @@ -1,169 +0,0 @@ -import time -import os -import shutil -import tarfile - -import pytest -import docker - -from mindsdb.integrations.handlers.mariadb_handler.mariadb_handler import MariaDBHandler -from mindsdb.api.executor.data_types.response_type import RESPONSE_TYPE -from mindsdb.utilities.fs import safe_extract - -HANDLER_KWARGS = { - "connection_data": { - "host": "localhost", - "port": "13306", - "user": "root", - "password": "supersecret", - "database": "test", - "ssl": False - } -} - -CERTS_ARCHIVE = "certs.tar" -CERTS_DIR = "mysql" - - -def get_certs(): - certs_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "mysql") - certs = {} - for cert_key, fname in [("ssl_ca", "ca.pem"), ("ssl_cert", "client-cert.pem"), ("ssl_key", "client-key.pem")]: - cert_file = os.path.join(certs_dir, fname) - certs[cert_key] = cert_file - return certs - - -def get_certificates(container): - cur_dir = os.path.dirname(os.path.abspath(__file__)) - archive_path = os.path.join(cur_dir, CERTS_ARCHIVE) - with open(archive_path, "wb") as f: - bits, _ = container.get_archive('/var/lib/mysql') - for chunk in bits: - f.write(chunk) - - with tarfile.open(archive_path) as tf: - safe_extract(tf, path=cur_dir) - certs = get_certs() - HANDLER_KWARGS["connection_data"].update(certs) - - -def waitReadiness(container, timeout=30): - threshold = time.time() + timeout - ready_msg = "mariadbd: ready for connections" - while True: - lines = container.logs().decode() - # container fully ready - # because it reloads the db server during initialization - # need to check that the 'ready for connections' has found second time - if lines.count(ready_msg) >= 2: - break - if time.time() > threshold: - raise Exception("timeout exceeded, container is still not ready") - - -@pytest.fixture(scope="module", params=[{"ssl": False}, {"ssl": True}], ids=["NoSSL", "SSL"]) -def handler(request): - image_name = "mindsdb/mariadb-handler-test" - docker_client = docker.from_env() - with_ssl = request.param["ssl"] - container = None - try: - container = docker_client.containers.run( - image_name, - command="--secure-file-priv=/", - detach=True, - environment={"MYSQL_ROOT_PASSWORD": "supersecret"}, - ports={"3306/tcp": 13306}, - ) - waitReadiness(container) - # ubnormal teardown - except Exception as e: - if container is not None: - container.kill() - raise e - - if with_ssl: - get_certificates(container) - handler = MariaDBHandler('test_mariadb_handler', **HANDLER_KWARGS) - yield handler - - # normal teardown - container.kill() - docker_client.close() - if with_ssl: - cur_dir = os.path.dirname(os.path.abspath(__file__)) - try: - os.remove(os.path.join(cur_dir, CERTS_ARCHIVE)) - shutil.rmtree(os.path.join(cur_dir, CERTS_DIR)) - except Exception as e: - print(f"unable to delete .tar/files of certificates: {e}") - - -class TestMariaDBHandler: - def test_connect(self, handler): - handler.connect() - assert handler.is_connected, "connection error" - - def test_check_connection(self, handler): - res = handler.check_connection() - assert res.success, res.error_message - - def test_native_query_show_dbs(self, handler): - dbs = handler.native_query("SHOW DATABASES;") - dbs = dbs.data_frame - assert dbs is not None, "expected to get some data, but got None" - assert 'Database' in dbs, f"expected to get 'Database' column in response:\n{dbs}" - dbs = list(dbs["Database"]) - expected_db = HANDLER_KWARGS["connection_data"]["database"] - assert expected_db in dbs, f"expected to have {expected_db} db in response: {dbs}" - - def test_get_tables(self, handler): - tables = self.get_table_names(handler) - assert "rentals" in tables, f"expected to have 'rentals' table in the db but got: {tables}" - - def test_describe_table(self, handler): - described = handler.get_columns("rentals") - describe_data = described.data_frame - self.check_valid_response(described) - got_columns = list(describe_data.iloc[:, 0]) - want_columns = ["number_of_rooms", "number_of_bathrooms", - "sqft", "location", "days_on_market", - "initial_price", "neighborhood", "rental_price"] - assert got_columns == want_columns, f"expected to have next columns in rentals table:\n{want_columns}\nbut got:\n{got_columns}" - - def test_create_table(self, handler): - new_table = "test_mdb" - res = handler.native_query(f"CREATE TABLE IF NOT EXISTS {new_table} (test_col INT)") - self.check_valid_response(res) - tables = self.get_table_names(handler) - assert new_table in tables, f"expected to have {new_table} in database, but got: {tables}" - - def test_drop_table(self, handler): - drop_table = "test_md" - res = handler.native_query(f"DROP TABLE IF EXISTS {drop_table}") - self.check_valid_response(res) - tables = self.get_table_names(handler) - assert drop_table not in tables - - def test_select_query(self, handler): - limit = 5 - query = f"SELECT * FROM rentals WHERE number_of_rooms = 2 LIMIT {limit}" - res = handler.query(query) - self.check_valid_response(res) - got_rows = res.data_frame.shape[0] - want_rows = limit - assert got_rows == want_rows, f"expected to have {want_rows} rows in response but got: {got_rows}" - - def check_valid_response(self, res): - if res.resp_type == RESPONSE_TYPE.TABLE: - assert res.data_frame is not None, "expected to have some data, but got None" - assert res.error_code == 0, f"expected to have zero error_code, but got {res.error_code}" - assert res.error_message is None, f"expected to have None in error message, but got {res.error_message}" - - def get_table_names(self, handler): - res = handler.get_tables() - tables = res.data_frame - assert tables is not None, "expected to have some tables in the db, but got None" - assert 'table_name' in tables, f"expected to get 'table_name' column in the response:\n{tables}" - return list(tables['table_name']) diff --git a/tests/unused/unit/handler_tests/test_milvus_handler.py b/tests/unused/unit/handler_tests/test_milvus_handler.py deleted file mode 100644 index 0e2170ba57c..00000000000 --- a/tests/unused/unit/handler_tests/test_milvus_handler.py +++ /dev/null @@ -1,460 +0,0 @@ -import importlib -from unittest.mock import patch - -import pandas as pd -import pytest -import time -from mindsdb_sql_parser import parse_sql - -from ..unit.executor_test_base import BaseExecutorTest - -try: - pymilvus = importlib.import_module("pymilvus") - MILVUS_INSTALLED = True -except ImportError: - MILVUS_INSTALLED = False - - -@pytest.mark.skipif(not MILVUS_INSTALLED, reason="pymilvus is not installed") -class TestMilvusHandler(BaseExecutorTest): - - def run_sql(self, sql): - ret = self.command_executor.execute_command(parse_sql(sql)) - assert ret.error_code is None - if ret.data is not None: - return ret.data.to_df() - - def setup_method(self): - super().setup_method() - # create a milvus database - self.run_sql(""" - CREATE DATABASE milvus_test - WITH - ENGINE = 'milvus', - PARAMETERS = { - "uri": "./milvus.db", - "create_embedding_dim": 3 - }; - """) - self.run_sql(""" - CREATE DATABASE milvus_test_auto_id - WITH - ENGINE = 'milvus', - PARAMETERS = { - "uri": "./milvus.db", - "create_embedding_dim": 3, - "create_auto_id": true - }; - """) - - def drop_table(self, table_name): - pymilvus.connections.connect( - uri="./milvus.db", - ) - pymilvus.utility.drop_collection(table_name) - - @pytest.mark.xfail(reason="create table for vectordatabase is not well supported") - @patch("mindsdb.integrations.handlers.postgres_handler.Handler") - def test_create_table(self, postgres_handler_mock): - # create an empty table - sql = """ - CREATE TABLE milvus_test.testable; - """ - self.run_sql(sql) - # create a table with the schema definition is not allowed - sql = """ - CREATE TABLE milvus_test.testable ( - id int, - metadata text, - embedding float[] - ); - """ - with pytest.raises(Exception): - self.run_sql(sql) - - @patch("mindsdb.integrations.handlers.postgres_handler.Handler") - def test_create_with_select(self, postgres_handler_mock): - df = pd.DataFrame( - { - "id": ["id1", "id2"], - "content": ["this is a test", "this is a test"], - "metadata": [{"test": "test"}, {"test": "test"}], - "embeddings": [[1.0, 2.0, 3.0], [1.0, 2.0, 3.0]], - } - ) - - self.set_handler(postgres_handler_mock, "pg", tables={"df": df}) - - self.drop_table("testable") - - sql = """ - CREATE TABLE milvus_test.testable ( - SELECT * FROM pg.df - ) - """ - # this should work - self.run_sql(sql) - - sql = """ - CREATE TABLE milvus_test.testable ( - SELECT * FROM pg.df - ) - """ - # this should work - self.run_sql(sql) - - self.drop_table("testable") - - @pytest.mark.xfail(reason="drop table for vectordatabase is not working") - @patch("mindsdb.integrations.handlers.postgres_handler.Handler") - def test_drop_table(self, postgres_handler_mock): - df = pd.DataFrame( - { - "id": ["id1", "id2"], - "content": ["this is a test", "this is a test"], - "metadata": [{"test": "test"}, {"test": "test"}], - "embeddings": [[1.0, 2.0, 3.0], [1.0, 2.0, 3.0]], - } - ) - self.set_handler(postgres_handler_mock, "pg", tables={"testable": df}) - - self.drop_table("testable") - - # create a table - sql = """ - CREATE TABLE milvus_test.testable ( - SELECT * FROM pg.df - ) - """ - self.run_sql(sql) - - # drop a table - sql = """ - DROP TABLE milvus_test.testable; - """ - self.run_sql(sql) - - # drop a non existent table will raise an error - sql = """ - DROP TABLE milvus_test.test_table2; - """ - with pytest.raises(Exception): - self.run_sql(sql) - - @patch("mindsdb.integrations.handlers.postgres_handler.Handler") - def test_insert_into(self, postgres_handler_mock): - df = pd.DataFrame( - { - "id": ["id1", "id2", "id3"], - "content": ["this is a test", "this is a test", "this is a test"], - "metadata": [{"test": "test1"}, {"test": "test2"}, {"test": "test3"}], - "embeddings": [[1.0, 2.0, 3.0], [1.0, 2.0, 3.0], [1.0, 2.0, 3.0]], - } - ) - df2 = pd.DataFrame( - { - "content": ["this is a test", "this is a test", "this is a test"], - "metadata": [{"test": "test1"}, {"test": "test2"}, {"test": "test3"}], - "embeddings": [ - [1.0, 2.0, 4.0], - [1.0, 2.0, 5.0], - [1.0, 2.0, 3.0], - ], - } - ) - self.set_handler(postgres_handler_mock, "pg", tables={"df": df, "df2": df2}) - - self.drop_table("testable") - self.drop_table("testableauto") - - # create tables - sql = """ - CREATE TABLE milvus_test.testable ( - SELECT * FROM pg.df - ) - """ - self.run_sql(sql) - sql = """ - CREATE TABLE milvus_test_auto_id.testableauto ( - SELECT * FROM pg.df2 - ) - """ - self.run_sql(sql) - - # insert into a table with values - sql = """ - INSERT INTO milvus_test.testable ( - id,content,metadata,embeddings - ) - VALUES ( - "id4", 'this is a test', '{"test": "test"}', '[1.0, 8.0, 9.0]' - ) - """ - self.run_sql(sql) - - time.sleep(1) # wait for milvus to load the data asynchronously - # check if the data is inserted - sql = """ - SELECT * FROM milvus_test.testable - WHERE id = "id4" - """ - ret = self.run_sql(sql) - assert ret.shape[0] == 1 - - # insert without specifying id should work in autoid one - sql = """ - INSERT INTO milvus_test_auto_id.testableauto ( - content,metadata,embeddings - ) - VALUES ( - 'this is a test', '{"test": "test"}', '[1.0, 2.0, 3.0]' - ) - """ - self.run_sql(sql) - - time.sleep(1) # wait for milvus to load the data asynchronously - # check if the data is inserted - sql = """ - SELECT * FROM milvus_test_auto_id.testableauto - """ - ret = self.run_sql(sql) - assert ret.shape[0] == 4 - - # insert into a table with a select statement - sql = """ - INSERT INTO milvus_test_auto_id.testableauto (content,metadata,embeddings) - SELECT * FROM pg.df2 - """ - self.run_sql(sql) - - time.sleep(1) # wait for milvus to load the data asynchronously - # check if the data is inserted - sql = """ - SELECT * FROM milvus_test.testableauto - """ - ret = self.run_sql(sql) - assert ret.shape[0] == 7 - - self.drop_table("testable") - self.drop_table("testableauto") - - @patch("mindsdb.integrations.handlers.postgres_handler.Handler") - def test_select_from(self, postgres_handler_mock): - df = pd.DataFrame( - { - "id": ["id1", "id2"], - "content": ["this is a test", "this is a test"], - "metadata": [{"test": "test"}, {"test": "test"}], - "embeddings": [[1.0, 2.0, 3.0], [1.0, 2.0, 3.0]], - } - ) - self.set_handler(postgres_handler_mock, "pg", tables={"testable": df}) - - self.drop_table("testable") - - # create a table - sql = """ - CREATE TABLE milvus_test.testable ( - SELECT * FROM pg.df - ) - """ - self.run_sql(sql) - - time.sleep(1) # wait for milvus to load the data asynchronously - # query a table without any filters - sql = """ - SELECT * FROM milvus_test.testable - """ - self.run_sql(sql) - - # query a table with id - sql = """ - SELECT * FROM milvus_test.testable - WHERE id = 'id1' - """ - ret = self.run_sql(sql) - assert ret.shape[0] == 1 - - # query a table with a search vector, without limit - sql = """ - SELECT * FROM milvus_test.testable - WHERE search_vector = '[1.0, 2.0, 3.0]' - """ - ret = self.run_sql(sql) - assert ret.shape[0] == 2 - - # query a table with a search vector, with limit - sql = """ - SELECT * FROM milvus_test.testable - WHERE search_vector = '[1.0, 2.0, 3.0]' - LIMIT 1 - """ - ret = self.run_sql(sql) - assert ret.shape[0] == 1 - - # query a table with a metadata filter - sql = """ - SELECT * FROM milvus_test.testable - WHERE test = 'test' - """ - ret = self.run_sql(sql) - assert ret.shape[0] == 2 - - # query a table with a metadata filter and a search vector - sql = """ - SELECT * FROM milvus_test.testable - WHERE test = 'test' - AND search_vector = '[1.0, 2.0, 3.0]' - """ - ret = self.run_sql(sql) - assert ret.shape[0] == 2 - - self.drop_table("testable") - - @pytest.mark.xfail(reason="update for vectordatabase is not implemented") - def test_update(self): - # update a table with a metadata filter - sql = """ - UPDATE milvus_test.testable - SET test = 'test2' - WHERE test = 'test' - """ - self.run_sql(sql) - # check if the data is updated - sql = """ - SELECT * FROM milvus_test.testable - WHERE test = 'test2' - """ - ret = self.run_sql(sql) - assert ret.shape[0] == 2 - - # update the embeddings - sql = """ - UPDATE milvus_test.testable - SET embedding = [3.0, 2.0, 1.0] - WHERE test = 'test2' - """ - self.run_sql(sql) - # check if the data is updated - sql = """ - SELECT * FROM milvus_test.testable - WHERE test = 'test2' - """ - ret = self.run_sql(sql) - assert ret.shape[0] == 2 - assert ret.embedding[0] == [3.0, 2.0, 1.0] - - # update multiple columns - sql = """ - UPDATE milvus_test.testable - SET test = 'test3', - embedding = [1.0, 2.0, 3.0] - content = 'this is a test' - WHERE test = 'test2' - """ - self.run_sql(sql) - # check if the data is updated - sql = """ - SELECT * FROM milvus_test.testable - WHERE test = 'test3' - """ - ret = self.run_sql(sql) - assert ret.shape[0] == 2 - assert ret.embedding[0] == [1.0, 2.0, 3.0] - assert ret.content[0] == "this is a test" - - # update a table with a search vector filter is not allowed - sql = """ - UPDATE milvus_test.testable - SET `metadata.test = 'test2' - WHERE search_vector = [1.0, 2.0, 3.0] - """ - with pytest.raises(Exception): - self.run_sql(sql) - - # update a table without any filters is allowed - sql = """ - UPDATE milvus_test.testable - SET metadata.test = 'test3' - """ - self.run_sql(sql) - # check if the data is updated - sql = """ - SELECT * FROM milvus_test.testable - WHERE `metadata.test` = 'test3' - """ - ret = self.run_sql(sql) - assert ret.shape[0] == 2 - - # update a table with a search vector filter and a metadata filter is not allowed - sql = """ - UPDATE milvus_test.testable - SET metadata.test = 'test3' - WHERE metadata.test = 'test2' - AND search_vector = [1.0, 2.0, 3.0] - """ - with pytest.raises(Exception): - self.run_sql(sql) - - @patch("mindsdb.integrations.handlers.postgres_handler.Handler") - def test_delete(self, postgres_handler_mock): - df = pd.DataFrame( - { - "id": ["id1", "id2", "id3"], - "content": ["this is a test", "this is a test", "this is a test"], - "metadata": [{"test": "test1"}, {"test": "test2"}, {"test": "test3"}], - "embeddings": [[1.0, 2.0, 3.0], [1.0, 2.0, 3.0], [1.0, 2.0, 3.0]], - } - ) - - self.drop_table("testable") - - self.set_handler(postgres_handler_mock, "pg", tables={"testable": df}) - - # create a table - sql = """ - CREATE TABLE milvus_test.testable ( - SELECT * FROM pg.df - ) - """ - self.run_sql(sql) - - time.sleep(1) # wait for milvus to load the data asynchronously - # delete by id - sql = """ - DELETE FROM milvus_test.testable - WHERE id IN ('id1') - """ - self.run_sql(sql) - - time.sleep(1) # wait for milvus to load the data asynchronously - # check if the data is deleted - sql = """ - SELECT * FROM milvus_test.testable - """ - ret = self.run_sql(sql) - assert ret.shape[0] == 2 - - # delete by multiple ids - sql = """ - DELETE FROM milvus_test.testable - WHERE id IN ('id2', 'id3') - """ - self.run_sql(sql) - - time.sleep(1) # wait for milvus to load the data asynchronously - # check if the data is deleted - sql = """ - SELECT * FROM milvus_test.testable - """ - ret = self.run_sql(sql) - assert ret.shape[0] == 2 - - # delete from a table without any filters is not allowed - sql = """ - DELETE FROM milvus_test.testable - """ - with pytest.raises(Exception): - self.run_sql(sql) - - self.drop_table("testable") diff --git a/tests/unused/unit/handler_tests/test_ms_teams_handler.py b/tests/unused/unit/handler_tests/test_ms_teams_handler.py deleted file mode 100644 index f12e6e3de9d..00000000000 --- a/tests/unused/unit/handler_tests/test_ms_teams_handler.py +++ /dev/null @@ -1,1050 +0,0 @@ -import unittest -from unittest.mock import Mock, patch - -from mindsdb_sql_parser import ast -from mindsdb_sql_parser.ast import Constant, BinaryOperation - -from mindsdb_sql_parser.ast.select.star import Star -from mindsdb_sql_parser.ast.select.identifier import Identifier - -from mindsdb.integrations.handlers.ms_teams_handler.ms_teams_handler import MSTeamsHandler -from mindsdb.integrations.handlers.ms_teams_handler.settings import ms_teams_handler_config -from mindsdb.integrations.handlers.ms_teams_handler.ms_graph_api_teams_client import MSGraphAPITeamsClient -from mindsdb.integrations.handlers.ms_teams_handler.ms_teams_tables import ChatsTable, ChatMessagesTable, ChannelsTable, ChannelMessagesTable - - -class TestMSGraphAPITeamsClient(unittest.TestCase): - @classmethod - def setUpClass(cls): - """ - Set up the tests. - """ - - # mock the api client with a dummy access_token parameter (calls to the API that use this parameter will be mocked) - cls.api_client = MSGraphAPITeamsClient("test_access_token") - - @patch('requests.get') - def test_get_chat_returns_chat_data(self, mock_get): - """ - Test that get_chat returns chat data. - """ - - # configure the mock to return a response with 'status_code' 200 - mock_get.return_value = Mock( - status_code=200, - headers={'Content-Type': 'application/json'}, - json=Mock(return_value=ms_teams_handler_config.TEST_CHAT_DATA) - ) - - chat_data = self.api_client.get_chat("test_id") - - # assert the requests.get call was made with the expected arguments - mock_get.assert_called_once_with( - 'https://graph.microsoft.com/v1.0/chats/test_id/', - headers={'Authorization': 'Bearer test_access_token'}, - params={'$expand': 'lastMessagePreview'} - ) - - self.assertEqual(chat_data["id"], "test_id") - self.assertEqual(chat_data["chatType"], "oneOnOne") - - @patch('requests.get') - def test_get_chats_returns_chats_data(self, mock_get): - """ - Test that get_chats returns chats data. - """ - - # configure the mock to return a response with 'status_code' 200 - mock_get.return_value = Mock( - status_code=200, - headers={'Content-Type': 'application/json'}, - json=Mock(return_value={'value': ms_teams_handler_config.TEST_CHATS_DATA}) - ) - - chats_data = self.api_client.get_chats() - - # assert the requests.get call was made with the expected arguments - mock_get.assert_called_once_with( - 'https://graph.microsoft.com/v1.0/chats/', - headers={'Authorization': 'Bearer test_access_token'}, - params={'$expand': 'lastMessagePreview', '$top': 20} - ) - - self.assertEqual(chats_data[0]["id"], "test_id") - self.assertEqual(chats_data[0]["chatType"], "oneOnOne") - - @patch('requests.get') - def test_get_chat_message_returns_chat_message_data(self, mock_get): - """ - Test that get_chat_message returns chat message data. - """ - - # configure the mock to return a response with 'status_code' 200 - mock_get.return_value = Mock( - status_code=200, - headers={'Content-Type': 'application/json'}, - json=Mock(return_value=ms_teams_handler_config.TEST_CHAT_MESSAGE_DATA) - ) - - chat_message_data = self.api_client.get_chat_message("test_chat_id", "test_id") - - # assert the requests.get call was made with the expected arguments - mock_get.assert_called_once_with( - 'https://graph.microsoft.com/v1.0/chats/test_chat_id/messages/test_id/', - headers={'Authorization': 'Bearer test_access_token'}, - params=None - ) - - self.assertEqual(chat_message_data["id"], "test_id") - self.assertEqual(chat_message_data["messageType"], "message") - self.assertEqual(chat_message_data["chatId"], "test_chat_id") - - @patch('requests.get') - def test_get_chat_messages_returns_chat_messages_data(self, mock_get): - """ - Test that get_chat_messages returns chat messages data. - """ - - # configure the mock to return a response with 'status_code' 200 - mock_get.return_value = Mock( - status_code=200, - headers={'Content-Type': 'application/json'}, - json=Mock(return_value={'value': ms_teams_handler_config.TEST_CHAT_MESSAGES_DATA}) - ) - - chat_messages_data = self.api_client.get_chat_messages("test_chat_id") - - # assert the requests.get call was made with the expected arguments - mock_get.assert_called_once_with( - 'https://graph.microsoft.com/v1.0/chats/test_chat_id/messages/', - headers={'Authorization': 'Bearer test_access_token'}, - params={'$top': 20} - ) - - self.assertEqual(chat_messages_data[0]["id"], "test_id") - self.assertEqual(chat_messages_data[0]["messageType"], "message") - self.assertEqual(chat_messages_data[0]["chatId"], "test_chat_id") - - @patch('requests.get') - def test_get_all_chat_messages_returns_all_chat_messages_data(self, mock_get): - """ - Test that get_all_chat_messages returns all chat messages data. - """ - - # configure the mock to return a response with 'status_code' 200 - mock_get.side_effect = [ - Mock( - status_code=200, - headers={'Content-Type': 'application/json'}, - json=Mock(return_value={'value': ms_teams_handler_config.TEST_CHATS_DATA}) - ), - Mock( - status_code=200, - headers={'Content-Type': 'application/json'}, - json=Mock(return_value={'value': ms_teams_handler_config.TEST_CHAT_MESSAGES_DATA}) - ) - ] - - chat_messages_data = self.api_client.get_all_chat_messages() - - # assert the requests.get calls were made with the expected arguments - mock_get.assert_any_call( - 'https://graph.microsoft.com/v1.0/chats/', - headers={'Authorization': 'Bearer test_access_token'}, - params={'$expand': 'lastMessagePreview', '$top': 20} - ) - - mock_get.assert_any_call( - 'https://graph.microsoft.com/v1.0/chats/test_id/messages/', - headers={'Authorization': 'Bearer test_access_token'}, - params={'$top': 20} - ) - - self.assertEqual(chat_messages_data[0]["id"], "test_id") - self.assertEqual(chat_messages_data[0]["messageType"], "message") - self.assertEqual(chat_messages_data[0]["chatId"], "test_chat_id") - - @patch('requests.post') - def test_send_chat_message_sends_correct_request(self, mock_post): - """ - Test that send_chat_message sends a chat message. - """ - - # configure the mock to return a response with 'status_code' 201 - mock_post.return_value = Mock( - status_code=201, - headers={'Content-Type': 'application/json'}, - ) - - self.api_client.send_chat_message("test_chat_id", "test_message", "test_subject") - - # assert the requests.post call was made with the expected arguments - mock_post.assert_called_once_with( - 'https://graph.microsoft.com/v1.0/chats/test_chat_id/messages/', - headers={'Authorization': 'Bearer test_access_token'}, - json={'subject': 'test_subject', 'body': {'content': 'test_message'}} - ) - - @patch('requests.get') - def test_get_channel_returns_channel_data(self, mock_get): - """ - Test that get_channel returns channel data. - """ - - # configure the mock to return a response with 'status_code' 200 - mock_get.return_value = Mock( - status_code=200, - headers={'Content-Type': 'application/json'}, - json=Mock(return_value=ms_teams_handler_config.TEST_CHANNEL_DATA) - ) - - channel_data = self.api_client.get_channel("test_team_id", "test_id") - - # assert the requests.get call was made with the expected arguments - mock_get.assert_called_once_with( - 'https://graph.microsoft.com/v1.0/teams/test_team_id/channels/test_id/', - headers={'Authorization': 'Bearer test_access_token'}, - params=None - ) - - self.assertEqual(channel_data["id"], "test_id") - self.assertEqual(channel_data["displayName"], "test_display_name") - self.assertEqual(channel_data["teamId"], "test_team_id") - - @patch('requests.get') - def test_get_channels_returns_channels_data(self, mock_get): - """ - Test that get_channels returns channels data. - """ - - # check if the group_ids parameter in the API client is set - is_group_ids_set = True if self.api_client._group_ids is not None else False - - # configure the mock to return a response with 'status_code' 200 - # if the group_ids parameter is not set, the mock will return the group data first, then the channels data - if not is_group_ids_set: - mock_get.side_effect = [ - Mock( - status_code=200, - headers={'Content-Type': 'application/json'}, - json=Mock(return_value=ms_teams_handler_config.TEST_GROUP_DATA) - ), - Mock( - status_code=200, - headers={'Content-Type': 'application/json'}, - json=Mock(return_value={'value': ms_teams_handler_config.TEST_CHANNELS_DATA}) - ) - ] - - # if the group_ids parameter is set, the mock will only return the channels data - else: - mock_get.return_value = Mock( - status_code=200, - headers={'Content-Type': 'application/json'}, - json=Mock(return_value={'value': ms_teams_handler_config.TEST_CHANNELS_DATA}) - ) - - channels_data = self.api_client.get_channels() - - # assert the requests.get calls were made with the expected arguments - # if the group_ids parameter is not set, the mock will check the calls to both the groups and channels endpoints - if not is_group_ids_set: - mock_get.assert_any_call( - 'https://graph.microsoft.com/v1.0/groups/', - headers={'Authorization': 'Bearer test_access_token'}, - params={'$select': 'id,resourceProvisioningOptions'} - ) - - mock_get.assert_any_call( - 'https://graph.microsoft.com/v1.0/teams/test_team_id/channels/', - headers={'Authorization': 'Bearer test_access_token'}, - params=None - ) - - # if the group_ids parameter is set, the mock will only check the call to the channels endpoint - else: - mock_get.assert_called_once_with( - 'https://graph.microsoft.com/v1.0/teams/test_team_id/channels/', - headers={'Authorization': 'Bearer test_access_token'}, - params=None - ) - - self.assertEqual(channels_data[0]["id"], "test_id") - self.assertEqual(channels_data[0]["displayName"], "test_display_name") - self.assertEqual(channels_data[0]["teamId"], "test_team_id") - - @patch('requests.get') - def test_get_channel_message_returns_channel_message_data(self, mock_get): - """ - Test that get_channel_message returns channel message data. - """ - - # configure the mock to return a response with 'status_code' 200 - mock_get.return_value = Mock( - status_code=200, - headers={'Content-Type': 'application/json'}, - json=Mock(return_value=ms_teams_handler_config.TEST_CHANNEL_MESSAGE_DATA) - ) - - channel_message_data = self.api_client.get_channel_message("test_team_id", "test_channel_id", "test_id") - - # assert the requests.get call was made with the expected arguments - mock_get.assert_called_once_with( - 'https://graph.microsoft.com/v1.0/teams/test_team_id/channels/test_channel_id/messages/test_id/', - headers={'Authorization': 'Bearer test_access_token'}, - params=None - ) - - self.assertEqual(channel_message_data["id"], "test_id") - self.assertEqual(channel_message_data["messageType"], "message") - self.assertEqual(channel_message_data["channelIdentity"]["channelId"], "test_channel_id") - self.assertEqual(channel_message_data["channelIdentity"]["teamId"], "test_team_id") - - @patch('requests.get') - def test_get_channel_messages_returns_channel_messages_data(self, mock_get): - """ - Test that get_channel_messages returns channel messages data. - """ - - # check if the group_ids parameter in the API client is set - is_group_ids_set = True if self.api_client._group_ids is not None else False - - # configure the mocks to return a response with 'status_code' 200 - # if the group_ids parameter is not set, the mocks will return the group data first, then the channel ID data, then the channel messages data - if not is_group_ids_set: - mock_get.side_effect = [ - Mock( - status_code=200, - headers={'Content-Type': 'application/json'}, - json=Mock(return_value=ms_teams_handler_config.TEST_GROUP_DATA) - ), - Mock( - status_code=200, - headers={'Content-Type': 'application/json'}, - json=Mock(return_value=ms_teams_handler_config.TEST_CHANNEL_ID_DATA) - ), - Mock( - status_code=200, - headers={'Content-Type': 'application/json'}, - json=Mock(return_value={'value': ms_teams_handler_config.TEST_CHANNEL_MESSAGES_DATA}) - ), - ] - - # if the group_ids parameter is set, the mocks will only return the channel ID data, then the channel messages data - else: - mock_get.side_effect = [ - Mock( - status_code=200, - headers={'Content-Type': 'application/json'}, - json=Mock(return_value=ms_teams_handler_config.TEST_CHANNEL_ID_DATA) - ), - Mock( - status_code=200, - headers={'Content-Type': 'application/json'}, - json=Mock(return_value={'value': ms_teams_handler_config.TEST_CHANNEL_MESSAGES_DATA}) - ), - ] - - channel_messages_data = self.api_client.get_channel_messages() - - # assert the requests.get calls were made with the expected arguments - # if the group_ids parameter is not set, check the calls to the groups endpoint - if not is_group_ids_set: - mock_get.assert_any_call( - 'https://graph.microsoft.com/v1.0/groups/', - headers={'Authorization': 'Bearer test_access_token'}, - params={'$select': 'id,resourceProvisioningOptions'} - ) - - mock_get.assert_any_call( - 'https://graph.microsoft.com/v1.0/teams/test_team_id/channels/', - headers={'Authorization': 'Bearer test_access_token'}, - params=None - ) - - mock_get.assert_any_call( - 'https://graph.microsoft.com/v1.0/teams/test_team_id/channels/test_channel_id/messages/', - headers={'Authorization': 'Bearer test_access_token'}, - params={'$top': 20} - ) - - self.assertEqual(channel_messages_data[0]["id"], "test_id") - self.assertEqual(channel_messages_data[0]["messageType"], "message") - self.assertEqual(channel_messages_data[0]["channelIdentity"]["channelId"], "test_channel_id") - self.assertEqual(channel_messages_data[0]["channelIdentity"]["teamId"], "test_team_id") - - @patch('requests.post') - def test_send_channel_message_sends_correct_request(self, mock_post): - """ - Test that send_channel_message sends a channel message. - """ - - # configure the mock to return a response with 'status_code' 201 - mock_post.return_value = Mock( - status_code=201, - headers={'Content-Type': 'application/json'}, - ) - - self.api_client.send_channel_message("test_team_id", "test_channel_id", "test_message", "test_subject") - - # assert the requests.post call was made with the expected arguments - mock_post.assert_called_once_with( - 'https://graph.microsoft.com/v1.0/teams/test_team_id/channels/test_channel_id/messages/', - headers={'Authorization': 'Bearer test_access_token'}, - json={'subject': 'test_subject', 'body': {'content': 'test_message'}} - ) - - -class TestChatsTable(unittest.TestCase): - """ - Tests for the ChatsTable class. - """ - - @classmethod - def setUpClass(cls): - """ - Set up the tests. - """ - - # mock the api handler - cls.api_handler = Mock(MSTeamsHandler) - - def test_get_columns_returns_all_columns(self): - """ - Test that get_columns returns all columns. - """ - - chats_table = ChatsTable(self.api_handler) - - self.assertListEqual(chats_table.get_columns(), ms_teams_handler_config.CHATS_TABLE_COLUMNS) - - def test_select_star_for_single_chat_returns_all_columns(self): - # patch the api handler to return the chat data - with patch.object(self.api_handler.connect(), 'get_chat', return_value=ms_teams_handler_config.TEST_CHAT_DATA): - chats_table = ChatsTable(self.api_handler) - - select_all = ast.Select( - # select all columns - targets=[Star()], - from_table="chats", - where=BinaryOperation( - op='=', - args=[ - Identifier('id'), - Constant("test_id") - ] - ) - ) - - all_chats = chats_table.select(select_all) - first_chat = all_chats.iloc[0] - - self.assertEqual(all_chats.shape[1], len(ms_teams_handler_config.CHATS_TABLE_COLUMNS)) - self.assertEqual(first_chat["id"], "test_id") - self.assertEqual(first_chat["chatType"], "oneOnOne") - - def test_select_star_for_all_chats_returns_all_columns(self): - # patch the api handler to return the chat data - with patch.object(self.api_handler.connect(), 'get_chats', return_value=ms_teams_handler_config.TEST_CHATS_DATA): - chats_table = ChatsTable(self.api_handler) - - select_all = ast.Select( - # select all columns - targets=[Star()], - from_table="chats", - ) - - all_chats = chats_table.select(select_all) - first_chat = all_chats.iloc[0] - - self.assertEqual(all_chats.shape[1], len(ms_teams_handler_config.CHATS_TABLE_COLUMNS)) - self.assertEqual(first_chat["id"], "test_id") - self.assertEqual(first_chat["chatType"], "oneOnOne") - - def test_select_for_single_chat_returns_only_selected_columns(self): - # patch the api handler to return the chat data - with patch.object(self.api_handler.connect(), 'get_chat', return_value=ms_teams_handler_config.TEST_CHAT_DATA): - chats_table = ChatsTable(self.api_handler) - - select_all = ast.Select( - # select only the id and chatType columns - targets=[ - Identifier('id'), - Identifier('chatType'), - ], - from_table="chats", - where=BinaryOperation( - op='=', - args=[ - Identifier('id'), - Constant("test_id") - ] - ) - ) - - all_chats = chats_table.select(select_all) - first_chat = all_chats.iloc[0] - - self.assertEqual(all_chats.shape[1], 2) - self.assertEqual(first_chat["id"], "test_id") - self.assertEqual(first_chat["chatType"], "oneOnOne") - - def test_select_for_all_chats_returns_only_selected_columns(self): - # patch the api handler to return the chat data - with patch.object(self.api_handler.connect(), 'get_chats', return_value=ms_teams_handler_config.TEST_CHATS_DATA): - chats_table = ChatsTable(self.api_handler) - - select_all = ast.Select( - # select all columns - targets=[ - Identifier('id'), - Identifier('chatType'), - ], - from_table="chats", - ) - - all_chats = chats_table.select(select_all) - first_chat = all_chats.iloc[0] - - self.assertEqual(all_chats.shape[1], 2) - self.assertEqual(first_chat["id"], "test_id") - self.assertEqual(first_chat["chatType"], "oneOnOne") - - -class TestChatMessagesTable(unittest.TestCase): - """ - Tests for the ChatMessagesTable class. - """ - - @classmethod - def setUpClass(cls): - """ - Set up the tests. - """ - - # mock the api handler - cls.api_handler = Mock(MSTeamsHandler) - - def test_get_columns_returns_all_columns(self): - """ - Test that get_columns returns all columns. - """ - - chat_messages_table = ChatMessagesTable(self.api_handler) - - self.assertListEqual(chat_messages_table.get_columns(), ms_teams_handler_config.CHAT_MESSAGES_TABLE_COLUMNS) - - def test_select_star_for_single_chat_returns_all_columns(self): - # patch the api handler to return the chat message data - with patch.object(self.api_handler.connect(), 'get_chat_message', return_value=ms_teams_handler_config.TEST_CHAT_MESSAGE_DATA): - chat_messages_table = ChatMessagesTable(self.api_handler) - - select_all = ast.Select( - # select all columns - targets=[Star()], - from_table="chat_messages", - where=[ - BinaryOperation( - op='=', - args=[ - Identifier('id'), - Constant("test_id") - ] - ), - BinaryOperation( - op='=', - args=[ - Identifier('chatId'), - Constant("test_chat_id") - ] - ) - ] - ) - - all_chat_messages = chat_messages_table.select(select_all) - first_chat_message = all_chat_messages.iloc[0] - - self.assertEqual(all_chat_messages.shape[1], len(ms_teams_handler_config.CHAT_MESSAGES_TABLE_COLUMNS)) - self.assertEqual(first_chat_message["id"], "test_id") - self.assertEqual(first_chat_message["messageType"], "message") - - def test_select_star_for_multiple_chats_returns_all_columns(self): - # patch the api handler to return the chat message data - with patch.object(self.api_handler.connect(), 'get_chat_messages', return_value=ms_teams_handler_config.TEST_CHAT_MESSAGES_DATA): - chat_messages_table = ChatMessagesTable(self.api_handler) - - select_all = ast.Select( - # select all columns - targets=[Star()], - from_table="chat_messages", - where=[ - BinaryOperation( - op='=', - args=[ - Identifier('chatId'), - Constant("test_chat_id") - ] - ) - ] - ) - - all_chat_messages = chat_messages_table.select(select_all) - first_chat_message = all_chat_messages.iloc[0] - - self.assertEqual(all_chat_messages.shape[1], len(ms_teams_handler_config.CHAT_MESSAGES_TABLE_COLUMNS)) - self.assertEqual(first_chat_message["id"], "test_id") - self.assertEqual(first_chat_message["messageType"], "message") - - def test_select_star_for_all_chats_returns_all_columns(self): - # patch the api handler to return the chat message data - with patch.object(self.api_handler.connect(), 'get_all_chat_messages', return_value=ms_teams_handler_config.TEST_CHAT_MESSAGES_DATA): - chat_messages_table = ChatMessagesTable(self.api_handler) - - select_all = ast.Select( - # select all columns - targets=[Star()], - from_table="chat_messages", - ) - - all_chat_messages = chat_messages_table.select(select_all) - first_chat_message = all_chat_messages.iloc[0] - - self.assertEqual(all_chat_messages.shape[1], len(ms_teams_handler_config.CHAT_MESSAGES_TABLE_COLUMNS)) - self.assertEqual(first_chat_message["id"], "test_id") - self.assertEqual(first_chat_message["messageType"], "message") - - def test_select_for_single_chat_returns_only_selected_columns(self): - # patch the api handler to return the chat message data - with patch.object(self.api_handler.connect(), 'get_chat_message', return_value=ms_teams_handler_config.TEST_CHAT_MESSAGE_DATA): - chat_messages_table = ChatMessagesTable(self.api_handler) - - select_all = ast.Select( - # select only the id and messageType columns - targets=[ - Identifier('id'), - Identifier('messageType'), - ], - from_table="chat_messages", - where=[ - BinaryOperation( - op='=', - args=[ - Identifier('id'), - Constant("test_id") - ] - ), - BinaryOperation( - op='=', - args=[ - Identifier('chatId'), - Constant("test_chat_id") - ] - ) - ] - ) - - all_chat_messages = chat_messages_table.select(select_all) - first_chat_message = all_chat_messages.iloc[0] - - self.assertEqual(all_chat_messages.shape[1], 2) - self.assertEqual(first_chat_message["id"], "test_id") - self.assertEqual(first_chat_message["messageType"], "message") - - def test_select_for_multiple_chats_returns_only_selected_columns(self): - # patch the api handler to return the chat message data - with patch.object(self.api_handler.connect(), 'get_chat_messages', return_value=ms_teams_handler_config.TEST_CHAT_MESSAGES_DATA): - chat_messages_table = ChatMessagesTable(self.api_handler) - - select_all = ast.Select( - # select only the id and messageType columns - targets=[ - Identifier('id'), - Identifier('messageType'), - ], - from_table="chat_messages", - where=[ - BinaryOperation( - op='=', - args=[ - Identifier('chatId'), - Constant("test_chat_id") - ] - ) - ] - ) - - all_chat_messages = chat_messages_table.select(select_all) - first_chat_message = all_chat_messages.iloc[0] - - self.assertEqual(all_chat_messages.shape[1], 2) - self.assertEqual(first_chat_message["id"], "test_id") - self.assertEqual(first_chat_message["messageType"], "message") - - def test_select_for_all_chats_returns_only_selected_columns(self): - # patch the api handler to return the chat message data - with patch.object(self.api_handler.connect(), 'get_all_chat_messages', return_value=ms_teams_handler_config.TEST_CHAT_MESSAGES_DATA): - chat_messages_table = ChatMessagesTable(self.api_handler) - - select_all = ast.Select( - # select only the id and messageType columns - targets=[ - Identifier('id'), - Identifier('messageType'), - ], - from_table="chat_messages", - ) - - all_chat_messages = chat_messages_table.select(select_all) - first_chat_message = all_chat_messages.iloc[0] - - self.assertEqual(all_chat_messages.shape[1], 2) - self.assertEqual(first_chat_message["id"], "test_id") - self.assertEqual(first_chat_message["messageType"], "message") - - def test_insert_chat_message_calls_correct_method_in_client(self): - """ - Test that send_chat_message sends a chat message. - """ - - # patch the api handler to return the chat message data - with patch.object(self.api_handler.connect(), 'send_chat_message', return_value=None) as mock_send_chat_message: - chat_messages_table = ChatMessagesTable(self.api_handler) - - insert = ast.Insert( - table="chat_messages", - columns=[ - Identifier('chatId'), - Identifier('body_content'), - Identifier('subject'), - ], - values=[ - ( - "test_chat_id", - "test_message", - "test_subject" - ) - ] - ) - - chat_messages_table.insert(insert) - - # assert the api handler's send_chat_message method was called with the expected arguments - mock_send_chat_message.assert_called_once_with(chat_id='test_chat_id', message='test_message', subject='test_subject') - - -class TestChannelsTable(unittest.TestCase): - """ - Tests for the ChannelsTable class. - """ - - @classmethod - def setUpClass(cls): - """ - Set up the tests. - """ - - # mock the api handler - cls.api_handler = Mock(MSTeamsHandler) - - def test_get_columns_returns_all_columns(self): - """ - Test that get_columns returns all columns. - """ - - channels_table = ChannelsTable(self.api_handler) - - self.assertListEqual(channels_table.get_columns(), ms_teams_handler_config.CHANNELS_TABLE_COLUMNS) - - def test_select_star_for_single_channel_returns_all_columns(self): - # patch the api handler to return the channel data - with patch.object(self.api_handler.connect(), 'get_channel', return_value=ms_teams_handler_config.TEST_CHANNEL_DATA): - channels_table = ChannelsTable(self.api_handler) - - select_all = ast.Select( - # select all columns - targets=[Star()], - from_table="channels", - where=[ - BinaryOperation( - op='=', - args=[ - Identifier('id'), - Constant("test_id") - ] - ), - BinaryOperation( - op='=', - args=[ - Identifier('teamId'), - Constant("test_team_id") - ] - ) - ] - ) - - all_channels = channels_table.select(select_all) - first_channel = all_channels.iloc[0] - - self.assertEqual(all_channels.shape[1], len(ms_teams_handler_config.CHANNELS_TABLE_COLUMNS)) - self.assertEqual(first_channel["id"], "test_id") - self.assertEqual(first_channel["displayName"], "test_display_name") - - def test_select_star_for_all_channels_returns_all_columns(self): - # patch the api handler to return the channel data - with patch.object(self.api_handler.connect(), 'get_channels', return_value=ms_teams_handler_config.TEST_CHANNELS_DATA): - channels_table = ChannelsTable(self.api_handler) - - select_all = ast.Select( - # select all columns - targets=[Star()], - from_table="channels", - ) - - all_channels = channels_table.select(select_all) - first_channel = all_channels.iloc[0] - - self.assertEqual(all_channels.shape[1], len(ms_teams_handler_config.CHANNELS_TABLE_COLUMNS)) - self.assertEqual(first_channel["id"], "test_id") - self.assertEqual(first_channel["displayName"], "test_display_name") - - def test_select_for_single_channel_returns_only_selected_columns(self): - # patch the api handler to return the channel data - with patch.object(self.api_handler.connect(), 'get_channel', return_value=ms_teams_handler_config.TEST_CHANNEL_DATA): - channels_table = ChannelsTable(self.api_handler) - - select_all = ast.Select( - # select only the id and displayName columns - targets=[ - Identifier('id'), - Identifier('displayName'), - ], - from_table="channels", - where=[ - BinaryOperation( - op='=', - args=[ - Identifier('id'), - Constant("test_id") - ] - ), - BinaryOperation( - op='=', - args=[ - Identifier('teamId'), - Constant("test_team_id") - ] - ) - ] - ) - - all_channels = channels_table.select(select_all) - first_channel = all_channels.iloc[0] - - self.assertEqual(all_channels.shape[1], 2) - self.assertEqual(first_channel["id"], "test_id") - self.assertEqual(first_channel["displayName"], "test_display_name") - - def test_select_for_all_channels_returns_only_selected_columns(self): - # patch the api handler to return the channel data - with patch.object(self.api_handler.connect(), 'get_channels', return_value=ms_teams_handler_config.TEST_CHANNELS_DATA): - channels_table = ChannelsTable(self.api_handler) - - select_all = ast.Select( - # select only the id and displayName columns - targets=[ - Identifier('id'), - Identifier('displayName'), - ], - from_table="channels", - ) - - all_channels = channels_table.select(select_all) - first_channel = all_channels.iloc[0] - - self.assertEqual(all_channels.shape[1], 2) - self.assertEqual(first_channel["id"], "test_id") - self.assertEqual(first_channel["displayName"], "test_display_name") - - -class TestChannelMessagesTable(unittest.TestCase): - """ - Tests for the ChannelMessagesTable class. - """ - - @classmethod - def setUpClass(cls): - """ - Set up the tests. - """ - - # mock the api handler - cls.api_handler = Mock(MSTeamsHandler) - - def test_get_columns_returns_all_columns(self): - """ - Test that get_columns returns all columns. - """ - - channel_messages_table = ChannelMessagesTable(self.api_handler) - - self.assertListEqual(channel_messages_table.get_columns(), ms_teams_handler_config.CHANNEL_MESSAGES_TABLE_COLUMNS) - - def test_select_star_for_single_channel_message_returns_all_columns(self): - # patch the api handler to return the channel message data - with patch.object(self.api_handler.connect(), 'get_channel_message', return_value=ms_teams_handler_config.TEST_CHANNEL_MESSAGE_DATA): - channel_messages_table = ChannelMessagesTable(self.api_handler) - - select_all = ast.Select( - # select all columns - targets=[Star()], - from_table="channel_messages", - where=[ - BinaryOperation( - op='=', - args=[ - Identifier('id'), - Constant("test_id") - ] - ), - BinaryOperation( - op='=', - args=[ - Identifier('channelIdentity_channelId'), - Constant("test_channel_id") - ] - ), - BinaryOperation( - op='=', - args=[ - Identifier('channelIdentity_teamId'), - Constant("test_team_id") - ] - ) - ] - ) - - all_channel_messages = channel_messages_table.select(select_all) - first_channel_message = all_channel_messages.iloc[0] - - self.assertEqual(all_channel_messages.shape[1], len(ms_teams_handler_config.CHANNEL_MESSAGES_TABLE_COLUMNS)) - self.assertEqual(first_channel_message["id"], "test_id") - self.assertEqual(first_channel_message["messageType"], "message") - - def test_select_star_for_all_channel_messages_returns_all_columns(self): - # patch the api handler to return the channel message data - with patch.object(self.api_handler.connect(), 'get_channel_messages', return_value=ms_teams_handler_config.TEST_CHANNEL_MESSAGES_DATA): - channel_messages_table = ChannelMessagesTable(self.api_handler) - - select_all = ast.Select( - # select all columns - targets=[Star()], - from_table="channel_messages", - ) - - all_channel_messages = channel_messages_table.select(select_all) - first_channel_message = all_channel_messages.iloc[0] - - self.assertEqual(all_channel_messages.shape[1], len(ms_teams_handler_config.CHANNEL_MESSAGES_TABLE_COLUMNS)) - self.assertEqual(first_channel_message["id"], "test_id") - self.assertEqual(first_channel_message["messageType"], "message") - - def test_select_for_single_channel_message_returns_only_selected_columns(self): - # patch the api handler to return the channel message data - with patch.object(self.api_handler.connect(), 'get_channel_message', return_value=ms_teams_handler_config.TEST_CHANNEL_MESSAGE_DATA): - channel_messages_table = ChannelMessagesTable(self.api_handler) - - select_all = ast.Select( - # select only the id and messageType columns - targets=[ - Identifier('id'), - Identifier('messageType'), - ], - from_table="channel_messages", - where=[ - BinaryOperation( - op='=', - args=[ - Identifier('id'), - Constant("test_id") - ] - ), - BinaryOperation( - op='=', - args=[ - Identifier('channelIdentity_channelId'), - Constant("test_channel_id") - ] - ), - BinaryOperation( - op='=', - args=[ - Identifier('channelIdentity_teamId'), - Constant("test_team_id") - ] - ) - ] - ) - - all_channel_messages = channel_messages_table.select(select_all) - first_channel_message = all_channel_messages.iloc[0] - - self.assertEqual(all_channel_messages.shape[1], 2) - self.assertEqual(first_channel_message["id"], "test_id") - self.assertEqual(first_channel_message["messageType"], "message") - - def test_select_for_all_channel_messages_returns_only_selected_columns(self): - # patch the api handler to return the channel message data - with patch.object(self.api_handler.connect(), 'get_channel_messages', return_value=ms_teams_handler_config.TEST_CHANNEL_MESSAGES_DATA): - channel_messages_table = ChannelMessagesTable(self.api_handler) - - select_all = ast.Select( - # select only the id and messageType columns - targets=[ - Identifier('id'), - Identifier('messageType'), - ], - from_table="channel_messages", - ) - - all_channel_messages = channel_messages_table.select(select_all) - first_channel_message = all_channel_messages.iloc[0] - - self.assertEqual(all_channel_messages.shape[1], 2) - self.assertEqual(first_channel_message["id"], "test_id") - self.assertEqual(first_channel_message["messageType"], "message") - - def test_insert_channel_message_calls_correct_method_in_client(self): - """ - Test that insert_channel_message calls the correct method in the client. - """ - - # patch the api handler to return the channel message data - with patch.object(self.api_handler.connect(), 'send_channel_message', return_value=None) as mock_send_channel_message: - channel_messages_table = ChannelMessagesTable(self.api_handler) - - insert = ast.Insert( - table="channel_messages", - columns=[ - Identifier('channelIdentity_teamId'), - Identifier('channelIdentity_channelId'), - Identifier('body_content'), - Identifier('subject'), - ], - values=[ - ( - "test_team_id", - "test_channel_id", - "test_message", - "test_subject" - ) - ] - ) - - channel_messages_table.insert(insert) - - # assert the api handler's send_channel_message method was called with the expected arguments - mock_send_channel_message.assert_called_once_with(group_id='test_team_id', channel_id='test_channel_id', message='test_message', subject='test_subject') - - -if __name__ == "__main__": - unittest.main() diff --git a/tests/unused/unit/handler_tests/test_npm_handler.py b/tests/unused/unit/handler_tests/test_npm_handler.py deleted file mode 100644 index 44fffb13f4f..00000000000 --- a/tests/unused/unit/handler_tests/test_npm_handler.py +++ /dev/null @@ -1,86 +0,0 @@ -import importlib - -import pytest -from mindsdb_sql_parser import parse_sql - -from ..unit.executor_test_base import BaseExecutorTest - -try: - importlib.import_module("requests") - REQUESTS_INSTALLED = True -except ImportError: - REQUESTS_INSTALLED = False - - -@pytest.mark.skipif(not REQUESTS_INSTALLED, reason="requests package is not installed") -class TestNPMHandler(BaseExecutorTest): - - def run_sql(self, sql): - ret = self.command_executor.execute_command(parse_sql(sql)) - assert ret.error_code is None - if ret.data is not None: - return ret.data.to_df() - - def setup_method(self): - super().setup_method() - self.test_package_name = "handlebars" - self.run_sql(""" - CREATE DATABASE npm_test - WITH ENGINE = "npm"; - """) - - def test_basic_select_from(self): - # Select from metadata table - sql = f""" - SELECT * FROM npm_test.metadata WHERE package='{self.test_package_name}'; - """ - assert self.run_sql(sql).shape[0] == 1 - - # Select from maintainers table - sql = f""" - SELECT * FROM npm_test.maintainers WHERE package='{self.test_package_name}'; - """ - self.run_sql(sql) - - # Select from keywords table - sql = f""" - SELECT * FROM npm_test.keywords WHERE package='{self.test_package_name}'; - """ - self.run_sql(sql) - - # Select from dependencies table - sql = f""" - SELECT * FROM npm_test.dependencies WHERE package='{self.test_package_name}'; - """ - self.run_sql(sql) - - # Select from dev_dependencies table - sql = f""" - SELECT * FROM npm_test.dev_dependencies WHERE package='{self.test_package_name}'; - """ - self.run_sql(sql) - - # Select from optional_dependencies table - sql = f""" - SELECT * FROM npm_test.optional_dependencies WHERE package='{self.test_package_name}'; - """ - self.run_sql(sql) - - # Select from github_stats table - sql = f""" - SELECT * FROM npm_test.github_stats WHERE package='{self.test_package_name}'; - """ - assert self.run_sql(sql).shape[0] == 1 - - def test_complex_select(self): - # Select email maintainers table - sql = f""" - SELECT email FROM npm_test.maintainers WHERE package='{self.test_package_name}'; - """ - assert self.run_sql(sql).shape[1] == 1 - - # Select single dependency - sql = f""" - SELECT * FROM npm_test.dependencies WHERE package='{self.test_package_name}' LIMIT 1; - """ - assert self.run_sql(sql).shape[0] == 1 diff --git a/tests/unused/unit/handler_tests/test_oilpriceapi_handler.py b/tests/unused/unit/handler_tests/test_oilpriceapi_handler.py deleted file mode 100644 index 907a171cab0..00000000000 --- a/tests/unused/unit/handler_tests/test_oilpriceapi_handler.py +++ /dev/null @@ -1,47 +0,0 @@ -import importlib -import os -import pytest -from mindsdb_sql_parser import parse_sql - -from ..unit.executor_test_base import BaseExecutorTest - -try: - importlib.import_module("requests") - REQUESTS_INSTALLED = True -except ImportError: - REQUESTS_INSTALLED = False - - -@pytest.mark.skipif(not REQUESTS_INSTALLED, reason="requests package is not installed") -class TestOilPriceAPIHandler(BaseExecutorTest): - - def run_sql(self, sql): - ret = self.command_executor.execute_command(parse_sql(sql)) - assert ret.error_code is None - if ret.data is not None: - return ret.data.to_df() - - def setup_method(self): - super().setup_method() - self.api_key = os.environ.get("OILPRICEAPI_KEY") - self.run_sql(f""" - CREATE DATABASE mindsdb_oilpriceapi - WITH ENGINE = 'oilpriceapi', - PARAMETERS = { - "api_key": '{self.api_key}' - }; - """) - - def test_basic_select_from(self): - sql = "SELECT * FROM mindsdb_oilpriceapi.latest_price;" - assert self.run_sql(sql).shape[0] == 1 - - sql = "SELECT * FROM mindsdb_oilpriceapi.past_day_price;" - assert self.run_sql(sql).shape[0] == 20 - - def test_complex_select(self): - sql = 'SELECT price FROM mindsdb_oilpriceapi.latest_price where by_type="daily_average_price" and by_code="WTI_USD";' - assert self.run_sql(sql).shape[1] == 1 - - sql = "SELECT * FROM npm_test.past_day_price LIMIT 1;" - assert self.run_sql(sql).shape[0] == 1 diff --git a/tests/unused/unit/handler_tests/test_paypal_handler.py b/tests/unused/unit/handler_tests/test_paypal_handler.py deleted file mode 100644 index cc02e8bb676..00000000000 --- a/tests/unused/unit/handler_tests/test_paypal_handler.py +++ /dev/null @@ -1,46 +0,0 @@ -import os -import unittest - -from mindsdb.integrations.handlers.paypal_handler.paypal_handler import PayPalHandler -from mindsdb.api.executor.data_types.response_type import RESPONSE_TYPE - - -class PayPalHandlerTest(unittest.TestCase): - - @classmethod - def setUpClass(cls): - cls.kwargs = { - "connection_data": { - "mode": os.environ.get('MODE'), - "client_id": os.environ.get('CLIENT_ID'), - "client_secret": os.environ.get('CLIENT_SECRET'), - } - } - cls.handler = PayPalHandler('test_paypal_handler', **cls.kwargs) - - def test_0_check_connection(self): - assert self.handler.check_connection() - - def test_1_get_tables(self): - tables = self.handler.get_tables() - assert tables.type is not RESPONSE_TYPE.ERROR - - def test_2_select_payments_query(self): - query = "SELECT * FROM test_paypal_handler.payments" - result = self.handler.native_query(query) - assert result.type is RESPONSE_TYPE.TABLE - - def test_3_select_invoices_query(self): - query = "SELECT * FROM test_paypal_handler.invoices" - result = self.handler.native_query(query) - assert result.type is RESPONSE_TYPE.TABLE - - def test_4_select_subscriptions_query(self): - query = "SELECT * FROM test_paypal_handler.subscriptions" - result = self.handler.native_query(query) - assert result.type is RESPONSE_TYPE.TABLE - - def test_5_select_orders_query(self): - query = "SELECT * FROM test_paypal_handler.orders WHERE ids = ('')" - result = self.handler.native_query(query) - assert result.type is RESPONSE_TYPE.TABLE diff --git a/tests/unused/unit/handler_tests/test_pgvector_handler.py b/tests/unused/unit/handler_tests/test_pgvector_handler.py deleted file mode 100644 index cc520bc4ee8..00000000000 --- a/tests/unused/unit/handler_tests/test_pgvector_handler.py +++ /dev/null @@ -1,134 +0,0 @@ -import os -import psycopg2 -import pytest - -from mindsdb.integrations.handlers.pgvector_handler.pgvector_handler import PgVectorHandler - - -TEST_DB_NAME = os.environ.get('MDB_TEST_PGVECTOR_DATABASE', 'pgvector_handler_test_db') -# Should match table name in data/pgvector/seed.sql -TEST_TABLE_NAME = 'items' -# Should match column names in data/pgvector/seed.sql -COLUMN_NAMES = ['id', 'content', 'embeddings', 'metadata'] - -HANDLER_KWARGS = { - 'connection_data': { - 'host': os.environ.get('MDB_TEST_PGVECTOR_HOST', '127.0.0.1'), - 'port': os.environ.get('MDB_TEST_PGVECTOR_PORT', '5432'), - 'user': os.environ.get('MDB_TEST_PGVECTOR_USER', 'postgres'), - 'password': os.environ.get('MDB_TEST_PGVECTOR_PASSWORD', 'supersecret'), - 'database': TEST_DB_NAME - } -} - - -def init_db(): - '''Seed the test DB with some data''' - conn_info = HANDLER_KWARGS['connection_data'].copy() - conn_info['database'] = 'postgres' - db = psycopg2.connect(**conn_info) - db.autocommit = True - cursor = db.cursor() - - try: - cursor.execute(f'DROP DATABASE IF EXISTS {TEST_DB_NAME};') - db.commit() - - # Create the test database - cursor.execute(f'CREATE DATABASE {TEST_DB_NAME};') - db.commit() - - # Reconnect to the new database - conn_info['database'] = TEST_DB_NAME - db = psycopg2.connect(**conn_info) - db.autocommit = True - cursor = db.cursor() - - # Seed the database with data - curr_dir = os.path.dirname(os.path.realpath(__file__)) - seed_sql_path = os.path.join(curr_dir, 'data', 'pgvector', 'seed.sql') - with open(seed_sql_path, 'r') as sql_seed_file: - cursor.execute(sql_seed_file.read()) - db.commit() - - finally: - # Close the cursor and the connection - cursor.close() - db.close() - - -@pytest.fixture(scope='module') -def handler(): - init_db() - handler = PgVectorHandler('test_handler', **HANDLER_KWARGS) - yield handler - - -@pytest.mark.skipif(os.environ.get('MDB_TEST_PGVECTOR_HOST') is None, reason='MDB_TEST_PGVECTOR_HOST environment variable not set') -class TestPgvectorConnection: - def test_connect(self, handler): - handler.connect() - assert handler.is_connected, 'connection error' - - def test_check_connection(self, handler): - res = handler.check_connection() - assert res.success, res.error_message - - -@pytest.mark.skipif(os.environ.get('MDB_TEST_PGVECTOR_HOST') is None, reason='MDB_TEST_PGVECTOR_HOST environment variable not set') -class TestPgvectorQuery: - def test_select(self, handler): - result = handler.select(TEST_TABLE_NAME) - assert not result.empty - for col in COLUMN_NAMES: - assert col in result.columns - - def test_hybrid_search_with_keywords(self, handler): - result = handler.hybrid_search( - TEST_TABLE_NAME, - # Embeddings (semantic) search. - [7.0, 8.0, 9.0], - # Keyword search. - query='cat rat' - ) - # Top result is an exact embeddings match. - assert result.iloc[0]['embeddings'].tolist() == [7.0, 8.0, 9.0] - # Top result should include both keywords. - assert 'cat' in result.iloc[0]['content'] - assert 'rat' in result.iloc[0]['content'] - - def test_hybrid_search_with_metadata(self, handler): - result = handler.hybrid_search( - TEST_TABLE_NAME, - # Embeddings (semantic) search. - [4.0, 5.0, 6.0], - # Metadata filters. - metadata={'location': 'Wonderland', 'author': 'Taishan'} - ) - # Only two items match metadata filters. - assert len(result.index) == 2 - # Top result is an exact embeddings match. - assert result.iloc[0]['embeddings'].tolist() == [4.0, 5.0, 6.0] - - def test_hybrid_search_with_keywords_and_metadata(self, handler): - result = handler.hybrid_search( - TEST_TABLE_NAME, - # Embeddings (semantic) search. - [4.0, 5.0, 6.0], - # Keyword search. - query='fat cat', - # Metadata filters. - metadata={'location': 'Wonderland', 'author': 'Taishan'} - ) - # Only two items match metadata filters. - assert len(result.index) == 2 - # Top result is actually a keyword match because embeddings are close. - assert result.iloc[0]['embeddings'].tolist() == [1.0, 2.0, 3.0] - - def test_hybrid_search_no_query_or_metadata(self, handler): - with pytest.raises(ValueError): - _ = handler.hybrid_search( - TEST_TABLE_NAME, - # Embeddings (semantic) search. - [4.0, 5.0, 6.0], - ) diff --git a/tests/unused/unit/handler_tests/test_pinecone_handler.py b/tests/unused/unit/handler_tests/test_pinecone_handler.py deleted file mode 100644 index 46def1b070a..00000000000 --- a/tests/unused/unit/handler_tests/test_pinecone_handler.py +++ /dev/null @@ -1,274 +0,0 @@ -# check if chroma_db is installed -import importlib -from unittest.mock import patch -import os - -import pandas as pd -import pytest -from mindsdb_sql_parser import parse_sql - -from tests.unit.executor_test_base import BaseExecutorTest - -try: - pinecone = importlib.import_module("pinecone") - PINECONE_CLIENT_INSTALLED = True -except ImportError: - PINECONE_CLIENT_INSTALLED = False - - -# NOTE: These tests might fail since pinecone is eventually consistent. Some queries return wrong result when tested - -@pytest.mark.skipif(not PINECONE_CLIENT_INSTALLED, reason="pinecone client is not installed") -class TestPineconeHandler(BaseExecutorTest): - - def run_sql(self, sql): - ret = self.command_executor.execute_command(parse_sql(sql)) - assert ret.error_code is None - if ret.data is not None: - return ret.data.to_df() - - def setup_method(self): - super().setup_method() - # Replace with your pinecone key - self.api_key = os.environ['PINECONE_API_KEY'] - self.environment = os.environ['PINECONE_ENV'] - self.run_sql(f""" - CREATE DATABASE pinecone_test - WITH ENGINE = "pinecone", - PARAMETERS = {{ - "api_key": "{self.api_key}", - "environment": "{self.environment}" - }} - """) - - @patch("mindsdb.integrations.handlers.postgres_handler.Handler") - def test_create_with_select(self, postgres_handler_mock): - df = pd.DataFrame( - { - "id": ["id1", "id2"], - "content": ["this is a test", "this is a test"], - "metadata": [{"test": "test"}, {"test": "test"}], - "embeddings": [[1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0], [1.0, 2.0, 3.0, 5.0, 6.0, 8.0, 9.0, 3.0]], - } - ) - - self.set_handler(postgres_handler_mock, "pg", tables={"df": df}) - sql = """ - CREATE TABLE pinecone_test.testtable ( - SELECT * FROM pg.df - ) - """ - self.run_sql(sql) - - @patch("mindsdb.integrations.handlers.postgres_handler.Handler") - def test_select_from(self, postgres_handler_mock): - df = pd.DataFrame( - { - "id": ["id1", "id2"], - "content": ["this is a test", "this is a test"], - "metadata": [{"test": "test"}, {"test": "test"}], - "embeddings": [[1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0], [1.0, 2.0, 3.0, 5.0, 6.0, 8.0, 9.0, 3.0]], - } - ) - - self.set_handler(postgres_handler_mock, "pg", tables={"testtable": df}) - sql = """ - CREATE TABLE pinecone_test.testtable ( - SELECT * FROM pg.df - ) - """ - self.run_sql(sql) - - # query a table with id - sql = """ - SELECT * FROM pinecone_test.testtable - WHERE id = 'id1' - """ - ret = self.run_sql(sql) - assert ret.shape[0] == 2 - - # query a table with a search vector, with out limit - sql = """ - SELECT * FROM pinecone_test.testtable - WHERE search_vector = '[1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0]' - """ - ret = self.run_sql(sql) - assert ret.shape[0] == 2 - - # query a table with a search vector, with limit - sql = """ - SELECT * FROM pinecone_test.testtable - WHERE search_vector = '[1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0]' - LIMIT 1 - """ - ret = self.run_sql(sql) - assert ret.shape[0] == 1 - - # query a table with a metadata filter and a search vector - sql = """ - SELECT * FROM pinecone_test.testtable - WHERE testable.metadata.test = 'test' - AND search_vector = '[1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0]' - """ - ret = self.run_sql(sql) - assert ret.shape[0] == 2 - - @patch("mindsdb.integrations.handlers.postgres_handler.Handler") - def test_insert_into(self, postgres_handler_mock): - df = pd.DataFrame( - { - "id": ["id1", "id2"], - "content": ["this is a test", "this is a test"], - "metadata": [{"test": "test"}, {"test": "test"}], - "embeddings": [[1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0], [1.0, 2.0, 3.0, 5.0, 6.0, 8.0, 9.0, 3.0]], - } - ) - - df2 = pd.DataFrame( - { - "id": ["id1", "id2", "id3"], - "content": ["this is a test", "this is a test", "this is a test"], - "metadata": [{"test": "test1"}, {"test": "test2"}, {"test": "test3"}], - "embeddings": [ - [1.0, 2.0, 3.0, 4.0, 3.0, 5.0, 2.0, 8.1], - [4.0, 2.0, 7.0, 4.0, 2.0, 5.0, 2.0, 9.0], - [5.0, 2.0, 3.0, 2.0, 3.0, 3.0, 2.0, 7.0], - ], - } - ) - self.set_handler(postgres_handler_mock, "pg", tables={"df": df, "df2": df2}) - - sql = """ - CREATE TABLE pinecone_test.testtable ( - SELECT * FROM pg.df - ) - """ - self.run_sql(sql) - - sql = """ - INSERT INTO pinecone_test.testtable ( - id,content,metadata,embeddings - ) - VALUES ( - 'some_unique_id', 'this is a test', '{"test": "test"}', '[1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0]' - ) - """ - self.run_sql(sql) - # check if the data is inserted - sql = """ - SELECT * FROM pinecone_test.testtable - WHERE id = 'some_unique_id' - """ - ret = self.run_sql(sql) - assert ret.shape[0] == 3 - - # insert into a table with existing id, shall work - sql = """ - INSERT INTO pinecone_test.testtable ( - id,content,metadata,embeddings - ) - VALUES ( - 'id1', 'this is a test', '{"test": "tester"}', '[1.0, 2.0, 3.0, 4.0, 6.0, 7.0, 8.0, 9.0]' - ) - """ - self.run_sql(sql) - - @patch("mindsdb.integrations.handlers.postgres_handler.Handler") - def test_delete(self, postgres_handler_mock): - df = pd.DataFrame( - { - "id": ["id1", "id2"], - "content": ["this is a test", "this is a test"], - "metadata": [{"test": "test1"}, {"test": "test2"}], - "embeddings": [[1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0], [1.0, 2.0, 3.0, 5.0, 6.0, 8.0, 9.0, 3.0]], - } - ) - self.set_handler(postgres_handler_mock, "pg", tables={"testtable": df}) - - # create a table - sql = """ - CREATE TABLE pinecone_test.testtable ( - SELECT * FROM pg.df - ) - """ - self.run_sql(sql) - - # delete from a table with a metadata filter - sql = """ - DELETE FROM pinecone_test.testtable - WHERE testtable.metadata.test = 'test1' - """ - self.run_sql(sql) - - # delete by id - sql = """ - DELETE FROM pinecone_test.testtable - WHERE id = 'id2' - """ - self.run_sql(sql) - - # delete from a table without any filters is not allowed - sql = """ - DELETE FROM pinecone_test.testtable - """ - with pytest.raises(Exception): - self.run_sql(sql) - - @pytest.mark.xfail(reason="update for pinecone is not implemented, use insert") - def test_update(self): - # update a table with a metadata filter - sql = """ - UPDATE pinecone_test.testtable - SET metadata.test = 'test2' - WHERE metadata.test = 'test' - """ - # sql shoudl fail - with pytest.raises(Exception): - self.run_sql(sql) - - @pytest.mark.xfail(reason="create table for vectordatabase is not well supported") - @patch("mindsdb.integrations.handlers.postgres_handler.Handler") - def test_create_table(self, postgres_handler_mock): - # create an empty table - sql = """ - CREATE TABLE pinecone_test.testtable; - """ - self.run_sql(sql) - # create a table with the schema definition is not allowed - sql = """ - CREATE TABLE pinecone_test.testtable ( - id int, - metadata text, - embedding float[] - ); - """ - with pytest.raises(Exception): - self.run_sql(sql) - - @pytest.mark.xfail(reason="drop table for vectordatabase is not working") - @patch("mindsdb.integrations.handlers.postgres_handler.Handler") - def test_drop_table(self, postgres_handler_mock): - df = pd.DataFrame( - { - "id": ["id1", "id2"], - "content": ["this is a test", "this is a test"], - "metadata": [{"test": "test"}, {"test": "test"}], - "embeddings": [[1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0], [1.0, 2.0, 3.0, 5.0, 6.0, 8.0, 9.0, 3.0]], - } - ) - self.set_handler(postgres_handler_mock, "pg", tables={"testtable": df}) - sql = """ - CREATE TABLE piecone_test.testtable( - SELECT * FROM pg.df - ) - """ - self.run_sql(sql) - sql = """ - DROP TABLE pinecone_test.testtable; - """ - self.run_sql(sql) - sql = """ - DROP TABLE pinecone_test.testtable2; - """ - with pytest.raises(Exception): - self.run_sql(sql) diff --git a/tests/unused/unit/handler_tests/test_qdrant_handler.py b/tests/unused/unit/handler_tests/test_qdrant_handler.py deleted file mode 100644 index 205fb9db392..00000000000 --- a/tests/unused/unit/handler_tests/test_qdrant_handler.py +++ /dev/null @@ -1,442 +0,0 @@ -from unittest.mock import patch - -import pytest -import pandas as pd -from mindsdb_sql_parser import parse_sql - -from tests.unit.executor_test_base import BaseExecutorTest - - -class TestQdrantHandler(BaseExecutorTest): - def run_sql(self, sql): - ret = self.command_executor.execute_command(parse_sql(sql)) - - assert ret.error_code is None - if ret.data is not None: - return ret.data.to_df() - - def setup_method(self): - super().setup_method() - # connect to a Qdrant instance and create a database - self.run_sql( - """ - CREATE DATABASE qtest - WITH ENGINE = "qdrant", - PARAMETERS = { - "location": ":memory:", - "collection_config": { - "size": 3, - "distance": "Cosine" - } - } - """ - ) - - @patch("mindsdb.integrations.handlers.postgres_handler.Handler") - def test_create_with_select(self, postgres_handler_mock): - df = pd.DataFrame( - { - - "id": [1, 2], - "content": ["this is a test", "this is a test"], - "metadata": [{"test": "test"}, {"test": "test"}], - "embeddings": [[1.0, 2.0, 3.0], [1.0, 2.0, 3.0]], - } - ) - - self.set_handler(postgres_handler_mock, "pg", tables={"test_table": df}) - - sql = """ - CREATE TABLE qtest.test_table_1 ( - SELECT * FROM pg.df - ) - """ - self.run_sql(sql) - - @pytest.mark.xfail(reason="drop table for vectordatabase is not working") - @patch("mindsdb.integrations.handlers.postgres_handler.Handler") - def test_drop_table(self, postgres_handler_mock): - df = pd.DataFrame( - { - "id": [32, 13], - "content": ["this is a test", "this is a test"], - "metadata": [{"test": "test"}, {"test": "test"}], - "embeddings": [[1.0, 2.0, 3.0], [1.0, 2.0, 3.0]], - } - ) - self.set_handler(postgres_handler_mock, "pg", tables={"test_table": df}) - - # create a table - sql = """ - CREATE TABLE qtest.test_table_2 ( - SELECT * FROM pg.df - ) - """ - self.run_sql(sql) - - sql = """ - DROP TABLE qtest.test_table_2; - """ - self.run_sql(sql) - - sql = """ - DROP TABLE qtest.test_table_22; - """ - with pytest.raises(Exception): - self.run_sql(sql) - - @patch("mindsdb.integrations.handlers.postgres_handler.Handler") - def test_insert_into(self, postgres_handler_mock): - df = pd.DataFrame( - { - "id": [81, 24, 33], - "content": ["this is a test", "this is a test", "this is a test"], - "metadata": [{"test": "test1"}, {"test": "test2"}, {"test": "test3"}], - "embeddings": [[1.0, 2.0, 3.0], [1.0, 2.0, 3.0], [1.0, 2.0, 3.0]], - } - ) - df2 = pd.DataFrame( - { - "id": [1, 2, 3], - "content": ["this is a test", "this is a test", "this is a test"], - "metadata": [{"test": "test1"}, {"test": "test2"}, {"test": "test3"}], - "embeddings": [ - [1.0, 2.0, 3.0, 4.0], - [1.0, 2.0], - [1.0, 2.0, 3.0], - ], # different dimensions - } - ) - self.set_handler(postgres_handler_mock, "pg", tables={"df": df, "df2": df2}) - num_record = df.shape[0] - - # create a table - sql = """ - CREATE TABLE qtest.test_table_3 ( - SELECT * FROM pg.df - ) - """ - self.run_sql(sql) - - # insert into a table with values - sql = """ - INSERT INTO qtest.test_table_3 ( - id,content,metadata,embeddings - ) - VALUES ( - 4, 'this is a test', '{"test": "test"}', '[1.0, 2.0, 3.0]' - ) - """ - self.run_sql(sql) - # check if the data is inserted - sql = """ - SELECT * FROM qtest.test_table_3 - WHERE id = 4 AND search_vector = '[1.0, 2.0, 3.0]' AND search_vector= '[1.0, 2.0, 4.0]' - """ - ret = self.run_sql(sql) - assert ret.shape[0] == 1 - - # insert without ids should auto-generate ids - sql = """ - INSERT INTO qtest.test_table_3 ( - content,metadata,embeddings - ) - VALUES ( - 'this is a test without ID', '{"test": "test"}', '[1.0, 2.0, 3.0]' - ) - """ - self.run_sql(sql) - - # check if the data is inserted - sql = """ - SELECT * FROM qtest.test_table_3 - """ - ret = self.run_sql(sql) - assert ret.shape[0] == num_record + 2 - - # insert into a table with a select statement - sql = """ - INSERT INTO qtest.test_table_3 ( - content,metadata,embeddings - ) - SELECT - content,metadata,embeddings - FROM - pg.df - """ - self.run_sql(sql) - - # check if the data is inserted - sql = """ - SELECT * FROM qtest.test_table_3 - """ - ret = self.run_sql(sql) - assert ret.shape[0] == num_record * 2 + 2 - - # insert into a table with a select statement, but wrong columns - sql = """ - INSERT INTO qtest.test_table_3 - SELECT - content,metadata,embeddings as wrong_column - FROM - pg.df - """ - with pytest.raises(Exception): - self.run_sql(sql) - - # insert into a table with a select statement, missing metadata column - sql = """ - INSERT INTO qtest.test_table_3 - SELECT - content,embeddings - FROM - pg.df - """ - self.run_sql(sql) - - # insert into a table with a select statement, missing embedding column, shall raise an error - sql = """ - INSERT INTO qtest.test_table_3 - SELECT - content,metadata - FROM - pg.df - """ - with pytest.raises(Exception): - self.run_sql(sql) - - # insert into a table with a select statement, with different embedding dimensions, shall raise an error - sql = """ - INSERT INTO qtest.test_table_3 - SELECT - content,metadata,embeddings - FROM - pg.df2 - """ - with pytest.raises(Exception): - self.run_sql(sql) - - # insert into a table with existing id overwrites the existing record - sql = """ - INSERT INTO qtest.test_table_3 ( - id,content,metadata,embeddings - ) - VALUES ( - 4, 'this is a test', '{"test": "test"}', '[1.0, 2.0, 3.0]' - ) - """ - self.run_sql(sql) - - @patch("mindsdb.integrations.handlers.postgres_handler.Handler") - def test_select_from(self, postgres_handler_mock): - df = pd.DataFrame( - { - "id": [32, 33], - "content": ["this is a test", "this is a test"], - "metadata": [{"test": "Info"}, {"test": "Info"}], - "embeddings": [[1.0, 2.0, 3.0], [1.0, 2.0, 3.0]], - } - ) - self.set_handler(postgres_handler_mock, "pg", tables={"test_table": df}) - # create a table - sql = """ - CREATE TABLE qtest.test_table_4 ( - SELECT * FROM pg.df - ) - """ - self.run_sql(sql) - - # query a table without any filters - sql = """ - SELECT * FROM qtest.test_table_4 - """ - self.run_sql(sql) - - # query a table with id - sql = """ - SELECT * FROM qtest.test_table_4 - WHERE id = 32 - """ - ret = self.run_sql(sql) - assert ret.shape[0] == 1 - - # query a table with a search vector, without limit - sql = """ - SELECT * FROM qtest.test_table_4 - WHERE search_vector = '[1.0, 2.0, 3.0]' - """ - ret = self.run_sql(sql) - assert ret.shape[0] == 2 - - # query a table with a search vector, with limit - sql = """ - SELECT * FROM qtest.test_table_4 - WHERE search_vector = '[1.0, 2.0, 3.0]' - LIMIT 1 - """ - ret = self.run_sql(sql) - assert ret.shape[0] == 1 - - # query a table with a metadata filter - sql = """ - SELECT * FROM qtest.test_table_4 - WHERE `metadata.test` = 'Info'; - """ - ret = self.run_sql(sql) - assert ret.shape[0] == 2 - - sql = """ - SELECT * FROM qtest.test_table_4 - WHERE `metadata.test` = 'Info' - AND search_vector = '[1.0, 2.0, 3.0]' - """ - ret = self.run_sql(sql) - assert ret.shape[0] == 2 - - @pytest.mark.xfail(reason="upsert for vectordatabase is not implemented") - def test_update(self): - # update a table with a metadata filter - sql = """ - UPDATE qtest.test_table_5 - SET `metadata.test` = 'test2' - WHERE `metadata.test` = 'test' - """ - self.run_sql(sql) - # check if the data is updated - sql = """ - SELECT * FROM qtest.test_table_5 - WHERE `metadata.test` = 'test2' - """ - ret = self.run_sql(sql) - assert ret.shape[0] == 2 - - # update the embeddings - sql = """ - UPDATE qtest.test_table_5 - SET embedding = [3.0, 2.0, 1.0] - WHERE `metadata.test` = 'test2' - """ - self.run_sql(sql) - # check if the data is updated - sql = """ - SELECT * FROM qtest.test_table_5 - WHERE `metadata.test` = 'test2' - """ - ret = self.run_sql(sql) - assert ret.shape[0] == 2 - assert ret.embedding[0] == [3.0, 2.0, 1.0] - - # update multiple columns - sql = """ - UPDATE qtest.test_table_5 - SET `metadata.test` = 'test3', - embedding = [1.0, 2.0, 3.0] - content = 'this is a test' - WHERE `metadata.test` = 'test2' - """ - self.run_sql(sql) - # check if the data is updated - sql = """ - SELECT * FROM qtest.test_table_5 - WHERE `metadata.test` = 'test3' - """ - ret = self.run_sql(sql) - assert ret.shape[0] == 2 - assert ret.embedding[0] == [1.0, 2.0, 3.0] - assert ret.content[0] == "this is a test" - - # update a table with a search vector filter is not allowed - sql = """ - UPDATE qtest.test_table_5 - SET `metadata.test = 'test2' - WHERE search_vector = [1.0, 2.0, 3.0] - """ - with pytest.raises(Exception): - self.run_sql(sql) - - # update a table without any filters is allowed - sql = """ - UPDATE qtest.test_table_5 - SET metadata.test = 'test3' - """ - self.run_sql(sql) - # check if the data is updated - sql = """ - SELECT * FROM qtest.test_table_5 - WHERE `metadata.test` = 'test3' - """ - ret = self.run_sql(sql) - assert ret.shape[0] == 2 - - # update a table with a search vector filter and a metadata filter is not allowed - sql = """ - UPDATE qtest.test_table_5 - SET metadata.test = 'test3' - WHERE metadata.test = 'test2' - AND search_vector = [1.0, 2.0, 3.0] - """ - with pytest.raises(Exception): - self.run_sql(sql) - - @patch("mindsdb.integrations.handlers.postgres_handler.Handler") - def test_delete(self, postgres_handler_mock): - df = pd.DataFrame( - { - "id": [1, 2], - "content": ["this is a test", "this is a test"], - "metadata": [{"test": "test1"}, {"test": "test2"}], - "embeddings": [[1.0, 2.0, 3.0], [1.0, 2.0, 3.0]], - } - ) - self.set_handler(postgres_handler_mock, "pg", tables={"test_table": df}) - - # create a table - sql = """ - CREATE TABLE qtest.test_table_6 ( - SELECT * FROM pg.df - ) - """ - self.run_sql(sql) - - # delete from a table with a metadata filter - sql = """ - DELETE FROM qtest.test_table_6 - WHERE `metadata.test` = 'test1' - """ - self.run_sql(sql) - # check if the data is deleted - sql = """ - SELECT * FROM qtest.test_table_6 - WHERE `metadata.test` = 'test2' - """ - ret = self.run_sql(sql) - assert ret.shape[0] == 1 - - # delete by id - sql = """ - DELETE FROM qtest.test_table_6 - WHERE id = 2 - """ - self.run_sql(sql) - # check if the data is deleted - sql = """ - SELECT * FROM qtest.test_table_6 - WHERE id = 2 - """ - ret = self.run_sql(sql) - assert ret.shape[0] == 0 - - # delete from a table with a search vector filter is not allowed - sql = """ - DELETE FROM qtest.test_table_6 - WHERE search_vector = [1.0, 2.0, 3.0] - """ - with pytest.raises(Exception): - self.run_sql(sql) - - # delete from a table without any filters is not allowed - sql = """ - DELETE FROM qtest.test_table_6 - """ - with pytest.raises(Exception): - self.run_sql(sql) From 19427f3b6b8c9ae31e9f3550e447fb0240e66db7 Mon Sep 17 00:00:00 2001 From: ZoranPandovski Date: Fri, 19 Dec 2025 15:51:20 +0100 Subject: [PATCH 4/4] Rmv unused tests --- .../unit/handler_tests/test_rag_pipelines.py | 53 - .../handler_tests/test_rocket_chat_handler.py | 96 - .../handler_tests/test_sap_erp_handler.py | 240 -- .../handler_tests/test_storage_handler.py | 23 - .../unit/handler_tests/test_symbl_handler.py | 57 - .../handler_tests/test_tripadvisor_handler.py | 324 -- .../test_vectordatabase_dispatch.py | 282 -- .../handler_tests/test_weaviate_handler.py | 503 --- .../unit/handler_tests/test_webz_handler.py | 227 -- .../unit/handler_tests/test_xata_handler.py | 413 --- .../handler_tests/test_zipcodebase_handler.py | 47 - .../unit/handler_tests/test_zotero_handler.py | 175 - .../unit/handlers/test_chromadb_handler.py | 529 --- .../agents/test_api_key_handling.py | 106 - .../custom/text2sql/test_mindsdb_kb_tools.py | 163 - tests/unused/unit/ml_handlers/conftest.py | 24 - .../ml_handlers/data/anomaly_detection.csv | 7 - .../unit/ml_handlers/data/house_sales.csv | 348 -- tests/unused/unit/ml_handlers/data/movies.csv | 90 - .../unused/unit/ml_handlers/data/ratings.csv | 3207 ----------------- .../data/vertex_anomaly_detection.csv | 6 - .../data/vertex_classification.csv | 6 - .../ml_handlers/data/vertex_regression.csv | 5 - .../ml_handlers/test_anomaly_detection.py | 291 -- .../unused/unit/ml_handlers/test_anthropic.py | 110 - .../unused/unit/ml_handlers/test_autogluon.py | 77 - .../unused/unit/ml_handlers/test_autokeras.py | 276 -- .../unused/unit/ml_handlers/test_clipdrop.py | 110 - tests/unused/unit/ml_handlers/test_dspy.py | 100 - .../unit/ml_handlers/test_google_gemini.py | 105 - .../unit/ml_handlers/test_huggingface.py | 381 -- .../unit/ml_handlers/test_huggingface_api.py | 46 - .../unused/unit/ml_handlers/test_langchain.py | 162 - .../ml_handlers/test_langchain_embedding.py | 362 -- .../unit/ml_handlers/test_leonardo_ai.py | 116 - tests/unused/unit/ml_handlers/test_lightfm.py | 136 - .../unused/unit/ml_handlers/test_lightwood.py | 132 - tests/unused/unit/ml_handlers/test_ludwig.py | 70 - .../unit/ml_handlers/test_merlion_handler.py | 203 -- tests/unused/unit/ml_handlers/test_mlflow.py | 57 - .../unit/ml_handlers/test_neuralforecast.py | 179 - .../test_popularity_recommender.py | 71 - tests/unused/unit/ml_handlers/test_rag.py | 324 -- tests/unused/unit/ml_handlers/test_spacy.py | 169 - .../unit/ml_handlers/test_stabilityai.py | 127 - .../unit/ml_handlers/test_statsforecast.py | 302 -- .../ml_handlers/test_time_series_utils.py | 144 - tests/unused/unit/ml_handlers/test_unify.py | 156 - tests/unused/unit/ml_handlers/test_vertex.py | 247 -- tests/unused/unit/ml_handlers/test_writer.py | 143 - 50 files changed, 11527 deletions(-) delete mode 100644 tests/unused/unit/handler_tests/test_rag_pipelines.py delete mode 100644 tests/unused/unit/handler_tests/test_rocket_chat_handler.py delete mode 100644 tests/unused/unit/handler_tests/test_sap_erp_handler.py delete mode 100644 tests/unused/unit/handler_tests/test_storage_handler.py delete mode 100644 tests/unused/unit/handler_tests/test_symbl_handler.py delete mode 100644 tests/unused/unit/handler_tests/test_tripadvisor_handler.py delete mode 100644 tests/unused/unit/handler_tests/test_vectordatabase_dispatch.py delete mode 100644 tests/unused/unit/handler_tests/test_weaviate_handler.py delete mode 100644 tests/unused/unit/handler_tests/test_webz_handler.py delete mode 100644 tests/unused/unit/handler_tests/test_xata_handler.py delete mode 100644 tests/unused/unit/handler_tests/test_zipcodebase_handler.py delete mode 100644 tests/unused/unit/handler_tests/test_zotero_handler.py delete mode 100644 tests/unused/unit/handlers/test_chromadb_handler.py delete mode 100644 tests/unused/unit/interfaces/agents/test_api_key_handling.py delete mode 100644 tests/unused/unit/interfaces/skills/custom/text2sql/test_mindsdb_kb_tools.py delete mode 100644 tests/unused/unit/ml_handlers/conftest.py delete mode 100644 tests/unused/unit/ml_handlers/data/anomaly_detection.csv delete mode 100644 tests/unused/unit/ml_handlers/data/house_sales.csv delete mode 100644 tests/unused/unit/ml_handlers/data/movies.csv delete mode 100644 tests/unused/unit/ml_handlers/data/ratings.csv delete mode 100755 tests/unused/unit/ml_handlers/data/vertex_anomaly_detection.csv delete mode 100644 tests/unused/unit/ml_handlers/data/vertex_classification.csv delete mode 100644 tests/unused/unit/ml_handlers/data/vertex_regression.csv delete mode 100644 tests/unused/unit/ml_handlers/test_anomaly_detection.py delete mode 100644 tests/unused/unit/ml_handlers/test_anthropic.py delete mode 100644 tests/unused/unit/ml_handlers/test_autogluon.py delete mode 100644 tests/unused/unit/ml_handlers/test_autokeras.py delete mode 100644 tests/unused/unit/ml_handlers/test_clipdrop.py delete mode 100644 tests/unused/unit/ml_handlers/test_dspy.py delete mode 100644 tests/unused/unit/ml_handlers/test_google_gemini.py delete mode 100644 tests/unused/unit/ml_handlers/test_huggingface.py delete mode 100644 tests/unused/unit/ml_handlers/test_huggingface_api.py delete mode 100644 tests/unused/unit/ml_handlers/test_langchain.py delete mode 100644 tests/unused/unit/ml_handlers/test_langchain_embedding.py delete mode 100644 tests/unused/unit/ml_handlers/test_leonardo_ai.py delete mode 100644 tests/unused/unit/ml_handlers/test_lightfm.py delete mode 100644 tests/unused/unit/ml_handlers/test_lightwood.py delete mode 100644 tests/unused/unit/ml_handlers/test_ludwig.py delete mode 100644 tests/unused/unit/ml_handlers/test_merlion_handler.py delete mode 100644 tests/unused/unit/ml_handlers/test_mlflow.py delete mode 100644 tests/unused/unit/ml_handlers/test_neuralforecast.py delete mode 100644 tests/unused/unit/ml_handlers/test_popularity_recommender.py delete mode 100644 tests/unused/unit/ml_handlers/test_rag.py delete mode 100644 tests/unused/unit/ml_handlers/test_spacy.py delete mode 100644 tests/unused/unit/ml_handlers/test_stabilityai.py delete mode 100644 tests/unused/unit/ml_handlers/test_statsforecast.py delete mode 100644 tests/unused/unit/ml_handlers/test_time_series_utils.py delete mode 100644 tests/unused/unit/ml_handlers/test_unify.py delete mode 100644 tests/unused/unit/ml_handlers/test_vertex.py delete mode 100644 tests/unused/unit/ml_handlers/test_writer.py diff --git a/tests/unused/unit/handler_tests/test_rag_pipelines.py b/tests/unused/unit/handler_tests/test_rag_pipelines.py deleted file mode 100644 index d2f884b8322..00000000000 --- a/tests/unused/unit/handler_tests/test_rag_pipelines.py +++ /dev/null @@ -1,53 +0,0 @@ -import pytest -import yaml -from langchain_core.documents import Document -from langchain_openai import ChatOpenAI, OpenAIEmbeddings - -from mindsdb.integrations.utilities.rag.rag_pipeline_builder import RAG -from pathlib import Path - -from mindsdb.integrations.utilities.rag.settings import DEFAULT_LLM_MODEL, RAGPipelineModel - -DEFAULT_LLM = ChatOpenAI(model_name=DEFAULT_LLM_MODEL, temperature=0) -DEFAULT_EMBEDDINGS = OpenAIEmbeddings() - -path = Path(__file__).parent -config_path = path / "data" / "rag_pipelines" -pipeline_configs = list(config_path.glob('*.yml')) - - -def create_test_documents(): - return [ - Document( - page_content="This is a test document", - metadata={"doc_id": "1"} - ), - Document( - page_content="This is also a test document", - metadata={"doc_id": "2"} - ), - Document( - page_content="This is another test document", - metadata={"doc_id": "3"} - ) - ] - - -@pytest.fixture(params=pipeline_configs, ids=lambda x: x.stem, scope='module') -def config(request): - with open(request.param, 'r') as file: - config = yaml.safe_load(file) - config['documents'] = create_test_documents() - config['llm'] = DEFAULT_LLM - config['embedding_model'] = DEFAULT_EMBEDDINGS - - return RAGPipelineModel(**config) - - -def test_rag_pipeline_creation(config): - rag = RAG(config) - result = rag.pipeline.invoke('test document') - - assert result is not None - assert isinstance(result, dict) - assert all(key in result for key in ['answer', 'context', 'question']) diff --git a/tests/unused/unit/handler_tests/test_rocket_chat_handler.py b/tests/unused/unit/handler_tests/test_rocket_chat_handler.py deleted file mode 100644 index 575ab17ab9a..00000000000 --- a/tests/unused/unit/handler_tests/test_rocket_chat_handler.py +++ /dev/null @@ -1,96 +0,0 @@ -from mindsdb.integrations.handlers.rocket_chat_handler.rocket_chat_tables import ( - RocketChatMessagesTable, -) -from mindsdb.integrations.handlers.rocket_chat_handler.rocket_chat_handler import ( - RocketChatHandler, -) -from mindsdb_sql_parser import ast -from mindsdb_sql_parser.ast.select.star import Star -from mindsdb_sql_parser.ast.select.identifier import Identifier - -from unittest.mock import Mock - -import pandas as pd -import unittest - - -class RocketChatMessagesTableTest(unittest.TestCase): - def test_get_columns_returns_all_columns(self): - api_handler = Mock(RocketChatHandler) - messages_table = RocketChatMessagesTable(api_handler) - # Order matters. - expected_columns = [ - "id", - "room_id", - "bot_id", - "text", - "username", - "name", - "sent_at", - ] - self.assertListEqual(messages_table.get_columns(), expected_columns) - - def test_select_returns_all_columns(self): - api_handler = Mock(RocketChatHandler) - api_handler.call_rocket_chat_api.return_value = pd.DataFrame( - [ - [ - "message_id_1", # id - "GENERAL", # room_id - "bot_id_1", # bot_id - "YEWWWWW", # text - "shoresey", # username - "Shore Keeso", # name - "2023-05-05T00:31:46.825Z", # sent_at - ] - ] - ) - messages_table = RocketChatMessagesTable(api_handler) - - select_all = ast.Select( - targets=[Star()], from_table="channel_messages", where='room_id = "GENERAL"' - ) - - all_messages = messages_table.select(select_all) - first_message = all_messages.iloc[0] - - self.assertEqual(all_messages.shape[1], 7) - self.assertEqual(first_message["id"], "message_id_1") - self.assertEqual(first_message["room_id"], "GENERAL") - self.assertEqual(first_message["bot_id"], "bot_id_1") - self.assertEqual(first_message["text"], "YEWWWWW") - self.assertEqual(first_message["username"], "shoresey") - self.assertEqual(first_message["name"], "Shore Keeso") - self.assertEqual(first_message["sent_at"], "2023-05-05T00:31:46.825Z") - - def test_select_returns_only_selected_columns(self): - api_handler = Mock(RocketChatHandler) - api_handler.call_rocket_chat_api.return_value = pd.DataFrame( - [ - [ - "message_id_1", # id - "GENERAL", # room_id - "bot_id_1", # bot_id - "YEWWWWW", # text - "shoresey", # username - "Shore Keeso", # name - "2023-05-05T00:31:46.825Z", # sent_at - ] - ] - ) - messages_table = RocketChatMessagesTable(api_handler) - - room_id_identifier = Identifier(path_str="room_id") - text_identifier = Identifier(path_str="text") - select_basic = ast.Select( - targets=[room_id_identifier, text_identifier], - from_table="channel_messages", - where='room_id = "GENERAL"', - ) - - all_messages = messages_table.select(select_basic) - first_message = all_messages.iloc[0] - - self.assertEqual(all_messages.shape[1], 2) - self.assertEqual(first_message["room_id"], "GENERAL") - self.assertEqual(first_message["text"], "YEWWWWW") diff --git a/tests/unused/unit/handler_tests/test_sap_erp_handler.py b/tests/unused/unit/handler_tests/test_sap_erp_handler.py deleted file mode 100644 index 4568907c150..00000000000 --- a/tests/unused/unit/handler_tests/test_sap_erp_handler.py +++ /dev/null @@ -1,240 +0,0 @@ -import importlib -import os - -import pytest -from mindsdb_sql_parser import parse_sql - -from ..unit.executor_test_base import BaseExecutorTest - -try: - importlib.import_module("requests") - REQUESTS_INSTALLED = True -except ImportError: - REQUESTS_INSTALLED = False - - -@pytest.mark.skipif(not REQUESTS_INSTALLED, reason="requests package is not installed") -class TestSAPERPHandler(BaseExecutorTest): - - def run_sql(self, sql): - ret = self.command_executor.execute_command(parse_sql(sql)) - assert ret.error_code is None - if ret.data is not None: - return ret.data.to_df() - - def setup_method(self): - super().setup_method() - self.base_url = os.environ.get("SAP_ERP_BASE_URL") - self.api_key = os.environ.get("SAP_ERP_API_KEY") - self.run_sql(f""" - CREATE DATABASE sap_datasource - WITH ENGINE = "sap_erp", - PARAMETERS = {{ - "api_key": '{self.api_key}', - "base_url": '{self.base_url}' - }}; - """) - - def test_basic_select_from(self): - sql = """ - SELECT * FROM sap_datasource.address_email_address; - """ - self.run_sql(sql) - sql = """ - SELECT * FROM sap_datasource.address_fax_number; - """ - self.run_sql(sql) - sql = """ - SELECT * FROM sap_datasource.address_home_page; - """ - self.run_sql(sql) - sql = """ - SELECT * FROM sap_datasource.address_phone_number; - """ - self.run_sql(sql) - sql = """ - SELECT * FROM sap_datasource.bp_addr_depdnt_intl_loc_number; - """ - self.run_sql(sql) - sql = """ - SELECT * FROM sap_datasource.bp_contact_to_address; - """ - self.run_sql(sql) - sql = """ - SELECT * FROM sap_datasource.bp_contact_to_func_and_dept; - """ - self.run_sql(sql) - sql = """ - SELECT * FROM sap_datasource.bp_credit_worthiness; - """ - self.run_sql(sql) - sql = """ - SELECT * FROM sap_datasource.bp_data_controller; - """ - self.run_sql(sql) - sql = """ - SELECT * FROM sap_datasource.bp_financial_services_extn; - """ - self.run_sql(sql) - sql = """ - SELECT * FROM sap_datasource.bp_financial_services_reporting; - """ - self.run_sql(sql) - sql = """ - SELECT * FROM sap_datasource.bp_fiscal_year_information; - """ - self.run_sql(sql) - sql = """ - SELECT * FROM sap_datasource.bp_relationship; - """ - self.run_sql(sql) - sql = """ - SELECT * FROM sap_datasource.bu_pa_address_usage; - """ - self.run_sql(sql) - sql = """ - SELECT * FROM sap_datasource.bu_pa_identification; - """ - self.run_sql(sql) - sql = """ - SELECT * FROM sap_datasource.bu_pa_industry; - """ - self.run_sql(sql) - sql = """ - SELECT * FROM sap_datasource.business_partner; - """ - self.run_sql(sql) - sql = """ - SELECT * FROM sap_datasource.business_partner_address; - """ - self.run_sql(sql) - sql = """ - SELECT * FROM sap_datasource.business_partner_contact; - """ - self.run_sql(sql) - sql = """ - SELECT * FROM sap_datasource.business_partner_payment_card; - """ - self.run_sql(sql) - sql = """ - SELECT * FROM sap_datasource.business_partner_rating; - """ - self.run_sql(sql) - sql = """ - SELECT * FROM sap_datasource.business_partner_role; - """ - self.run_sql(sql) - sql = """ - SELECT * FROM sap_datasource.business_partner_tax_number; - """ - self.run_sql(sql) - sql = """ - SELECT * FROM sap_datasource.business_partner_address_dependent_tax_number; - """ - self.run_sql(sql) - sql = """ - SELECT * FROM sap_datasource.cust_addr_depdnt_ext_identifier; - """ - self.run_sql(sql) - sql = """ - SELECT * FROM sap_datasource.customer; - """ - self.run_sql(sql) - sql = """ - SELECT * FROM sap_datasource.customer_company; - """ - self.run_sql(sql) - sql = """ - SELECT * FROM sap_datasource.customer_company_text; - """ - self.run_sql(sql) - sql = """ - SELECT * FROM sap_datasource.customer_dunning; - """ - self.run_sql(sql) - sql = """ - SELECT * FROM sap_datasource.customer_sales_area; - """ - self.run_sql(sql) - sql = """ - SELECT * FROM sap_datasource.customer_sales_area_tax; - """ - self.run_sql(sql) - sql = """ - SELECT * FROM sap_datasource.customer_sales_area_text; - """ - self.run_sql(sql) - sql = """ - SELECT * FROM sap_datasource.customer_tax_grouping; - """ - self.run_sql(sql) - sql = """ - SELECT * FROM sap_datasource.customer_text; - """ - self.run_sql(sql) - sql = """ - SELECT * FROM sap_datasource.customer_unloading_point; - """ - self.run_sql(sql) - sql = """ - SELECT * FROM sap_datasource.customer_withholding_tax; - """ - self.run_sql(sql) - sql = """ - SELECT * FROM sap_datasource.customer_sales_partner_func; - """ - self.run_sql(sql) - sql = """ - SELECT * FROM sap_datasource.customer_sales_area_addr_depdnt_info; - """ - self.run_sql(sql) - sql = """ - SELECT * FROM sap_datasource.customer_sales_area_addr_depdnt_tax_info; - """ - self.run_sql(sql) - sql = """ - SELECT * FROM sap_datasource.customer_unloading_point_addr_depdnt_info; - """ - self.run_sql(sql) - sql = """ - SELECT * FROM sap_datasource.supplier; - """ - self.run_sql(sql) - sql = """ - SELECT * FROM sap_datasource.supplier_company; - """ - self.run_sql(sql) - sql = """ - SELECT * FROM sap_datasource.supplier_company_text; - """ - self.run_sql(sql) - sql = """ - SELECT * FROM sap_datasource.supplier_dunning; - """ - self.run_sql(sql) - sql = """ - SELECT * FROM sap_datasource.supplier_partner_func; - """ - self.run_sql(sql) - sql = """ - SELECT * FROM sap_datasource.supplier_purchasing_org; - """ - self.run_sql(sql) - sql = """ - SELECT * FROM sap_datasource.supplier_purchasing_org_text; - """ - self.run_sql(sql) - sql = """ - SELECT * FROM sap_datasource.supplier_text; - """ - self.run_sql(sql) - sql = """ - SELECT * FROM sap_datasource.supplier_withholding_tax; - """ - self.run_sql(sql) - - def test_complex_select(self): - sql = """ - SELECT AddressID FROM sap_datasource.address_email_address; - """ - assert self.run_sql(sql).shape[1] == 1 diff --git a/tests/unused/unit/handler_tests/test_storage_handler.py b/tests/unused/unit/handler_tests/test_storage_handler.py deleted file mode 100644 index 1aba0fd5a35..00000000000 --- a/tests/unused/unit/handler_tests/test_storage_handler.py +++ /dev/null @@ -1,23 +0,0 @@ -import unittest - -from mindsdb.utilities.config import Config -from mindsdb.integrations.libs.storage_handler import RedisStorageHandler, SqliteStorageHandler - - -class StorageHandlerTest(unittest.TestCase): - def test_1_redis_storage(self): - store = RedisStorageHandler({'test_1_redis_storage': 'value'}, config={'host': 'localhost', 'port': '6379'}) - store.set('test_key', 42) - self.assertTrue(store.get('test_key') == 42) - self.assertRaises(Exception, store.get('test_key2')) - - def test_2_sqlite_storage(self): - config = Config() - name = 'test_2_sqlite_storage' - store = SqliteStorageHandler(context=name, config={ - 'path': config['paths']['root'], - 'name': name - }) - store.set('test_key', 42) - self.assertTrue(store.get('test_key') == 42) - self.assertRaises(Exception, store.get('test_key2')) diff --git a/tests/unused/unit/handler_tests/test_symbl_handler.py b/tests/unused/unit/handler_tests/test_symbl_handler.py deleted file mode 100644 index 2911d433674..00000000000 --- a/tests/unused/unit/handler_tests/test_symbl_handler.py +++ /dev/null @@ -1,57 +0,0 @@ -import importlib -import os -import pytest -from mindsdb_sql_parser import parse_sql - -from ..unit.executor_test_base import BaseExecutorTest - -try: - importlib.import_module("symbl") - SYMBL_INSTALLED = True -except ImportError: - SYMBL_INSTALLED = False - - -@pytest.mark.skipif(not SYMBL_INSTALLED, reason="symbl package is not installed") -class TestSymblAPIHandler(BaseExecutorTest): - - def run_sql(self, sql): - ret = self.command_executor.execute_command(parse_sql(sql)) - assert ret.error_code is None - if ret.data is not None: - return ret.data.to_df() - - def setup_method(self): - super().setup_method() - self.app_id = os.environ.get("SYMBL_APP_ID") - self.app_secret = os.environ.get("SYMBL_APP_SECRET") - self.run_sql(f""" - CREATE DATABASE mindsdb_symbl - WITH ENGINE = 'symbl', - PARAMETERS = { - "app_id": '{self.app_id}', - "app_secret": '{self.app_secret}' - }; - """) - - def test_basic_select_from(self): - - conversation_id = "5682305049034752" - - sql = f'SELECT * FROM mindsdb_symbl.get_messages where conversation_id="{conversation_id}"' - self.run_sql(sql) - - sql = f'SELECT * FROM mindsdb_symbl.get_topics where conversation_id="{conversation_id}"' - self.run_sql(sql) - - sql = f'SELECT * FROM mindsdb_symbl.get_questions where conversation_id="{conversation_id}"' - self.run_sql(sql) - - sql = f'SELECT * FROM mindsdb_symbl.get_analytics where conversation_id="{conversation_id}"' - self.run_sql(sql) - - sql = f'SELECT * FROM mindsdb_symbl.get_action_items where conversation_id="{conversation_id}"' - self.run_sql(sql) - - sql = f'SELECT * FROM mindsdb_symbl.get_follow_ups where conversation_id="{conversation_id}"' - self.run_sql(sql) diff --git a/tests/unused/unit/handler_tests/test_tripadvisor_handler.py b/tests/unused/unit/handler_tests/test_tripadvisor_handler.py deleted file mode 100644 index 51d7a02b833..00000000000 --- a/tests/unused/unit/handler_tests/test_tripadvisor_handler.py +++ /dev/null @@ -1,324 +0,0 @@ -from mindsdb.integrations.handlers.tripadvisor_handler.tripadvisor_handler import ( - TripAdvisorHandler, -) - -from mindsdb.integrations.handlers.tripadvisor_handler.tripadvisor_table import ( - SearchLocationTable, - LocationDetailsTable, - ReviewsTable, - PhotosTable, - NearbyLocationTable, -) - -from mindsdb_sql_parser import ast -from mindsdb_sql_parser.ast.select.star import Star -from mindsdb_sql_parser.ast.select.identifier import Identifier - -from unittest.mock import Mock - -import pandas as pd -import unittest - - -class SearchLocationTableTest(unittest.TestCase): - def test_get_columns_returns_all_columns(self): - api_handler = Mock(TripAdvisorHandler) - trades_table = SearchLocationTable(api_handler) - # Order matters. - expected_columns = [ - "location_id", - "name", - "distance", - "rating", - "bearing", - "street1", - "street2", - "city", - "state", - "country", - "postalcode", - "address_string", - "phone", - "latitude", - "longitude", - ] - self.assertListEqual(trades_table.get_columns(), expected_columns) - - def test_select_returns_some_columns(self): - api_handler = Mock(TripAdvisorHandler) - api_handler.call_tripadvisor_searchlocation_api.return_value = pd.DataFrame( - [ - [ - "186338", # locationId - "London", # name - "United Kingdom", # country - "London England", # address_string - ] - ] - ) - tripadvisor_table = SearchLocationTable(api_handler) - - select_all = ast.Select( - targets=[Star()], - from_table="searchLocationTable", - where='searchQuery = "London"', - ) - - all_location_data = tripadvisor_table.select(select_all) - first_data = all_location_data.iloc[0] - - self.assertEqual(first_data["locationId"], "186338") - self.assertEqual(first_data["name"], "London") - self.assertEqual(first_data["country"], "United Kingdom") - self.assertEqual(first_data["address_string"], "London England") - - -class LocationDetailsTableTest(unittest.TestCase): - def test_get_columns_returns_all_columns(self): - api_handler = Mock(TripAdvisorHandler) - trades_table = LocationDetailsTable(api_handler) - # Order matters. - expected_columns = [ - "location_id", - "distance", - "name", - "description", - "web_url", - "street1", - "street2", - "city", - "state", - "country", - "postalcode", - "address_string", - "latitude", - "longitude", - "timezone", - "email", - "phone", - "website", - "write_review", - "ranking_data", - "rating", - "rating_image_url", - "num_reviews", - "photo_count", - "see_all_photos", - "price_level", - "brand", - "parent_brand", - "ancestors", - "periods", - "weekday", - "features", - "cuisines", - "amenities", - "trip_types", - "styles", - "awards", - "neighborhood_info", - "parent_brand", - "brand", - "groups", - ] - self.assertListEqual(trades_table.get_columns(), expected_columns) - - def test_select_returns_some_columns(self): - api_handler = Mock(TripAdvisorHandler) - api_handler.call_tripadvisor_searchlocation_api.return_value = pd.DataFrame( - [ - [ - "23322232", # locationId - "La Polleria Alicante", # name - "We are revolutionizing Alicante! Come and try the waffle that is on everyone's mouth. Come and get your #pollofre or #pollolo, we are waiting for you!", # description - "https://www.tripadvisor.com/Restaurant_Review-g1064230-d23322232-Reviews-La_Polleria_Alicante-Alicante_Costa_Blanca_Province_of_Alicante_Valencian_Commu.html?m=66827", # web_url - ] - ] - ) - - tripadvisor_table = LocationDetailsTable(api_handler) - - select_all = ast.Select( - targets=[Star()], - from_table="locationDetailsTable", - where='searchQuery = "23322232"', - ) - - all_location_data = tripadvisor_table.select(select_all) - first_data = all_location_data.iloc[0] - - self.assertEqual(first_data["locationId"], "23322232") - self.assertEqual(first_data["name"], "La Polleria Alicante") - self.assertEqual( - first_data["description"], - "We are revolutionizing Alicante! Come and try the waffle that is on everyone's mouth. Come and get your #pollofre or #pollolo, we are waiting for you!", - ) - self.assertEqual( - first_data["web_url"], - "https://www.tripadvisor.com/Restaurant_Review-g1064230-d23322232-Reviews-La_Polleria_Alicante-Alicante_Costa_Blanca_Province_of_Alicante_Valencian_Commu.html?m=66827", - ) - - -class ReviewTableTest(unittest.TestCase): - def test_get_columns_returns_all_columns(self): - api_handler = Mock(TripAdvisorHandler) - trades_table = ReviewsTable(api_handler) - # Order matters. - expected_columns = [ - "id", - "lang", - "location_id", - "published_date", - "rating", - "helpful_votes", - "rating_image_url", - "url", - "trip_type", - "travel_date", - "text_review", - "title", - "owner_response", - "is_machine_translated", - "user", - "subratings", - ] - self.assertListEqual(trades_table.get_columns(), expected_columns) - - def test_select_returns_some_columns(self): - api_handler = Mock(TripAdvisorHandler) - api_handler.call_tripadvisor_searchlocation_api.return_value = pd.DataFrame( - [ - [ - "921095426", # id - "en", # lang - "99288", # location_id - "2023-10-13T09:48:46Z", # published_date - "1", # rating - "Check in is at 4:00 - my room wasn't ready until 9:00. I had no A/C on my first night and it was too late for engineering to fix it. I was offered a $40 discount from some ridiculous hoteL fee - that was a joke on a 700/night stay. I would not recommend this place at all.", # text review - "POOR CHECK -IN - NO A/C AND NO DISCOUNT", # title - ] - ] - ) - tripadvisor_table = ReviewsTable(api_handler) - - id_identifier = Identifier(path_str='id') - lang_identifier = Identifier(path_str='en') - location_id_identifier = Identifier(path_str='location_id') - published_date_identifier = Identifier(path_str='published_date') - rating_identifier = Identifier(path_str='rating') - text_review_identifier = Identifier(path_str='room_id') - title_identifier = Identifier(path_str='text') - select_all = ast.Select( - targets=[id_identifier, lang_identifier, location_id_identifier, published_date_identifier, rating_identifier, text_review_identifier, title_identifier], - from_table="reviewsTable", - where='locationId = "99288"', - ) - - review_data = tripadvisor_table.select(select_all) - first_data = review_data.iloc[0] - - self.assertEqual(review_data.shape[1], 7) - self.assertEqual(first_data["id"], "921095426") - self.assertEqual(first_data["en"], "en") - self.assertEqual(first_data["rating"], "1") - self.assertEqual(first_data["title"], "POOR CHECK -IN - NO A/C AND NO DISCOUNT") - - -class PhotosTableTest(unittest.TestCase): - def test_get_columns_returns_all_columns(self): - api_handler = Mock(TripAdvisorHandler) - trades_table = PhotosTable(api_handler) - # Order matters. - expected_columns = [ - "id", - "is_blessed", - "album", - "caption", - "published_date", - "images", - "source", - "user", - ] - self.assertListEqual(trades_table.get_columns(), expected_columns) - - def test_select_returns_some_columns(self): - api_handler = Mock(TripAdvisorHandler) - api_handler.call_tripadvisor_searchlocation_api.return_value = pd.DataFrame( - [ - [ - "673312657", # id - "false", # is_blessed - "Hotel & Grounds", # album - "{'name': 'Management', 'localized_name': 'Management'}", # source - ] - ] - ) - tripadvisor_table = PhotosTable(api_handler) - - id_identifier = Identifier(path_str='id') - is_blessed_identifier = Identifier(path_str='is_blessed') - album_identifier = Identifier(path_str='album') - source_identifier = Identifier(path_str='source') - select_all = ast.Select( - targets=[id_identifier, is_blessed_identifier, album_identifier, source_identifier], - from_table="photosTable", - where='locationId = "99288"', - ) - - all_location_data = tripadvisor_table.select(select_all) - first_data = all_location_data.iloc[0] - - self.assertEqual(all_location_data.shape[1], 4) - self.assertEqual(first_data["id"], "673312657") - self.assertEqual(first_data["is_blessed"], "false") - self.assertEqual(first_data["album"], "Hotel & Grounds") - self.assertEqual(first_data["source"], "{'name': 'Management', 'localized_name': 'Management'}") - - -class NearbySearchTableTest(unittest.TestCase): - def test_get_columns_returns_all_columns(self): - api_handler = Mock(TripAdvisorHandler) - trades_table = NearbyLocationTable(api_handler) - # Order matters. - expected_columns = [ - "location_id", - "name", - "distance", - "rating", - "bearing", - "address_obj", - ] - self.assertListEqual(trades_table.get_columns(), expected_columns) - - def test_select_returns_some_columns(self): - api_handler = Mock(TripAdvisorHandler) - api_handler.call_tripadvisor_searchlocation_api.return_value = pd.DataFrame( - [ - [ - "210108", # location_id - "American Museum of Natural History", # name - "0.039615104835680856", # distance - "{'street1': '79th Street', 'street2': 'Central Park West', 'city': 'New York City', 'state': 'New York', 'country': 'United States', 'postalcode': '10024', 'address_string': '79th Street Central Park West, New York City, NY 10024'}", # address_obj - ] - ] - ) - tripadvisor_table = NearbyLocationTable(api_handler) - - location_id_identifier = Identifier(path_str='location_id') - name_identifier = Identifier(path_str='name') - distance_identifier = Identifier(path_str='distance') - address_obj_identifier = Identifier(path_str='address_obj') - select_all = ast.Select( - targets=[location_id_identifier, name_identifier, distance_identifier, address_obj_identifier], - from_table="nearbyLocationTable", - where='latLong = "40.780825, -73.972781"', - ) - - all_location_data = tripadvisor_table.select(select_all) - first_data = all_location_data.iloc[0] - - self.assertEqual(all_location_data.shape[1], 4) - self.assertEqual(first_data["location_id"], "210108") - self.assertEqual(first_data["name"], "American Museum of Natural History") - self.assertEqual(first_data["distance"], "0.039615104835680856") - self.assertEqual(first_data["address_obj"], "{'street1': '79th Street', 'street2': 'Central Park West', 'city': 'New York City', 'state': 'New York', 'country': 'United States', 'postalcode': '10024', 'address_string': '79th Street Central Park West, New York City, NY 10024'}") diff --git a/tests/unused/unit/handler_tests/test_vectordatabase_dispatch.py b/tests/unused/unit/handler_tests/test_vectordatabase_dispatch.py deleted file mode 100644 index 3bf6b2d6b9a..00000000000 --- a/tests/unused/unit/handler_tests/test_vectordatabase_dispatch.py +++ /dev/null @@ -1,282 +0,0 @@ -from unittest.mock import Mock - -import pandas as pd -import pytest -from mindsdb_sql_parser import parse_sql -from pandas.testing import assert_frame_equal - -from mindsdb.integrations.libs.vectordatabase_handler import ( - FilterCondition, - FilterOperator, - VectorStoreHandler, -) - - -@pytest.fixture -def vector_store_handler(): - # patch the actual "execute" methods of the handler with Mock - vector_store_handler: VectorStoreHandler = VectorStoreHandler("test") - vector_store_handler.create_table = Mock() - vector_store_handler.drop_table = Mock() - vector_store_handler.insert = Mock() - vector_store_handler.update = Mock() - vector_store_handler.delete = Mock() - vector_store_handler.select = Mock() - - return vector_store_handler - - -def test_vectordatabase_parsing(vector_store_handler): - # create a table - # due to the limitation of the parser - # we can only create a table with a select statement - sql = """ - CREATE TABLE chroma_db.test_table ( - SELECT * - FROM chroma_db.test_table - ) - """ - query = parse_sql(sql) - vector_store_handler._dispatch(query) - vector_store_handler.create_table.assert_called_once() - vector_store_handler.create_table.assert_called_with( - "test_table", if_not_exists=False - ) - - # drop a table - sql = """ - DROP TABLE chroma_db.test_table - """ - query = parse_sql(sql) - vector_store_handler._dispatch(query) - vector_store_handler.drop_table.assert_called_once() - vector_store_handler.drop_table.assert_called_with("test_table", if_exists=False) - - # insert into a table - sql = """ - INSERT INTO chroma_db.test_table ( - id,content,metadata,embeddings - ) - VALUES ( - 1, 'test', '{"some_field": "some_value"}', '[1,2,3]' - ), - ( - 2, 'test', '{"some_field": "some_value"}', '[1,2,3]' - ) - """ - - data = pd.DataFrame( - { - "id": [1, 2], - "content": ["test", "test"], - "embeddings": [[1, 2, 3], [1, 2, 3]], - "metadata": [{"some_field": "some_value"}, {"some_field": "some_value"}], - } - ) - - query = parse_sql(sql) - vector_store_handler._dispatch(query) - vector_store_handler.insert.assert_called_once() - # get the args passed to the insert method - args, kwargs = vector_store_handler.insert.call_args - # get the data passed to the insert method - assert args[0] == "test_table" - data = args[1] - # assert the data is the same - assert_frame_equal(data, data) - assert kwargs["columns"] == ["id", "content", "metadata", "embeddings"] - - # select from a table - # select without filters - sql = """ - SELECT * - FROM chroma_db.test_table - """ - query = parse_sql(sql) - vector_store_handler._dispatch(query) - vector_store_handler.select.assert_called_once() - vector_store_handler.select.assert_called_with( - "test_table", - columns=["id", "content", "embeddings", "metadata"], - conditions=None, - offset=None, - limit=None, - ) - # select with search_vector filter - sql = """ - SELECT * - FROM chroma_db.test_table - WHERE search_vector = '[1, 2, 3]' - LIMIT 10 - """ - query = parse_sql(sql) - # reset the mock - vector_store_handler.select.reset_mock() - vector_store_handler._dispatch(query) - vector_store_handler.select.assert_called_once() - vector_store_handler.select.assert_called_with( - "test_table", - columns=["id", "content", "embeddings", "metadata"], - conditions=[ - FilterCondition( - column="search_vector", op=FilterOperator.EQUAL, value=[1, 2, 3] - ) - ], - limit=10, - offset=None, - ) - - # select with limit and offset - sql = """ - SELECT * - FROM chroma_db.test_table - LIMIT 10 - OFFSET 5 - """ - query = parse_sql(sql) - # reset the mock - vector_store_handler.select.reset_mock() - vector_store_handler._dispatch(query) - vector_store_handler.select.assert_called_once() - vector_store_handler.select.assert_called_with( - "test_table", - columns=["id", "content", "embeddings", "metadata"], - conditions=None, - limit=10, - offset=5, - ) - - # select with a subset of columns - sql = """ - SELECT id, content - FROM chroma_db.test_table - """ - query = parse_sql(sql) - # reset the mock - vector_store_handler.select.reset_mock() - vector_store_handler._dispatch(query) - vector_store_handler.select.assert_called_once() - vector_store_handler.select.assert_called_with( - "test_table", - columns=["id", "content"], - conditions=None, - limit=None, - offset=None, - ) - - # select with metadata filter - sql = """ - SELECT * - FROM chroma_db.test_table - WHERE metadata.created_at = '2021-01-01' - AND metadata.some_field in ('some_value', 'some_other_value') - AND search_vector = '[1, 2, 3]' - """ - query = parse_sql(sql) - # reset the mock - vector_store_handler.select.reset_mock() - vector_store_handler._dispatch(query) - vector_store_handler.select.assert_called_once() - vector_store_handler.select.assert_called_with( - "test_table", - columns=["id", "content", "embeddings", "metadata"], - conditions=[ - FilterCondition( - column="metadata.created_at", - op=FilterOperator.EQUAL, - value="2021-01-01", - ), - FilterCondition( - column="metadata.some_field", - op=FilterOperator.IN, - value=["some_value", "some_other_value"], - ), - FilterCondition( - column="search_vector", op=FilterOperator.EQUAL, value=[1, 2, 3] - ), - ], - limit=None, - offset=None, - ) - - # delete from a table - sql = """ - DELETE FROM chroma_db.test_table - WHERE id = 1 - """ - query = parse_sql(sql) - vector_store_handler._dispatch(query) - vector_store_handler.delete.assert_called_once() - vector_store_handler.delete.assert_called_with( - "test_table", - conditions=[FilterCondition(column="id", op=FilterOperator.EQUAL, value=1)], - ) - - -def test_unsupported_ops(vector_store_handler): - # select unsupported columns - sql = """ - SELECT id, some_column_not_supported - FROM chroma_db.test_table - """ - query = parse_sql(sql) - with pytest.raises(Exception) as e: - vector_store_handler._dispatch(query) - assert "not allowed" in str(e.value) - - # insert unsupported columns - sql = """ - INSERT INTO chroma_db.test_table ( - id, some_column_not_supported - ) - VALUES ( - 1, 'test' - ) - """ - query = parse_sql(sql) - with pytest.raises(Exception) as e: - vector_store_handler._dispatch(query) - assert "not allowed" in str(e.value) - - # unsupported filter - sql = """ - SELECT * - FROM chroma_db.test_table - WHERE metadata.created_at > '2021-01-01' - AND unknown_column = 'some_value' - """ - query = parse_sql(sql) - # reset the mock - vector_store_handler.select.reset_mock() - vector_store_handler._dispatch(query) - vector_store_handler.select.assert_called_once() - vector_store_handler.select.assert_called_with( - "test_table", - columns=["id", "content", "embeddings", "metadata"], - conditions=[ - FilterCondition( - column="metadata.created_at", - op=FilterOperator.GREATER_THAN, - value="2021-01-01", - ), - FilterCondition( - column="metadata.unknown_column", # we will treat this as a metadata filter - op=FilterOperator.EQUAL, - value="some_value", - ), - ], - limit=None, - offset=None, - ) - - -@pytest.mark.xfail(reason="not implemented yet") -def test_unimplemented_yet(vector_store_handler): - # select count(*) is not implemented yet - sql = """ - SELECT count(*) - FROM chroma_db.test_table - """ - query = parse_sql(sql) - with pytest.raises(Exception): - vector_store_handler._dispatch(query) diff --git a/tests/unused/unit/handler_tests/test_weaviate_handler.py b/tests/unused/unit/handler_tests/test_weaviate_handler.py deleted file mode 100644 index cf71e1dbc7f..00000000000 --- a/tests/unused/unit/handler_tests/test_weaviate_handler.py +++ /dev/null @@ -1,503 +0,0 @@ -# check if weaviate is installed -import re -import importlib -from unittest.mock import patch -import tempfile -import psutil -import pandas as pd -import pytest -from mindsdb_sql_parser import parse_sql - -from ..unit.executor_test_base import BaseExecutorTest - -try: - importlib.import_module("weaviate") - WEAVIATE_INSTALLED = True -except ImportError: - WEAVIATE_INSTALLED = False - - -@pytest.mark.skipif(not WEAVIATE_INSTALLED, reason="weaviate is not installed") -class TestWeaviateHandler(BaseExecutorTest): - def run_sql(self, sql): - ret = self.command_executor.execute_command(parse_sql(sql)) - - assert ret.error_code is None - if ret.data is not None: - return ret.data.to_df() - - def setup_method(self): - super().setup_method() - # create a weaviate database connection - tmp_directory = tempfile.mkdtemp() - self.run_sql( - f""" - CREATE DATABASE weaviate_test - WITH ENGINE = "weaviate", - PARAMETERS = {{ - "persistence_directory": "{tmp_directory}" - }} - """ - ) - - @staticmethod - def teardown_class(cls): - super().teardown_class(cls) - for proc in psutil.process_iter(): - # check whether the process name matches (kill orphan processes) - if re.search("weaviate*", proc.name()): - proc.kill() - - @pytest.mark.xfail(reason="create table for vectordatabase is not well supported") - @patch("mindsdb.integrations.handlers.postgres_handler.Handler") - def test_create_table(self, postgres_handler_mock): - # create an empty table - sql = """ - CREATE TABLE weaviate_test.test_table; - """ - self.run_sql(sql) - - # create a table with the schema definition is not allowed - sql = """ - CREATE TABLE weaviate_test.test_table ( - id int, - metadata text, - embedding float[] - ); - """ - with pytest.raises(Exception): - self.run_sql(sql) - - @patch("mindsdb.integrations.handlers.postgres_handler.Handler") - def test_create_with_select(self, postgres_handler_mock): - df = pd.DataFrame( - { - "id": [ - "6af613b6-569c-5c22-9c37-2ed93f31d3af", - "b04965e6-a9bb-591f-8f8a-1adcb2c8dc39", - ], - "content": ["this is a test", "this is a test"], - "metadata": [{"test": "test"}, {"test": "test"}], - "embeddings": [[1.0, 2.0, 3.0], [1.0, 2.0, 3.0]], - } - ) - - self.set_handler(postgres_handler_mock, "weaviate", tables={"test_table2": df}) - - sql = """ - CREATE TABLE weaviate_test.test_table2 ( - SELECT * FROM weaviate.df - ) - """ - # this should work - self.run_sql(sql) - - @pytest.mark.xfail(reason="drop table for vectordatabase is not working") - @patch("mindsdb.integrations.handlers.postgres_handler.Handler") - def test_drop_table(self, postgres_handler_mock): - df = pd.DataFrame( - { - "id": [ - "4b166dbe-d99d-5091-abdd-95b83330ed3a", - "98123fde-012f-5ff3-8b50-881449dac91a", - ], - "content": ["this is a test", "this is a test"], - "metadata": [{"test": "test"}, {"test": "test"}], - "embeddings": [[1.0, 2.0, 3.0], [1.0, 2.0, 3.0]], - } - ) - self.set_handler(postgres_handler_mock, "weaviate", tables={"test_table3": df}) - - # create a table - sql = """ - CREATE TABLE weaviate_test.test_table3 ( - SELECT * FROM weaviate.df - ) - """ - with pytest.raises(Exception): - self.run_sql(sql) - - # drop a table - sql = """ - DROP TABLE weaviate_test.test_table3; - """ - self.run_sql(sql) - - # drop a non existent table will raise an error - sql = """ - DROP TABLE weaviate_test.test_table4; - """ - with pytest.raises(Exception): - self.run_sql(sql) - - @patch("mindsdb.integrations.handlers.postgres_handler.Handler") - def test_insert_into(self, postgres_handler_mock): - df = pd.DataFrame( - { - "id": [ - "6ed955c6-506a-5343-9be4-2c0afae02eef", - "c8691da2-158a-5ed6-8537-0e6f140801f2", - "a6c4fc8f-6950-51de-a9ae-2c519c465071", - ], - "content": ["this is a test", "this is a test", "this is a test"], - "metadata": [{"test": "test1"}, {"test": "test2"}, {"test": "test3"}], - "embeddings": [[1.0, 2.0, 3.0], [1.0, 2.0, 3.0], [1.0, 2.0, 3.0]], - } - ) - df2 = pd.DataFrame( - { - "id": [ - "a9f96b98-dd44-5216-ab0d-dbfc6b262edf", - "e99caacd-6c45-5906-bd9f-b79e62f25963", - "e4d80b30-151e-51b5-9f4f-18a3b82718e6", - ], - "content": ["this is a test", "this is a test", "this is a test"], - "metadata": [{"test": "test1"}, {"test": "test2"}, {"test": "test3"}], - "embeddings": [ - [1.0, 2.0, 3.0, 4.0], - [1.0, 2.0], - [1.0, 2.0, 3.0], - ], # different dimensions - } - ) - self.set_handler( - postgres_handler_mock, "weaviate", tables={"df": df, "df2": df2} - ) - num_record = df.shape[0] - - # create a table - sql = """ - CREATE TABLE weaviate_test.test_table5 ( - SELECT * FROM weaviate.df - ) - """ - self.run_sql(sql) - - # insert into a table with values - sql = """ - INSERT INTO weaviate_test.test_table5 ( - id,content,metadata,embeddings - ) - VALUES ( - '0159d6c7-973f-5e7a-a9a0-d195d0ea6fe2', 'this is a test', '{"test": "test"}', '[1.0, 2.0, 3.0]' - ) - """ - self.run_sql(sql) - # check if the data is inserted - sql = """ - SELECT * FROM weaviate_test.test_table5 - WHERE id = '0159d6c7-973f-5e7a-a9a0-d195d0ea6fe2' - """ - ret = self.run_sql(sql) - assert ret.shape[0] == 1 - - # insert without specifying id should also work - sql = """ - INSERT INTO weaviate_test.test_table5 ( - content,metadata,embeddings - ) - VALUES ( - 'this is a test', '{"test": "test"}', '[1.0, 2.0, 3.0]' - ) - """ - self.run_sql(sql) - # check if the data is inserted - sql = """ - SELECT * FROM weaviate_test.test_table5 - """ - ret = self.run_sql(sql) - assert ret.shape[0] == num_record + 2 - - # insert into a table with a select statement - sql = """ - INSERT INTO weaviate_test.test_table5 ( - content,metadata,embeddings - ) - SELECT - content,metadata,embeddings - FROM - weaviate.df - """ - self.run_sql(sql) - # check if the data is inserted - sql = """ - SELECT * FROM weaviate_test.test_table5 - """ - ret = self.run_sql(sql) - assert ret.shape[0] == num_record * 2 + 2 - - # insert into a table with a select statement, but wrong columns - with pytest.raises(Exception): - sql = """ - INSERT INTO weaviate_test.test_table5 - SELECT - content,metadata,embeddings as wrong_column - FROM - weaviate.df - """ - self.run_sql(sql) - - # insert into a table with a select statement, missing metadata column - sql = """ - INSERT INTO weaviate_test.test_table5 - SELECT - content,embeddings - FROM - weaviate.df - """ - self.run_sql(sql) - - # insert into a table with a select statement, missing embedding column, shall raise an error - with pytest.raises(Exception): - sql = """ - INSERT INTO weaviate_test.test_table5 - SELECT - content,metadata - FROM - weaviate.df - """ - self.run_sql(sql) - - # insert into a table with a select statement, with different embedding dimensions, shall raise an error - sql = """ - INSERT INTO weaviate_test.test_table5 - SELECT - content,metadata,embeddings - FROM - weaviate.df2 - """ - with pytest.raises(Exception): - self.run_sql(sql) - - # insert into a table with existing id, shall raise an error - sql = """ - INSERT INTO weaviate_test.test_table5 ( - id,content,metadata,embeddings - ) - VALUES ( - '6ed955c6-506a-5343-9be4-2c0afae02eef', 'this is a test', '{"test": "test"}', '[1.0, 2.0, 3.0]' - ) - """ - with pytest.raises(Exception): - self.run_sql(sql) - - @patch("mindsdb.integrations.handlers.postgres_handler.Handler") - def test_select_from(self, postgres_handler_mock): - df = pd.DataFrame( - { - "id": [ - "7fef88f7-411d-5669-b42d-bf5fc7f9b58b", - "52524d6e-10dc-5261-aa36-8b2efcbaa5f0", - ], - "content": ["this is a test", "this is a test"], - "metadata": [{"test": "test"}, {"test": "test"}], - "embeddings": [[1.0, 2.0, 3.0], [1.0, 2.0, 3.0]], - } - ) - self.set_handler(postgres_handler_mock, "weaviate", tables={"test_table6": df}) - # create a table - sql = """ - CREATE TABLE weaviate_test.test_table6 ( - SELECT * FROM weaviate.df - ) - """ - self.run_sql(sql) - - # query a table without any filters - sql = """ - SELECT * FROM weaviate_test.test_table6 - """ - self.run_sql(sql) - - # query a table with id - sql = """ - SELECT * FROM weaviate_test.test_table6 - WHERE id = '7fef88f7-411d-5669-b42d-bf5fc7f9b58b' - """ - ret = self.run_sql(sql) - assert ret.shape[0] == 1 - - # query a table with a search vector, without limit - sql = """ - SELECT * FROM weaviate_test.test_table6 - WHERE search_vector = '[1.0, 2.0, 3.0]' - """ - ret = self.run_sql(sql) - assert ret.shape[0] == 2 - - # query a table with a search vector, with limit - sql = """ - SELECT * FROM weaviate_test.test_table6 - WHERE search_vector = '[1.0, 2.0, 3.0]' - LIMIT 1 - """ - ret = self.run_sql(sql) - assert ret.shape[0] == 1 - - # query a table with a metadata filter - sql = """ - SELECT * FROM weaviate_test.test_table6 - WHERE `metadata.test` = 'test' - """ - ret = self.run_sql(sql) - assert ret.shape[0] == 2 - - # query a table with a metadata filter and a search vector - sql = """ - SELECT * FROM weaviate_test.test_table6 - WHERE `metadata.test` = 'test' - AND search_vector = '[1.0, 2.0, 3.0]' - """ - ret = self.run_sql(sql) - assert ret.shape[0] == 2 - - @pytest.mark.xfail(reason="upsert for vectordatabase is not implemented") - def test_update(self): - # update a table with a metadata filter - sql = """ - UPDATE weaviate_test.test_table6 - SET `metadata.test` = 'test2' - WHERE `metadata.test` = 'test' - """ - self.run_sql(sql) - # check if the data is updated - sql = """ - SELECT * FROM weaviate_test.test_table6 - WHERE `metadata.test` = 'test2' - """ - ret = self.run_sql(sql) - assert ret.shape[0] == 2 - - # update the embeddings - sql = """ - UPDATE weaviate_test.test_table6 - SET embedding = [3.0, 2.0, 1.0] - WHERE `metadata.test` = 'test2' - """ - self.run_sql(sql) - # check if the data is updated - sql = """ - SELECT * FROM weaviate_test.test_table6 - WHERE `metadata.test` = 'test2' - """ - ret = self.run_sql(sql) - assert ret.shape[0] == 2 - assert ret.embedding[0] == [3.0, 2.0, 1.0] - - # update multiple columns - sql = """ - UPDATE weaviate_test.test_table6 - SET `metadata.test` = 'test3', - embedding = [1.0, 2.0, 3.0] - content = 'this is a test' - WHERE `metadata.test` = 'test2' - """ - self.run_sql(sql) - # check if the data is updated - sql = """ - SELECT * FROM weaviate_test.test_table6 - WHERE `metadata.test` = 'test3' - """ - ret = self.run_sql(sql) - assert ret.shape[0] == 2 - assert ret.embedding[0] == [1.0, 2.0, 3.0] - assert ret.content[0] == "this is a test" - - # update a table with a search vector filter is not allowed - sql = """ - UPDATE weaviate_test.test_table6 - SET `metadata.test = 'test2' - WHERE search_vector = [1.0, 2.0, 3.0] - """ - with pytest.raises(Exception): - self.run_sql(sql) - - # update a table without any filters is allowed - sql = """ - UPDATE weaviate_test.test_table6 - SET metadata.test = 'test3' - """ - self.run_sql(sql) - # check if the data is updated - sql = """ - SELECT * FROM weaviate_test.test_table6 - WHERE `metadata.test` = 'test3' - """ - ret = self.run_sql(sql) - assert ret.shape[0] == 2 - - # update a table with a search vector filter and a metadata filter is not allowed - sql = """ - UPDATE weaviate_test.test_table6 - SET metadata.test = 'test3' - WHERE metadata.test = 'test2' - AND search_vector = [1.0, 2.0, 3.0] - """ - with pytest.raises(Exception): - self.run_sql(sql) - - @patch("mindsdb.integrations.handlers.postgres_handler.Handler") - def test_delete(self, postgres_handler_mock): - df = pd.DataFrame( - { - "id": [ - "91c274f2-9a0d-5ce6-ac3d-7529f452df21", - "0ff1e264-520d-543a-87dd-181a491e667e", - ], - "content": ["this is a test", "this is a test"], - "metadata": [{"test": "test1"}, {"test": "test2"}], - "embeddings": [[1.0, 2.0, 3.0], [1.0, 2.0, 3.0]], - } - ) - self.set_handler(postgres_handler_mock, "weaviate", tables={"test_table7": df}) - - # create a table - sql = """ - CREATE TABLE weaviate_test.test_table7 ( - SELECT * FROM weaviate.df - ) - """ - self.run_sql(sql) - - # delete from a table with a metadata filter - sql = """ - DELETE FROM weaviate_test.test_table7 - WHERE `metadata.test` = 'test1' - """ - self.run_sql(sql) - # check if the data is deleted - sql = """ - SELECT * FROM weaviate_test.test_table7 - WHERE `metadata.test` = 'test2' - """ - ret = self.run_sql(sql) - assert ret.shape[0] == 1 - - # delete by id - sql = """ - DELETE FROM weaviate_test.test_table7 - WHERE id = '0ff1e264-520d-543a-87dd-181a491e667e' - """ - self.run_sql(sql) - # check if the data is deleted - sql = """ - SELECT * FROM weaviate_test.test_table7 - WHERE id = '0ff1e264-520d-543a-87dd-181a491e667e' - """ - ret = self.run_sql(sql) - assert ret.shape[0] == 0 - - # delete from a table with a search vector filter is not allowed - sql = """ - DELETE FROM weaviate_test.test_table7 - WHERE search_vector = [1.0, 2.0, 3.0] - """ - with pytest.raises(Exception): - self.run_sql(sql) - - # delete from a table without any filters is not allowed - sql = """ - DELETE FROM weaviate_test.test_table7 - """ - with pytest.raises(Exception): - self.run_sql(sql) diff --git a/tests/unused/unit/handler_tests/test_webz_handler.py b/tests/unused/unit/handler_tests/test_webz_handler.py deleted file mode 100644 index 6cc22fc7e69..00000000000 --- a/tests/unused/unit/handler_tests/test_webz_handler.py +++ /dev/null @@ -1,227 +0,0 @@ -import unittest -from unittest.mock import Mock - -import pandas as pd -from mindsdb_sql_parser import parse_sql - -from mindsdb.integrations.handlers.webz_handler.webz_handler import WebzHandler -from mindsdb.integrations.handlers.webz_handler.webz_tables import ( - WebzPostsTable, - WebzReviewsTable, -) - -COLUMNS_POST = [ - "thread__uuid", - "thread__url", - "thread__site_full", - "thread__site", - "thread__site_section", - "thread__section_title", - "thread__title", - "thread__title_full", - "thread__published", - "thread__replies_count", - "thread__participants_count", - "thread__site_type", - "thread__main_image", - "thread__country", - "thread__site_categories", - "thread__social__facebook__likes", - "thread__social__facebook__shares", - "thread__social__facebook__comments", - "thread__social__gplus__shares", - "thread__social__pinterest__shares", - "thread__social__linkedin__shares", - "thread__social__stumbledupon__shares", - "thread__social__vk__shares", - "thread__performance_score", - "thread__domain_rank", - "thread__domain_rank_updated", - "thread__reach__per_million", - "thread__reach__page_views", - "thread__reach__updated", - "uuid", - "url", - "ord_in_thread", - "parent_url", - "author", - "published", - "title", - "text", - "language", - "external_links", - "external_images", - "rating", - "entities__persons", - "entities__organizations", - "entities__locations", - "crawled", -] - - -SAMPLE_POST = { - "thread__uuid": "e893796adad8a85e6ab5202ac34b5791c8fbb017", - "thread__url": "https://www.economist.com/business/2023/06/06/generative-ai-could-radically-alter-the-practice-of-law", - "thread__site_full": "https://www.economist.com", - "thread__site": "economist.com", -} - - -class WebzPostsTableTest(unittest.TestCase): - def test_get_columns_returns_all_columns(self): - webz_handler = Mock(WebzHandler) - posts_table = WebzPostsTable(webz_handler) - # Order matters. - expected_columns = COLUMNS_POST - self.assertListEqual(posts_table.get_columns(), expected_columns) - - def test_select_with_query_order_by_and_limit(self): - webz_handler = Mock(WebzHandler) - webz_handler.call_webz_api.return_value = pd.DataFrame([SAMPLE_POST]) - posts_table = WebzPostsTable(webz_handler) - query = parse_sql( - "SELECT * FROM posts WHERE query='language:english' ORDER BY posts.relevancy LIMIT 10", - ) - results = posts_table.select(query) - first_result = results.iloc[0] - webz_handler.call_webz_api.assert_called_once_with( - method_name="posts", - params={ - "q": "language:english", - "sort": "relevancy", - "order": "default", - "size": 10, - }, - ) - self.assertEqual(results.shape[1], len(COLUMNS_POST)) - for column in COLUMNS_POST: - self.assertEqual(first_result[column], SAMPLE_POST.get(column, None)) - - def test_select_with_targets(self): - webz_handler = Mock(WebzHandler) - webz_handler.call_webz_api.return_value = pd.DataFrame([SAMPLE_POST]) - posts_table = WebzPostsTable(webz_handler) - target_field = "thread__uuid" - query = parse_sql( - f"SELECT {target_field} FROM posts", - ) - results = posts_table.select(query) - first_result = results.iloc[0] - webz_handler.call_webz_api.assert_called_once_with( - method_name="posts", - params={}, - ) - self.assertEqual(results.shape[1], 1) - self.assertEqual(first_result[target_field], SAMPLE_POST[target_field]) - - def test_select_with_invalid_order_by_field_fails(self): - webz_handler = Mock(WebzHandler) - webz_handler.call_webz_api.return_value = pd.DataFrame([SAMPLE_POST]) - posts_table = WebzPostsTable(webz_handler) - query = parse_sql( - "SELECT thread__uuid FROM posts ORDER BY posts.invalid_field", - ) - with self.assertRaises(ValueError) as context: - posts_table.select(query) - self.assertEqual( - str(context.exception), "Order by unknown column invalid_field" - ) - - -COLUMNS_REVIEW = [ - "item__uuid", - "item__url", - "item__site_full", - "item__site", - "item__site_section", - "item__section_title", - "item__title", - "item__title_full", - "item__published", - "item__reviews_count", - "item__reviewers_count", - "item__main_image", - "item__country", - "item__site_categories", - "item__domain_rank", - "item__domain_rank_updated", - "uuid", - "url", - "ord_in_thread", - "author", - "published", - "title", - "text", - "language", - "external_links", - "rating", - "crawled", -] - - -SAMPLE_REVIEW = { - "item__uuid": "3bf76e1cee69da4e89ec88d5f0f23d0b66f4b5c6", - "item__url": "https://www.watsons.com.my/baking-soda-laundry-detergent/p/BP_56634", - "item__site_full": "www.watsons.com.my", - "uuid": "d6afd2c04c995f34d9003cea353d7f5e01fcce0b", -} - - -class WebzReviewsTableTest(unittest.TestCase): - def test_get_columns_returns_all_columns(self): - webz_handler = Mock(WebzHandler) - reviews_table = WebzReviewsTable(webz_handler) - expected_columns = COLUMNS_REVIEW - self.assertListEqual(reviews_table.get_columns(), expected_columns) - - def test_select_with_query_order_by_and_limit(self): - webz_handler = Mock(WebzHandler) - webz_handler.call_webz_api.return_value = pd.DataFrame([SAMPLE_REVIEW]) - reviews_table = WebzReviewsTable(webz_handler) - query = parse_sql( - "SELECT * FROM reviews WHERE query='language:english' ORDER BY reviews.reviews_count LIMIT 10", - ) - results = reviews_table.select(query) - first_result = results.iloc[0] - webz_handler.call_webz_api.assert_called_once_with( - method_name="reviews", - params={ - "q": "language:english", - "sort": "reviews_count", - "order": "default", - "size": 10, - }, - ) - self.assertEqual(results.shape[1], len(COLUMNS_REVIEW)) - for column in COLUMNS_REVIEW: - self.assertEqual(first_result[column], SAMPLE_REVIEW.get(column, None)) - - def test_select_with_targets(self): - webz_handler = Mock(WebzHandler) - webz_handler.call_webz_api.return_value = pd.DataFrame([SAMPLE_REVIEW]) - reviews_table = WebzReviewsTable(webz_handler) - target_field = "uuid" - query = parse_sql( - f"SELECT {target_field} FROM reviews", - ) - results = reviews_table.select(query) - first_result = results.iloc[0] - webz_handler.call_webz_api.assert_called_once_with( - method_name="reviews", - params={}, - ) - self.assertEqual(results.shape[1], 1) - self.assertEqual(first_result[target_field], SAMPLE_REVIEW[target_field]) - - def test_select_with_invalid_order_by_field_fails(self): - webz_handler = Mock(WebzHandler) - webz_handler.call_webz_api.return_value = pd.DataFrame([SAMPLE_REVIEW]) - reviews_table = WebzReviewsTable(webz_handler) - query = parse_sql( - "SELECT item__uuid FROM reviews ORDER BY reviews.invalid_field", - ) - with self.assertRaises(ValueError) as context: - reviews_table.select(query) - self.assertEqual( - str(context.exception), "Order by unknown column invalid_field" - ) diff --git a/tests/unused/unit/handler_tests/test_xata_handler.py b/tests/unused/unit/handler_tests/test_xata_handler.py deleted file mode 100644 index c0192795f5b..00000000000 --- a/tests/unused/unit/handler_tests/test_xata_handler.py +++ /dev/null @@ -1,413 +0,0 @@ -import os -import importlib -from unittest.mock import patch - -import pandas as pd -import pytest -from mindsdb_sql_parser import parse_sql - -from mindsdb.tests.unit.executor_test_base import BaseExecutorTest - -try: - xata = importlib.import_module("xata") - XATA_INSTALLED = True -except ImportError: - XATA_INSTALLED = False - - -@pytest.mark.skipif(not XATA_INSTALLED, reason="xata is not installed") -class TestXetaHandler(BaseExecutorTest): - - def run_sql(self, sql): - ret = self.command_executor.execute_command(parse_sql(sql)) - assert ret.error_code is None - if ret.data is not None: - return ret.data.to_df() - - def setup_method(self): - super().setup_method() - self.api_key = os.environ['XATA_TESTING_API_KEY'] - self.db_url = os.environ['XATA_TESTING_DB_URL'] - self.run_sql(f""" - CREATE DATABASE xata_test - WITH - ENGINE = 'xata', - PARAMETERS = {{ - "api_key": "{self.api_key}", - "db_url": "{self.db_url}", - "dimension": 3 - }}; - """) - self._client = xata.XataClient(api_key=self.api_key, db_url=self.db_url) - - def drop_table(self, table_name): - resp = self._client.table().delete(table_name) - if not resp.is_success(): - print(f"Unable to delete {table_name}: {resp['message']}") - - def get_num_records(self, table_name): - return self._client.search_and_filter().summarize(table_name, {"columns": [], "summaries": {"total": {"count": "*"}}})["summaries"][0]["total"] - - @pytest.mark.xfail(reason="create table for vectordatabase is not well supported") - @patch("mindsdb.integrations.handlers.postgres_handler.Handler") - def test_create_table(self, postgres_handler_mock): - # create an empty table - sql = """CREATE TABLE xata_test.testingtable;""" - self.run_sql(sql) - # create a table with the schema definition is not allowed - sql = """ - CREATE TABLE xata_test.testingtable ( - id int, - metadata text, - embedding float[] - ); - """ - with pytest.raises(Exception): - self.run_sql(sql) - - @pytest.mark.xfail(reason="drop table for vectordatabase is not working") - @patch("mindsdb.integrations.handlers.postgres_handler.Handler") - def test_drop_table(self, postgres_handler_mock): - df = pd.DataFrame( - { - "id": ["id1", "id2"], - "content": ["this is a test", "this is a test"], - "metadata": [{"test": "test"}, {"test": "test"}], - "embeddings": [[1.0, 2.0, 3.0], [1.0, 2.0, 3.0]], - } - ) - self.set_handler(postgres_handler_mock, "pg", tables={"testingtable": df}) - # create a table - sql = """ - CREATE TABLE xata_test.testingtable ( - SELECT * FROM pg.df - ) - """ - self.run_sql(sql) - # drop a table - sql = """ - DROP TABLE xata_test.testingtable; - """ - self.run_sql(sql) - - @pytest.mark.xfail(reason="update for vectordatabase is not implemented") - def test_update(self): - # update a table with a metadata filter - sql = """ - UPDATE xata_test.testingtable - SET metadata.test = 'test2' - WHERE metadata.test = 'test' - """ - self.run_sql(sql) - # check if the data is updated - sql = """ - SELECT * FROM xata_test.testingtable - WHERE metadata.test = 'test2' - """ - ret = self.run_sql(sql) - assert ret.shape[0] == 2 - # update the embeddings - sql = """ - UPDATE xata_test.testingtable - SET embedding = '[3.0, 2.0, 1.0]' - WHERE metadata.test = 'test2' - """ - self.run_sql(sql) - # check if the data is updated - sql = """ - SELECT * FROM xata_test.testingtable - WHERE metadata.test = 'test2' - """ - ret = self.run_sql(sql) - assert ret.shape[0] == 2 - assert ret.embedding[0] == [3.0, 2.0, 1.0] - # update multiple columns - sql = """ - UPDATE xata_test.testingtable - SET metadata.test = 'test3', - embedding = '[1.0, 2.0, 3.0]' - content = 'this is a test' - WHERE metadata.test = 'test2' - """ - self.run_sql(sql) - # check if the data is updated - sql = """ - SELECT * FROM xata_test.testingtable - WHERE metadata.test = 'test3' - """ - ret = self.run_sql(sql) - assert ret.shape[0] == 2 - assert ret.embedding[0] == [1.0, 2.0, 3.0] - assert ret.content[0] == "this is a test" - # update a table with a search vector filter is not allowed - sql = """ - UPDATE xata_test.testingtable - SET metadata.test = 'test2' - WHERE search_vector = '[1.0, 2.0, 3.0]' - """ - with pytest.raises(Exception): - self.run_sql(sql) - # update a table without any filters is allowed - sql = """ - UPDATE xata_test.testingtable - SET metadata.test = 'test3' - """ - self.run_sql(sql) - # check if the data is updated - sql = """ - SELECT * FROM xata_test.testingtable - WHERE metadata.test = 'test3' - """ - ret = self.run_sql(sql) - assert ret.shape[0] == 2 - # update a table with a search vector filter and a metadata filter is not allowed - sql = """ - UPDATE xata_test.testingtable - SET metadata.test = 'test3' - WHERE metadata.test = 'test2' - AND search_vector = '[1.0, 2.0, 3.0]' - """ - with pytest.raises(Exception): - self.run_sql(sql) - - @patch("mindsdb.integrations.handlers.postgres_handler.Handler") - def test_create_with_select(self, postgres_handler_mock): - df = pd.DataFrame( - { - "id": ["id1", "id2"], - "content": ["this is a test", "this is a test"], - "metadata": ['{"test": "test"}', '{"test": "test"}'], - "embeddings": [[1.0, 2.0, 3.0], [1.0, 2.0, 3.0]], - } - ) - self.set_handler(postgres_handler_mock, "pg", tables={"testingtable": df}) - sql = """ - CREATE TABLE xata_test.testingtable (SELECT * FROM pg.df) - """ - self.drop_table("testingtable") - # this should work - self.run_sql(sql) - assert self.get_num_records("testingtable") == 2 - self.drop_table("testingtable") - - @patch("mindsdb.integrations.handlers.postgres_handler.Handler") - def test_insert_into(self, postgres_handler_mock): - df = pd.DataFrame( - { - "id": ["id1", "id2", "id3"], - "content": ["this is a test", "this is a test", "this is a test"], - "metadata": ['{"test": "test1"}', '{"test": "test2"}', '{"test": "test3"}'], - "embeddings": [[1.0, 2.0, 3.0], [1.0, 2.0, 3.0], [1.0, 2.0, 3.0]], - } - ) - df2 = pd.DataFrame( - { - "id": ["id4", "id5", "id6"], - "content": ["this is a test", "this is a test", "this is a test"], - "metadata": [{"test": "test1"}, {"test": "test2"}, {"test": "test3"}], - "embeddings": [ - [1.0, 2.0, 3.0], - [1.0, 2.0, 4.0], - [5.0, 2.0, 3.0], - ], - } - ) - self.set_handler(postgres_handler_mock, "pg", tables={"df": df, "df2": df2}) - # create a table - sql = """ - CREATE TABLE xata_test.testingtable (SELECT * FROM pg.df) - """ - self.drop_table("testingtable") - self.run_sql(sql) - # insert into a table with values - sql = """ - INSERT INTO xata_test.testingtable (id,content,metadata,embeddings) - VALUES ('some_unique_id', 'this is a test', '{"test": "test"}', '[1.0, 2.0, 3.0]') - """ - self.run_sql(sql) - self.get_num_records("testingtable") == 4 - # insert without specifying id should also work - sql = """ - INSERT INTO xata_test.testingtable (content,metadata,embeddings) - VALUES ('this is a test', '{"test": "test"}', '[1.0, 2.0, 3.0]') - """ - self.run_sql(sql) - self.get_num_records("testingtable") == 5 - # insert into a table with a select statement - sql = """ - INSERT INTO xata_test.testingtable (content,metadata,embeddings) - SELECT content,metadata,embeddings FROM pg.df2 - """ - self.run_sql(sql) - self.get_num_records("testingtable") == 8 - # insert into a table with a select statement, but wrong columns - with pytest.raises(Exception): - sql = """ - INSERT INTO xata_test.testingtable - SELECT (content,metadata,embeddings as wrong_column) FROM pg.df - """ - self.run_sql(sql) - # insert into a table with a select statement, missing metadata column - sql = """ - INSERT INTO xata_test.testingtable - SELECT content,embeddings FROM pg.df - """ - self.run_sql(sql) - self.get_num_records("testingtable") == 11 - # insert into a table with a select statement, with different embedding dimensions, shall raise an error - sql = """ - INSERT INTO xata_test.testingtable - VALUES ('this is a test', '{"test": "test"}', '[1.0, 2.0, 3.0, 4.0]') - """ - with pytest.raises(Exception): - self.run_sql(sql) - self.drop_table("testingtable") - - @patch("mindsdb.integrations.handlers.postgres_handler.Handler") - def test_general_select_queries(self, postgres_handler_mock): - df = pd.DataFrame( - { - "id": ["id1", "id2", "id3", "id4", "id5", "id6"], - "content": ["test content", "test paragraph", "toast types", "", "tast misspelled", "hello"], - "metadata": ['{"price": 10}', '{"price": 100}', '{"price": 30}', '{"test": "test1"}', '{"test": "test2"}', '{"test": "test3"}'], - "embeddings": [[1.0, 2.0, 3.0], [5.0, 2.0, 8.0], [3.0, 6.0, 3.0], [1.0, 2.0, 3.0], [3.0, 1.0, 8.0], [1.0, 3.0, 7.0]], - } - ) - self.set_handler(postgres_handler_mock, "pg", tables={"testingtable": df}) - # create a table - sql = """ - CREATE TABLE xata_test.testingtable (SELECT * FROM pg.df) - """ - self.drop_table("testingtable") - self.run_sql(sql) - # query a table without any filters - sql = """ - SELECT * FROM xata_test.testingtable - """ - assert self.run_sql(sql).shape[0] == 6 - # query a table with limit - sql = """ - SELECT * FROM xata_test.testingtable - LIMIT 2 - """ - assert self.run_sql(sql).shape[0] == 2 - # query a table with id - sql = """ - SELECT * FROM xata_test.testingtable - WHERE id = 'id1' - """ - assert self.run_sql(sql).shape[0] == 1 - # query a table with a metadata filter - sql = """ - SELECT * FROM xata_test.testingtable - WHERE testingtable.metadata.test = 'test1' - """ - assert self.run_sql(sql).shape[0] == 1 - # query a table with a metadata complex filter - sql = """ - SELECT * FROM xata_test.testingtable - WHERE testingtable.metadata.price > 10 AND testingtable.metadata.price <= 100 - """ - assert self.run_sql(sql).shape[0] == 2 - # query a table with a content filter - sql = """ - SELECT * FROM xata_test.testingtable - WHERE content = 'test content' - """ - assert self.run_sql(sql).shape[0] == 1 - # query a table with a content filter - sql = """ - SELECT * FROM xata_test.testingtable - WHERE content = 'test content' - """ - assert self.run_sql(sql).shape[0] == 1 - # query a table with like operator - sql = """ - SELECT * FROM xata_test.testingtable - WHERE content LIKE 'test%' - """ - assert self.run_sql(sql).shape[0] == 2 - self.drop_table("testingtable") - - @patch("mindsdb.integrations.handlers.postgres_handler.Handler") - def test_vector_search(self, postgres_handler_mock): - df = pd.DataFrame( - { - "id": ["id1", "id2", "id3", "id4", "id5", "id6"], - "content": ["test content", "test paragraph", "toast types", "", "tast misspelled", "hello"], - "metadata": ['{"price": 10}', '{"price": 100}', '{"price": 30}', '{"test": "test1"}', '{"test": "test2"}', '{"test": "test3"}'], - "embeddings": [[1.0, 2.0, 3.0], [5.0, 2.0, 8.0], [3.0, 6.0, 3.0], [1.0, 2.0, 3.0], [3.0, 1.0, 8.0], [1.0, 3.0, 7.0]], - } - ) - self.set_handler(postgres_handler_mock, "pg", tables={"testingtable": df}) - # create a table - sql = """ - CREATE TABLE xata_test.testingtable ( - SELECT * FROM pg.df - ) - """ - self.drop_table("testingtable") - self.run_sql(sql) - # query a table with a search vector, without limit - sql = """ - SELECT * FROM xata_test.testingtable - WHERE search_vector = '[1.0, 2.0, 3.0]' - """ - assert self.run_sql(sql).shape[0] == 6 - # query a table with a search vector, with limit - sql = """ - SELECT * FROM xata_test.testingtable - WHERE search_vector = '[1.0, 2.0, 3.0]' - LIMIT 1 - """ - assert self.run_sql(sql).shape[0] == 1 - # query a table with a search vector, and content column - sql = """ - SELECT * FROM xata_test.testingtable - WHERE search_vector = '[1.0, 2.0, 3.0]' - AND content LIKE 'test%' - """ - assert self.run_sql(sql).shape[0] == 2 - # query a table with a metadata filter and a search vector does not work - sql = """ - SELECT * FROM xata_test.testingtable - WHERE metadata.price < 200 - AND search_vector = '[1.0, 2.0, 3.0]' - """ - with pytest.raises(Exception): - self.run_sql(sql) - self.drop_table("testingtable") - - @patch("mindsdb.integrations.handlers.postgres_handler.Handler") - def test_delete(self, postgres_handler_mock): - df = pd.DataFrame( - { - "id": ["id1", "id2", "id3", "id4", "id5", "id6"], - "content": ["test content", "test paragraph", "toast types", "", "tast misspelled", "hello"], - "metadata": ['{"price": 10}', '{"price": 100}', '{"price": 30}', '{"test": "test1"}', '{"test": "test2"}', '{"test": "test3"}'], - "embeddings": [[1.0, 2.0, 3.0], [5.0, 2.0, 8.0], [3.0, 6.0, 3.0], [1.0, 2.0, 3.0], [3.0, 1.0, 8.0], [1.0, 3.0, 7.0]], - } - ) - self.set_handler(postgres_handler_mock, "pg", tables={"testingtable": df}) - # create a table - sql = """ - CREATE TABLE xata_test.testingtable ( - SELECT * FROM pg.df - ) - """ - self.drop_table("testingtable") - self.run_sql(sql) - # delete by id - sql = """ - DELETE FROM xata_test.testingtable - WHERE id = 'id2' - """ - self.run_sql(sql) - self.get_num_records("testingtable") == 5 - # delete non existant passes - sql = """ - DELETE FROM xata_test.testingtable - WHERE id = 'id9' - """ - self.run_sql(sql) - self.drop_table("testingtable") diff --git a/tests/unused/unit/handler_tests/test_zipcodebase_handler.py b/tests/unused/unit/handler_tests/test_zipcodebase_handler.py deleted file mode 100644 index fa1c72992cf..00000000000 --- a/tests/unused/unit/handler_tests/test_zipcodebase_handler.py +++ /dev/null @@ -1,47 +0,0 @@ -import importlib -import os -import pytest -from mindsdb_sql_parser import parse_sql - -from ..unit.executor_test_base import BaseExecutorTest - -try: - importlib.import_module("requests") - REQUESTS_INSTALLED = True -except ImportError: - REQUESTS_INSTALLED = False - - -@pytest.mark.skipif(not REQUESTS_INSTALLED, reason="requests package is not installed") -class TestZipCodeBaseHandler(BaseExecutorTest): - - def run_sql(self, sql): - ret = self.command_executor.execute_command(parse_sql(sql)) - assert ret.error_code is None - if ret.data is not None: - return ret.data.to_df() - - def setup_method(self): - super().setup_method() - self.api_key = os.environ.get("ZIPCODEBASE_API_KEY") - self.run_sql(f""" - CREATE DATABASE mindsdb_zipcodebase - WITH ENGINE = 'zipcodebase', - PARAMETERS = { - "api_key": '{self.api_key}' - }; - """) - - def test_basic_select_from(self): - sql = "SELECT * FROM mindsdb_zipcodebase.code_to_location where codes='10005';" - self.run_sql(sql) - - sql = 'SELECT * FROM mindsdb_zipcodebase.codes_within_radius WHERE code="10005" AND radius="100" AND country="us";' - self.run_sql(sql) - - def test_complex_select(self): - sql = 'SELECT state FROM mindsdb_zipcodebase.codes_within_radius WHERE code="10005" AND radius="100" AND country="us";' - assert self.run_sql(sql).shape[1] == 6 - - sql = "SELECT * FROM mindsdb_zipcodebase.code_to_location where codes='10005'; LIMIT 1;" - assert self.run_sql(sql).shape[0] == 1 diff --git a/tests/unused/unit/handler_tests/test_zotero_handler.py b/tests/unused/unit/handler_tests/test_zotero_handler.py deleted file mode 100644 index ceae6780595..00000000000 --- a/tests/unused/unit/handler_tests/test_zotero_handler.py +++ /dev/null @@ -1,175 +0,0 @@ -import unittest -from unittest.mock import Mock, patch -import pandas as pd -from mindsdb_sql_parser import ast -from mindsdb_sql_parser import parse_sql -from mindsdb.integrations.handlers.zotero_handler.zotero_handler import ZoteroHandler -from mindsdb.integrations.handlers.zotero_handler.zotero_tables import AnnotationsTable - - -class AnnotationsTableTest(unittest.TestCase): - def setUp(self): - self.api_handler = Mock(ZoteroHandler) - self.annotations_table = AnnotationsTable(self.api_handler) - - def test_get_columns_returns_all_columns(self): - expected_columns = [ - 'annotationColor', 'annotationComment', 'annotationPageLabel', 'annotationText', - 'annotationType', 'dateAdded', 'dateModified', 'key', 'parentItem', - 'relations', 'tags', 'version' - ] - self.assertListEqual(self.annotations_table.get_columns(), expected_columns) - - @patch.object(AnnotationsTable, '_get_items') - def test_select_returns_all_columns(self, mock_get_items): - mock_get_items.return_value = pd.DataFrame([ - { - 'annotationColor': 'red', - 'annotationComment': 'comment', - 'annotationPageLabel': 'page1', - 'annotationText': 'text', - 'annotationType': 'highlight', - 'dateAdded': '2023-01-01', - 'dateModified': '2023-01-02', - 'key': '12345', - 'parentItem': '67890', - 'relations': {}, - 'tags': [], - 'version': 1 - } - ]) - - select_all = ast.Select( - targets=[ast.Star()], - from_table='annotations' - ) - - result = self.annotations_table.select(select_all) - first_row = result.iloc[0] - - self.assertEqual(result.shape[1], 12) - self.assertEqual(first_row['annotationColor'], 'red') - self.assertEqual(first_row['annotationComment'], 'comment') - self.assertEqual(first_row['annotationPageLabel'], 'page1') - self.assertEqual(first_row['annotationText'], 'text') - self.assertEqual(first_row['annotationType'], 'highlight') - self.assertEqual(first_row['dateAdded'], '2023-01-01') - self.assertEqual(first_row['dateModified'], '2023-01-02') - self.assertEqual(first_row['key'], '12345') - self.assertEqual(first_row['parentItem'], '67890') - self.assertEqual(first_row['relations'], {}) - self.assertEqual(first_row['tags'], []) - self.assertEqual(first_row['version'], 1) - - @patch.object(AnnotationsTable, '_get_item') - def test_select_with_conditions_item_id(self, mock_get_item): - mock_get_item.return_value = pd.DataFrame([ - { - 'annotationColor': 'blue', - 'annotationComment': 'another comment', - 'annotationPageLabel': 'page2', - 'annotationText': 'another text', - 'annotationType': 'underline', - 'dateAdded': '2023-03-01', - 'dateModified': '2023-03-02', - 'key': '54321', - 'parentItem': '09876', - 'relations': {}, - 'tags': [], - 'version': 2 - } - ]) - - select_query = parse_sql('SELECT * FROM annotations WHERE item_id = "12345"') - - result = self.annotations_table.select(select_query) - first_row = result.iloc[0] - - self.assertEqual(result.shape[1], 12) - self.assertEqual(first_row['annotationColor'], 'blue') - self.assertEqual(first_row['annotationComment'], 'another comment') - self.assertEqual(first_row['annotationPageLabel'], 'page2') - self.assertEqual(first_row['annotationText'], 'another text') - self.assertEqual(first_row['annotationType'], 'underline') - self.assertEqual(first_row['dateAdded'], '2023-03-01') - self.assertEqual(first_row['dateModified'], '2023-03-02') - self.assertEqual(first_row['key'], '54321') - self.assertEqual(first_row['parentItem'], '09876') - self.assertEqual(first_row['relations'], {}) - self.assertEqual(first_row['tags'], []) - self.assertEqual(first_row['version'], 2) - - @patch.object(AnnotationsTable, '_get_item_children') - def test_select_with_conditions_parent_item_id(self, mock_get_item_children): - mock_get_item_children.return_value = pd.DataFrame([ - { - 'annotationColor': 'green', - 'annotationComment': 'yet another comment', - 'annotationPageLabel': 'page3', - 'annotationText': 'yet another text', - 'annotationType': 'strikeout', - 'dateAdded': '2023-05-01', - 'dateModified': '2023-05-02', - 'key': '98765', - 'parentItem': '43210', - 'relations': {}, - 'tags': [], - 'version': 3 - } - ]) - - select_query = parse_sql('SELECT * FROM annotations WHERE parent_item_id = "67890"') - - result = self.annotations_table.select(select_query) - first_row = result.iloc[0] - - self.assertEqual(result.shape[1], 12) - self.assertEqual(first_row['annotationColor'], 'green') - self.assertEqual(first_row['annotationComment'], 'yet another comment') - self.assertEqual(first_row['annotationPageLabel'], 'page3') - self.assertEqual(first_row['annotationText'], 'yet another text') - self.assertEqual(first_row['annotationType'], 'strikeout') - self.assertEqual(first_row['dateAdded'], '2023-05-01') - self.assertEqual(first_row['dateModified'], '2023-05-02') - self.assertEqual(first_row['key'], '98765') - self.assertEqual(first_row['parentItem'], '43210') - self.assertEqual(first_row['relations'], {}) - self.assertEqual(first_row['tags'], []) - self.assertEqual(first_row['version'], 3) - - -class ZoteroHandlerTest(unittest.TestCase): - - @patch('pyzotero.zotero.Zotero') - def setUp(self, mock_zotero): - self.mock_zotero = mock_zotero - connection_data = { - 'library_id': 'test_lib_id', - 'library_type': 'user', - 'api_key': 'test_api_key' - } - self.handler = ZoteroHandler(connection_data=connection_data) - self.handler.connect() - - def test_connect(self): - self.handler.connect() - self.mock_zotero.assert_called_once_with( - 'test_lib_id', 'user', 'test_api_key' - ) - self.assertTrue(self.handler.is_connected) - - def test_check_connection_success(self): - self.handler.connect = Mock(return_value=None) - self.handler.is_connected = True - response = self.handler.check_connection() - self.assertTrue(response.success) - - def test_check_connection_failure(self): - self.handler.connect = Mock(side_effect=Exception('Connection failed')) - response = self.handler.check_connection() - self.assertFalse(response.success) - self.assertIn('Error connecting to Zotero API', response.error_message) - - -if __name__ == '__main__': - unittest.main() diff --git a/tests/unused/unit/handlers/test_chromadb_handler.py b/tests/unused/unit/handlers/test_chromadb_handler.py deleted file mode 100644 index 5268c2ea441..00000000000 --- a/tests/unused/unit/handlers/test_chromadb_handler.py +++ /dev/null @@ -1,529 +0,0 @@ -import shutil -import tempfile -from unittest.mock import patch - -import pandas as pd -import pytest - -from tests.unit.executor_test_base import BaseExecutorTest - -# check if chroma_db is installed -import importlib - -try: - importlib.import_module("chromadb") - CHROMA_DB_INSTALLED = True -except ImportError: - CHROMA_DB_INSTALLED = False - - -@pytest.mark.skipif(not CHROMA_DB_INSTALLED, reason="chroma_db is not installed") -class TestChromaDBHandler(BaseExecutorTest): - - @pytest.fixture(autouse=True, scope="function") - def setup_method(self): - super().setup_method() - # create a chroma database under the tmp directory - tmp_directory = tempfile.mkdtemp() - self.run_sql( - f""" - CREATE DATABASE chroma_test - WITH ENGINE = "chromadb", - PARAMETERS = {{ - "persist_directory" : "{tmp_directory}" - }} - """ - ) - yield - # Teardown code: drop the database and remove the temporary directory - self.run_sql("DROP DATABASE chroma_test;") - shutil.rmtree(tmp_directory) - - @pytest.mark.xfail(reason="create table for vectordatabase is not well supported") - @patch("mindsdb.integrations.handlers.postgres_handler.Handler") - def test_create_table(self, postgres_handler_mock): - # create an empty table - sql = """ - CREATE TABLE chroma_test.test_table; - """ - self.run_sql(sql) - - # create a table with the schema definition is not allowed - - sql = """ - CREATE TABLE chroma_test.test_table ( - id int, - metadata text, - embedding float[] - ); - """ - with pytest.raises(Exception): - self.run_sql(sql) - - @patch("mindsdb.integrations.handlers.postgres_handler.Handler") - def test_create_with_select(self, postgres_handler_mock): - df = pd.DataFrame( - { - "id": ["id1", "id2"], - "content": ["this is a test", "this is a test"], - "metadata": [{"test": "test"}, {"test": "test"}], - "embeddings": [[1.0, 2.0, 3.0], [1.0, 2.0, 3.0]], - } - ) - - self.set_handler(postgres_handler_mock, "pg", tables={"test_table": df}) - - sql = """ - CREATE TABLE chroma_test.test_table2 ( - SELECT * FROM pg.df - ) - """ - # this should work - self.run_sql(sql) - - @patch("mindsdb.integrations.handlers.postgres_handler.Handler") - def test_drop_table(self, postgres_handler_mock): - df = pd.DataFrame( - { - "id": ["id1", "id2"], - "content": ["this is a test", "this is a test"], - "metadata": [{"test": "test"}, {"test": "test"}], - "embeddings": [[1.0, 2.0, 3.0], [1.0, 2.0, 3.0]], - } - ) - self.set_handler(postgres_handler_mock, "pg", tables={"test_table": df}) - - # create a table - sql = """ - CREATE TABLE chroma_test.test_table ( - SELECT * FROM pg.df - ) - """ - self.run_sql(sql) - - # drop a table - sql = """ - DROP TABLE chroma_test.test_table; - """ - self.run_sql(sql) - - # drop a non existent table will raise an error - sql = """ - DROP TABLE chroma_test.test_table2; - """ - with pytest.raises(Exception): - self.run_sql(sql) - - @patch("mindsdb.integrations.handlers.postgres_handler.Handler") - def test_insert_into(self, postgres_handler_mock): - df = pd.DataFrame( - { - "id": ["id1", "id2", "id3"], - "content": ["this is a test", "this is a test", "this is a test"], - "metadata": [{"test": "test1"}, {"test": "test2"}, {"test": "test3"}], - "embeddings": [[1.0, 2.0, 3.0], [1.0, 2.0, 3.0], [1.0, 2.0, 3.0]], - } - ) - df2 = pd.DataFrame( - { - "id": ["id1", "id2", "id3"], - "content": ["this is a test", "this is a test", "this is a test"], - "metadata": [{"test": "test1"}, {"test": "test2"}, {"test": "test3"}], - "embeddings": [ - [1.0, 2.0, 3.0, 4.0], - [1.0, 2.0], - [1.0, 2.0, 3.0], - ], # different dimensions - } - ) - self.set_handler(postgres_handler_mock, "pg", tables={"df": df, "df2": df2}) - num_record = df.shape[0] - - # create a table - sql = """ - CREATE TABLE chroma_test.test_table ( - SELECT * FROM pg.df - ) - """ - self.run_sql(sql) - - # insert into a table with values - sql = """ - INSERT INTO chroma_test.test_table ( - id,content,metadata,embeddings - ) - VALUES ( - 'some_unique_id', 'this is a test', '{"test": "test"}', '[1.0, 2.0, 3.0]' - ) - """ - self.run_sql(sql) - # check if the data is inserted - sql = """ - SELECT * FROM chroma_test.test_table - WHERE id = 'some_unique_id' - """ - ret = self.run_sql(sql) - assert ret.shape[0] == 1 - - # insert without specifying id should also work - sql = """ - INSERT INTO chroma_test.test_table ( - content,metadata,embeddings - ) - VALUES ( - 'this is a test 0', '{"test": "test"}', '[1.0, 2.0, 3.0]' - ) - """ - self.run_sql(sql) - # check if the data is inserted - sql = """ - SELECT * FROM chroma_test.test_table - """ - ret = self.run_sql(sql) - assert ret.shape[0] == num_record + 2 - - # insert into a table with a select statement - sql = """ - INSERT INTO chroma_test.test_table ( - content,metadata,embeddings - ) - SELECT - content,metadata,embeddings - FROM - pg.df - """ - self.run_sql(sql) - # check if the data is inserted - sql = """ - SELECT * FROM chroma_test.test_table - """ - ret = self.run_sql(sql) - assert ret.shape[0] == num_record + 3 # only one unique record was added - - # insert into a table with a select statement, but wrong columns - with pytest.raises(Exception): - sql = """ - INSERT INTO chroma_test.test_table - SELECT - content,metadata,embeddings as wrong_column - FROM - pg.df - """ - self.run_sql(sql) - - # insert into a table with a select statement, missing metadata column - sql = """ - INSERT INTO chroma_test.test_table - SELECT - content,embeddings - FROM - pg.df - """ - self.run_sql(sql) - - # insert into a table with a select statement, missing embedding column, shall raise an error - with pytest.raises(Exception): - sql = """ - INSERT INTO chroma_test.test_table - SELECT - content,metadata - FROM - pg.df - """ - self.run_sql(sql) - - # insert into a table with a select statement, with different embedding dimensions, shall raise an error - sql = """ - INSERT INTO chroma_test.test_table - SELECT - content,metadata,embeddings - FROM - pg.df2 - """ - with pytest.raises(Exception): - self.run_sql(sql) - - # TODO: this behavior is not consistent with chromadb doc - # tracked in https://github.com/chroma-core/chroma/issues/1062 - # insert into a table with existing id, shall raise an error - # sql = """ - # INSERT INTO chroma_test.test_table ( - # id,content,metadata,embeddings - # ) - # VALUES ( - # 'id1', 'this is a test', '{"test": "test"}', '[1.0, 2.0, 3.0]' - # ) - # """ - # with pytest.raises(Exception): - # self.run_sql(sql) - - @patch("mindsdb.integrations.handlers.postgres_handler.Handler") - def test_select_from(self, postgres_handler_mock): - df = pd.DataFrame( - { - "id": ["id1", "id2"], - "content": ["this is a test", "this is a test"], - "metadata": [{"test": "test"}, {"test": "test"}], - "embeddings": [[1.0, 2.0, 3.0], [1.0, 2.0, 3.0]], - } - ) - self.set_handler(postgres_handler_mock, "pg", tables={"test_table": df}) - # create a table - sql = """ - CREATE TABLE chroma_test.test_table ( - SELECT * FROM pg.df - ) - """ - self.run_sql(sql) - - # query a table without any filters - sql = """ - SELECT * FROM chroma_test.test_table - """ - self.run_sql(sql) - - # query a table with id - sql = """ - SELECT * FROM chroma_test.test_table - WHERE id = 'id1' - """ - ret = self.run_sql(sql) - assert ret.shape[0] == 1 - - # query a table with a search vector, without limit - sql = """ - SELECT * FROM chroma_test.test_table - WHERE search_vector = '[1.0, 2.0, 3.0]' - """ - ret = self.run_sql(sql) - assert ret.shape[0] == 2 - - # query a table with a search vector, with limit - sql = """ - SELECT * FROM chroma_test.test_table - WHERE search_vector = '[1.0, 2.0, 3.0]' - LIMIT 1 - """ - ret = self.run_sql(sql) - assert ret.shape[0] == 1 - - # query a table with a metadata filter - sql = """ - SELECT * FROM chroma_test.test_table - WHERE `metadata.test` = 'test' - """ - ret = self.run_sql(sql) - assert ret.shape[0] == 2 - - # query a table with a metadata filter and a search vector - sql = """ - SELECT * FROM chroma_test.test_table - WHERE `metadata.test` = 'test' - AND search_vector = '[1.0, 2.0, 3.0]' - """ - ret = self.run_sql(sql) - assert ret.shape[0] == 2 - - @patch("mindsdb.integrations.handlers.postgres_handler.Handler") - def test_update(self, postgres_handler_mock): - - df = pd.DataFrame( - { - "id": ["id1", "id2"], - "content": ["this is a test", "this is a test"], - "metadata": [{"ext_id": "1"}, {"ext_id": "2"}], - "embeddings": [[1.0, 2.0, 3.0], [1.0, 2.0, 3.0]], - } - ) - self.set_handler(postgres_handler_mock, "pg", tables={"test_table": df}) - - # create a table - sql = """ - CREATE TABLE chroma_test.test_table ( - SELECT * FROM pg.df - ) - """ - self.run_sql(sql) - - # updating the collection with only embeddings and not content is not allowed - sql = """ - UPDATE chroma_test.test_table - SET embeddings = '[3.0, 2.0, 1.0]', - id = 'id1' - """ - - with pytest.raises(Exception): - self.run_sql(sql) - - # updating the collection with only content and not embeddings is not allowed - sql = """ - UPDATE chroma_test.test_table - SET content = 'blah blah', - id = 'id1' - """ - - with pytest.raises(Exception): - self.run_sql(sql) - - # update multiple columns - sql = """ - UPDATE chroma_test.test_table - SET id = 'id1', - embeddings = '[1.0, 2.0, 3.0]', - content = 'this is a test' - """ - self.run_sql(sql) - # check if the data is updated - sql = """ - SELECT * FROM chroma_test.test_table - WHERE id = 'id1' - """ - ret = self.run_sql(sql) - assert ret.shape[0] == 1 - assert ret.embeddings[0] == [1.0, 2.0, 3.0] - assert ret.content[0] == "this is a test" - - # update a table with a where clause is not allowed - sql = """ - UPDATE chroma_test.test_table - SET `metadata.test` = 'test2' - WHERE search_vector = [1.0, 2.0, 3.0] - """ - with pytest.raises(Exception): - self.run_sql(sql) - - # update a table with all columns - sql = """ - UPDATE chroma_test.test_table - SET id = 'id1', - embeddings = '[1.0, 2.0, 3.0]', - content = 'this is a test', - `metadata.ext_id` = '1' - """ - self.run_sql(sql) - # check if the data is updated - sql = """ - SELECT * FROM chroma_test.test_table - WHERE id = 'id1' - """ - ret = self.run_sql(sql) - assert ret.shape[0] == 1 - assert ret.embeddings[0] == [1.0, 2.0, 3.0] - assert ret.content[0] == "this is a test" - assert ret.metadata[0] == {"ext_id": "1"} - - # update a table without providing a id is not allowed - sql = """ - UPDATE chroma_test.test_table - SET metadata.test = 'test3' - - """ - with pytest.raises(Exception): - self.run_sql(sql) - - @patch("mindsdb.integrations.handlers.postgres_handler.Handler") - def test_delete(self, postgres_handler_mock): - df = pd.DataFrame( - { - "id": ["id1", "id2"], - "content": ["this is a test", "this is a test"], - "metadata": [{"test": "test1"}, {"test": "test2"}], - "embeddings": [[1.0, 2.0, 3.0], [1.0, 2.0, 3.0]], - } - ) - self.set_handler(postgres_handler_mock, "pg", tables={"test_table": df}) - - # create a table - sql = """ - CREATE TABLE chroma_test.test_table ( - SELECT * FROM pg.df - ) - """ - self.run_sql(sql) - - # delete from a table with a metadata filter - sql = """ - DELETE FROM chroma_test.test_table - WHERE `metadata.test` = 'test1' - """ - self.run_sql(sql) - # check if the data is deleted - sql = """ - SELECT * FROM chroma_test.test_table - WHERE `metadata.test` = 'test2' - """ - ret = self.run_sql(sql) - assert ret.shape[0] == 1 - - # delete by id - sql = """ - DELETE FROM chroma_test.test_table - WHERE id = 'id2' - """ - self.run_sql(sql) - # check if the data is deleted - sql = """ - SELECT * FROM chroma_test.test_table - WHERE id = 'id2' - """ - ret = self.run_sql(sql) - assert ret.shape[0] == 0 - - # delete from a table with a search vector filter is not allowed - sql = """ - DELETE FROM chroma_test.test_table - WHERE search_vector = [1.0, 2.0, 3.0] - """ - with pytest.raises(Exception): - self.run_sql(sql) - - # delete from a table without any filters is not allowed - sql = """ - DELETE FROM chroma_test.test_table - """ - with pytest.raises(Exception): - self.run_sql(sql) - - @patch("mindsdb.integrations.handlers.postgres_handler.Handler") - def test_insert_upsert_behavior(self, postgres_handler_mock): - # Initial data with IDs - df1 = pd.DataFrame({ - "id": ["id1", "id2"], - "content": ["content1", "content2"], - "metadata": [{"test": "test1"}, {"test": "test2"}], - "embeddings": [[1.0, 2.0], [2.0, 3.0]] - }) - - # Same IDs, different metadata - df2 = pd.DataFrame({ - "id": ["id1", "id2"], - "content": ["content1", "content2"], - "metadata": [{"test": "updated1"}, {"test": "updated2"}], - "embeddings": [[1.0, 2.0], [2.0, 3.0]] - }) - - self.set_handler(postgres_handler_mock, "pg", tables={"df1": df1, "df2": df2}) - - # Create table and insert initial data - self.run_sql(""" - CREATE TABLE chroma_test.test_table ( - SELECT * FROM pg.df1 - ) - """) - - # Verify initial insert - result = self.run_sql("SELECT * FROM chroma_test.test_table") - assert result.shape[0] == 2 - assert result.iloc[0].metadata == {"test": "test1"} - - # Insert same IDs with different metadata (should update) - self.run_sql(""" - INSERT INTO chroma_test.test_table ( - SELECT * FROM pg.df2 - ) - """) - - # Verify update - result = self.run_sql("SELECT * FROM chroma_test.test_table") - assert result.shape[0] == 2 # Should still have 2 rows - assert result.iloc[0].metadata == {"test": "updated1"} # Metadata should be updated diff --git a/tests/unused/unit/interfaces/agents/test_api_key_handling.py b/tests/unused/unit/interfaces/agents/test_api_key_handling.py deleted file mode 100644 index 484ba775577..00000000000 --- a/tests/unused/unit/interfaces/agents/test_api_key_handling.py +++ /dev/null @@ -1,106 +0,0 @@ -import os -import unittest -from unittest.mock import patch, MagicMock - -from mindsdb.integrations.utilities.handler_utils import get_api_key -from mindsdb.interfaces.agents.agents_controller import AgentsController - - -class TestAgentApiKeyHandling(unittest.TestCase): - """Test API key handling in agent creation and usage.""" - - def setUp(self): - """Set up test environment.""" - # Mock environment variables - self.env_patcher = patch.dict(os.environ, { - 'OPENAI_API_KEY': 'test-env-api-key', - 'ANTHROPIC_API_KEY': 'test-env-anthropic-key' - }) - self.env_patcher.start() - - def tearDown(self): - """Clean up after tests.""" - self.env_patcher.stop() - - def test_get_api_key_from_env(self): - """Test retrieving API key from environment variables.""" - # Test getting API key from environment variable - api_key = get_api_key('openai', {}) - self.assertEqual(api_key, 'test-env-api-key') - - def test_get_api_key_from_args(self): - """Test retrieving API key from create_args.""" - # Test getting API key from create_args - api_key = get_api_key('openai', {'openai_api_key': 'test-args-api-key'}) - self.assertEqual(api_key, 'test-args-api-key') - - def test_get_api_key_from_params(self): - """Test retrieving API key from params dictionary.""" - # Test getting API key from params dictionary - api_key = get_api_key('openai', {'params': {'openai_api_key': 'test-params-api-key'}}) - self.assertEqual(api_key, 'test-params-api-key') - - def test_get_api_key_priority(self): - """Test API key retrieval priority.""" - # Test that create_args takes priority over environment variables - api_key = get_api_key('openai', {'openai_api_key': 'test-args-api-key'}) - self.assertEqual(api_key, 'test-args-api-key') - - # Test that params takes priority over environment variables - api_key = get_api_key('openai', {'params': {'openai_api_key': 'test-params-api-key'}}) - self.assertEqual(api_key, 'test-params-api-key') - - # Test that create_args takes priority over params - api_key = get_api_key('openai', { - 'openai_api_key': 'test-args-api-key', - 'params': {'openai_api_key': 'test-params-api-key'} - }) - self.assertEqual(api_key, 'test-args-api-key') - - @patch('mindsdb.interfaces.agents.agents_controller.AgentsController.check_model_provider') - @patch('mindsdb.interfaces.agents.agents_controller.AgentsController.get_agent') - @patch('mindsdb.interfaces.agents.agents_controller.ProjectController') - @patch('mindsdb.interfaces.storage.db.session') - def test_add_agent_with_api_key(self, mock_session, mock_project_controller, mock_get_agent, mock_check_model_provider): - """Test adding an agent with an API key in params.""" - # Mock project controller - mock_project = MagicMock() - mock_project_controller.return_value.get.return_value = mock_project - - # Mock get_agent to return None (agent doesn't exist yet) - mock_get_agent.return_value = None - - # Mock check_model_provider to return a provider - mock_check_model_provider.return_value = (None, 'openai') - - # Create an instance of AgentsController - agent_controller = AgentsController() - - # Test adding an agent with an API key in params - params = { - 'openai_api_key': 'test-agent-api-key', - 'other_param': 'value' - } - - # Create a mock agent with proper params - mock_agent = MagicMock() - mock_agent.params = params.copy() # Set params directly - - # Mock db.Agents to return our prepared mock agent - with patch('mindsdb.interfaces.storage.db.Agents', return_value=mock_agent): - # Add the agent - agent = agent_controller.add_agent( - name='test_agent', - project_name='mindsdb', - model_name='gpt-4', - skills=[], - provider='openai', - params=params - ) - - # Verify that the API key was preserved in the params - self.assertEqual(agent.params.get('openai_api_key'), 'test-agent-api-key') - - -if __name__ == '__main__': - unittest.main() diff --git a/tests/unused/unit/interfaces/skills/custom/text2sql/test_mindsdb_kb_tools.py b/tests/unused/unit/interfaces/skills/custom/text2sql/test_mindsdb_kb_tools.py deleted file mode 100644 index 468756c16bc..00000000000 --- a/tests/unused/unit/interfaces/skills/custom/text2sql/test_mindsdb_kb_tools.py +++ /dev/null @@ -1,163 +0,0 @@ -import unittest -from unittest.mock import MagicMock - -from typing import List, Dict, Any - -from mindsdb.interfaces.skills.custom.text2sql.mindsdb_kb_tools import ( - KnowledgeBaseListTool, - KnowledgeBaseInfoTool, - KnowledgeBaseQueryTool -) - - -class TestKnowledgeBaseTools(unittest.TestCase): - """Test cases for the MindsDB knowledge base tools.""" - - def setUp(self) -> None: - """Set up test fixtures.""" - self.mock_db = MagicMock() - - # Sample knowledge base data - self.kb_list_data: List[Dict[str, str]] = [ - {"name": "kb1"}, - {"name": "kb2"}, - {"name": "kb3"} - ] - - self.kb_schema_data: List[Dict[str, Any]] = [ - { - "name": "kb1", - "engine": "vector", - "embedding_model": "openai", - "storage": "qdrant", - "metadata_columns": ["product", "category"] - } - ] - - self.kb_sample_data: List[Dict[str, Any]] = [ - { - "id": "A1B", - "chunk_id": "A1B_notes:1of1:0to20", - "chunk_content": "Request color: black", - "metadata": {"product": "Wireless Mouse", "category": "Electronics"}, - "distance": 0.574, - "relevance": 0.509 - }, - { - "id": "Q7P", - "chunk_id": "Q7P_notes:1of1:0to22", - "chunk_content": "Prefer aluminum finish", - "metadata": {"product": "Aluminum Laptop Stand", "category": "Accessories"}, - "distance": 0.774, - "relevance": 0.250 - } - ] - - def test_knowledge_base_list_tool(self) -> None: - """Test the KnowledgeBaseListTool.""" - # Configure mock - self.mock_db.run.return_value = self.kb_list_data - - # Create tool instance - kb_list_tool = KnowledgeBaseListTool(db=self.mock_db) - - # Test tool execution - result = kb_list_tool._run("") - - # Verify results - self.assertEqual(result, "`kb1`, `kb2`, `kb3`") - self.mock_db.run.assert_called_once_with("SHOW KNOWLEDGE_BASES;") - - def test_knowledge_base_list_tool_empty_result(self) -> None: - """Test the KnowledgeBaseListTool with empty result.""" - # Configure mock - self.mock_db.run.return_value = [] - - # Create tool instance - kb_list_tool = KnowledgeBaseListTool(db=self.mock_db) - - # Test tool execution - result = kb_list_tool._run("") - - # Verify results - self.assertEqual(result, "No knowledge bases found.") - - def test_knowledge_base_info_tool(self) -> None: - """Test the KnowledgeBaseInfoTool.""" - # Configure mock - self.mock_db.run.side_effect = [self.kb_schema_data, self.kb_sample_data] - - # Create tool instance - kb_info_tool = KnowledgeBaseInfoTool(db=self.mock_db) - - # Test tool execution - result = kb_info_tool._run("$START$ `kb1` $STOP$") - - # Verify results - self.assertIn("## Knowledge Base: `kb1`", result) - self.assertIn("### Schema Information:", result) - self.assertIn("### Sample Data:", result) - self.assertEqual(self.mock_db.run.call_count, 2) - - def test_knowledge_base_info_tool_invalid_input(self) -> None: - """Test the KnowledgeBaseInfoTool with invalid input.""" - # Create tool instance - kb_info_tool = KnowledgeBaseInfoTool(db=self.mock_db) - - # Test tool execution with invalid input - result = kb_info_tool._run("invalid input") - - # Verify results - self.assertEqual( - result, - "No valid knowledge base names provided. Please provide names enclosed in backticks between $START$ and $STOP$." - ) - - def test_knowledge_base_query_tool(self) -> None: - """Test the KnowledgeBaseQueryTool.""" - # Configure mock - self.mock_db.run.return_value = self.kb_sample_data - - # Create tool instance - kb_query_tool = KnowledgeBaseQueryTool(db=self.mock_db) - - # Test tool execution - query = "SELECT * FROM kb1 WHERE content = 'color';" - result = kb_query_tool._run(f"$START$ {query} $STOP$") - - # Verify results - self.assertIn("| id | chunk_id | chunk_content | metadata | distance | relevance |", result) - self.mock_db.run.assert_called_once_with(query) - - def test_knowledge_base_query_tool_invalid_input(self) -> None: - """Test the KnowledgeBaseQueryTool with invalid input.""" - # Create tool instance - kb_query_tool = KnowledgeBaseQueryTool(db=self.mock_db) - - # Test tool execution with invalid input - result = kb_query_tool._run("invalid input") - - # Verify results - self.assertEqual( - result, - "No valid SQL query provided. Please provide a query between $START$ and $STOP$." - ) - - def test_knowledge_base_query_tool_empty_result(self) -> None: - """Test the KnowledgeBaseQueryTool with empty result.""" - # Configure mock - self.mock_db.run.return_value = [] - - # Create tool instance - kb_query_tool = KnowledgeBaseQueryTool(db=self.mock_db) - - # Test tool execution - query = "SELECT * FROM kb1 WHERE content = 'nonexistent';" - result = kb_query_tool._run(f"$START$ {query} $STOP$") - - # Verify results - self.assertEqual(result, "Query executed successfully, but no results were returned.") - - -if __name__ == "__main__": - unittest.main() diff --git a/tests/unused/unit/ml_handlers/conftest.py b/tests/unused/unit/ml_handlers/conftest.py deleted file mode 100644 index 8ffd64431cb..00000000000 --- a/tests/unused/unit/ml_handlers/conftest.py +++ /dev/null @@ -1,24 +0,0 @@ -from pathlib import Path - -import pandas as pd -import pytest - -TEST_DATA_PATH = Path(__file__).parent.resolve() / "data" - - -def get_df(file_name: str, dtype: dict = None) -> pd.DataFrame: - return pd.read_csv(TEST_DATA_PATH / file_name, dtype=dtype) - - -@pytest.fixture -def lightfm_interaction_data() -> pd.DataFrame: - return get_df( - "ratings.csv", dtype={"userId": "str", "movieId": "str", "rating": "float64"} - ) - - -@pytest.fixture -def lightfm_item_data() -> pd.DataFrame: - return get_df( - "movies.csv", dtypes={"movieId": "str", "title": "str", "genres": "str"} - ) diff --git a/tests/unused/unit/ml_handlers/data/anomaly_detection.csv b/tests/unused/unit/ml_handlers/data/anomaly_detection.csv deleted file mode 100644 index 3aaa58d2eb4..00000000000 --- a/tests/unused/unit/ml_handlers/data/anomaly_detection.csv +++ /dev/null @@ -1,7 +0,0 @@ -carat,depth,table,x,y,z,category,class -0.23,61.5,55,3.95,3.98,2.43,"a",0 -0.21,59.8,61,3.89,3.84,2.31,"b",0 -0.23,56.9,65,4.05,4.07,2.31,"c",1 -0.29,62.4,58,4.2,4.23,2.63,"a",0 -0.31,63.3,58,4.34,4.35,2.75,"b",0 -0.31,64.3,28,4.24,4.35,2.75,"c",1 diff --git a/tests/unused/unit/ml_handlers/data/house_sales.csv b/tests/unused/unit/ml_handlers/data/house_sales.csv deleted file mode 100644 index 5eaf7a7304b..00000000000 --- a/tests/unused/unit/ml_handlers/data/house_sales.csv +++ /dev/null @@ -1,348 +0,0 @@ -saledate,ma,type,bedrooms -2007-09-30,441854,house,2 -2007-12-31,441854,house,2 -2008-03-31,441854,house,2 -2008-06-30,441854,house,2 -2008-09-30,451583,house,2 -2008-12-31,440256,house,2 -2009-03-31,442566,house,2 -2009-06-30,446113,house,2 -2009-09-30,440123,house,2 -2009-12-31,442131,house,2 -2010-03-31,459222,house,2 -2010-06-30,456822,house,2 -2010-09-30,457806,house,2 -2010-12-31,459109,house,2 -2011-03-31,460758,house,2 -2011-06-30,464788,house,2 -2011-09-30,467546,house,2 -2011-12-31,470333,house,2 -2012-03-31,470365,house,2 -2012-06-30,469149,house,2 -2012-09-30,465919,house,2 -2012-12-31,463090,house,2 -2013-03-31,451077,house,2 -2013-06-30,451516,house,2 -2013-09-30,454270,house,2 -2013-12-31,456548,house,2 -2014-03-31,469920,house,2 -2014-06-30,472726,house,2 -2014-09-30,475326,house,2 -2014-12-31,478413,house,2 -2015-03-31,478398,house,2 -2015-06-30,477238,house,2 -2015-09-30,477330,house,2 -2015-12-31,479010,house,2 -2016-03-31,482440,house,2 -2016-06-30,486436,house,2 -2016-09-30,489104,house,2 -2016-12-31,491152,house,2 -2017-03-31,494544,house,2 -2017-06-30,498846,house,2 -2017-09-30,504592,house,2 -2017-12-31,506578,house,2 -2018-03-31,507248,house,2 -2018-06-30,506116,house,2 -2018-09-30,504318,house,2 -2018-12-31,506001,house,2 -2019-03-31,496133,house,2 -2019-06-30,500158,house,2 -2019-09-30,510712,house,2 -2007-03-31,421291,house,3 -2007-06-30,421291,house,3 -2007-09-30,421291,house,3 -2007-12-31,421291,house,3 -2008-03-31,416031,house,3 -2008-06-30,419628,house,3 -2008-09-30,423811,house,3 -2008-12-31,426488,house,3 -2009-03-31,437724,house,3 -2009-06-30,444351,house,3 -2009-09-30,449742,house,3 -2009-12-31,457394,house,3 -2010-03-31,466433,house,3 -2010-06-30,474590,house,3 -2010-09-30,483176,house,3 -2010-12-31,491715,house,3 -2011-03-31,498022,house,3 -2011-06-30,503891,house,3 -2011-09-30,507090,house,3 -2011-12-31,507744,house,3 -2012-03-31,507449,house,3 -2012-06-30,507014,house,3 -2012-09-30,506615,house,3 -2012-12-31,506615,house,3 -2013-03-31,506380,house,3 -2013-06-30,505739,house,3 -2013-09-30,505823,house,3 -2013-12-31,506406,house,3 -2014-03-31,508499,house,3 -2014-06-30,512374,house,3 -2014-09-30,516618,house,3 -2014-12-31,522103,house,3 -2015-03-31,528926,house,3 -2015-06-30,534927,house,3 -2015-09-30,542051,house,3 -2015-12-31,549278,house,3 -2016-03-31,556586,house,3 -2016-06-30,564267,house,3 -2016-09-30,572582,house,3 -2016-12-31,581485,house,3 -2017-03-31,590949,house,3 -2017-06-30,601041,house,3 -2017-09-30,609355,house,3 -2017-12-31,615743,house,3 -2018-03-31,619638,house,3 -2018-06-30,622466,house,3 -2018-09-30,624602,house,3 -2018-12-31,626608,house,3 -2019-03-31,628423,house,3 -2019-06-30,630814,house,3 -2019-09-30,631875,house,3 -2007-03-31,548969,house,4 -2007-06-30,548969,house,4 -2007-09-30,548969,house,4 -2007-12-31,548969,house,4 -2008-03-31,552484,house,4 -2008-06-30,559580,house,4 -2008-09-30,561852,house,4 -2008-12-31,565467,house,4 -2009-03-31,569682,house,4 -2009-06-30,574680,house,4 -2009-09-30,579369,house,4 -2009-12-31,588379,house,4 -2010-03-31,599614,house,4 -2010-06-30,608528,house,4 -2010-09-30,615603,house,4 -2010-12-31,623105,house,4 -2011-03-31,628969,house,4 -2011-06-30,634155,house,4 -2011-09-30,636582,house,4 -2011-12-31,637421,house,4 -2012-03-31,635411,house,4 -2012-06-30,633695,house,4 -2012-09-30,634803,house,4 -2012-12-31,633875,house,4 -2013-03-31,634229,house,4 -2013-06-30,635515,house,4 -2013-09-30,636687,house,4 -2013-12-31,641125,house,4 -2014-03-31,648174,house,4 -2014-06-30,655757,house,4 -2014-09-30,664635,house,4 -2014-12-31,673762,house,4 -2015-03-31,684006,house,4 -2015-06-30,694800,house,4 -2015-09-30,706711,house,4 -2015-12-31,718261,house,4 -2016-03-31,727736,house,4 -2016-06-30,737159,house,4 -2016-09-30,745430,house,4 -2016-12-31,755683,house,4 -2017-03-31,771216,house,4 -2017-06-30,789732,house,4 -2017-09-30,810694,house,4 -2017-12-31,828058,house,4 -2018-03-31,836056,house,4 -2018-06-30,837295,house,4 -2018-09-30,830727,house,4 -2018-12-31,820924,house,4 -2019-03-31,811121,house,4 -2019-06-30,803925,house,4 -2019-09-30,791446,house,4 -2007-09-30,735904,house,5 -2007-12-31,735904,house,5 -2008-03-31,735904,house,5 -2008-06-30,735904,house,5 -2008-09-30,758340,house,5 -2008-12-31,764025,house,5 -2009-03-31,770046,house,5 -2009-06-30,765555,house,5 -2009-09-30,765515,house,5 -2009-12-31,771280,house,5 -2010-03-31,773355,house,5 -2010-06-30,776325,house,5 -2010-09-30,772699,house,5 -2010-12-31,775199,house,5 -2011-03-31,778470,house,5 -2011-06-30,789627,house,5 -2011-09-30,789614,house,5 -2011-12-31,790965,house,5 -2012-03-31,794533,house,5 -2012-06-30,792171,house,5 -2012-09-30,800432,house,5 -2012-12-31,804474,house,5 -2013-03-31,807826,house,5 -2013-06-30,812224,house,5 -2013-09-30,805066,house,5 -2013-12-31,805682,house,5 -2014-03-31,811908,house,5 -2014-06-30,820368,house,5 -2014-09-30,843904,house,5 -2014-12-31,855039,house,5 -2015-03-31,866489,house,5 -2015-06-30,880625,house,5 -2015-09-30,891981,house,5 -2015-12-31,909131,house,5 -2016-03-31,923594,house,5 -2016-06-30,933589,house,5 -2016-09-30,952327,house,5 -2016-12-31,968331,house,5 -2017-03-31,980953,house,5 -2017-06-30,995349,house,5 -2017-09-30,1004117,house,5 -2017-12-31,1010848,house,5 -2018-03-31,1015529,house,5 -2018-06-30,1017752,house,5 -2018-09-30,1007114,house,5 -2018-12-31,1002323,house,5 -2019-03-31,998136,house,5 -2019-06-30,995363,house,5 -2019-09-30,970268,house,5 -2007-12-31,326076,unit,1 -2008-03-31,326076,unit,1 -2008-06-30,326076,unit,1 -2008-09-30,326076,unit,1 -2008-12-31,327321,unit,1 -2009-03-31,324712,unit,1 -2009-06-30,323556,unit,1 -2009-09-30,318922,unit,1 -2009-12-31,316914,unit,1 -2010-03-31,316751,unit,1 -2010-06-30,317711,unit,1 -2010-09-30,318695,unit,1 -2010-12-31,324778,unit,1 -2011-03-31,329856,unit,1 -2011-06-30,333049,unit,1 -2011-09-30,337144,unit,1 -2011-12-31,337400,unit,1 -2012-03-31,339125,unit,1 -2012-06-30,341807,unit,1 -2012-09-30,344793,unit,1 -2012-12-31,347754,unit,1 -2013-03-31,348491,unit,1 -2013-06-30,348512,unit,1 -2013-09-30,347962,unit,1 -2013-12-31,345573,unit,1 -2014-03-31,343298,unit,1 -2014-06-30,341289,unit,1 -2014-09-30,338293,unit,1 -2014-12-31,336520,unit,1 -2015-03-31,334488,unit,1 -2015-06-30,332703,unit,1 -2015-09-30,330278,unit,1 -2015-12-31,328300,unit,1 -2016-03-31,326476,unit,1 -2016-06-30,324725,unit,1 -2016-09-30,325127,unit,1 -2016-12-31,325521,unit,1 -2017-03-31,327870,unit,1 -2017-06-30,330319,unit,1 -2017-09-30,332481,unit,1 -2017-12-31,334804,unit,1 -2018-03-31,336637,unit,1 -2018-06-30,338105,unit,1 -2018-09-30,339220,unit,1 -2018-12-31,339350,unit,1 -2019-03-31,337838,unit,1 -2019-06-30,336551,unit,1 -2019-09-30,335449,unit,1 -2007-06-30,368817,unit,2 -2007-09-30,368817,unit,2 -2007-12-31,368817,unit,2 -2008-03-31,368817,unit,2 -2008-06-30,373482,unit,2 -2008-09-30,377481,unit,2 -2008-12-31,382010,unit,2 -2009-03-31,380810,unit,2 -2009-06-30,385791,unit,2 -2009-09-30,391161,unit,2 -2009-12-31,396448,unit,2 -2010-03-31,402898,unit,2 -2010-06-30,408608,unit,2 -2010-09-30,412509,unit,2 -2010-12-31,415991,unit,2 -2011-03-31,417970,unit,2 -2011-06-30,419777,unit,2 -2011-09-30,421158,unit,2 -2011-12-31,423144,unit,2 -2012-03-31,424673,unit,2 -2012-06-30,424249,unit,2 -2012-09-30,425453,unit,2 -2012-12-31,425922,unit,2 -2013-03-31,425751,unit,2 -2013-06-30,426621,unit,2 -2013-09-30,428398,unit,2 -2013-12-31,428365,unit,2 -2014-03-31,429283,unit,2 -2014-06-30,429361,unit,2 -2014-09-30,428911,unit,2 -2014-12-31,429832,unit,2 -2015-03-31,431567,unit,2 -2015-06-30,432730,unit,2 -2015-09-30,432791,unit,2 -2015-12-31,432801,unit,2 -2016-03-31,431418,unit,2 -2016-06-30,430880,unit,2 -2016-09-30,430654,unit,2 -2016-12-31,430308,unit,2 -2017-03-31,429897,unit,2 -2017-06-30,429059,unit,2 -2017-09-30,428878,unit,2 -2017-12-31,428532,unit,2 -2018-03-31,427856,unit,2 -2018-06-30,427623,unit,2 -2018-09-30,426970,unit,2 -2018-12-31,426936,unit,2 -2019-03-31,426669,unit,2 -2019-06-30,425659,unit,2 -2019-09-30,424412,unit,2 -2007-09-30,518911,unit,3 -2007-12-31,518911,unit,3 -2008-03-31,518911,unit,3 -2008-06-30,518911,unit,3 -2008-09-30,518911,unit,3 -2008-12-31,518911,unit,3 -2009-03-31,518911,unit,3 -2009-06-30,518911,unit,3 -2009-09-30,523285,unit,3 -2009-12-31,522862,unit,3 -2010-03-31,524008,unit,3 -2010-06-30,535063,unit,3 -2010-09-30,538694,unit,3 -2010-12-31,555117,unit,3 -2011-03-31,550851,unit,3 -2011-06-30,547981,unit,3 -2011-09-30,539828,unit,3 -2011-12-31,530987,unit,3 -2012-03-31,540344,unit,3 -2012-06-30,537592,unit,3 -2012-09-30,548326,unit,3 -2012-12-31,555644,unit,3 -2013-03-31,566706,unit,3 -2013-06-30,580696,unit,3 -2013-09-30,581428,unit,3 -2013-12-31,586470,unit,3 -2014-03-31,583883,unit,3 -2014-06-30,583370,unit,3 -2014-09-30,598512,unit,3 -2014-12-31,598812,unit,3 -2015-03-31,599507,unit,3 -2015-06-30,602877,unit,3 -2015-09-30,603343,unit,3 -2015-12-31,612295,unit,3 -2016-03-31,617363,unit,3 -2016-06-30,622045,unit,3 -2016-09-30,616198,unit,3 -2016-12-31,610618,unit,3 -2017-03-31,606935,unit,3 -2017-06-30,605273,unit,3 -2017-09-30,606850,unit,3 -2017-12-31,604413,unit,3 -2018-03-31,604293,unit,3 -2018-06-30,603434,unit,3 -2018-09-30,603281,unit,3 -2018-12-31,601167,unit,3 -2019-03-31,605637,unit,3 -2019-06-30,599339,unit,3 -2019-09-30,597884,unit,3 \ No newline at end of file diff --git a/tests/unused/unit/ml_handlers/data/movies.csv b/tests/unused/unit/ml_handlers/data/movies.csv deleted file mode 100644 index b2e75d71137..00000000000 --- a/tests/unused/unit/ml_handlers/data/movies.csv +++ /dev/null @@ -1,90 +0,0 @@ -movieId,title,genres -1,Toy Story (1995),Adventure|Animation|Children|Comedy|Fantasy -2,Jumanji (1995),Adventure|Children|Fantasy -3,Grumpier Old Men (1995),Comedy|Romance -4,Waiting to Exhale (1995),Comedy|Drama|Romance -5,Father of the Bride Part II (1995),Comedy -6,Heat (1995),Action|Crime|Thriller -7,Sabrina (1995),Comedy|Romance -8,Tom and Huck (1995),Adventure|Children -9,Sudden Death (1995),Action -10,GoldenEye (1995),Action|Adventure|Thriller -11,"American President, The (1995)",Comedy|Drama|Romance -12,Dracula: Dead and Loving It (1995),Comedy|Horror -13,Balto (1995),Adventure|Animation|Children -14,Nixon (1995),Drama -15,Cutthroat Island (1995),Action|Adventure|Romance -16,Casino (1995),Crime|Drama -17,Sense and Sensibility (1995),Drama|Romance -18,Four Rooms (1995),Comedy -19,Ace Ventura: When Nature Calls (1995),Comedy -20,Money Train (1995),Action|Comedy|Crime|Drama|Thriller -21,Get Shorty (1995),Comedy|Crime|Thriller -22,Copycat (1995),Crime|Drama|Horror|Mystery|Thriller -23,Assassins (1995),Action|Crime|Thriller -24,Powder (1995),Drama|Sci-Fi -25,Leaving Las Vegas (1995),Drama|Romance -26,Othello (1995),Drama -27,Now and Then (1995),Children|Drama -28,Persuasion (1995),Drama|Romance -29,"City of Lost Children, The (Cité des enfants perdus, La) (1995)",Adventure|Drama|Fantasy|Mystery|Sci-Fi -30,Shanghai Triad (Yao a yao yao dao waipo qiao) (1995),Crime|Drama -31,Dangerous Minds (1995),Drama -32,Twelve Monkeys (a.k.a. 12 Monkeys) (1995),Mystery|Sci-Fi|Thriller -34,Babe (1995),Children|Drama -36,Dead Man Walking (1995),Crime|Drama -38,It Takes Two (1995),Children|Comedy -39,Clueless (1995),Comedy|Romance -40,"Cry, the Beloved Country (1995)",Drama -41,Richard III (1995),Drama|War -42,Dead Presidents (1995),Action|Crime|Drama -43,Restoration (1995),Drama -44,Mortal Kombat (1995),Action|Adventure|Fantasy -45,To Die For (1995),Comedy|Drama|Thriller -46,How to Make an American Quilt (1995),Drama|Romance -47,Seven (a.k.a. Se7en) (1995),Mystery|Thriller -48,Pocahontas (1995),Animation|Children|Drama|Musical|Romance -49,When Night Is Falling (1995),Drama|Romance -50,"Usual Suspects, The (1995)",Crime|Mystery|Thriller -52,Mighty Aphrodite (1995),Comedy|Drama|Romance -53,Lamerica (1994),Adventure|Drama -54,"Big Green, The (1995)",Children|Comedy -55,Georgia (1995),Drama -57,Home for the Holidays (1995),Drama -58,"Postman, The (Postino, Il) (1994)",Comedy|Drama|Romance -60,"Indian in the Cupboard, The (1995)",Adventure|Children|Fantasy -61,Eye for an Eye (1996),Drama|Thriller -62,Mr. Holland's Opus (1995),Drama -63,Don't Be a Menace to South Central While Drinking Your Juice in the Hood (1996),Comedy|Crime -64,Two if by Sea (1996),Comedy|Romance -65,Bio-Dome (1996),Comedy -66,Lawnmower Man 2: Beyond Cyberspace (1996),Action|Sci-Fi|Thriller -68,French Twist (Gazon maudit) (1995),Comedy|Romance -69,Friday (1995),Comedy -70,From Dusk Till Dawn (1996),Action|Comedy|Horror|Thriller -71,Fair Game (1995),Action -72,Kicking and Screaming (1995),Comedy|Drama -73,"Misérables, Les (1995)",Drama|War -74,Bed of Roses (1996),Drama|Romance -75,Big Bully (1996),Comedy|Drama -76,Screamers (1995),Action|Sci-Fi|Thriller -77,Nico Icon (1995),Documentary -78,"Crossing Guard, The (1995)",Action|Crime|Drama|Thriller -79,"Juror, The (1996)",Drama|Thriller -80,"White Balloon, The (Badkonake sefid) (1995)",Children|Drama -81,Things to Do in Denver When You're Dead (1995),Crime|Drama|Romance -82,Antonia's Line (Antonia) (1995),Comedy|Drama -83,Once Upon a Time... When We Were Colored (1995),Drama|Romance -85,Angels and Insects (1995),Drama|Romance -86,White Squall (1996),Action|Adventure|Drama -87,Dunston Checks In (1996),Children|Comedy -88,Black Sheep (1996),Comedy -89,Nick of Time (1995),Action|Thriller -92,Mary Reilly (1996),Drama|Horror|Thriller -93,Vampire in Brooklyn (1995),Comedy|Horror|Romance -94,Beautiful Girls (1996),Comedy|Drama|Romance -95,Broken Arrow (1996),Action|Adventure|Thriller -96,In the Bleak Midwinter (1995),Comedy|Drama -97,"Hate (Haine, La) (1995)",Crime|Drama -99,Heidi Fleiss: Hollywood Madam (1995),Documentary -100,City Hall (1996),Drama|Thriller diff --git a/tests/unused/unit/ml_handlers/data/ratings.csv b/tests/unused/unit/ml_handlers/data/ratings.csv deleted file mode 100644 index eb8ce0e976d..00000000000 --- a/tests/unused/unit/ml_handlers/data/ratings.csv +++ /dev/null @@ -1,3207 +0,0 @@ -userId,movieId,rating,timestamp -1,1,4.0,964982703 -1,3,4.0,964981247 -1,6,4.0,964982224 -1,47,5.0,964983815 -1,50,5.0,964982931 -1,70,3.0,964982400 -3,31,0.5,1306463578 -4,21,3.0,986935199 -4,32,2.0,945173447 -4,45,3.0,986935047 -4,47,2.0,945173425 -4,52,3.0,964622786 -4,58,3.0,964538444 -5,1,4.0,847434962 -5,21,4.0,847435238 -5,34,4.0,847434881 -5,36,4.0,847435292 -5,39,3.0,847434961 -5,50,4.0,847434881 -5,58,5.0,847435238 -6,2,4.0,845553522 -6,3,5.0,845554296 -6,4,3.0,845554349 -6,5,5.0,845553938 -6,6,4.0,845553757 -6,7,4.0,845554264 -6,8,3.0,845555281 -6,10,3.0,845553253 -6,11,4.0,845553489 -6,13,3.0,845555588 -6,15,4.0,845554505 -6,16,4.0,845553819 -6,17,4.0,845553559 -6,19,2.0,845553382 -6,21,2.0,845553382 -6,22,5.0,845553875 -6,24,4.0,845554397 -6,25,3.0,845553695 -6,26,4.0,845555362 -6,27,3.0,845555402 -6,31,3.0,845553819 -6,32,4.0,845553426 -6,34,4.0,845553354 -6,36,5.0,845553726 -6,41,4.0,845554962 -6,43,4.0,845555607 -6,45,3.0,845553907 -6,46,4.0,845554551 -6,47,4.0,845553317 -6,50,1.0,845553381 -6,54,4.0,845555402 -6,60,4.0,845554263 -6,61,4.0,845555454 -6,62,4.0,845553660 -6,65,3.0,845555070 -6,66,3.0,845555151 -6,76,4.0,845555317 -6,79,3.0,845554907 -6,86,5.0,845556131 -6,87,3.0,845555300 -6,88,2.0,845555694 -6,89,4.0,845555124 -6,92,4.0,845555454 -6,93,4.0,845554584 -6,95,4.0,845553559 -6,100,3.0,845555151 -7,1,4.5,1106635946 -7,50,4.5,1106635993 -7,58,3.0,1106635520 -8,2,4.0,839463806 -8,10,2.0,839463509 -8,11,4.0,839463806 -8,21,4.0,839463564 -8,32,3.0,839463624 -8,34,5.0,839463546 -8,39,3.0,839463644 -8,47,4.0,839463546 -8,50,5.0,839463644 -9,41,3.0,1044656650 -11,6,5.0,902154266 -11,10,3.0,902154316 -11,36,4.0,902155135 -11,44,2.0,902154593 -11,95,3.0,902154458 -12,39,4.0,1247264471 -13,47,5.0,987895819 -14,4,3.0,835441653 -14,7,3.0,835441989 -14,19,1.0,835441168 -14,25,4.0,835441394 -14,32,4.0,835441168 -14,39,3.0,835441186 -14,47,5.0,835441133 -14,95,5.0,835441295 -15,1,2.5,1510577970 -15,44,1.0,1299424916 -15,47,3.5,1510571970 -16,47,3.5,1377477814 -16,50,4.0,1377476781 -17,1,4.5,1305696483 -17,44,3.5,1305696245 -17,47,4.0,1307262715 -17,50,4.5,1305697013 -18,1,3.5,1455209816 -18,2,3.0,1455617462 -18,6,4.0,1460138360 -18,16,4.5,1461311583 -18,32,4.0,1455209840 -18,34,2.5,1455617533 -18,36,4.0,1455617478 -18,47,4.5,1455050013 -18,50,5.0,1455049343 -18,70,3.5,1455735732 -19,1,4.0,965705637 -19,2,3.0,965704331 -19,3,3.0,965707636 -19,7,2.0,965706657 -19,10,2.0,965709556 -19,12,1.0,965705347 -19,13,3.0,965709102 -19,15,2.0,965710039 -19,19,2.0,965708339 -19,32,4.0,965703646 -19,34,4.0,965705661 -19,44,3.0,965710019 -19,47,3.0,965710720 -19,48,1.0,965709172 -19,54,2.0,965702660 -19,64,2.0,965708037 -19,65,2.0,965708217 -19,70,2.0,965704974 -19,87,2.0,965708059 -19,92,2.0,965712048 -20,2,3.0,1054038313 -20,8,1.0,1054038422 -20,13,4.0,1054038425 -20,34,4.0,1054038093 -20,48,5.0,1054038357 -21,1,3.5,1407618878 -21,2,3.5,1419795031 -21,10,5.0,1403459783 -21,19,2.5,1419795052 -21,38,2.5,1419795113 -21,44,1.0,1376822969 -21,48,3.0,1376822924 -23,6,4.0,1107342267 -23,29,4.0,1107341574 -23,32,3.5,1107341750 -23,50,4.0,1107163741 -23,58,3.0,1107164183 -24,6,4.5,1458941767 -24,32,3.5,1458942033 -24,50,4.0,1458942023 -26,10,3.0,836950403 -26,34,3.0,836950483 -26,47,4.0,836950431 -27,1,3.0,962685262 -27,2,4.0,962685711 -27,34,5.0,962685351 -27,48,4.0,962685318 -27,60,3.0,962685387 -27,62,5.0,962684909 -28,6,3.5,1234570483 -28,16,2.5,1234570375 -28,21,3.0,1242290535 -28,23,1.5,1242290862 -28,31,2.5,1234334920 -28,32,3.5,1234335329 -28,47,3.0,1235975946 -28,50,3.5,1234337966 -28,62,3.5,1242290542 -28,95,2.0,1234516201 -29,50,3.5,1308007653 -31,1,5.0,850466616 -31,5,3.0,850466642 -31,7,4.0,850466642 -31,10,4.0,850467366 -31,17,3.0,850466616 -31,25,2.0,850466616 -31,62,4.0,850466616 -32,1,3.0,856736119 -32,3,3.0,856736172 -32,6,3.0,856736172 -32,7,4.0,856736173 -32,21,4.0,856737002 -32,24,3.0,856737205 -32,25,4.0,856736119 -32,26,4.0,856736347 -32,32,4.0,856736119 -32,36,4.0,856736172 -32,39,3.0,856737205 -32,50,5.0,856737002 -32,52,3.0,856736227 -32,58,5.0,856736227 -32,62,3.0,856736119 -32,74,4.0,856736316 -32,78,4.0,856736477 -32,95,3.0,856736119 -32,100,4.0,856736290 -33,1,3.0,939647444 -33,7,1.0,939654896 -33,11,2.0,939654896 -33,17,4.0,939654828 -33,21,4.0,939715904 -33,25,3.0,939646902 -33,28,5.0,939654815 -33,32,3.0,939647370 -33,34,3.0,939646940 -33,36,5.0,939715317 -33,39,5.0,939654896 -33,43,2.0,939716739 -33,50,5.0,939646733 -33,58,4.0,939646784 -33,94,4.0,939716218 -34,10,5.0,1162048773 -34,70,3.5,1162048002 -35,11,4.0,830939577 -35,21,5.0,830939505 -35,39,3.0,830939546 -35,50,5.0,830939598 -35,60,5.0,830939912 -35,62,5.0,830939748 -36,25,2.5,1100803583 -38,11,5.0,841341447 -38,17,3.0,841341494 -38,21,3.0,841341362 -38,39,3.0,841341384 -38,48,3.0,841341570 -38,50,5.0,841341362 -38,62,3.0,841341570 -39,32,3.0,974787510 -39,47,3.0,974789632 -39,50,5.0,974788030 -40,1,5.0,832058959 -40,17,5.0,832059273 -40,19,2.0,832059137 -40,21,4.0,832059053 -40,26,4.0,832059937 -40,31,4.0,832059371 -40,34,5.0,832059080 -40,44,3.0,832059393 -40,46,4.0,832059892 -40,48,2.0,832059371 -40,60,4.0,832059509 -40,62,5.0,832059339 -40,82,5.0,832060151 -41,47,3.5,1458939486 -41,50,3.0,1459367479 -42,3,4.0,996221045 -42,7,3.0,996220162 -42,10,5.0,996215205 -42,11,5.0,996219314 -42,16,5.0,996218017 -42,19,2.0,996256258 -42,21,4.0,996219086 -42,22,5.0,996219167 -42,47,4.0,996218105 -42,50,5.0,996217838 -42,86,4.0,996220615 -42,95,3.0,996214545 -43,1,5.0,848993983 -43,3,5.0,848994405 -43,5,5.0,848994281 -43,7,5.0,848994392 -43,8,5.0,848994814 -43,10,4.0,848993747 -43,11,4.0,848993928 -43,23,5.0,848994451 -43,29,5.0,848994937 -43,34,5.0,848993816 -43,47,4.0,848993793 -43,48,5.0,848994152 -43,57,5.0,848994678 -43,60,5.0,848994424 -43,79,5.0,848994617 -43,95,4.0,848993983 -44,1,3.0,869251860 -44,3,3.0,869251910 -44,6,3.0,869251910 -44,12,1.0,869252043 -44,18,4.0,869252115 -44,36,4.0,869251910 -44,65,3.0,869252497 -44,66,3.0,869252563 -44,94,4.0,869252333 -44,95,4.0,869251861 -45,1,4.0,951170182 -45,5,3.0,959625102 -45,6,4.0,1121724608 -45,7,3.0,951170390 -45,11,3.0,951170225 -45,19,4.5,1091306129 -45,21,4.0,1091306011 -45,32,4.5,1121724503 -45,39,3.0,951170338 -45,50,5.0,951756750 -45,62,4.0,1091306047 -45,65,3.0,1020803228 -45,69,3.0,951170141 -45,70,4.0,951170563 -45,88,4.0,951170543 -46,1,5.0,834787906 -46,10,3.0,834787826 -46,32,4.0,834788094 -46,39,3.0,834788093 -46,50,5.0,834788094 -47,31,3.0,1496205717 -47,47,3.0,1496209354 -47,62,3.0,1496205312 -48,48,4.0,1127128718 -50,1,3.0,1514238116 -50,32,3.0,1523740563 -51,2,4.5,1230932741 -51,3,4.0,1230932736 -51,7,4.0,1230932700 -51,36,3.0,1230929322 -51,65,3.5,1230930652 -51,70,5.0,1230932691 -51,76,5.0,1230930644 -51,93,3.0,1230931640 -54,1,3.0,830247330 -54,17,3.0,830248246 -54,21,3.0,839921390 -54,32,3.0,830247417 -54,47,3.0,839921084 -54,50,3.0,830248246 -56,10,4.0,835799162 -56,11,4.0,835799366 -56,19,5.0,835799219 -56,39,4.0,835799274 -56,47,5.0,835799219 -56,69,4.0,835799457 -57,1,5.0,965796031 -57,6,3.0,972173446 -57,10,3.0,965798286 -57,11,3.0,965797264 -57,21,3.0,965796969 -57,32,4.0,965798685 -57,39,3.0,965796392 -57,50,5.0,965796686 -57,52,3.0,969753586 -57,65,1.0,965797815 -57,69,4.0,965797105 -57,70,1.0,965797305 -57,89,2.0,972174827 -57,95,3.0,969754664 -58,3,3.0,847719397 -58,5,4.0,847719151 -58,7,5.0,847719397 -58,19,1.0,847718718 -58,21,4.0,847718718 -58,22,3.0,847719108 -58,31,4.0,847719088 -58,32,5.0,847718745 -58,36,4.0,847718991 -58,39,5.0,847718745 -58,44,2.0,847718960 -58,47,5.0,847718657 -58,48,3.0,847719035 -58,50,5.0,847718718 -58,62,3.0,847718910 -59,10,3.0,953609378 -59,41,5.0,953609923 -60,48,3.0,1393541734 -60,50,3.0,1393542060 -60,60,3.0,1393541955 -61,16,4.0,1145531659 -61,32,4.5,1145532647 -61,50,4.5,1145532639 -62,2,4.0,1528843890 -62,6,4.5,1522190219 -62,47,4.5,1521489234 -63,1,5.0,1443199669 -63,10,3.0,1443201199 -63,32,3.0,1443199999 -63,34,3.0,1443201169 -63,47,4.0,1443201084 -63,50,5.0,1443199758 -64,1,4.0,1161520134 -64,3,3.5,1161519668 -64,6,4.5,1161520752 -64,16,5.0,1161528794 -64,19,3.5,1161521687 -64,22,3.5,1161559916 -64,25,3.5,1161521571 -64,32,4.0,1161520763 -64,34,4.5,1161520212 -64,36,4.0,1161521343 -64,39,4.0,1161520967 -64,45,3.5,1161564506 -64,47,4.5,1161520185 -64,48,3.0,1161529467 -64,50,3.0,1161528982 -64,70,4.0,1161559767 -66,1,4.0,1104643957 -66,5,4.0,1113190367 -66,18,4.0,1113190353 -66,19,3.0,1093143913 -66,21,4.0,1113190363 -66,29,4.5,1099187646 -66,32,5.0,1093747471 -66,47,5.0,1093747353 -66,50,4.0,1104644110 -68,1,2.5,1158531426 -68,2,2.5,1158532776 -68,3,2.0,1158533415 -68,5,2.0,1158533624 -68,6,4.0,1158532058 -68,7,2.0,1230498124 -68,10,4.5,1158531612 -68,11,4.5,1158531050 -68,16,3.5,1158533018 -68,17,3.5,1158531987 -68,18,2.0,1532897231 -68,19,1.5,1158532448 -68,25,3.5,1158531974 -68,26,3.0,1158534106 -68,31,3.5,1158535464 -68,34,1.0,1158531735 -68,39,4.0,1158532000 -68,44,3.0,1158534993 -68,47,4.0,1158531489 -68,48,4.0,1158533544 -68,50,3.0,1158531764 -68,62,3.5,1158531021 -68,65,1.5,1269123315 -68,70,4.0,1158534541 -68,95,3.5,1158532180 -69,50,5.0,1021646926 -70,36,5.0,1355198746 -71,1,5.0,864737933 -71,7,3.0,864738008 -71,17,1.0,864737933 -71,24,2.0,864740028 -71,62,4.0,864737933 -71,86,5.0,864738119 -71,95,4.0,864737933 -72,32,4.5,1217324825 -72,47,4.5,1217324851 -72,50,4.5,1217324720 -73,1,4.5,1464196374 -74,58,5.0,1207502891 -75,47,2.0,1158968272 -76,1,0.5,1439165548 -76,47,3.5,1439168120 -76,48,0.5,1439168949 -78,1,4.0,1252575124 -78,20,3.0,1252573422 -78,32,3.5,1252575140 -79,6,4.0,975282111 -80,32,4.0,1377308186 -80,50,4.5,1377308037 -81,10,1.0,845299756 -81,32,5.0,845299983 -81,47,3.0,845299983 -82,1,2.5,1084467729 -82,2,3.0,1084465035 -82,6,3.5,1084467865 -82,10,3.5,1084467796 -82,34,2.0,1084467775 -82,47,3.5,1084467783 -84,4,3.0,858772461 -84,5,3.0,857653289 -84,6,4.0,857653289 -84,7,3.0,857653289 -84,10,3.0,860397812 -84,11,4.0,858771861 -84,14,4.0,857653349 -84,17,5.0,857653240 -84,21,4.0,858772111 -84,25,5.0,860396793 -84,31,3.0,860398679 -84,34,4.0,858772153 -84,36,5.0,857653289 -84,45,4.0,858772239 -84,46,3.0,858771890 -84,50,4.0,857653594 -84,52,5.0,857653318 -84,55,4.0,858772543 -84,57,3.0,858771951 -84,62,4.0,857653240 -84,94,4.0,857653422 -84,95,2.0,857653240 -84,100,3.0,860396882 -85,53,5.0,889468268 -86,1,4.0,1344082549 -87,60,3.0,1270702696 -88,16,4.5,1331421395 -88,50,5.0,1331421330 -88,69,3.5,1331420307 -89,1,3.0,1520408314 -89,11,2.5,1520408449 -89,88,2.0,1520408790 -90,1,3.0,856353996 -90,7,4.0,856354037 -90,14,5.0,856354100 -90,17,5.0,856353996 -90,25,5.0,856353996 -90,32,4.0,856353996 -90,36,4.0,856354037 -90,52,5.0,856354072 -90,58,5.0,856354071 -90,68,3.0,856354249 -90,81,3.0,856354174 -90,82,5.0,856354212 -90,85,5.0,856354195 -91,1,4.0,1112713037 -91,2,3.0,1112713392 -91,3,3.0,1112712323 -91,6,5.0,1112712032 -91,10,3.5,1112713269 -91,16,4.5,1112710867 -91,19,2.0,1112713417 -91,21,4.0,1112712052 -91,22,3.5,1112712292 -91,25,2.0,1112713314 -91,29,4.0,1112711719 -91,32,4.0,1112711273 -91,36,3.0,1112712316 -91,39,1.5,1112713319 -91,41,4.0,1112716937 -91,47,4.5,1112712832 -91,50,4.5,1112712816 -91,58,2.0,1112710933 -91,88,3.0,1112716912 -91,92,2.0,1112716903 -91,95,3.0,1112711260 -93,1,3.0,942767337 -93,2,5.0,942946208 -93,10,4.0,942946208 -93,15,4.0,942946091 -93,34,5.0,942767143 -93,60,4.0,942946445 -93,86,4.0,942946013 -94,2,4.0,843406960 -94,10,3.0,843406732 -94,11,3.0,843406930 -94,17,1.0,843406942 -94,19,2.0,843406846 -94,21,3.0,843406846 -94,32,5.0,843406866 -94,34,4.0,843406765 -94,39,1.0,843406866 -94,44,1.0,843406960 -94,47,2.0,843406765 -94,95,3.0,843406942 -95,7,3.0,1043340043 -95,18,3.5,1105400752 -95,25,5.0,1044744590 -95,29,5.0,1043340522 -95,32,4.0,1043340522 -95,34,4.0,1071803856 -95,39,4.0,1043339476 -96,1,5.0,964772990 -96,34,5.0,964773008 -96,50,5.0,964773008 -98,1,4.5,1532457849 -99,10,4.0,829827514 -99,22,4.0,829828005 -99,23,4.0,829828005 -100,3,3.5,1100183804 -100,11,4.0,1100184041 -100,16,4.5,1100185959 -100,17,4.5,1100184147 -100,19,1.0,1100183757 -100,28,4.5,1100184447 -100,62,4.0,1100185952 -100,74,4.0,1100186732 -100,89,4.0,1100186731 -100,95,4.5,1100185961 -102,3,5.0,840635033 -102,6,3.0,835877535 -102,21,3.0,835876107 -102,23,3.0,835877570 -102,39,3.0,835876151 -102,47,5.0,835876045 -103,1,4.0,1431954238 -103,2,4.0,1431957270 -103,5,4.0,1431957598 -103,16,5.0,1450982615 -103,18,5.0,1431969228 -103,19,3.5,1431957278 -103,34,4.0,1431957104 -103,36,4.0,1431957252 -103,48,3.5,1431957563 -103,50,4.0,1431955220 -103,60,4.0,1431968436 -103,70,3.5,1431957632 -104,2,3.0,1114809641 -104,10,3.0,1048595683 -104,31,4.0,1049135743 -104,39,4.0,1048587379 -104,47,0.5,1053336550 -104,87,3.0,1048795372 -105,6,4.0,1446773632 -105,16,4.5,1446749417 -105,32,3.5,1446571805 -105,47,5.0,1446571714 -105,50,5.0,1446571713 -107,1,4.0,829322340 -107,2,5.0,829322340 -107,5,4.0,829322340 -107,11,5.0,829322340 -107,62,5.0,829322340 -108,25,4.0,1042838964 -108,82,5.0,1042839636 -109,6,3.0,841108665 -109,11,4.0,841108045 -109,14,4.0,841109326 -109,16,4.0,841108751 -109,18,3.0,841109921 -109,21,3.0,841107538 -109,25,5.0,841108589 -109,31,3.0,841108623 -109,32,4.0,841107643 -109,34,3.0,841107487 -109,36,5.0,841143673 -109,39,3.0,841107584 -109,45,3.0,841108914 -109,47,3.0,841107393 -109,50,4.0,841107584 -109,52,3.0,841109666 -109,62,5.0,841108564 -109,76,3.0,841151480 -110,47,4.5,1175330162 -111,5,3.5,1517441319 -111,16,4.5,1518640768 -111,24,2.5,1518640854 -111,34,2.5,1516153818 -111,39,4.0,1516153474 -111,48,3.5,1518640791 -111,65,3.5,1518640926 -112,1,3.0,1442535639 -112,2,1.5,1513989948 -112,6,4.5,1513989933 -112,16,4.5,1513990003 -112,17,0.5,1513989967 -112,19,4.0,1513989970 -112,21,2.0,1513989975 -112,25,2.5,1513989973 -112,32,5.0,1442535842 -112,36,0.5,1513989966 -112,39,0.5,1513989927 -112,47,5.0,1442535846 -112,50,5.0,1442535839 -112,62,4.0,1513989987 -112,95,1.5,1513989977 -113,11,3.0,980051838 -113,25,1.0,980051660 -113,39,3.0,980051704 -113,46,3.0,980051838 -113,64,2.0,980051988 -113,71,1.0,980051522 -113,74,3.0,980051922 -115,21,4.0,970756771 -115,32,5.0,958574098 -115,34,2.0,957760059 -116,3,3.5,1337200325 -116,47,3.5,1337199584 -117,2,3.0,844163002 -117,3,3.0,844163663 -117,5,3.0,844163754 -117,6,3.0,844163102 -117,7,4.0,844163615 -117,10,3.0,844162850 -117,11,4.0,844162970 -117,17,3.0,844163037 -117,19,2.0,844162892 -117,21,4.0,844162913 -117,26,4.0,844163712 -117,31,3.0,844163204 -117,32,3.0,844162955 -117,34,3.0,844163454 -117,36,3.0,844163102 -117,39,3.0,844162955 -117,41,4.0,844163693 -117,44,2.0,844163037 -117,47,4.0,844162892 -117,48,3.0,844163082 -117,50,4.0,844162933 -117,60,3.0,844163754 -117,62,4.0,844163122 -117,73,4.0,844163663 -118,25,2.0,944924731 -119,1,3.5,1435942468 -119,10,4.0,1435943180 -119,44,3.0,1435943918 -120,5,4.0,860070029 -120,12,3.0,860070182 -120,32,3.0,860069973 -120,52,3.0,860070065 -121,1,4.0,847656180 -121,5,3.0,847656405 -121,6,5.0,847656264 -121,11,4.0,847656100 -121,16,5.0,847656340 -121,19,2.0,847656045 -121,22,3.0,847656357 -121,25,4.0,847656224 -121,39,4.0,847656062 -121,44,1.0,847656224 -121,47,3.0,847656010 -121,62,5.0,847656203 -121,95,3.0,847656129 -122,2,4.0,1461561176 -122,19,3.5,1461562132 -122,32,5.0,1461561526 -122,47,4.5,1461561420 -122,50,5.0,1461561151 -122,70,4.5,1461562250 -123,47,4.5,1447291940 -124,1,4.0,1336584336 -124,50,4.5,1336412889 -125,2,4.0,1474311709 -125,81,3.0,1474415153 -126,34,3.0,845925854 -126,47,5.0,845925822 -129,47,3.5,1167376335 -130,1,3.0,832589610 -131,31,3.0,1349838570 -131,47,4.0,1349840567 -131,50,4.0,1349840171 -132,1,2.0,1157921785 -132,17,3.0,1157922698 -132,29,2.0,1157924165 -132,32,3.0,1329983726 -132,34,1.5,1157921395 -132,39,3.0,1157921453 -132,45,2.5,1157923125 -132,47,4.0,1157921243 -132,48,3.0,1157919960 -132,50,4.0,1157920377 -132,58,2.0,1157919923 -132,70,2.5,1157923053 -132,89,2.5,1157997580 -133,32,4.0,843491488 -133,47,4.0,843491396 -133,50,3.0,843491446 -134,1,3.0,832841103 -134,47,4.0,832841168 -134,48,3.0,832841524 -135,1,4.0,1009691859 -135,2,3.0,1009692764 -135,21,3.0,1009691915 -135,32,5.0,1009691695 -135,47,5.0,1009691144 -135,65,1.0,1009692359 -136,10,5.0,832449222 -136,15,5.0,832449934 -136,16,5.0,832449614 -136,19,3.0,832449345 -136,23,5.0,832449838 -136,34,2.0,832449299 -136,44,2.0,832449539 -136,47,5.0,832449299 -136,62,5.0,832449522 -136,93,4.0,832450076 -136,95,4.0,832449391 -137,1,4.0,1204859907 -139,19,1.0,1453924016 -140,1,3.0,942924980 -140,2,3.5,1085569813 -140,6,5.0,942843185 -140,11,4.0,949667337 -140,21,4.0,949666898 -140,22,3.0,951163606 -140,23,3.0,967049087 -140,34,4.0,942910010 -140,47,4.0,942842215 -140,50,3.0,942840991 -140,62,4.5,1055092420 -140,86,4.0,942844005 -140,95,2.5,1085569725 -141,1,4.0,1513130643 -141,19,2.0,1513130814 -141,47,3.0,1513130660 -142,34,4.0,838932132 -142,36,4.0,838933753 -142,47,4.0,838934238 -142,50,5.0,838934155 -142,95,3.0,838934522 -144,1,3.5,1137323419 -144,2,3.0,1137323803 -144,10,3.0,1137323629 -144,17,4.0,1137323659 -144,19,3.0,1136812137 -144,25,3.0,1136813341 -144,32,4.0,1137323444 -144,34,3.0,1137323545 -144,39,3.5,1137323676 -144,47,4.5,1137323517 -144,48,4.5,1137324255 -145,1,5.0,832105242 -145,50,5.0,832105428 -146,32,5.0,1312508179 -147,5,4.5,1203267700 -149,2,1.0,902084874 -149,32,4.0,902085272 -150,3,3.0,854203124 -150,5,3.0,854203124 -150,6,4.0,854203123 -150,7,3.0,854203124 -150,25,4.0,854203072 -150,32,5.0,854203071 -150,36,4.0,854203123 -150,52,4.0,854203163 -150,58,3.0,854203163 -150,62,3.0,854203072 -150,79,3.0,854203229 -150,95,3.0,854203072 -151,1,5.0,855947195 -151,3,3.0,855947242 -151,9,4.0,855947372 -151,12,3.0,855947434 -151,62,4.0,855947196 -151,75,3.0,855948083 -151,92,1.0,855948256 -151,95,4.0,855947196 -152,47,5.0,1450867741 -152,50,4.5,1450572430 -153,1,2.0,1525548642 -153,2,2.0,1525550601 -155,1,3.0,961861723 -156,1,4.0,1106854640 -156,11,3.0,946799769 -156,17,4.0,939884874 -156,19,3.0,1106855017 -156,21,5.0,946799679 -156,25,4.0,1106854805 -156,34,4.0,939853183 -156,39,1.0,939842934 -156,45,4.0,946799570 -156,47,3.5,1106854709 -156,50,4.0,940001349 -156,52,3.5,1106855391 -156,58,4.0,1106855269 -156,62,2.0,1106854830 -156,68,2.0,946799375 -159,1,4.5,1508640172 -159,31,3.5,1508641164 -159,62,3.0,1508641179 -160,1,4.0,971115026 -160,2,4.0,971619578 -160,6,2.0,971115114 -160,10,1.0,971196422 -160,22,1.0,971437089 -160,32,5.0,971113953 -160,34,5.0,971619022 -160,44,3.0,971115727 -160,47,5.0,971115962 -160,50,4.0,971113158 -160,60,2.0,971619579 -160,76,4.0,971196402 -160,79,1.0,971196754 -160,85,5.0,991075851 -160,93,1.0,976798624 -160,95,1.0,971112529 -161,1,4.0,1176751765 -161,48,4.0,1176498494 -162,4,3.0,836684306 -162,16,5.0,836511416 -162,17,5.0,836510953 -162,31,4.0,836511596 -162,36,5.0,836511416 -162,50,4.0,836511263 -162,62,5.0,836510953 -166,1,5.0,1189980529 -166,6,3.5,1190828796 -166,10,4.5,1190827465 -166,17,4.0,1190828781 -166,32,4.0,1189038252 -166,47,4.0,1188774624 -166,50,5.0,1188774404 -167,1,3.5,1154721923 -167,39,2.0,1154723333 -167,69,2.5,1154719322 -169,1,4.5,1059427918 -169,2,4.0,1078284713 -169,3,5.0,1078284750 -169,5,5.0,1078284788 -169,7,4.5,1078284741 -169,11,4.0,1059427956 -169,34,4.0,1059427862 -169,39,3.5,1059428140 -169,48,3.5,1059427123 -169,60,4.0,1078285375 -169,62,5.0,1078284604 -169,73,4.0,1070250173 -170,5,3.0,840473290 -170,10,3.0,840472869 -170,34,5.0,840472895 -170,48,4.0,840473093 -170,95,3.0,840473046 -171,1,5.0,866904159 -171,25,5.0,866904159 -171,29,5.0,866904396 -171,32,5.0,866904158 -171,36,4.0,866904192 -171,47,5.0,866905267 -171,81,5.0,866904379 -173,10,3.0,843397944 -173,17,4.0,843398078 -174,10,3.0,848486985 -174,11,5.0,848487132 -174,32,3.0,848487101 -174,34,4.0,848487060 -174,39,4.0,848487101 -174,50,3.0,848487075 -174,62,1.0,848487212 -176,10,5.0,840108984 -176,39,3.0,840108930 -176,47,5.0,840109138 -177,1,5.0,1435533535 -177,2,3.5,1435534109 -177,7,1.0,1435534432 -177,11,3.0,1435890660 -177,16,3.0,1435890664 -177,19,2.0,1435534140 -177,28,2.5,1435536420 -177,39,4.0,1435890554 -177,47,4.5,1435533571 -177,48,3.0,1435534447 -177,50,4.0,1435523529 -177,60,3.0,1435535258 -178,1,4.0,1164354911 -178,10,4.0,1164355337 -178,25,4.5,1164355401 -178,47,4.5,1164355292 -178,50,4.5,1163673981 -179,1,4.0,852114051 -179,3,4.0,852114317 -179,7,3.0,852115405 -179,9,3.0,852114156 -179,18,4.0,852115405 -179,19,3.0,840907679 -179,32,4.0,852114116 -179,34,5.0,840907679 -179,47,4.0,840907616 -179,52,4.0,852115696 -179,65,3.0,852115576 -179,95,3.0,852114051 -181,5,3.0,845470124 -181,6,3.0,845469804 -181,7,3.0,845470611 -181,10,2.0,845469438 -181,11,5.0,845469653 -181,16,3.0,845469893 -181,21,2.0,845469555 -181,22,3.0,845469972 -181,24,3.0,845470571 -181,25,1.0,845469842 -181,31,3.0,845469893 -181,34,5.0,845469500 -181,39,3.0,845469625 -181,45,3.0,845470124 -181,47,3.0,845469500 -181,61,4.0,845472115 -181,62,4.0,845469756 -181,79,4.0,845470717 -181,86,4.0,845472271 -181,100,3.0,845470909 -182,1,4.0,1063289621 -182,6,4.5,1054782012 -182,10,3.5,1054782216 -182,14,4.0,1063289654 -182,16,5.0,1054783631 -182,17,4.0,1066428620 -182,18,5.0,1055153282 -182,21,2.5,1054782030 -182,23,3.5,1055153587 -182,25,4.5,1054783186 -182,26,4.0,1063648819 -182,29,4.0,1054779789 -182,32,4.0,1054779785 -182,36,4.5,1063289589 -182,41,4.5,1054781875 -182,44,1.5,1055150820 -182,45,3.0,1075764933 -182,47,4.0,1054781315 -182,50,4.5,1054781309 -182,69,3.0,1054784267 -182,70,4.5,1077804802 -182,76,3.5,1055152107 -182,81,3.5,1055154219 -182,89,3.0,1055151186 -182,94,4.0,1075765007 -182,97,4.5,1075764905 -182,100,3.0,1055153511 -185,1,4.0,1044311830 -185,34,2.0,1044311830 -186,1,4.0,1031080831 -186,2,4.0,1031087675 -186,10,4.0,1031088020 -187,16,4.0,1161849621 -187,25,3.0,1161872627 -187,29,4.0,1161849623 -187,47,4.0,1161850486 -187,50,4.5,1161849680 -187,70,4.0,1161849108 -187,97,3.0,1180301412 -188,7,4.0,962559461 -191,1,4.0,829759809 -191,6,4.0,829759809 -191,16,4.0,829759809 -191,17,5.0,829759809 -191,21,4.0,829759809 -191,25,5.0,829759809 -191,32,5.0,829759809 -191,34,4.0,829760897 -191,36,5.0,829759809 -191,39,1.0,829760897 -191,47,4.0,829760898 -191,50,5.0,829760898 -191,52,5.0,829759809 -191,58,4.0,829759809 -191,72,4.0,829760897 -191,85,5.0,829759809 -191,94,4.0,829759809 -191,95,3.0,829759809 -191,99,5.0,829759809 -192,10,5.0,835128874 -192,47,3.0,835129031 -193,1,2.0,1435856890 -194,48,2.0,1110316714 -195,6,4.0,974705807 -195,10,4.0,974705349 -195,16,4.0,974705903 -195,25,4.0,1008558673 -195,32,4.0,974709650 -195,36,4.0,1008558588 -195,50,5.0,974705671 -195,70,4.0,979858326 -196,62,4.5,1460954240 -197,50,3.0,947462391 -198,17,3.0,1034136028 -198,24,4.0,1034138101 -198,25,4.0,1034136139 -198,32,5.0,1034135531 -198,34,4.0,1034137414 -198,36,5.0,1034136028 -198,47,5.0,1034136177 -198,50,5.0,1034136008 -198,58,5.0,1034137364 -198,66,1.0,1034135137 -199,6,4.0,1057590506 -199,7,3.0,940544181 -199,11,4.0,940543988 -199,20,2.0,1022161793 -199,21,4.0,940372914 -199,25,5.0,940372513 -199,36,4.0,940372656 -199,47,3.0,940372883 -199,50,4.0,940372419 -199,62,1.0,941295529 -199,81,3.0,940544216 -199,85,1.0,940380890 -200,1,3.5,1229886312 -200,5,4.0,1229876436 -200,10,4.5,1229887453 -200,19,3.5,1229877095 -200,34,2.5,1229877775 -200,39,5.0,1229886362 -200,47,4.0,1229885752 -200,62,3.0,1229886642 -201,1,5.0,939801780 -201,11,4.0,939227085 -201,16,4.0,939227554 -201,24,4.0,941211478 -201,25,5.0,939227591 -201,32,4.0,939833041 -201,34,5.0,939801740 -201,46,1.0,939227085 -202,1,4.0,974923506 -202,2,4.0,974923336 -202,6,5.0,974918622 -202,10,4.0,974919042 -202,11,4.0,975013705 -202,29,4.0,974923156 -202,32,4.0,974925068 -202,44,2.0,974923392 -202,49,3.0,974925453 -202,50,4.0,974924628 -202,58,4.0,975013724 -202,62,3.0,975013683 -203,31,3.5,1390094511 -204,47,5.0,1327182956 -206,1,5.0,850763267 -206,7,4.0,850763310 -206,14,4.0,850763367 -206,17,5.0,850763267 -206,25,5.0,850763267 -206,32,3.0,850763267 -206,36,5.0,850763310 -206,58,5.0,850763367 -206,62,4.0,850763267 -206,95,3.0,850763267 -207,100,3.0,1258548270 -208,10,2.0,940639452 -211,50,4.0,1350912267 -213,1,3.5,1316196157 -214,1,3.0,853937855 -214,17,3.0,853937855 -214,25,2.0,853937855 -214,62,3.0,853937855 -214,66,3.0,853938014 -214,83,3.0,853938185 -215,50,5.0,1260908668 -216,1,3.0,975211713 -216,21,3.0,975212544 -216,34,5.0,975212451 -216,39,3.0,975212451 -216,48,2.0,975211866 -217,1,4.0,955942540 -217,2,2.0,955942327 -217,3,1.0,955944713 -217,6,2.0,955935939 -217,9,3.0,955941157 -217,10,4.0,955940584 -217,12,3.0,955945336 -217,19,1.0,955945611 -217,20,2.0,955941424 -217,22,3.0,955943052 -217,34,4.0,955943345 -217,38,2.0,955945548 -217,44,2.0,955941505 -217,45,2.0,955943999 -217,47,2.0,955942953 -217,50,3.0,955942801 -217,60,2.0,955942221 -217,65,1.0,955945452 -217,87,3.0,955945423 -217,89,4.0,955940533 -217,95,3.0,955941157 -219,1,3.5,1194681084 -219,2,2.5,1194740185 -219,6,3.5,1198783144 -219,10,4.5,1194932162 -219,19,2.5,1194932235 -219,21,3.5,1199581468 -219,32,3.5,1194686177 -219,44,1.5,1195349252 -219,47,3.5,1194686017 -219,50,5.0,1194685882 -219,65,1.0,1198782611 -219,95,1.5,1198782277 -220,1,5.0,1230055565 -220,6,3.5,1230061735 -220,10,4.0,1230055828 -220,32,4.5,1230055680 -220,34,4.5,1230055796 -220,47,3.0,1230055738 -220,50,5.0,1230054959 -221,2,3.5,1111177796 -221,29,4.5,1119984574 -221,32,5.0,1111177792 -221,50,4.5,1118246575 -221,58,4.5,1111176234 -222,2,2.5,1391353926 -222,19,3.5,1391351897 -222,32,3.0,1391353917 -222,47,4.0,1391350444 -222,50,3.0,1391346849 -223,1,3.5,1226209758 -223,34,1.0,1226209953 -223,47,3.0,1226209770 -224,39,5.0,971812919 -225,69,5.0,949111262 -226,1,3.5,1095662606 -226,2,3.0,1095662788 -226,3,3.5,1095662861 -226,10,4.0,1095662675 -226,16,4.5,1095662900 -226,19,3.5,1095662814 -226,22,2.0,1095662268 -226,32,4.0,1095662618 -226,39,3.0,1095662724 -226,44,3.5,1095663137 -226,47,5.0,1160003508 -226,48,3.0,1095663041 -226,60,2.5,1114838860 -226,63,3.5,1096420461 -226,65,3.0,1095712984 -226,69,4.0,1172040506 -226,88,3.0,1097545177 -227,17,3.5,1447210004 -227,32,4.5,1447210296 -227,47,5.0,1447209787 -228,50,4.5,1363222968 -228,65,2.0,1363222731 -229,1,5.0,838144316 -229,5,3.0,838143681 -229,10,4.0,836941790 -229,19,3.0,836942063 -229,21,4.0,836942097 -229,34,5.0,836942064 -229,36,4.0,838147251 -229,45,3.0,838143681 -230,2,2.5,1196305107 -230,34,2.0,1196304670 -230,39,3.0,1196304844 -230,47,3.0,1196304391 -232,1,3.5,1076955621 -232,2,4.0,1085351710 -232,10,3.0,1218167397 -232,39,3.0,1182909940 -232,47,4.5,1241823324 -232,48,2.5,1218169473 -233,1,3.0,1524781249 -233,47,3.5,1524781264 -233,50,4.0,1472587568 -234,1,5.0,1004409347 -234,24,5.0,1004407893 -234,34,3.0,1004409582 -234,42,4.0,1004408338 -234,48,5.0,1004409503 -234,60,4.0,1004409020 -234,65,3.0,1001975877 -235,10,2.0,841422389 -235,11,4.0,841422530 -235,21,4.0,841422461 -235,25,5.0,841422634 -235,32,4.0,841422499 -235,34,4.0,841422446 -235,36,4.0,841422650 -235,39,3.0,841422477 -235,48,3.0,841422615 -235,62,5.0,841422615 -237,32,5.0,1411233598 -237,50,2.5,1410631753 -239,1,4.0,1221158265 -239,6,5.0,1221158564 -239,11,5.0,1221159019 -239,16,4.5,1221159148 -239,20,3.5,1221147484 -239,21,4.0,1221158640 -239,23,3.5,1221147477 -239,32,5.0,1221159452 -239,47,5.0,1221158250 -239,50,4.5,1221158083 -239,95,3.5,1221158503 -240,1,5.0,849122434 -240,2,5.0,849122404 -240,3,4.0,849122858 -240,10,3.0,849122194 -240,16,3.0,849122640 -240,19,5.0,849122301 -240,31,4.0,849122640 -240,34,5.0,849122277 -240,39,5.0,849122324 -240,44,4.0,849122528 -240,46,3.0,849123161 -240,48,3.0,849122594 -240,60,4.0,849122924 -240,95,5.0,849122434 -241,47,4.0,1447540959 -241,50,4.0,1447536935 -242,21,3.0,834073178 -242,32,5.0,834073281 -242,39,3.0,834073303 -242,47,5.0,834073178 -243,10,5.0,837155138 -243,36,4.0,837155409 -243,44,4.0,837155345 -243,48,4.0,837155356 -243,62,5.0,837155394 -244,6,5.0,975092819 -244,10,5.0,975091789 -246,17,5.0,1354126066 -246,28,4.5,1354126962 -246,29,5.0,1353864666 -246,50,4.5,1353869486 -247,1,5.0,1467644119 -247,32,3.0,1467661273 -247,47,4.0,1467644262 -247,50,5.0,1467643861 -248,10,3.5,1534591944 -249,1,4.0,1347317775 -249,2,4.0,1353800871 -249,19,3.5,1354107358 -249,20,3.5,1355366891 -249,32,5.0,1346752537 -249,47,5.0,1346757700 -249,48,3.0,1346752050 -249,50,4.0,1364546154 -249,70,4.0,1355677606 -249,89,3.5,1370785235 -250,45,4.0,1121217522 -251,47,5.0,1470677268 -252,1,4.5,1498284904 -253,29,4.5,1286643322 -254,1,4.5,1180446553 -254,32,4.5,1180446451 -254,47,4.5,1180447550 -254,50,4.5,1180564704 -254,79,2.0,1180443477 -255,34,1.0,1005717433 -256,18,5.0,1447000271 -257,7,1.0,1141625546 -257,16,3.5,1141625441 -259,2,2.0,1146845339 -259,32,5.0,1146845633 -260,29,4.0,1109409486 -260,47,4.5,1109408487 -260,50,5.0,1109410623 -261,16,4.0,1404881583 -261,47,4.0,1404881499 -261,50,4.0,1404881245 -262,4,1.0,840306203 -262,7,3.0,840306238 -262,10,2.0,840305646 -262,17,3.0,840305810 -262,21,3.0,840305713 -262,25,3.0,840305912 -262,26,3.0,840309913 -262,28,5.0,840310932 -262,36,5.0,840305940 -262,48,1.0,840305912 -262,50,3.0,840305713 -262,57,3.0,840306644 -262,85,3.0,840306620 -263,1,4.0,940384199 -263,11,4.0,941590364 -263,17,5.0,940384427 -263,24,3.0,941590705 -263,34,4.0,940384374 -263,36,4.0,940384427 -263,39,4.0,941590574 -264,1,4.0,1136978964 -264,32,1.0,1136979041 -264,48,3.0,1136978326 -265,25,1.0,965318357 -265,32,4.0,965316504 -265,36,4.0,965316145 -265,79,2.0,965318627 -266,1,2.0,945669542 -266,6,4.0,944980835 -266,16,5.0,944981193 -266,17,1.0,944980787 -266,21,4.0,945669287 -266,24,1.0,948586506 -266,32,4.0,945751855 -266,39,2.0,945669397 -266,45,2.0,945669246 -266,50,4.0,944980462 -266,64,1.0,945669246 -266,69,5.0,945669505 -266,95,3.0,946768666 -267,29,4.0,997136080 -267,58,5.0,959807857 -268,29,5.0,940182766 -268,41,4.0,940181204 -268,46,1.0,940180773 -268,47,3.0,940180858 -268,50,5.0,940180799 -269,1,5.0,850865423 -269,3,4.0,850865480 -269,5,3.0,850865480 -269,6,5.0,850865480 -269,9,2.0,850865553 -269,25,5.0,850865423 -269,32,4.0,850865423 -269,63,3.0,850865688 -269,74,5.0,850865586 -269,76,2.0,850865622 -269,79,4.0,850865553 -269,81,3.0,850865720 -269,95,3.0,850865423 -270,1,5.0,853918728 -270,3,3.0,853918793 -270,5,3.0,853918793 -270,6,3.0,853918793 -270,7,3.0,853918793 -270,9,3.0,853918943 -270,14,5.0,853918850 -270,17,4.0,853918728 -270,25,4.0,853918728 -270,32,4.0,853918727 -270,36,5.0,853918793 -270,52,4.0,853918850 -270,58,4.0,853918849 -270,62,5.0,853918728 -270,79,2.0,853918942 -270,95,2.0,853918728 -271,32,4.0,1234302161 -273,1,5.0,835861234 -273,12,1.0,835860711 -273,21,5.0,835860782 -273,32,5.0,835861257 -273,34,4.0,835860782 -274,1,4.0,1171410158 -274,2,3.5,1171934785 -274,6,4.0,1197022122 -274,8,3.0,1172030892 -274,10,4.0,1171428459 -274,12,3.5,1171829597 -274,16,4.5,1171493420 -274,19,4.0,1171934796 -274,20,3.5,1171830022 -274,22,3.5,1171759024 -274,23,3.5,1171829251 -274,24,3.5,1171785219 -274,29,4.0,1238050945 -274,32,4.0,1171409321 -274,34,4.0,1171756208 -274,44,4.0,1171759773 -274,47,4.0,1171172762 -274,48,2.0,1171943719 -274,50,4.0,1171408986 -274,60,3.5,1171827419 -274,62,3.0,1171492326 -274,65,3.0,1171829616 -274,69,4.0,1171932360 -274,70,4.5,1171493880 -274,86,3.5,1171828191 -274,87,3.0,1197272712 -274,88,3.5,1171828649 -274,93,3.5,1172024378 -274,95,2.5,1174524214 -275,1,5.0,1049076484 -275,17,5.0,1049079511 -275,21,5.0,1049076555 -275,25,3.0,1049079449 -275,32,5.0,1049078728 -275,34,5.0,1049078728 -275,39,4.0,1049076538 -275,45,2.0,1049076616 -275,50,4.0,1049078044 -276,1,4.0,858350384 -276,2,4.0,858351189 -276,5,3.0,858350427 -276,7,4.0,858350645 -276,12,4.0,858350757 -276,19,4.0,858351186 -276,62,5.0,858350385 -276,88,5.0,858350816 -277,1,4.0,861812794 -277,32,5.0,861812794 -277,62,2.0,861812794 -277,65,3.0,861812976 -277,95,3.0,861812794 -278,50,5.0,1193753316 -279,1,3.0,1506394495 -279,50,3.5,1506394189 -280,1,4.5,1348435273 -280,7,4.5,1348532595 -280,19,3.0,1348435266 -280,27,4.5,1348531940 -280,39,4.0,1348532012 -280,50,4.5,1348434052 -282,1,4.5,1378495714 -282,6,4.0,1378497085 -282,10,3.5,1378497072 -282,16,4.0,1378491787 -282,25,4.0,1378490653 -282,31,4.5,1378488783 -282,32,4.0,1378497758 -282,50,4.5,1378489751 -283,1,3.0,901227602 -283,39,1.0,901228254 -283,63,3.0,901228285 -283,69,4.0,901228313 -283,70,3.0,901228337 -284,2,4.0,832699451 -284,10,4.0,832699451 -284,15,4.0,832699795 -284,19,4.0,832786975 -284,20,1.0,832699760 -284,21,3.0,832699760 -284,32,5.0,832699723 -284,39,3.0,832786975 -284,44,3.0,832699890 -284,47,3.0,832695534 -284,95,5.0,832699673 -286,6,4.5,1119563039 -286,7,3.5,1119562096 -286,39,3.5,1119562094 -286,47,5.0,1119562911 -286,70,3.0,1119563855 -287,16,2.0,1110229950 -287,29,4.5,1110231627 -287,48,1.0,1110229874 -287,50,3.5,1110230077 -287,62,2.0,1110231040 -288,1,4.5,1054568869 -288,2,2.0,978467973 -288,3,4.0,975691635 -288,5,2.0,978622571 -288,10,3.0,978465794 -288,12,2.0,978622871 -288,13,2.0,978469581 -288,17,3.5,1054569627 -288,21,4.0,975693063 -288,32,5.0,975692000 -288,34,4.0,975693063 -288,43,3.0,976122034 -288,47,3.5,1054568985 -288,48,2.0,978469623 -288,73,3.0,979163671 -288,87,3.0,1174395882 -288,95,1.0,978466299 -289,3,2.5,1143424657 -289,16,4.5,1143424648 -290,1,4.0,975031464 -290,11,4.0,974943069 -290,24,3.0,975032355 -290,25,4.0,974942930 -290,34,4.0,974942304 -290,36,4.0,975031318 -290,50,4.0,975031748 -291,1,4.0,1453051567 -292,1,4.0,1219625000 -292,10,3.5,1219625069 -292,19,1.5,1442099069 -292,32,2.0,1019516667 -292,34,3.5,1219625047 -292,62,3.0,1293563062 -293,1,3.0,1044870886 -294,2,3.0,966634189 -294,3,1.0,966596854 -294,6,3.0,966597476 -294,10,3.0,966634030 -294,12,1.0,966597190 -294,19,2.0,966597233 -294,21,3.0,966595514 -294,39,2.0,966595276 -294,44,3.0,966634266 -294,47,2.0,966597476 -294,50,3.0,966597387 -294,60,1.0,966634119 -294,65,3.0,966597039 -294,69,4.0,966596095 -294,70,4.0,966595946 -295,18,3.5,1320064940 -295,29,5.0,1320064417 -295,50,5.0,1320064969 -295,70,5.0,1320064943 -296,50,5.0,1532993858 -297,6,5.0,900871748 -297,22,2.0,900871989 -297,47,4.0,900871748 -297,50,5.0,900871748 -297,70,2.0,900871989 -297,79,1.0,900872461 -297,95,1.0,900872461 -297,100,1.0,900872461 -298,1,2.0,1447518257 -298,2,0.5,1450452897 -298,16,4.0,1447597782 -298,32,4.0,1450369288 -298,47,4.0,1447518037 -298,50,3.5,1447516828 -299,2,3.0,974620151 -301,10,4.0,1211378532 -301,17,4.0,1211378910 -301,21,4.0,1211378459 -301,36,4.5,1211378851 -301,47,4.5,1211377521 -301,50,4.5,1211377304 -302,3,3.0,854472084 -302,14,4.0,854472122 -302,17,5.0,854472022 -302,21,4.0,854473184 -302,25,5.0,854472022 -302,32,3.0,854472021 -302,36,4.0,854472084 -302,47,5.0,854473264 -302,58,5.0,854472122 -302,95,3.0,854472021 -303,16,2.5,1053302761 -303,32,3.5,1053303318 -304,1,5.0,881428344 -304,2,4.0,891173962 -304,7,4.0,881428370 -304,10,4.0,891173528 -304,11,5.0,891173135 -304,13,4.0,913327439 -304,17,3.0,891174111 -304,21,4.0,896268435 -304,32,4.0,881427991 -304,36,1.0,881428195 -304,46,5.0,911720227 -304,58,4.0,899026578 -304,60,1.0,891174024 -304,62,5.0,881427812 -304,73,4.0,920884193 -304,81,4.0,947050233 -304,86,5.0,880915450 -305,2,3.5,1460136227 -305,6,3.5,1460222104 -305,16,4.5,1460136042 -305,25,3.0,1518197993 -305,32,5.0,1460222250 -305,34,3.0,1460136295 -305,47,4.0,1460135569 -305,50,5.0,1460134079 -305,70,5.0,1494259450 -307,1,4.0,1186160893 -307,2,2.5,1186161482 -307,3,3.5,1186161652 -307,10,2.5,1186161010 -307,16,4.5,1186087665 -307,18,3.0,1186410788 -307,19,4.0,1186084466 -307,21,2.5,1189457112 -307,22,2.0,1186162078 -307,24,2.0,1186162409 -307,27,2.5,1186172544 -307,31,1.5,1186162274 -307,32,3.5,1186160917 -307,39,2.0,1186161053 -307,47,4.0,1186160966 -307,50,4.5,1186160949 -307,62,3.0,1186161410 -307,65,2.5,1186086548 -307,70,3.5,1186161936 -307,72,2.0,1186173251 -307,88,3.5,1186086639 -307,94,3.5,1186086089 -308,2,3.0,1421374418 -308,3,0.5,1421374465 -308,6,1.0,1421374400 -308,19,1.0,1421374425 -308,21,1.0,1421374404 -308,25,1.0,1421374411 -308,36,1.0,1421374415 -308,39,3.0,1421374380 -308,48,4.0,1421374475 -308,50,2.5,1421373873 -309,50,4.5,1126451972 -310,16,1.0,1078647827 -310,58,4.5,1078647847 -311,16,2.5,1057854247 -311,40,3.5,1057854804 -312,6,4.0,1043177752 -312,16,4.0,1043177752 -312,32,4.0,1043176620 -313,6,3.0,1030556299 -313,10,4.0,1030556439 -313,29,4.0,1030474666 -313,32,4.0,1030475177 -313,39,4.0,1030555731 -313,47,5.0,1030476272 -313,50,5.0,1030476169 -313,70,4.0,1030475884 -313,76,1.0,1030475081 -314,1,3.0,834398280 -314,6,3.0,842432711 -314,7,4.0,834241492 -314,10,3.0,834241870 -314,11,5.0,834241810 -314,15,2.0,834428676 -314,17,4.0,834398442 -314,21,3.0,834398026 -314,22,3.0,834398622 -314,23,3.0,834241586 -314,26,4.0,834398961 -314,31,3.0,834241586 -314,32,3.0,839857723 -314,39,3.0,834398364 -314,41,3.0,834398878 -314,44,3.0,834398518 -314,47,1.0,834398302 -314,50,4.0,847175449 -314,52,3.0,845285951 -314,60,3.0,834790837 -314,62,4.0,836234560 -314,95,2.0,834241545 -314,100,3.0,847175533 -316,45,4.5,1111493212 -316,48,1.5,1111493120 -317,6,5.0,1430532917 -317,16,5.0,1430598211 -317,32,4.0,1430361493 -317,47,5.0,1430361508 -317,50,5.0,1430361374 -317,97,3.0,1430598706 -318,2,3.5,1270753195 -318,6,4.0,1347180277 -318,18,3.0,1426353075 -318,19,3.5,1262805276 -318,29,3.5,1413627585 -318,32,4.5,1263848497 -318,47,4.0,1433139531 -318,48,3.5,1275844835 -318,72,4.5,1417278807 -318,97,4.5,1419694783 -321,2,5.0,843212595 -321,3,3.0,843212762 -321,5,3.0,843212719 -321,19,3.0,843212522 -321,21,3.0,843212550 -321,24,4.0,843212762 -322,1,3.5,1217676206 -322,2,3.0,1217676495 -322,10,4.0,1217676313 -322,11,4.0,1217676534 -322,47,4.0,1217676246 -322,50,4.0,1217675827 -323,1,3.5,1422640363 -323,2,4.0,1422640110 -323,17,3.5,1422640288 -323,19,2.5,1422640116 -323,22,3.0,1422640551 -323,29,3.5,1422640570 -323,32,2.5,1422640375 -323,34,2.5,1422640415 -323,36,3.5,1422640290 -323,48,3.5,1422640448 -323,50,4.5,1422640061 -323,60,3.0,1422640654 -323,62,2.5,1422640114 -325,6,4.0,1039398204 -325,19,2.0,1039395714 -325,22,3.0,1039397193 -325,29,4.0,1039398353 -325,30,4.0,1039399501 -325,32,4.0,1039396494 -325,58,4.0,1039395583 -325,80,4.0,1039397611 -326,20,3.5,1322250792 -326,47,4.0,1419880411 -326,50,2.0,1322867550 -326,97,3.5,1443983581 -327,50,4.5,1234788095 -328,1,5.0,1494210665 -328,13,3.0,1494212082 -328,34,5.0,1494210549 -328,39,2.0,1494210780 -328,47,4.5,1494211964 -328,50,4.0,1494206971 -329,50,2.0,1523468332 -330,1,4.0,1285904910 -330,2,1.5,1285905277 -330,3,3.0,1285905545 -330,16,3.5,1285905440 -330,25,4.5,1285905238 -330,29,3.0,1285903982 -330,32,5.0,1285904958 -330,34,3.0,1285905096 -330,47,3.0,1285904519 -330,50,5.0,1285904637 -330,58,5.0,1285904454 -330,62,3.0,1285905259 -331,10,3.0,1537157573 -331,34,2.0,1537157568 -331,50,5.0,1537157516 -332,1,4.0,1352672340 -332,16,3.5,1352673555 -332,32,2.5,1352671273 -332,47,4.0,1352672211 -332,50,4.0,1352671786 -334,1,3.5,1225477466 -334,10,3.5,1234629982 -334,47,2.0,1234629901 -335,50,5.0,1261542414 -336,1,4.0,1122227329 -336,6,4.0,1122227549 -336,47,4.5,1122227343 -336,50,5.0,1120568496 -336,70,4.0,1120568169 -337,1,4.0,860255715 -337,3,4.0,860255784 -337,5,4.0,860255784 -337,6,5.0,860255784 -337,7,3.0,860255784 -337,9,5.0,860255929 -337,12,3.0,860255992 -337,14,3.0,860255866 -337,16,4.0,860256120 -337,17,4.0,860255716 -337,24,5.0,860256119 -337,25,4.0,860255716 -337,27,5.0,860256159 -337,31,5.0,860256120 -337,32,4.0,860255715 -337,36,4.0,860255783 -337,41,3.0,860255992 -337,47,5.0,860256118 -337,50,3.0,860256158 -337,62,3.0,860255716 -337,65,3.0,860255929 -337,66,4.0,860255992 -337,74,5.0,860255992 -337,76,5.0,860256043 -337,79,4.0,860255867 -337,95,5.0,860255716 -337,100,3.0,860255992 -338,50,4.5,1530148314 -339,1,4.0,1460183470 -339,6,4.0,1460345729 -339,16,4.5,1460794139 -339,32,3.0,1460518918 -339,47,4.5,1460186377 -340,10,4.0,848666415 -341,1,5.0,1439750939 -342,24,3.0,1042822170 -343,50,4.5,1202061253 -345,11,2.5,1342828883 -345,32,3.5,1342827269 -346,17,4.0,1155066710 -346,47,3.5,1172693170 -346,50,4.0,1125857414 -347,1,5.0,847645986 -347,2,3.0,847645925 -347,10,4.0,847645690 -347,11,4.0,847645925 -347,19,4.0,847645789 -347,32,3.0,847645812 -347,34,4.0,847645761 -347,39,4.0,847645812 -347,47,3.0,847645738 -348,50,5.0,1378850183 -349,10,4.0,834750699 -349,34,5.0,834750842 -350,1,4.0,864940931 -350,7,3.0,864941017 -350,12,3.0,864941118 -350,17,2.0,864940932 -350,32,4.0,864940930 -350,65,3.0,864941118 -350,95,3.0,864940931 -351,12,5.0,1325978665 -351,47,4.5,1326027964 -352,47,5.0,1493931953 -352,50,5.0,1493931911 -353,1,5.0,831939685 -353,2,4.0,831939875 -353,5,3.0,831939914 -353,6,4.0,831939947 -353,9,3.0,831940313 -353,10,3.0,831939669 -353,11,4.0,831939792 -353,19,4.0,831939775 -353,22,5.0,831939991 -353,25,4.0,831939875 -353,32,5.0,831939731 -353,34,5.0,831939731 -353,39,1.0,831939750 -353,47,5.0,831939731 -353,69,3.0,831940600 -353,70,4.0,831940127 -354,10,3.5,1200870391 -354,32,4.0,1200870157 -354,34,3.5,1200870571 -354,44,3.5,1200865357 -354,47,4.0,1200870867 -354,50,4.5,1200869832 -354,70,4.5,1200953640 -355,60,3.0,974966167 -356,21,3.5,1229140823 -356,50,3.5,1229142733 -356,62,4.5,1229142896 -357,1,5.0,1348610184 -357,2,3.0,1348611277 -357,11,3.5,1348612270 -357,16,3.5,1348610125 -357,17,5.0,1348612178 -357,19,2.0,1348612202 -357,34,4.0,1348611388 -357,36,3.5,1348610447 -357,39,4.5,1348612128 -357,50,5.0,1348610163 -357,62,3.0,1348612191 -359,1,4.0,1198112023 -359,2,3.5,1198112829 -359,34,2.5,1198112136 -359,58,4.5,1198113196 -361,10,3.5,1204045505 -361,70,2.0,1204046026 -362,6,4.0,1530637587 -362,16,4.0,1530640994 -362,31,4.0,1530642798 -362,47,4.5,1530640109 -362,50,3.5,1530637009 -362,70,4.0,1530637651 -363,50,4.0,1502584540 -363,95,3.0,1502584443 -364,1,5.0,869443366 -364,9,3.0,869443802 -364,32,3.0,869443366 -364,95,5.0,869443367 -367,1,5.0,997811550 -367,34,3.0,997811126 -367,39,4.0,997812337 -368,3,3.0,971273951 -368,6,4.0,971275527 -368,10,3.0,971276726 -368,16,4.0,971275668 -368,21,3.0,975828964 -368,22,3.0,971276062 -368,42,2.0,975828507 -368,47,4.0,971275475 -368,50,4.0,971275320 -368,70,3.0,971273705 -368,79,2.0,971276901 -368,81,3.0,975828421 -368,95,2.0,971277081 -369,19,4.0,1237081519 -369,47,3.5,1237083091 -370,39,3.5,1159162930 -370,47,3.5,1159162973 -370,50,4.5,1159161956 -371,48,4.5,1407691602 -372,1,3.0,874416443 -372,6,5.0,874415865 -372,8,2.0,874415441 -372,10,3.0,874416808 -372,11,4.0,874415285 -372,14,4.0,874416949 -372,16,4.0,874415966 -372,21,3.0,874416570 -372,25,4.0,874415164 -372,31,2.0,874416808 -372,32,4.0,874415441 -372,34,4.0,874415934 -372,36,3.0,874414994 -372,39,3.0,874417086 -372,41,4.0,874415991 -372,47,5.0,874417240 -372,48,2.0,874416616 -372,50,5.0,874414678 -372,52,4.0,874416234 -372,62,3.0,874415902 -372,70,3.0,874415199 -372,71,2.0,874416544 -372,81,2.0,874416280 -373,1,3.0,846830172 -373,2,3.0,846830111 -373,6,5.0,846830247 -373,11,2.0,846830094 -373,16,4.0,846830296 -373,19,1.0,846830035 -373,21,1.0,846830035 -373,22,3.0,846830333 -373,25,5.0,846830207 -373,32,4.0,846830055 -373,34,4.0,846830015 -373,44,1.0,846830190 -373,47,5.0,846829997 -373,50,5.0,846830055 -373,60,3.0,846830521 -373,95,2.0,846830128 -375,32,5.0,1225314381 -376,10,4.5,1364994181 -376,19,2.0,1364994453 -376,32,5.0,1364994049 -376,95,3.5,1364994336 -377,19,2.0,1340342704 -377,32,4.5,1340342216 -377,34,4.0,1340347654 -378,1,4.5,1445347576 -378,36,4.0,1445347078 -379,19,2.0,847397556 -379,21,2.0,847397556 -379,34,5.0,847397499 -379,47,3.0,847397459 -380,1,5.0,1493420345 -380,2,5.0,1493420295 -380,6,5.0,1494278663 -380,10,5.0,1493419787 -380,12,4.0,1493668065 -380,16,3.0,1494803499 -380,18,4.0,1494278868 -380,19,5.0,1493667522 -380,21,2.0,1493422718 -380,32,5.0,1493494899 -380,34,4.0,1493420018 -380,44,4.0,1493667678 -380,47,5.0,1493494893 -380,48,3.0,1493423481 -380,50,4.0,1493420347 -380,60,4.0,1494035896 -380,70,5.0,1493423196 -380,76,3.0,1494278971 -380,95,3.0,1493420301 -381,1,3.5,1164383653 -381,2,4.0,1166971855 -381,19,2.5,1165975855 -381,32,3.5,1200824503 -381,34,3.5,1164877286 -381,47,2.0,1166980226 -381,48,3.0,1165976148 -381,50,4.5,1168576731 -381,62,4.5,1263494357 -382,1,4.5,1515162628 -382,50,5.0,1515160611 -384,60,4.0,994038823 -385,1,4.0,834691642 -385,6,3.0,840648313 -385,10,3.0,834691622 -385,14,3.0,834692097 -385,16,3.0,834691914 -385,21,5.0,835118614 -385,25,3.0,834691845 -385,32,4.0,838323677 -385,45,3.0,837949548 -385,50,3.0,834691694 -385,62,3.0,836844635 -385,68,3.0,865024733 -385,85,3.0,844794767 -385,94,4.0,847137503 -385,95,3.0,834691768 -386,6,3.0,842613783 -386,10,3.0,842610246 -386,16,4.0,842613849 -386,20,2.0,842614033 -386,21,4.0,842610304 -386,22,3.0,842613867 -386,25,2.0,842613763 -386,32,3.0,842610360 -386,34,4.0,842610286 -386,39,3.0,842610325 -386,44,2.0,842613763 -386,45,3.0,842613904 -386,47,3.0,842610286 -386,50,3.0,842610344 -387,10,3.5,1094938515 -387,11,2.5,1117415000 -387,29,3.5,1094875272 -387,31,2.5,1094939853 -387,32,3.5,1094876449 -387,39,2.5,1095040527 -387,44,1.0,1182720368 -387,45,2.5,1094877493 -387,47,4.5,1094876919 -387,50,4.5,1094876246 -387,63,2.0,1095042100 -387,70,3.5,1183536308 -387,71,1.5,1150877466 -387,97,4.5,1199607279 -389,1,5.0,857934174 -389,5,4.0,857934242 -389,6,5.0,857934242 -389,9,3.0,857934552 -389,17,4.0,857934174 -389,25,4.0,857934175 -389,32,4.0,857934174 -389,62,5.0,857934174 -389,65,4.0,857934553 -389,95,4.0,857934174 -391,1,3.0,1032388077 -391,6,4.0,1030944221 -391,10,3.0,1030944309 -391,25,5.0,1030827466 -391,29,5.0,1030826859 -391,32,4.0,1030826859 -391,34,3.0,1032389962 -391,47,3.0,1030944178 -391,50,4.0,1030827636 -391,58,4.0,1030827343 -391,70,1.0,1030944454 -394,34,3.0,838994398 -394,50,5.0,838994626 -395,2,3.0,841503884 -395,10,3.0,841503555 -395,34,3.0,841503656 -395,48,2.0,841504003 -395,60,3.0,841505041 -395,95,3.0,841503940 -396,1,5.0,1111688626 -396,44,2.0,1111688564 -396,45,3.0,1111688518 -396,50,4.0,1111688630 -398,32,5.0,1311207513 -399,1,4.0,1167220428 -400,6,5.0,1498870480 -400,47,5.0,1498870391 -400,50,5.0,1498870285 -401,1,3.5,1510450550 -401,48,2.0,1514347122 -402,5,3.0,849598135 -402,9,3.0,849598259 -402,25,3.0,849598104 -402,36,3.0,849598135 -402,47,3.0,849654599 -402,52,3.0,849598217 -402,61,5.0,849598453 -402,95,4.0,849598075 -403,47,5.0,1225243620 -404,11,4.0,838376006 -404,17,4.0,838376049 -404,21,3.0,838375894 -404,34,4.0,838375864 -404,36,3.0,838376195 -404,47,3.0,838375864 -404,62,4.0,838376141 -405,16,4.0,1295916006 -405,25,4.0,1299377952 -405,32,4.5,1295910764 -405,70,4.0,1295917097 -408,10,4.5,1467913128 -408,19,3.5,1469521999 -408,44,3.5,1484264475 -409,39,4.0,968979119 -410,3,4.0,990910830 -410,11,3.0,990910298 -410,21,3.0,990910575 -410,52,4.0,990910213 -410,58,4.0,990807791 -411,1,5.0,835532155 -411,2,4.0,835532398 -411,4,2.0,835533021 -411,7,3.0,835533471 -411,10,3.0,835532065 -411,11,4.0,835532370 -411,21,4.0,835532191 -411,22,3.0,835532644 -411,31,4.0,835532539 -411,34,4.0,835532191 -411,46,2.0,835533337 -411,47,4.0,835532191 -411,50,3.0,835532221 -411,52,2.0,835533198 -411,62,5.0,835532559 -412,1,2.0,939114353 -412,17,5.0,939136944 -412,34,5.0,939114265 -412,47,3.0,939114573 -413,16,5.0,1484440002 -414,1,4.0,961438127 -414,2,3.0,961594981 -414,3,4.0,961439278 -414,5,2.0,961437647 -414,6,3.0,961515642 -414,7,3.0,961439170 -414,8,3.0,961594849 -414,10,3.0,961515863 -414,11,5.0,1052148205 -414,15,2.0,961514611 -414,16,3.0,961517557 -414,17,4.0,961513829 -414,18,3.0,961682128 -414,21,4.0,961438199 -414,22,3.0,961518227 -414,23,2.0,961682276 -414,24,3.0,961436964 -414,25,3.0,961517140 -414,27,2.0,961518812 -414,31,3.0,961518520 -414,32,5.0,961514667 -414,34,5.0,961438127 -414,36,3.0,961516989 -414,39,4.0,961438265 -414,42,2.0,961515844 -414,44,2.0,961516249 -414,45,3.0,961438476 -414,46,2.0,961514407 -414,47,4.0,961681857 -414,48,3.0,961437741 -414,50,5.0,961681714 -414,52,3.0,961438413 -414,54,1.0,1027521065 -414,57,3.0,961517912 -414,62,4.0,961517885 -414,65,2.0,961439623 -414,71,2.0,961515844 -414,72,4.0,961438532 -414,75,1.0,1027521022 -414,78,3.0,961518581 -414,81,2.0,961514568 -414,86,3.0,961437096 -414,88,2.0,961439433 -414,89,3.0,961515928 -414,92,2.0,961518731 -414,94,5.0,961517421 -414,95,2.0,961515958 -415,47,4.0,1382470301 -415,50,4.5,1382469955 -417,47,5.0,1532134167 -418,50,4.5,1461865740 -419,10,3.5,1321659128 -419,47,4.0,1321659049 -419,50,4.0,1321854706 -420,1,4.0,1218207191 -420,32,3.5,1218047864 -420,73,4.0,1218036406 -421,73,4.0,1311494239 -422,1,4.0,986173307 -424,32,3.5,1457901858 -424,47,5.0,1457842442 -424,50,5.0,1457842255 -425,2,3.0,1085477682 -425,6,4.0,1085477536 -425,10,3.0,1085477406 -425,32,4.0,1085477320 -425,34,3.5,1114173653 -425,36,3.0,1085477524 -425,47,4.5,1085477391 -425,50,4.5,1085477355 -425,58,3.5,1085490369 -425,70,4.0,1085490625 -425,95,2.5,1085477510 -426,2,4.5,1451080838 -426,31,5.0,1451080848 -426,47,0.5,1451081886 -427,16,4.0,1053068794 -427,58,2.0,1053071377 -428,9,2.0,1111524871 -428,19,1.0,1111523373 -428,22,2.5,1111487500 -428,44,2.0,1111623964 -428,69,3.5,1111524882 -428,70,3.0,1111524672 -428,95,2.0,1111524678 -429,22,4.0,828124615 -429,48,4.0,828124616 -429,60,4.0,828124616 -430,34,3.0,963889406 -432,1,2.5,1316391457 -432,2,4.0,1316391739 -432,19,2.0,1316391760 -432,25,4.5,1315243647 -432,36,3.5,1316391708 -432,47,4.0,1315244565 -432,50,3.0,1315243055 -433,47,3.0,1506823900 -433,50,5.0,1506823884 -434,1,4.0,1270604402 -434,2,2.5,1271039378 -434,6,4.0,1270603905 -434,10,3.5,1270606683 -434,32,3.5,1270604323 -434,34,3.5,1270604933 -434,39,3.0,1270606827 -434,47,4.0,1270603499 -434,95,2.0,1270606732 -435,48,4.0,1366675847 -435,50,4.0,1366676016 -436,1,4.0,833529571 -436,2,4.0,833529751 -436,8,3.0,833530760 -436,34,5.0,833529621 -436,48,4.0,833529821 -436,60,3.0,833530067 -437,5,2.0,859721015 -437,6,5.0,859721015 -437,9,3.0,859721103 -437,14,3.0,859721080 -437,16,5.0,859721743 -437,17,4.0,859720978 -437,25,4.0,859720978 -437,31,4.0,859721815 -437,32,4.0,859720977 -437,36,4.0,859721015 -437,43,3.0,859721556 -437,47,4.0,859721361 -437,50,4.0,859721362 -437,52,4.0,859721046 -437,62,3.0,859720978 -437,78,3.0,859721693 -437,79,2.0,859721080 -437,81,3.0,859721790 -437,86,3.0,859721170 -437,95,1.0,859720977 -438,1,4.5,1105650469 -438,6,5.0,1105664272 -438,10,4.0,1105664201 -438,11,4.0,1105668426 -438,19,3.0,1105666629 -438,21,3.5,1105666251 -438,32,4.0,1105666143 -438,44,3.0,1105667144 -438,62,4.0,1105649800 -438,70,3.0,1105762813 -438,71,2.0,1105664825 -438,95,3.5,1105666265 -440,29,4.5,1237569069 -441,10,4.5,1449070452 -441,47,4.5,1451166486 -443,1,4.0,1501722482 -444,6,4.0,832677558 -444,16,4.0,832678415 -444,21,4.0,832670075 -444,47,4.0,832670399 -444,50,5.0,832670838 -444,58,5.0,832679295 -444,97,5.0,839310140 -444,100,3.0,839310140 -445,17,3.5,1454621917 -445,32,5.0,1454622049 -445,47,4.5,1454622061 -446,2,3.0,843839379 -446,10,3.0,843839232 -446,11,4.0,843839379 -446,16,3.0,843839544 -446,17,5.0,843839379 -446,21,3.0,843839290 -446,25,3.0,843839504 -446,32,4.0,843839327 -446,34,5.0,843839272 -446,39,3.0,843839306 -446,45,3.0,843839593 -446,47,4.0,843839250 -446,50,4.0,843839306 -446,95,4.0,843839401 -447,2,5.0,836961067 -447,10,3.0,836960825 -447,31,4.0,836961195 -447,44,5.0,836961153 -447,48,3.0,836961178 -448,1,5.0,1019126661 -448,2,3.0,1019125424 -448,3,3.0,1019128536 -448,5,3.0,1019128415 -448,10,4.0,1019124400 -448,12,2.0,1019563753 -448,16,5.0,1019138531 -448,19,2.0,1019132168 -448,20,3.0,1019124922 -448,21,2.0,1019124231 -448,32,2.0,1019132949 -448,38,3.0,1019227804 -448,47,4.0,1019132386 -448,50,4.0,1064741727 -448,65,1.0,1028111080 -448,66,2.0,1019133230 -448,95,2.0,1019124644 -449,32,4.0,1053200119 -449,50,4.5,1053199959 -450,70,2.0,974705218 -451,1,5.0,854089165 -451,5,3.0,854089243 -451,6,4.0,854089242 -451,7,3.0,854089243 -451,17,5.0,854089172 -451,25,5.0,854089175 -451,32,5.0,854089163 -451,94,4.0,854089769 -451,95,4.0,854089167 -452,10,4.0,1013395144 -452,44,4.0,1019580991 -452,47,5.0,1019581177 -452,69,5.0,1019585277 -452,70,4.0,1013397998 -453,1,5.0,1005966797 -453,10,2.0,972621985 -453,16,3.0,972622830 -453,21,3.0,972621787 -453,32,5.0,972621444 -453,34,4.0,972622496 -453,47,5.0,972622637 -453,50,5.0,972621262 -453,70,4.0,972622055 -454,82,3.5,1279476639 -455,11,4.0,836436201 -455,34,4.0,836436023 -455,50,3.0,836436049 -455,62,4.0,836436499 -456,1,5.0,856883308 -456,3,3.0,856883349 -456,5,3.0,856883349 -456,9,4.0,856883450 -456,32,3.0,856883308 -456,64,3.0,856883540 -456,65,2.0,856883450 -456,74,4.0,856883468 -456,79,2.0,856883417 -457,34,2.0,993610564 -458,2,4.0,845653124 -458,5,3.0,845652992 -458,10,4.0,845651737 -458,21,5.0,845653030 -458,27,5.0,845652968 -458,39,4.0,845653086 -458,48,3.0,845652560 -458,62,5.0,845652560 -458,95,5.0,845652537 -460,1,4.5,1359177505 -462,1,1.5,1154037653 -462,10,3.0,1269929071 -462,16,3.5,1123893685 -462,21,4.0,1121923492 -462,25,3.0,1154037817 -462,32,3.5,1121921239 -462,36,3.5,1123891148 -462,47,4.0,1154037716 -462,50,3.5,1154037688 -462,52,3.0,1123890939 -464,9,2.5,1287400084 -464,16,4.5,1287400356 -464,20,4.0,1275548142 -464,23,3.0,1275548130 -464,25,4.0,1287400227 -464,31,4.0,1287400817 -464,32,3.5,1275548714 -464,47,5.0,1275549635 -465,95,3.0,959896430 -467,41,4.0,919671922 -467,58,5.0,919672099 -468,1,4.0,831400444 -468,32,4.0,831400500 -468,39,5.0,831400519 -468,47,5.0,831400545 -469,1,4.0,965336888 -469,6,3.0,965336673 -469,10,2.0,965334356 -469,11,3.0,965425831 -469,29,4.0,965335401 -469,32,5.0,965335350 -469,36,3.0,965846167 -469,39,2.0,965425327 -469,44,1.0,965335037 -469,45,4.0,965425742 -469,47,4.0,965336711 -469,50,4.0,965336630 -469,70,2.0,965334011 -469,89,4.0,965334954 -470,1,4.0,849224825 -470,2,3.0,849224778 -470,3,3.0,849370396 -470,5,3.0,849370453 -470,6,3.0,849843318 -470,7,3.0,849370453 -470,10,3.0,849075144 -470,14,4.0,849843318 -470,19,3.0,849075545 -470,21,3.0,849075545 -470,26,3.0,849843245 -470,32,3.0,849075682 -470,34,4.0,849075432 -470,36,4.0,849370395 -470,39,3.0,849075682 -470,41,3.0,849843245 -470,43,3.0,849370292 -470,47,3.0,849075299 -470,50,3.0,849075545 -470,62,3.0,849224778 -470,95,3.0,849843245 -471,1,5.0,1496671820 -472,50,5.0,1345843346 -473,60,2.0,1169351160 -474,1,4.0,978575760 -474,2,3.0,1046886814 -474,5,1.5,1053021982 -474,6,3.0,1047054565 -474,7,3.0,978576381 -474,11,2.5,1053021437 -474,14,3.0,1120827247 -474,16,4.0,1088426731 -474,17,5.0,974668666 -474,21,4.0,1119232784 -474,22,3.0,1046896006 -474,24,3.0,1060105861 -474,25,3.5,1127143175 -474,26,3.5,1136942664 -474,27,2.0,1069686414 -474,28,4.5,1165540007 -474,29,3.5,1053021379 -474,31,3.0,1060105936 -474,32,4.0,1081177409 -474,34,4.5,1081177349 -474,36,5.0,979180034 -474,38,1.0,1089387538 -474,39,3.5,1129579520 -474,41,3.5,1089386983 -474,43,3.5,1081177921 -474,45,4.0,1014924369 -474,46,3.0,1081178156 -474,47,4.0,979180247 -474,50,4.0,979179872 -474,52,4.0,1004131663 -474,57,3.0,1060105374 -474,58,3.5,1126533613 -474,62,2.5,1053021366 -474,74,3.0,974669217 -474,82,2.5,1121262740 -474,92,3.5,1087832141 -474,96,3.5,1053020997 -474,100,2.0,1048710159 -475,2,4.5,1498031744 -475,19,4.0,1498031776 -476,1,4.0,835021447 -476,2,4.0,835021693 -476,10,3.0,835021420 -476,11,3.0,835021635 -476,13,3.0,835022487 -476,32,4.0,835021513 -476,34,4.0,835021494 -476,45,3.0,835022455 -476,48,4.0,835022192 -476,73,4.0,835022035 -477,1,4.0,1200939636 -477,2,4.0,1200939962 -477,3,3.0,1200941177 -477,19,3.0,1200939977 -477,24,4.0,1201159341 -477,32,4.5,1200939654 -477,34,4.0,1200939719 -477,47,4.0,1200939679 -477,66,0.5,1201158662 -477,76,4.0,1201158833 -479,24,3.0,1039362593 -479,31,3.0,1039362413 -479,45,3.0,1039367502 -479,82,5.0,1039362593 -480,1,3.0,1179178004 -480,2,3.0,1179178191 -480,3,2.5,1179178556 -480,6,4.0,1179162163 -480,10,4.0,1179177922 -480,16,4.0,1179161099 -480,19,1.5,1179178233 -480,21,2.5,1179161927 -480,32,4.0,1179177844 -480,34,4.0,1179178044 -480,39,2.5,1179177930 -480,47,4.5,1179177656 -480,50,3.5,1179160287 -480,60,2.0,1179159595 -480,62,3.5,1179178063 -480,69,2.0,1179161861 -480,95,1.0,1179177869 -482,2,4.5,1105395956 -482,16,2.0,1105396054 -482,50,4.0,1105396885 -482,62,5.0,1105396550 -483,1,4.0,1178293130 -483,2,4.0,1178293652 -483,5,2.5,1327277284 -483,10,2.0,1178293444 -483,16,4.0,1178293782 -483,18,4.0,1215897224 -483,19,3.5,1181494938 -483,23,3.0,1215897538 -483,24,2.5,1327277916 -483,26,4.0,1215898801 -483,29,5.0,1181495581 -483,31,2.0,1181495275 -483,32,5.0,1178213437 -483,47,3.5,1178215187 -483,48,3.0,1181496689 -483,50,4.5,1204405320 -483,81,3.5,1215898195 -484,1,4.5,1342295949 -484,2,2.5,1342296219 -484,39,4.5,1342296074 -484,47,4.0,1342228947 -484,48,4.5,1342296910 -484,63,4.0,1342228081 -484,69,4.5,1342300148 -484,72,4.0,1342369324 -485,10,4.0,837943350 -486,6,5.0,839537263 -486,10,4.0,839537237 -486,21,4.0,839537017 -486,32,5.0,839537271 -486,39,3.0,839537186 -486,44,4.0,839537298 -486,47,3.0,839537220 -486,86,5.0,839537298 -486,95,3.0,839537249 -488,1,4.5,1112382025 -488,17,5.0,1112382176 -488,26,2.5,1112382126 -488,34,3.0,1112382292 -488,36,4.5,1112382199 -488,73,2.5,1112382455 -489,2,2.5,1333101570 -489,5,2.0,1385823772 -489,7,4.0,1334587547 -489,10,2.5,1333101410 -489,11,1.5,1334170648 -489,17,4.5,1332773255 -489,18,2.0,1333234401 -489,19,2.0,1333101593 -489,21,2.5,1333101507 -489,22,3.5,1333022826 -489,32,3.5,1333023575 -489,34,2.0,1333101391 -489,39,3.5,1332772964 -489,46,3.5,1333658594 -489,47,3.0,1333101316 -489,48,4.0,1334587634 -489,70,2.0,1385823826 -489,95,1.5,1333101502 -490,1,3.5,1328229305 -490,5,0.5,1324370305 -492,1,4.0,863975949 -492,3,4.0,863976005 -492,5,3.0,863976004 -492,6,3.0,863976004 -492,7,3.0,863976055 -492,9,5.0,863976201 -492,12,3.0,863976249 -492,14,3.0,863976101 -492,32,3.0,863975946 -492,36,4.0,863976004 -492,52,3.0,863976101 -492,61,4.0,863976447 -492,62,4.0,863975954 -492,63,3.0,863976526 -492,64,3.0,863976525 -492,65,5.0,863976248 -492,66,3.0,863976249 -492,74,4.0,863976249 -492,75,3.0,863976878 -492,76,5.0,863976409 -492,79,4.0,863976101 -492,88,5.0,863976409 -492,95,3.0,863975954 -492,100,3.0,863976249 -493,6,4.0,1001562846 -495,19,4.5,1458636447 -495,50,4.0,1458634563 -497,2,2.5,1429127190 -497,19,4.0,1429127195 -497,50,3.0,1429127291 -498,7,4.0,839197378 -498,10,3.0,839197307 -498,34,3.0,839197341 -498,47,3.0,839197341 -498,62,5.0,839197444 -500,1,4.0,1005527755 -500,11,1.0,1005528017 -500,39,1.0,1005527926 -501,2,3.0,844973419 -501,3,5.0,844973817 -501,5,3.0,844973535 -501,6,3.0,844973487 -501,7,4.0,844973817 -501,8,3.0,844974090 -501,10,4.0,844973340 -501,11,3.0,844973340 -501,15,1.0,844973980 -501,16,3.0,844973535 -501,17,3.0,844973419 -501,18,5.0,844974006 -501,20,1.0,844974037 -501,21,3.0,844973340 -501,25,2.0,844973487 -501,27,3.0,844973931 -501,32,3.0,844973340 -501,36,3.0,844973487 -501,45,3.0,844973535 -501,50,3.0,844973340 -501,61,3.0,844973980 -501,62,3.0,844973487 -501,73,2.0,844974214 -501,86,3.0,844974037 -501,93,3.0,844974090 -501,95,4.0,844973419 -502,45,3.5,1111757345 -504,1,4.0,1063644695 -504,22,3.5,1063644469 -505,47,5.0,1298780253 -506,27,3.0,1424487740 -506,39,5.0,1424487595 -507,34,5.0,838964683 -507,39,3.0,838964728 -507,47,3.0,838964683 -509,1,4.0,1435992343 -509,5,1.5,1435992893 -509,13,3.0,1436101243 -509,17,3.0,1435992515 -509,19,4.0,1436027225 -509,28,3.5,1436031727 -509,32,4.0,1435998135 -509,34,3.5,1435998986 -509,39,4.0,1435992749 -509,48,3.5,1436000115 -510,7,1.0,1141158812 -510,16,1.0,1141158760 -510,50,4.0,1141160526 -512,2,3.0,841449636 -512,32,5.0,841449445 -512,39,4.0,841449426 -512,47,5.0,841449359 -512,50,5.0,841449402 -513,7,3.0,1159980407 -513,32,4.0,1159980466 -514,1,4.0,1533872400 -514,11,4.0,1533949297 -514,16,3.5,1533872553 -514,22,3.0,1533947171 -514,34,4.0,1533872519 -514,44,2.5,1533945558 -514,47,4.0,1533872325 -514,62,4.0,1533949200 -515,50,4.5,1513678307 -517,1,4.0,1487954343 -517,2,3.0,1487954340 -517,10,0.5,1487957717 -517,17,0.5,1487953834 -517,34,5.0,1487954303 -517,47,2.0,1487958109 -518,24,2.5,1056907643 -518,31,1.0,1056907629 -520,10,4.0,1326609139 -520,19,1.0,1326609359 -520,32,3.5,1326608236 -521,5,3.0,852713143 -521,6,4.0,852713143 -521,7,3.0,852713143 -521,14,4.0,852713185 -521,18,4.0,852713356 -521,25,5.0,852713083 -521,29,3.0,852713417 -521,32,3.0,852713082 -521,36,4.0,852713143 -521,43,4.0,852713446 -521,52,4.0,852713185 -521,58,4.0,852713185 -521,79,4.0,852713251 -521,81,3.0,852713417 -521,86,4.0,852713380 -521,95,3.0,852713082 -522,1,3.0,1253344674 -522,10,4.5,1253344761 -522,50,4.5,1253430096 -522,62,3.0,1253345769 -523,2,4.5,1503126180 -524,1,4.0,851608466 -524,6,4.0,852404399 -524,10,4.0,851608818 -524,12,1.0,852404800 -524,19,3.0,851609256 -524,20,2.0,851609083 -524,21,3.0,852404913 -524,23,2.0,851608986 -524,25,3.0,851608466 -524,32,3.0,851608466 -524,47,5.0,851608960 -524,50,2.0,851608781 -524,76,2.0,852404800 -524,86,3.0,852404550 -524,95,4.0,851608466 -525,1,4.0,1476475973 -525,2,3.5,1476480324 -525,34,3.0,1476480775 -525,39,4.5,1476477672 -525,47,3.5,1476476493 -525,48,3.0,1476480566 -525,50,4.5,1476476363 -525,62,3.5,1476480183 -527,2,4.0,1033173338 -527,30,1.0,1033173581 -527,34,5.0,1033173966 -527,48,3.0,1033173290 -528,1,2.5,1391736605 -529,1,3.0,855583216 -529,7,2.0,855583292 -529,32,5.0,855583215 -529,62,3.0,855583216 -529,65,1.0,855583470 -529,95,4.0,855583216 -530,11,4.0,843227087 -531,10,4.0,1032961647 -532,6,5.0,1025523798 -533,1,5.0,1424753740 -534,1,4.0,1459787997 -534,2,4.5,1459787996 -534,10,4.0,1459787996 -534,19,4.0,1459787996 -534,31,3.5,1459788707 -534,34,4.0,1459793302 -534,44,4.0,1459788735 -534,47,4.0,1459787998 -534,48,4.0,1459792580 -536,45,5.0,832840081 -539,65,4.5,1332474525 -539,88,3.5,1332474517 -540,47,4.5,1179109020 -541,1,3.0,835643027 -541,7,4.0,835644446 -541,10,4.0,835642985 -541,11,4.0,835643146 -541,15,3.0,835643931 -541,19,2.0,835643052 -541,22,4.0,835643333 -541,47,1.0,835643038 -541,50,5.0,835643052 -541,95,3.0,835643186 -542,47,5.0,1163386913 -544,1,3.0,850688537 -544,3,3.0,850688562 -544,14,3.0,850688581 -544,32,3.0,850688537 -544,40,5.0,850688776 -544,62,5.0,850688537 -544,68,5.0,850688776 -544,95,4.0,850688537 -545,44,2.5,1240358381 -546,70,5.0,973588518 -548,69,5.0,1488243429 -550,1,4.0,1488728441 -551,47,4.5,1505548073 -552,3,1.0,1111472953 -552,19,3.5,1111473056 -552,25,3.0,1112151250 -552,95,1.5,1111473067 -553,6,5.0,1219558120 -553,16,5.0,1219558107 -553,32,5.0,1219564918 -553,42,4.0,1219559052 -553,50,4.0,1219557525 -555,1,4.0,978746159 -555,3,5.0,978747454 -555,19,3.0,980123949 -555,21,4.0,978746440 -555,24,5.0,978841879 -555,29,4.0,978841345 -555,32,4.0,978841464 -555,39,4.0,978746326 -555,50,5.0,978819462 -555,65,3.0,980125946 -555,72,3.0,978746552 -555,75,3.0,980125866 -555,88,4.0,980126008 -557,10,4.5,1452797765 -558,94,3.0,1035415930 -559,1,5.0,865095758 -559,2,4.0,845476032 -559,6,5.0,865095857 -559,10,3.0,845475880 -559,15,3.0,845476569 -559,19,2.0,845475946 -559,32,3.0,845475965 -559,34,5.0,845475917 -559,36,4.0,845476089 -559,39,3.0,845475987 -559,48,3.0,845476159 -559,58,4.0,865095758 -559,66,3.0,865096234 -559,76,3.0,865096444 -559,95,4.0,865095801 -560,1,3.0,1469653413 -560,32,3.5,1469647882 -560,34,2.5,1469647264 -560,47,4.0,1469648029 -560,48,2.5,1469654312 -560,50,4.0,1469647239 -560,70,4.0,1469653546 -560,97,4.0,1469653182 -561,1,4.0,1491094681 -561,2,4.0,1491094318 -561,5,3.0,1491094488 -561,6,4.0,1491092289 -561,31,2.5,1491094481 -561,32,3.5,1491091981 -561,34,2.5,1491095062 -561,39,3.0,1491091334 -561,44,2.0,1491091620 -561,47,4.5,1491091954 -561,50,4.5,1491090860 -562,1,4.5,1368893997 -562,50,4.0,1368894758 -563,2,2.5,1447185161 -563,34,2.0,1441846213 -563,48,3.5,1440800284 -564,39,3.5,1478453734 -565,19,3.0,846533399 -565,21,3.0,846533399 -565,32,5.0,846533428 -565,34,4.0,846533367 -565,47,4.0,846533338 -565,50,5.0,846533399 -566,2,4.0,849005893 -566,7,4.0,849006845 -566,10,3.0,849005345 -566,11,5.0,849005826 -566,17,5.0,849006000 -566,21,4.0,849005643 -566,25,2.0,849006116 -566,32,4.0,849005720 -566,39,4.0,849005720 -566,50,5.0,849005642 -566,57,3.0,849006827 -567,1,3.5,1525286001 -567,34,2.5,1525288053 -567,50,1.0,1525282012 -568,50,5.0,1243576177 -569,10,4.0,849190709 -569,50,3.0,849190709 -570,1,4.0,1181476989 -570,2,3.5,1181477805 -570,10,3.5,1181477300 -570,11,3.5,1181477768 -570,25,4.0,1181477537 -570,32,4.0,1181477032 -570,34,3.5,1181477210 -570,39,3.0,1181477492 -570,47,3.5,1181477162 -570,95,2.5,1181477499 -571,12,1.0,966901337 -571,70,2.0,966900368 -572,1,4.0,945892484 -572,17,5.0,945888053 -572,21,5.0,945890765 -572,62,4.0,945890338 -573,1,5.0,1186722182 -573,2,4.5,1187044862 -573,6,4.5,1248842019 -573,10,4.5,1186722464 -573,47,5.0,1186589586 -573,50,5.0,1248841981 -574,47,5.0,834634527 -576,29,3.5,1358151482 -577,6,4.0,945967415 -577,39,3.0,945964946 -577,88,3.0,945968259 -579,1,4.0,958881146 -579,11,3.0,958879371 -579,17,5.0,977364909 -579,34,3.0,958880089 -579,48,4.0,958881238 -580,1,3.0,1167792349 -580,6,4.0,1167789917 -580,10,3.5,1167792602 -580,16,4.5,1167790725 -580,22,4.0,1167861702 -580,25,4.0,1167789966 -580,32,5.0,1167790855 -580,34,2.5,1167673463 -580,47,5.0,1167791127 -580,50,5.0,1167789884 -580,62,2.0,1167790047 -580,70,5.0,1167673477 -583,39,5.0,1481474136 -584,1,5.0,834987643 -584,10,5.0,834987172 -584,19,3.0,834987751 -584,22,4.0,834988132 -584,34,3.0,834987730 -584,39,1.0,834987810 -584,47,5.0,834987730 -584,48,5.0,834988006 -584,60,5.0,834988340 -585,16,5.0,1307417343 -585,88,4.0,1307416427 -586,2,4.0,1529901723 -587,1,5.0,953137847 -587,11,4.0,953138510 -587,21,4.0,953138653 -587,32,5.0,953141417 -587,50,5.0,953141366 -587,58,5.0,953141592 -588,3,3.0,839317471 -588,6,5.0,839316454 -588,10,3.0,839316215 -588,16,4.0,839316454 -588,20,2.0,839317230 -588,21,3.0,839316350 -588,22,3.0,839317568 -588,25,3.0,839316993 -588,36,2.0,839316709 -588,42,3.0,839316637 -588,47,3.0,839316278 -588,50,5.0,839316659 -589,25,5.0,856038816 -589,36,5.0,856038894 -590,1,4.0,1258420408 -590,2,2.5,1258420835 -590,3,3.0,1258416995 -590,5,2.0,1258421220 -590,6,3.5,1258420706 -590,10,3.5,1258420600 -590,11,3.0,1258419975 -590,17,3.5,1258418302 -590,19,2.0,1258420848 -590,32,3.0,1258420444 -590,36,3.5,1258420766 -590,47,3.0,1258420506 -590,50,4.5,1264910688 -591,24,2.0,970525102 -592,2,4.0,837350242 -592,6,3.0,837350390 -592,10,3.0,837349966 -592,15,4.0,837350747 -592,19,4.0,837350082 -592,21,3.0,837350081 -592,24,4.0,837350801 -592,39,4.0,837350111 -592,44,3.0,837350308 -592,93,3.0,837350801 -592,95,3.0,837350282 -593,34,4.0,1181008004 -593,41,4.0,1181007216 -593,50,4.5,1181007737 -594,2,4.0,1109037094 -594,3,4.0,1108798921 -594,11,5.0,1109036973 -594,17,4.0,1108972872 -594,28,4.5,1108973143 -594,39,4.5,1115885611 -594,46,4.5,1108973615 -594,48,4.5,1109038257 -594,70,3.5,1108951120 -595,50,5.0,938807286 -596,1,4.0,1535709666 -596,32,3.5,1535709749 -596,34,4.0,1535827362 -596,39,4.0,1535827547 -596,50,3.5,1535709301 -597,1,4.0,941557863 -597,6,3.0,940420695 -597,7,1.0,941558874 -597,10,3.0,941729264 -597,11,3.0,941558713 -597,17,3.0,940362409 -597,21,5.0,941559030 -597,34,4.0,940362281 -597,39,4.0,941558116 -597,42,3.0,941729264 -597,45,5.0,941559030 -597,47,4.0,940361541 -597,50,5.0,940362491 -597,52,4.0,941559030 -597,69,4.0,941558258 -597,70,2.0,941559139 -599,1,3.0,1498524204 -599,2,2.5,1498514085 -599,3,1.5,1498505071 -599,6,4.5,1498539623 -599,7,2.5,1498514161 -599,9,1.5,1498504960 -599,10,3.5,1498500281 -599,11,2.5,1498516445 -599,12,1.5,1519181787 -599,15,1.5,1519239842 -599,16,3.0,1498523389 -599,17,3.5,1498501103 -599,18,3.0,1498523048 -599,19,3.0,1498524930 -599,20,1.5,1498504813 -599,21,4.0,1498499235 -599,23,1.0,1498503332 -599,24,2.5,1498517444 -599,26,2.5,1498518655 -599,29,3.5,1498500987 -599,31,2.0,1498511120 -599,32,3.0,1498519822 -599,39,3.0,1498525783 -599,41,2.5,1498518847 -599,42,3.0,1498525483 -599,43,3.0,1519347048 -599,44,2.5,1498517161 -599,45,2.5,1498516640 -599,47,4.0,1498499364 -599,50,3.5,1498500777 -599,52,3.0,1498525392 -599,57,2.5,1519240604 -599,60,2.0,1519118310 -599,61,2.5,1519327817 -599,65,2.0,1498511235 -599,69,2.5,1498515243 -599,70,3.5,1498501183 -599,73,3.0,1519421396 -599,75,1.0,1519353713 -599,76,2.5,1498518457 -599,79,2.0,1519336237 -599,81,2.5,1498517265 -599,87,0.5,1519184941 -599,88,0.5,1498533540 -599,89,2.5,1498517086 -599,93,1.5,1498504070 -599,95,2.0,1498510588 -599,97,3.0,1519120150 -599,100,2.0,1498511085 -600,1,2.5,1237764347 -600,2,4.0,1237764627 -600,4,1.5,1237760055 -600,5,2.5,1237759452 -600,7,3.5,1237851387 -600,17,3.5,1237712509 -600,19,3.0,1237709125 -600,24,2.0,1237707977 -600,29,4.5,1237713604 -600,32,4.5,1237858629 -600,34,2.0,1237711536 -600,39,3.0,1237858693 -600,46,3.0,1237851925 -600,47,4.0,1237852430 -600,52,3.5,1237715563 -600,62,2.5,1237713038 -600,72,1.0,1237760885 -600,73,3.5,1237760041 -601,1,4.0,1521467801 -601,47,4.0,1521467863 -601,50,5.0,1441639169 -602,2,4.0,840875851 -602,6,3.0,840876055 -602,10,3.0,840875622 -602,11,3.0,840875825 -602,14,5.0,840875999 -602,16,3.0,840876085 -602,19,2.0,840875700 -602,21,4.0,840875720 -602,22,3.0,840876417 -602,25,4.0,840875998 -602,29,2.0,840876620 -602,32,3.0,840875779 -602,34,1.0,840875700 -602,36,3.0,840876228 -602,39,5.0,840875757 -602,45,5.0,840876055 -602,47,5.0,840875668 -602,50,5.0,840875720 -602,52,3.0,840876566 -602,95,3.0,840875901 -602,100,3.0,840876228 -603,1,4.0,963178147 -603,6,4.0,963177624 -603,16,4.0,963179585 -603,17,3.0,954482210 -603,21,5.0,963177624 -603,25,4.0,954482181 -603,28,5.0,953925191 -603,29,2.0,963177361 -603,30,4.0,963179273 -603,32,3.0,963179615 -603,34,4.0,963179273 -603,36,4.0,953925157 -603,39,5.0,954482276 -603,45,4.0,963179538 -603,52,1.0,963178236 -603,53,5.0,963180003 -603,57,2.0,963180025 -603,58,3.0,954482414 -603,62,1.0,963180075 -603,70,4.0,953925705 -603,77,4.0,954482106 -603,82,1.0,963180075 -603,85,5.0,953925191 -603,97,4.0,963179791 -603,99,5.0,954482070 -604,1,3.0,832079851 -604,2,5.0,832080293 -604,5,3.0,832080355 -604,6,3.0,832080355 -604,14,4.0,832081027 -604,17,4.0,832080092 -604,19,1.0,832080050 -604,22,3.0,832080546 -604,23,4.0,832081042 -604,25,3.0,832080316 -604,32,4.0,832079958 -604,34,4.0,832079958 -604,39,3.0,832079983 -604,60,4.0,832080939 -604,62,4.0,832080293 -604,76,4.0,832080615 -604,92,3.0,832080615 -604,95,4.0,832080071 -605,1,4.0,1277097561 -605,2,3.5,1277176522 -605,28,4.0,1277094943 -605,73,3.0,1277094964 -606,1,2.5,1349082950 -606,7,2.5,1171754710 -606,11,2.5,1174349629 -606,15,3.5,1171839063 -606,17,4.0,1171838026 -606,18,4.0,1171327151 -606,19,2.0,1171814553 -606,28,3.5,1173049970 -606,29,4.5,1179419005 -606,32,4.0,1173653921 -606,36,3.5,1171820699 -606,46,4.0,1171757334 -606,47,3.0,1171927423 -606,50,4.5,1171234887 -606,58,3.5,1181771144 -606,68,4.0,1171817003 -606,70,4.0,1171733439 -606,73,4.0,1171410274 -606,80,4.0,1171409272 -606,82,4.0,1175637619 -606,92,3.5,1171365342 -607,1,4.0,964744033 -607,11,3.0,964744602 -607,25,3.0,963078417 -607,34,3.0,963079238 -607,36,4.0,964744413 -607,86,4.0,963079311 -608,1,2.5,1117408267 -608,2,2.0,1117490786 -608,3,2.0,1117504413 -608,10,4.0,1117408486 -608,16,4.5,1189471181 -608,19,2.0,1117504385 -608,21,3.5,1147210949 -608,24,2.0,1117504646 -608,31,3.0,1117504582 -608,32,3.5,1117336682 -608,34,3.5,1117491662 -608,39,3.0,1117415401 -608,44,0.5,1117504562 -608,47,4.5,1117162426 -608,48,0.5,1117161754 -608,50,4.5,1117491010 -608,63,0.5,1117506926 -608,65,2.0,1117415653 -608,70,3.0,1117415406 -608,88,2.5,1117505159 -608,93,2.5,1117506858 -608,95,2.0,1117490752 -609,1,3.0,847221025 -609,10,4.0,847220937 -610,1,5.0,1479542900 -610,6,5.0,1493850345 -610,16,4.5,1479542171 -610,32,4.5,1479543331 -610,47,5.0,1479545853 -610,50,4.0,1493844757 -610,70,4.0,1495959282 -610,95,3.5,1479542004 diff --git a/tests/unused/unit/ml_handlers/data/vertex_anomaly_detection.csv b/tests/unused/unit/ml_handlers/data/vertex_anomaly_detection.csv deleted file mode 100755 index b87f4cb8e2d..00000000000 --- a/tests/unused/unit/ml_handlers/data/vertex_anomaly_detection.csv +++ /dev/null @@ -1,6 +0,0 @@ -carat,cut,color,clarity,depth,table,x,y,z -0.23,Ideal,E,VS2,61.5,55,3.95,3.98,2.43 -0.21,Premium,E,VS2,59.8,61,3.89,3.84,2.31 -0.23,Good,E,VS2,56.9,65,4.05,4.07,2.31 -0.29,Premium,I,VS2,62.4,58,4.2,4.23,2.63 -0.31,Good,J,VS2,63.3,58,4.34,4.35,2.75 \ No newline at end of file diff --git a/tests/unused/unit/ml_handlers/data/vertex_classification.csv b/tests/unused/unit/ml_handlers/data/vertex_classification.csv deleted file mode 100644 index 994bd3a5804..00000000000 --- a/tests/unused/unit/ml_handlers/data/vertex_classification.csv +++ /dev/null @@ -1,6 +0,0 @@ -Amount,Class,Time,V1,V10,V11,V12,V13,V14,V15,V16,V17,V18,V19,V2,V20,V21,V22,V23,V24,V25,V26,V27,V28,V3,V4,V5,V6,V7,V8,V9 -149.62,'0',0,-1.3598071337,0.090794172,-0.5515995333,-0.6178008558,-0.9913898472,-0.3111693537,1.4681769721,-0.47040052530000004,0.20797124190000002,0.0257905802,0.40399296030000004,-0.0727811733,0.2514120982,-0.0183067779,0.2778375756,-0.1104739102,0.06692807490000001,0.12853935830000002,-0.1891148439,0.1335583767,-0.021053053500000002,2.5363467379999998,1.3781552243,-0.3383207699,0.4623877778,0.2395985541,0.0986979013,0.3637869696 -2.69,'0',0,1.1918571113,-0.16697441400000002,1.6127266611,1.0652353114,0.48909501590000004,-0.1437722964,0.6355580933,0.46391704100000003,-0.11480466310000001,-0.1833612701,-0.1457830413,0.2661507121,-0.0690831352,-0.225775248,-0.6386719528,0.1012880213,-0.3398464755,0.1671704044,0.1258945324,-0.008983099100000001,0.0147241692,0.16648011340000002,0.4481540785,0.0600176493,-0.0823608088,-0.0788029833,0.0851016549,-0.2554251281 -378.66,'0',1,-1.3583540616,0.2076428652,0.6245014594,0.0660836853,0.7172927314,-0.1659459228,2.345864949,-2.8900831944,1.1099693787,-0.1213593132,-2.2618570953,-1.3401630747,0.5249797252,0.2479981535,0.7716794019000001,0.9094122623,-0.6892809565,-0.3276418337,-0.13909657150000002,-0.055352794000000004,-0.0597518406,1.7732093426,0.379779593,-0.5031981333000001,1.8004993808,0.7914609565,0.2476757866,-1.5146543226 -123.5,'0',1,-0.9662717116,-0.0549519225,-0.2264872638,0.1782282259,0.50775687,-0.2879237455,-0.6314181177,-1.0596472454,-0.6840927863,1.9657750035000001,-1.2326219701,-0.1852260081,-0.2080377812,-0.108300452,0.0052735968000000005,-0.1903205187,-1.1755753319,0.6473760346,-0.2219288445,0.0627228487,0.0614576285,1.7929933396000002,-0.863291275,-0.010308879600000001,1.2472031675,0.2376089398,0.3774358747,-1.3870240627000001 -69.99,'0',2,-1.1582330935,0.753074432,-0.8228428779,0.5381955501,1.3458515932,-1.1196698347,0.17512113,-0.4514491828,-0.2370332394,-0.038194787,0.8034869250000001,0.8777367548,0.4085423604,-0.0094306971,0.7982784946,-0.1374580796,0.1412669838,-0.20600958760000002,0.5022922242,0.2194222295,0.2151531475,1.5487178465,0.40303393400000004,-0.4071933773,0.0959214625,0.5929407454,-0.2705326772,0.8177393082000001 diff --git a/tests/unused/unit/ml_handlers/data/vertex_regression.csv b/tests/unused/unit/ml_handlers/data/vertex_regression.csv deleted file mode 100644 index dba96576054..00000000000 --- a/tests/unused/unit/ml_handlers/data/vertex_regression.csv +++ /dev/null @@ -1,5 +0,0 @@ -date,quarter,department,day,team,targeted_productivity,smv,wip,over_time,incentive,idle_time,idle_men,no_of_style_change,no_of_workers,actual_productivity -1/1/2015,Quarter1,sweing,Thursday,8,0.8,26.16,1108,7080,98,0,0,0,59,0.940725424 -1/1/2015,Quarter1,finishing ,Thursday,1,0.75,3.94,,960,0,0,0,0,8,0.8865 -1/1/2015,Quarter1,sweing,Thursday,11,0.8,11.41,968,3660,50,0,0,0,30.5,0.800570492 -1/1/2015,Quarter1,sweing,Thursday,12,0.8,11.41,968,3660,50,0,0,0,30.5,0.800570492 diff --git a/tests/unused/unit/ml_handlers/test_anomaly_detection.py b/tests/unused/unit/ml_handlers/test_anomaly_detection.py deleted file mode 100644 index c27f77c7a86..00000000000 --- a/tests/unused/unit/ml_handlers/test_anomaly_detection.py +++ /dev/null @@ -1,291 +0,0 @@ -import time -import pandas as pd -from unittest.mock import patch -from mindsdb_sql_parser import parse_sql - -from tests.unit.executor_test_base import BaseExecutorTest -from mindsdb.integrations.handlers.anomaly_detection_handler.anomaly_detection_handler import ( - choose_model, - preprocess_data, -) - - -def test_choose_model(): - df = pd.read_csv("tests/unit/ml_handlers/data/anomaly_detection.csv") - # If no target is specified, we should use the unsupervised model - model = choose_model(df) - assert model.__class__.__name__ == "ECOD" - # If the size of the dataset is less than the semi_supervised_threshold, we should use the semi-supervised model - model = choose_model(df, target="class", supervised_threshold=50) - assert model.__class__.__name__ == "XGBOD" - # If the model type is specified, we should use that model type and override default logic - model = choose_model(df, target="class", model_type="supervised", supervised_threshold=50) - assert model.__class__.__name__ == "CatBoostClassifier" - # If the size of the dataset is greater than the semi_supervised_threshold, we should use the supervised model - model = choose_model(df, target="class", supervised_threshold=2) - assert model.__class__.__name__ == "CatBoostClassifier" - # If the model type is specified, we should use that model type and override default logic - model = choose_model(df, target="class", model_type="semi-supervised", supervised_threshold=2) - assert model.__class__.__name__ == "XGBOD" - # If the model name is specified, we should use that model name and override default logic - model = choose_model(df, target=None, model_name="knn", supervised_threshold=2) - assert model.__class__.__name__ == "KNN" - # If the model does not exist, we should raise an error - try: - model = choose_model(df, target="class", model_name="not_a_model", supervised_threshold=2) - assert False - except AssertionError: - assert True - - -def test_preprocess_data(): - df = pd.read_csv("tests/unit/ml_handlers/data/anomaly_detection.csv") - preprocessed_df = preprocess_data(df) - assert len(preprocessed_df) == len(df) - - -class TestAnomalyDetectionHandler(BaseExecutorTest): - def wait_predictor(self, project, name): - # wait - done = False - for attempt in range(200): - ret = self.run_sql(f"select * from {project}.models where name='{name}'") - if not ret.empty: - if ret["STATUS"][0] == "complete": - done = True - break - elif ret["STATUS"][0] == "error": - break - time.sleep(0.5) - if not done: - raise RuntimeError("predictor wasn't created") - - def run_sql(self, sql): - ret = self.command_executor.execute_command(parse_sql(sql)) - assert ret.error_code is None - if ret.data is not None: - return ret.data.to_df() - - @patch("mindsdb.integrations.handlers.postgres_handler.Handler") - def test_default_supervised_model(self, mock_handler): - # create project - self.run_sql("create database proj") - df = pd.read_csv("tests/unit/ml_handlers/data/anomaly_detection.csv") - self.set_handler(mock_handler, name="pg", tables={"df": df}) - - # create predictor - self.run_sql( - """ - create model proj.modelx - from pg (select * from df) - predict class - using - engine='anomaly_detection', - type='supervised' - """ - ) - self.wait_predictor("proj", "modelx") - - # run predict - ret = self.run_sql( - """ - SELECT p.* - FROM pg.df as t - JOIN proj.modelx as p - """ - ) - assert len(ret) == len(df) - - ret = self.run_sql( - """ - describe model proj.modelx.model - """ - ) - assert ret["model_name"][0] == "CatBoostClassifier" - - @patch("mindsdb.integrations.handlers.postgres_handler.Handler") - def test_non_default_supervised_model(self, mock_handler): - # create project - self.run_sql("create database proj") - df = pd.read_csv("tests/unit/ml_handlers/data/anomaly_detection.csv") - self.set_handler(mock_handler, name="pg", tables={"df": df}) - - # create predictor - self.run_sql( - """ - create model proj.modelx - from pg (select * from df) - predict class - using - engine='anomaly_detection', - type='supervised', - model_name='nb' - """ - ) - self.wait_predictor("proj", "modelx") - - # run predict - ret = self.run_sql( - """ - SELECT p.* - FROM pg.df as t - JOIN proj.modelx as p - """ - ) - assert len(ret) == len(df) - - ret = self.run_sql( - """ - describe model proj.modelx.model - """ - ) - assert ret["model_name"][0] == "GaussianNB" - - @patch("mindsdb.integrations.handlers.postgres_handler.Handler") - def test_specify_anomaly_type(self, mock_handler): - # create project - self.run_sql("create database proj") - df = pd.read_csv("tests/unit/ml_handlers/data/anomaly_detection.csv") - self.set_handler(mock_handler, name="pg", tables={"df": df}) - - # create predictor - self.run_sql( - """ - create model proj.modelx - from pg (select * from df) - predict outlier - using - engine='anomaly_detection', - anomaly_type='clustered', - type='unsupervised' - """ - ) - self.wait_predictor("proj", "modelx") - - # run predict - ret = self.run_sql( - """ - SELECT p.* - FROM pg.df as t - JOIN proj.modelx as p - """ - ) - assert len(ret) == len(df) - - ret = self.run_sql( - """ - describe model proj.modelx.model - """ - ) - assert ret["model_name"][0] == "PCA" - - @patch("mindsdb.integrations.handlers.postgres_handler.Handler") - def test_ensemble(self, mock_handler): - # create project - self.run_sql("create database proj") - df = pd.read_csv("tests/unit/ml_handlers/data/anomaly_detection.csv") - self.set_handler(mock_handler, name="pg", tables={"df": df}) - - # create predictor - self.run_sql( - """ - create ANOMALY DETECTION MODEL proj.modelx - from pg (select * from df) - using - engine='anomaly_detection', - ensemble_models=['pca', 'knn', 'ecod'] - """ - ) - # change model_names to ensemble_models for clarity - self.wait_predictor("proj", "modelx") - - # run predict - ret = self.run_sql( - """ - SELECT p.* - FROM pg.df as t - JOIN proj.modelx as p - """ - ) - assert len(ret) == len(df) - - ret = self.run_sql( - """ - describe model proj.modelx.model - """ - ) - assert all(ret["model_name"] == pd.Series(["PCA", "KNN", "ECOD"])) - - @patch("mindsdb.integrations.handlers.postgres_handler.Handler") - def test_default_semi_supervised_model(self, mock_handler): - # create database - self.run_sql("create database proj") - df = pd.read_csv("tests/unit/ml_handlers/data/anomaly_detection.csv") - self.set_handler(mock_handler, name="pg", tables={"df": df}) - - # create predictor - self.run_sql( - """ - create model proj.modelx - from pg (select * from df) - predict class - using - engine='anomaly_detection', - type='semi-supervised' - """ - ) - self.wait_predictor("proj", "modelx") - - # run predict - ret = self.run_sql( - """ - SELECT p.* - FROM pg.df as t - JOIN proj.modelx as p - """ - ) - assert len(ret) == len(df) - - ret = self.run_sql( - """ - describe model proj.modelx.model - """ - ) - assert ret["model_name"][0] == "XGBOD" - - @patch("mindsdb.integrations.handlers.postgres_handler.Handler") - def test_default_unsupervised_model(self, mock_handler): - # dataset, string values - df = pd.read_csv("tests/unit/ml_handlers/data/anomaly_detection.csv") - self.set_handler(mock_handler, name="pg", tables={"df": df}) - - # create project - self.run_sql("create database proj") - - # create predictor - self.run_sql( - """ - create anomaly detection model proj.modelx - from pg (select * from df) - using - engine='anomaly_detection' - """ - ) - self.wait_predictor("proj", "modelx") - - # run predict - ret = self.run_sql( - """ - SELECT p.outlier - FROM pg.df as t - JOIN proj.modelx as p - """ - ) - assert len(ret) == len(df) - - ret = self.run_sql( - """ - describe model proj.modelx.model - """ - ) - assert ret["model_name"][0] == "ECOD" diff --git a/tests/unused/unit/ml_handlers/test_anthropic.py b/tests/unused/unit/ml_handlers/test_anthropic.py deleted file mode 100644 index 020e1d13e57..00000000000 --- a/tests/unused/unit/ml_handlers/test_anthropic.py +++ /dev/null @@ -1,110 +0,0 @@ -import os -import pytest -import pandas as pd -from unittest.mock import patch - -from .base_ml_test import BaseMLAPITest - - -@pytest.mark.skipif(os.environ.get('ANTHROPIC_API_KEY') is None, reason='Missing API key!') -class TestAnthropic(BaseMLAPITest): - """Test Class for Anthropic Integration Testing""" - - def setup_method(self): - """Setup test environment, creating a project""" - super().setup_method() - self.run_sql("create database proj") - self.run_sql( - f""" - CREATE ML_ENGINE anthropic - FROM anthropic - USING - anthropic_api_key = '{self.get_api_key('ANTHROPIC_API_KEY')}'; - """ - ) - - def test_invalid_model_parameter(self): - """Test for invalid Anthropic model parameter""" - self.run_sql( - f""" - CREATE MODEL proj.test_anthropic_invalid_model - PREDICT answer - USING - engine='anthropic', - column='question', - model='this-claude-does-not-exist', - api_key='{self.get_api_key('ANTHROPIC_API_KEY')}'; - """ - ) - with pytest.raises(Exception): - self.wait_predictor("proj", "test_anthropic_invalid_model") - - def test_unknown_model_argument(self): - """Test for unknown argument when creating a Anthropic model""" - self.run_sql( - f""" - CREATE MODEL proj.test_anthropic_unknown_argument - PREDICT answer - USING - engine='anthropic', - column='question', - api_key='{self.get_api_key('ANTHROPIC_API_KEY')}', - evidently_wrong_argument='wrong value'; - """ - ) - with pytest.raises(Exception): - self.wait_predictor("proj", "test_anthropic_unknown_argument") - - def test_single_qa(self): - """Test for single question/answer pair""" - self.run_sql( - f""" - CREATE MODEL proj.test_anthropic_single_qa - PREDICT answer - USING - engine='anthropic', - column='question', - api_key='{self.get_api_key('ANTHROPIC_API_KEY')}'; - """ - ) - self.wait_predictor("proj", "test_anthropic_single_qa") - - result_df = self.run_sql( - """ - SELECT answer - FROM proj.test_anthropic_single_qa - WHERE question = 'What is the capital of Sweden?'; - """ - ) - assert "stockholm" in result_df["answer"].iloc[0].lower() - - @patch("mindsdb.integrations.handlers.postgres_handler.Handler") - def test_bulk_qa(self, mock_handler): - """Test for bulk question/answer pairs""" - df = pd.DataFrame.from_dict({"question": [ - "What is the capital of Sweden?", - "What is the second planet of the solar system?" - ]}) - self.set_handler(mock_handler, name="pg", tables={"df": df}) - - self.run_sql( - f""" - CREATE MODEL proj.test_anthropic_bulk_qa - PREDICT answer - USING - engine='anthropic', - column='question', - api_key='{self.get_api_key('ANTHROPIC_API_KEY')}'; - """ - ) - self.wait_predictor("proj", "test_anthropic_bulk_qa") - - result_df = self.run_sql( - """ - SELECT p.answer - FROM pg.df as t - JOIN proj.test_anthropic_bulk_qa as p; - """ - ) - assert "stockholm" in result_df["answer"].iloc[0].lower() - assert "venus" in result_df["answer"].iloc[1].lower() diff --git a/tests/unused/unit/ml_handlers/test_autogluon.py b/tests/unused/unit/ml_handlers/test_autogluon.py deleted file mode 100644 index 1b35d2bc45f..00000000000 --- a/tests/unused/unit/ml_handlers/test_autogluon.py +++ /dev/null @@ -1,77 +0,0 @@ -import time -from unittest.mock import patch -import pandas as pd - -from mindsdb_sql_parser import parse_sql - - -from unit.executor_test_base import BaseExecutorTest - - -class TestAutoGluon(BaseExecutorTest): - def wait_predictor(self, project, name): - # wait - done = False - for attempt in range(200): - ret = self.run_sql( - f"select * from {project}.models where name='{name}'" - ) - # print(ret['STATUS'][0]) - if not ret.empty: - if ret['STATUS'][0] == 'complete': - done = True - break - elif ret['STATUS'][0] == 'error': - # print(f"{ret['ERROR'][0]}") - break - time.sleep(15) - if not done: - raise RuntimeError("predictor wasn't created") - - def run_sql(self, sql): - ret = self.command_executor.execute_command( - parse_sql(sql) - ) - assert ret.error_code is None - if ret.data is not None: - return ret.data.to_df() - - @patch('mindsdb.integrations.handlers.postgres_handler.Handler') - def test_simple(self, mock_handler): - - # dataset, string values - df = pd.DataFrame(range(1, 50), columns=['a']) - df['b'] = 50 - df.a - df['c'] = round((df['a'] * 3 + df['b']) / 50) - - self.set_handler(mock_handler, name='pg', tables={'df': df}) - - # create project - self.run_sql('create database proj;') - - # create predictor - self.run_sql(''' - create model proj.modelx - from pg (select * from df) - predict c - using - engine='autogluon'; - ''') - - self.wait_predictor('proj', 'modelx') - - # run predict - ret = self.run_sql(''' - SELECT p.* - FROM pg.df as t - JOIN proj.modelx as p - where t.c=1 - ''') - avg_c = pd.to_numeric(ret.c).mean() - # value is around 1 - assert (avg_c > 0.9) and (avg_c < 1.1) - - -# df = pd.DataFrame(range(1, 50), columns=['a']) -# df['b'] = 50 - df.a -# df['c'] = round((df['a']*3 + df['b']) / 50) diff --git a/tests/unused/unit/ml_handlers/test_autokeras.py b/tests/unused/unit/ml_handlers/test_autokeras.py deleted file mode 100644 index fd63a03875a..00000000000 --- a/tests/unused/unit/ml_handlers/test_autokeras.py +++ /dev/null @@ -1,276 +0,0 @@ -import time -from unittest.mock import patch -import pandas as pd -import numpy as np - -from mindsdb_sql_parser import parse_sql - - -from mindsdb.integrations.handlers.autokeras_handler.autokeras_handler import ( - format_categorical_preds, -) -from tests.unit.executor_test_base import BaseExecutorTest - - -def test_format_categorical_preds(): - """Tests helper function to put categorical predictions into the right format""" - predictions = np.array([[0.9, 0.05, 0.05], [0, 1, 0], [0, 0, 1]]) - original_y = pd.Series(["a", "b", "c"]) - keras_output_df = pd.DataFrame({"target": predictions.tolist()}) - formatted_df = format_categorical_preds(predictions, original_y, keras_output_df, "target") - assert formatted_df["target"].tolist() == ["a", "b", "c"] - assert formatted_df["confidence"].tolist() == [max(row) for row in predictions] - - -class TestAutokeras(BaseExecutorTest): - def wait_predictor(self, project, name): - # wait - done = False - for attempt in range(200): - ret = self.run_sql(f"select * from {project}.models where name='{name}'") - if not ret.empty: - if ret["STATUS"][0] == "complete": - done = True - break - elif ret["STATUS"][0] == "error": - break - time.sleep(0.5) - if not done: - raise RuntimeError("predictor wasn't created") - - def run_sql(self, sql): - ret = self.command_executor.execute_command(parse_sql(sql)) - assert ret.error_code is None - if ret.data is not None: - return ret.data.to_df() - - @patch("mindsdb.integrations.handlers.postgres_handler.Handler") - def test_regression_with_numerical_training(self, mock_handler): - # dataset, string values - df = pd.DataFrame(range(1, 50), columns=["a"]) - df["b"] = 50 - df.a - df["c"] = round((df["a"] * 3 + df["b"]) / 50) - - self.set_handler(mock_handler, name="pg", tables={"df": df}) - - # create project - self.run_sql("create database proj") - - # create predictor - self.run_sql( - """ - create model proj.modelx - from pg (select * from df) - predict c - using - engine='autokeras', - train_time=0.01 - """ - ) - self.wait_predictor("proj", "modelx") - - # run predict - ret = self.run_sql( - """ - SELECT * - FROM proj.modelx - WHERE a=1 - AND b=25; - """ - ) - avg_c = pd.to_numeric(ret.c).mean() - assert ret.columns.tolist() == ["a", "b", "c"] - assert len(ret) == 1 - assert (avg_c > -5) and (avg_c < 5) - - @patch("mindsdb.integrations.handlers.postgres_handler.Handler") - def test_regression_with_categorical_training(self, mock_handler): - # dataset, string values - df = pd.DataFrame(range(1, 50), columns=["a"]) - df["b"] = 50 - df.a - df["c"] = round((df["a"] * 3 + df["b"]) / 50) - df["d"] = np.where(df.index % 2, "even", "odd") - - self.set_handler(mock_handler, name="pg", tables={"df": df}) - - # create project - self.run_sql("create database proj") - - # create predictor - self.run_sql( - """ - create model proj.modelx - from pg (select * from df) - predict c - using - engine='autokeras', - train_time=0.01 - """ - ) - self.wait_predictor("proj", "modelx") - - # run predict - ret = self.run_sql( - """ - SELECT c - FROM proj.modelx - WHERE a=1 AND b=25 AND d="odd" - """ - ) - avg_c = pd.to_numeric(ret.c).mean() - assert (avg_c > -5) and (avg_c < 5) - - @patch("mindsdb.integrations.handlers.postgres_handler.Handler") - def test_regression_with_nulls_in_training_data(self, mock_handler): - # dataset, string values - df = pd.DataFrame(range(1, 50), columns=["a"]) - df["b"] = 50 - df.a - df["c"] = round((df["a"] * 3 + df["b"]) / 50) - df["d"] = np.where(df.index % 2, "even", "odd") - # Make it look like we have missing data - df["a"][10] = None - df["b"][25] = np.nan - df["d"][31] = "" - - self.set_handler(mock_handler, name="pg", tables={"df": df}) - - # create project - self.run_sql("create database proj") - - # create predictor - self.run_sql( - """ - create model proj.modelx - from pg (select * from df) - predict c - using - engine='autokeras', - train_time=0.01 - """ - ) - self.wait_predictor("proj", "modelx") - - # run predict - ret = self.run_sql( - """ - SELECT c - FROM proj.modelx - WHERE a=1 AND b=25 AND d="odd"; - """ - ) - avg_c = pd.to_numeric(ret.c).mean() - assert (avg_c > -5) and (avg_c < 5) - - @patch("mindsdb.integrations.handlers.postgres_handler.Handler") - def test_regression_with_bulk_predict_query(self, mock_handler): - # dataset, string values - df = pd.DataFrame(range(1, 50), columns=["a"]) - df["b"] = 50 - df.a - df["c"] = round((df["a"] * 3 + df["b"]) / 50) - df["d"] = np.where(df.index % 2, "even", "odd") - - self.set_handler(mock_handler, name="pg", tables={"df": df}) - - # create project - self.run_sql("create database proj") - - # create predictor - self.run_sql( - """ - create model proj.modelx - from pg (select * from df) - predict c - using - engine='autokeras', - train_time=0.01 - """ - ) - self.wait_predictor("proj", "modelx") - - # run predict - ret = self.run_sql( - """ - SELECT m.* - FROM pg.df as t - JOIN proj.modelx as m - where t.b>25 - """ - ) - avg_c = pd.to_numeric(ret.c).mean() - assert (avg_c > -5) and (avg_c < 5) - - @patch("mindsdb.integrations.handlers.postgres_handler.Handler") - def test_regression_error_on_predict_query_missing_cols(self, mock_handler): - # dataset, string values - df = pd.DataFrame(range(1, 50), columns=["a"]) - df["b"] = 50 - df.a - df["c"] = round((df["a"] * 3 + df["b"]) / 50) - df["d"] = np.where(df.index % 2, "even", "odd") - - self.set_handler(mock_handler, name="pg", tables={"df": df}) - - # create project - self.run_sql("create database proj") - - # create predictor - self.run_sql( - """ - create model proj.modelx - from pg (select * from df) - predict c - using - engine='autokeras', - train_time=0.01 - """ - ) - self.wait_predictor("proj", "modelx") - - try: - # run predict but missing column d in the WHERE clause - _ = self.run_sql( - """ - SELECT c - FROM proj.modelx - WHERE a=1 - AND b=2; - """ - ) - assert False - except Exception: - assert True - - @patch("mindsdb.integrations.handlers.postgres_handler.Handler") - def test_classification_with_numerical_training(self, mock_handler): - # dataset, string values - df = pd.DataFrame(range(1, 50), columns=["a"]) - df["b"] = 50 - df.a - df["c"] = round((df["a"] * 3 + df["b"]) / 50) - df["d"] = np.where(df.index % 2, "even", "odd") - - self.set_handler(mock_handler, name="pg", tables={"df": df}) - - # create project - self.run_sql("create database proj") - - # create predictor - self.run_sql( - """ - create model proj.modelx - from pg (select * from df) - predict d - using - engine='autokeras', - train_time=0.01 - """ - ) - self.wait_predictor("proj", "modelx") - - # run predict - ret = self.run_sql( - """ - SELECT d - FROM proj.modelx - WHERE a=1 AND b=25 AND c=10 - """ - ) - assert ret.d[0] in ["even", "odd"] diff --git a/tests/unused/unit/ml_handlers/test_clipdrop.py b/tests/unused/unit/ml_handlers/test_clipdrop.py deleted file mode 100644 index bd4cb473b7b..00000000000 --- a/tests/unused/unit/ml_handlers/test_clipdrop.py +++ /dev/null @@ -1,110 +0,0 @@ -import os -import pytest -import pandas as pd -from unittest.mock import patch - -from .base_ml_test import BaseMLAPITest - - -@pytest.mark.skipif(os.environ.get('CLIPDROP_API_KEY') is None, reason='Missing API key!') -class TestClipdrop(BaseMLAPITest): - """Test Class for Clipdrop Integration Testing""" - - def setup_method(self): - """Setup test environment, creating a project""" - super().setup_method() - self.run_sql("create database proj") - self.run_sql( - f""" - CREATE ML_ENGINE clipdrop_engine - FROM clipdrop - USING - clipdrop_api_key = '{self.get_api_key('CLIPDROP_API_KEY')}'; - """ - ) - - def test_missing_task_argument(self): - """Test for unknown argument when creating a clidrop model""" - self.run_sql( - f""" - CREATE MODEL proj.test_clipdrop_invalid_model - PREDICT answer - USING - engine='clipdrop_engine', - local_directory_path = "tests/unit/ml_handlers/data", - api_key='{self.get_api_key('CLIPDROP_API_KEY')}'; - """ - ) - with pytest.raises(Exception): - self.wait_predictor("proj", "test_missing_task_argument") - - def test_unknown_task_argument(self): - """Test for unknown argument when creating a clipdrop model""" - self.run_sql( - f""" - CREATE MODEL proj.test_clipdrop_invalid_model - PREDICT answer - USING - engine='clipdrop_engine', - task = "unknown-task", - local_directory_path = "tests/unit/ml_handlers/data", - api_key='{self.get_api_key('CLIPDROP_API_KEY')}'; - """ - ) - with pytest.raises(Exception): - self.wait_predictor("proj", "test_unknown_task_argument") - - def test_text_image_single(self): - """Test for single text""" - self.run_sql( - f""" - CREATE MODEL proj.test_clipdrop_t2i_single - PREDICT answer - USING - engine='clipdrop_engine', - task = "text_to_image", - local_directory_path = "tests/unit/ml_handlers/data", - api_key='{self.get_api_key('CLIPDROP_API_KEY')}'; - """ - ) - self.wait_predictor("proj", "test_clipdrop_t2i_single") - - result_df = self.run_sql( - """ - SELECT * - FROM proj.test_clipdrop_t2i_single - WHERE text = 'A blue lagoon'; - """ - ) - assert result_df["answer"].size == 1 - - @patch("mindsdb.integrations.handlers.postgres_handler.Handler") - def test_bulk_text(self, mock_handler): - """Test for bulk question/answer pairs""" - df = pd.DataFrame.from_dict({"text": [ - "A black swan", - "A pink unicorn" - ]}) - self.set_handler(mock_handler, name="pg", tables={"df": df}) - - self.run_sql( - f""" - CREATE MODEL proj.test_clipdrop_bulk_text - PREDICT answer - USING - engine='clipdrop_engine', - task = "text_to_image", - local_directory_path = "tests/unit/ml_handlers/data", - api_key='{self.get_api_key('CLIPDROP_API_KEY')}'; - """ - ) - self.wait_predictor("proj", "test_clipdrop_bulk_text") - - result_df = self.run_sql( - """ - SELECT p.answer - FROM pg.df as t - JOIN proj.test_clipdrop_bulk_text as p; - """ - ) - assert result_df["answer"].size == 2 diff --git a/tests/unused/unit/ml_handlers/test_dspy.py b/tests/unused/unit/ml_handlers/test_dspy.py deleted file mode 100644 index 10d5ad4ebe3..00000000000 --- a/tests/unused/unit/ml_handlers/test_dspy.py +++ /dev/null @@ -1,100 +0,0 @@ -import os - - -import ollama -import pytest -from ..executor_test_base import BaseExecutorTest - - -OPENAI_API_KEY = os.environ.get("OPENAI_API_KEY") - - -def ollama_model_exists(model_name: str) -> bool: - - try: - ollama.show(model_name) - return True - except Exception: - return False - - -class TestDSPy(BaseExecutorTest): - - """Test Class for DSPy Integration Testing""" - @pytest.fixture(autouse=True, scope="function") - def setup_method(self): - """Setup test environment, creating a project""" - super().setup_method() - self.run_sql("create database proj") - - @pytest.mark.skipif(OPENAI_API_KEY is None, reason='Missing OpenAI API key (OPENAI_API_KEY env variable)') - def test_default_provider(self): - - self.run_sql( - f""" - CREATE ML_ENGINE dspy_engine - FROM dspy - USING - openai_api_key = '{OPENAI_API_KEY}'; - """ - ) - - self.run_sql( - """ - create model proj.test_conversational_model - predict answer - using - engine='dspy_engine', - provider = 'openai', - model_name = 'gpt-4', - mode = 'conversational', - user_column = 'question', - assistant_column = 'answer', - prompt_template='Answer the user in a useful way'; - """ - ) - self.wait_predictor("proj", "test_conversational_model") - result_df = self.run_sql( - """ - SELECT question, answer - FROM proj.test_conversational_model - WHERE question='What is the capital of Sweden?;' - """ - ) - assert "stockholm" in result_df['answer'].iloc[0].lower() - - @pytest.mark.skipif(OPENAI_API_KEY is None, reason='Missing OpenAI API key (OPENAI_API_KEY env variable)') - def test_default_provider2(self): - - self.run_sql( - f""" - CREATE ML_ENGINE dspy_engine - FROM dspy - USING - openai_api_key = '{OPENAI_API_KEY}'; - """ - ) - - self.run_sql( - """ - create model proj.test_conversational_model - predict answer - using - engine='dspy_engine', - provider = 'openai', - model_name = 'gpt-3.5-turbo', - mode = 'conversational', - user_column = 'question', - assistant_column = 'answer', - prompt_template='Answer the user in a useful way'; - """ - ) - self.wait_predictor("proj", "test_conversational_model") - result_df = self.run_sql( - """ - SELECT question, answer - FROM proj.test_conversational_model - WHERE question='What is 3 + 4?;' - """ - ) - assert "7" in result_df['answer'].iloc[0].lower() diff --git a/tests/unused/unit/ml_handlers/test_google_gemini.py b/tests/unused/unit/ml_handlers/test_google_gemini.py deleted file mode 100644 index 8e6726f2343..00000000000 --- a/tests/unused/unit/ml_handlers/test_google_gemini.py +++ /dev/null @@ -1,105 +0,0 @@ -import os -import pytest -import pandas as pd -from unittest.mock import patch - -from .base_ml_test import BaseMLAPITest - -GEMINI_API_KEY = os.environ.get('GOOGLE_GENAI_API_KEY') - - -@pytest.mark.skipif(GEMINI_API_KEY is None, reason='Missing API key!') -class TestGeminiHandler(BaseMLAPITest): - """Test Class for Google Gemini (Bard) API handler""" - - def setup_method(self): - """Setup test environment, creating a project""" - super().setup_method() - self.run_sql("create database proj") - - def test_invalid_model_parameter(self): - """Test for invalid Gemini model parameter""" - self.run_sql( - f""" - CREATE MODEL proj.test_google_invalid_model - PREDICT answer - USING - engine='google_gemini', - column='question', - model='non-existing-gemini-model', - api_key='{GEMINI_API_KEY}'; - """ - ) - with pytest.raises(Exception): - self.wait_predictor("proj", "test_google_invalid_model") - - @pytest.mark.skip(reason="This test is failing as no error is being thrown") - def test_unknown_model_argument(self): - """Test for unknown argument when creating Gemini model""" - self.run_sql( - f""" - CREATE MODEL proj.test_google_unknown_arg - PREDICT answer - USING - engine='google', - column='question', - api_key='{GEMINI_API_KEY}', - evidently_wrong_argument='wrong value'; - """ - ) - with pytest.raises(Exception): - self.wait_predictor("proj", "test_google_unknown_arg") - - def test_single_qa(self): - """Test for single question/answer pair""" - self.run_sql( - f""" - CREATE MODEL proj.test_google_single_qa - PREDICT answer - USING - engine='google_gemini', - column='question', - api_key='{GEMINI_API_KEY}'; - """ - ) - self.wait_predictor("proj", "test_google_single_qa") - - result_df = self.run_sql( - """ - SELECT answer - FROM proj.test_google_single_qa - WHERE question = 'What is the capital of Sweden?'; - """ - ) - assert "stockholm" in result_df["answer"].iloc[0].lower() - - @patch("mindsdb.integrations.handlers.postgres_handler.Handler") - def test_bulk_qa(self, mock_handler): - """Test for bulk question/answer pairs""" - df = pd.DataFrame.from_dict({"question": [ - "What is the capital of Sweden?", - "What is the second planet of the solar system?" - ]}) - self.set_handler(mock_handler, name="pg", tables={"df": df}) - - self.run_sql( - f""" - CREATE MODEL proj.test_google_bulk_qa - PREDICT answer - USING - engine='google_gemini', - column='question', - api_key='{GEMINI_API_KEY}'; - """ - ) - self.wait_predictor("proj", "test_google_bulk_qa") - - result_df = self.run_sql( - """ - SELECT p.answer - FROM pg.df as t - JOIN proj.test_google_bulk_qa as p; - """ - ) - assert "stockholm" in result_df["answer"].iloc[0].lower() - assert "venus" in result_df["answer"].iloc[1].lower() diff --git a/tests/unused/unit/ml_handlers/test_huggingface.py b/tests/unused/unit/ml_handlers/test_huggingface.py deleted file mode 100644 index f83d62de50b..00000000000 --- a/tests/unused/unit/ml_handlers/test_huggingface.py +++ /dev/null @@ -1,381 +0,0 @@ -import time -from unittest.mock import patch - -import pandas as pd -from mindsdb_sql_parser import parse_sql -from tests.unit.executor_test_base import BaseExecutorTest - -# How to run: -# env PYTHONPATH=./ pytest -vx tests/unit/test_ml_handlers.py -# Warning: a big huggingface models will be downloaded - - -class TestHuggingface(BaseExecutorTest): - def run_sql(self, sql): - return self.command_executor.execute_command(parse_sql(sql)) - - def hf_test_run(self, mock_handler, model_name, create_sql, predict_sql): - # prepare table - text_spammy = [ - "It is the best time to launch the Robot to get more money. https:\\/\\/Gof.bode-roesch.de\\/Gof", - "Start making thousands of dollars every week just using this robot. https:\\/\\/Gof.coronect.de\\/Gof", - ] - - text_short = ["I want to dance", "Baking is the best"] - - text_long = [ - "Dance is a performing art form consisting of sequences of movement, either improvised or purposefully selected. This movement has aesthetic and often symbolic value.[nb 1] Dance can be categorized and described by its choreography, by its repertoire of movements, or by its historical period or place of origin.", - "Baking is a method of preparing food that uses dry heat, typically in an oven, but can also be done in hot ashes, or on hot stones. The most common baked item is bread but many other types of foods can be baked. Heat is gradually transferred from the surface of cakes, cookies, and pieces of bread to their center. As heat travels through, it transforms batters and doughs into baked goods and more with a firm dry crust and a softer center. Baking can be combined with grilling to produce a hybrid barbecue variant by using both methods simultaneously, or one after the other. Baking is related to barbecuing because the concept of the masonry oven is similar to that of a smoke pit.", - ] - - df = pd.DataFrame(data=[text_spammy, text_short, text_long]).T - df.columns = ["text_spammy", "text_short", "text_long"] - - self.set_handler(mock_handler, name="pg", tables={"df": df}) - - # create predictor - ret = self.run_sql(create_sql) - assert ret.error_code is None - - # wait - done = False - for attempt in range(900): - ret = self.run_sql( - f"select status from mindsdb.models where name='{model_name}'" - ) - data = ret.data.to_lists() - if len(data) > 0: - if data[0][0] == "complete": - done = True - break - elif data[0][0] == "error": - break - time.sleep(0.5) - if not done: - raise RuntimeError("predictor not created") - - # use predictor - ret = self.command_executor.execute_command( - parse_sql(predict_sql) - ) - assert ret.error_code is None - - @patch("mindsdb.integrations.handlers.postgres_handler.Handler") - def test_hf_classification_bin(self, mock_handler): - # create predictor - create_sql = """ - CREATE PREDICTOR mindsdb.spam_classifier - predict PRED - USING - engine='huggingface', - join_learn_process=true, - task='text-classification', - model_name= "mrm8488/bert-tiny-finetuned-sms-spam-detection", - input_column = 'text_spammy', - labels=['ham','spam'] - """ - - model_name = "spam_classifier" - - predict_sql = """ - SELECT h.* - FROM pg.df as t - JOIN mindsdb.spam_classifier as h - """ - self.hf_test_run(mock_handler, model_name, create_sql, predict_sql) - - # one line prediction - predict_sql = """ - SELECT * from mindsdb.spam_classifier - where text_spammy= 'It is the best time to launch the Robot to get more money. https:\\/\\/Gof.bode-roesch.de\\/Gof' - """ - # use predictor - ret = self.command_executor.execute_command( - parse_sql(predict_sql) - ) - assert ret.error_code is None - - @patch("mindsdb.integrations.handlers.postgres_handler.Handler") - def test_hf_classification_multy(self, mock_handler): - # create predictor - create_sql = """ - CREATE PREDICTOR mindsdb.sentiment_classifier - predict PRED - USING - engine='huggingface', - join_learn_process=true, - task='text-classification', - model_name= "cardiffnlp/twitter-roberta-base-sentiment", - input_column = 'text_short', - labels=['neg','neu','pos'] - """ - - model_name = "sentiment_classifier" - - predict_sql = """ - SELECT h.* - FROM pg.df as t - JOIN mindsdb.sentiment_classifier as h - """ - self.hf_test_run(mock_handler, model_name, create_sql, predict_sql) - - @patch("mindsdb.integrations.handlers.postgres_handler.Handler") - def test_hf_zero_shot(self, mock_handler): - # create predictor - create_sql = """ - CREATE PREDICTOR mindsdb.zero_shot_tcd - predict PREDZS - USING - engine='huggingface', - join_learn_process=true, - task="zero-shot-classification", - model_name= "facebook/bart-large-mnli", - input_column = "text_short", - candidate_labels=['travel', 'cooking', 'dancing'] - """ - - model_name = "zero_shot_tcd" - - predict_sql = """ - SELECT h.* - FROM pg.df as t - JOIN mindsdb.zero_shot_tcd as h - """ - self.hf_test_run(mock_handler, model_name, create_sql, predict_sql) - - @patch("mindsdb.integrations.handlers.postgres_handler.Handler") - def test_summarization(self, mock_handler): - # create predictor - create_sql = """ - CREATE MODEL mindsdb.hf_summarization - PREDICT summary - USING - engine = 'huggingface', - task = 'summarization', - model_name = 'sshleifer/distilbart-xsum-12-1', - input_column = 'text_long', - min_output_length = 5, - max_output_length = 20; - """ - - model_name = "hf_summarization" - - predict_sql = """ - SELECT h.* - FROM pg.df as t - JOIN mindsdb.hf_summarization as h - """ - - self.hf_test_run(mock_handler, model_name, create_sql, predict_sql) - - @patch("mindsdb.integrations.handlers.postgres_handler.Handler") - def test_hf_translation(self, mock_handler): - # create predictor - create_sql = """ - CREATE PREDICTOR mindsdb.translator_en_fr - predict TRANSLATION - USING - engine='huggingface', - join_learn_process=true, - task = "translation", - model_name = "t5-base", - input_column = "text_short", - lang_input = "en", - lang_output = "fr" - """ - - model_name = "translator_en_fr" - - predict_sql = """ - SELECT h.* - FROM pg.df as t - JOIN mindsdb.translator_en_fr as h - """ - self.hf_test_run(mock_handler, model_name, create_sql, predict_sql) - - @patch("mindsdb.integrations.handlers.postgres_handler.Handler") - def test_hf_text2text(self, mock_handler): - # create predictor - create_sql = """ - CREATE MODEL mindsdb.text_generator - predict PREDICTION - USING - engine='huggingface', - join_learn_process=true, - task = "text2text-generation", - model_name = "google/flan-t5-base", - input_column = 'comment' - """ - - model_name = "text_generator" - - predict_sql = """ - SELECT * FROM text_generator - WHERE comment='Question: Why did the chicken cross the road?' - """ - self.hf_test_run(mock_handler, model_name, create_sql, predict_sql) - - @patch("mindsdb.integrations.handlers.postgres_handler.Handler") - def test_hf_text_classification_finetune(self, mock_handler): - create_sql = """ - CREATE PREDICTOR mindsdb.spam_classifier - predict PRED - USING - engine='huggingface', - join_learn_process=true, - task='text-classification', - model_name= "mrm8488/bert-tiny-finetuned-sms-spam-detection", - input_column = 'text_spammy', - labels=['ham','spam'] - """ - - model_name = "spam_classifier" - - predict_sql = """ - SELECT h.* - FROM pg.df as t - JOIN mindsdb.spam_classifier as h - """ - self.hf_test_run(mock_handler, model_name, create_sql, predict_sql) - - # one line prediction - predict_sql = """ - SELECT * from mindsdb.spam_classifier - where text_spammy= 'It is the best time to launch the Robot to get more money. https:\\/\\/Gof.bode-roesch.de\\/Gof' - """ - # use predictor - ret = self.command_executor.execute_command( - parse_sql(predict_sql) - ) - assert ret.error_code is None - - # fine tune - - fine_tune_sql = """ - FINETUNE mindsdb.spam_classifier - FROM pg ( - SELECT label as PRED, text as text_spammy FROM df WHERE PRED <= 1 - ) - USING - tokenizer_from = 'bert-base-uncased'; - """ - - ret = self.command_executor.execute_command( - parse_sql(fine_tune_sql) - ) - - assert ret.error_code is None - - @patch("mindsdb.integrations.handlers.postgres_handler.Handler") - def test_hf_zero_shot_classification_finetune(self, mock_handler): - # create predictor - create_sql = """ - CREATE PREDICTOR mindsdb.zero_shot_tcd - predict PREDZS - USING - engine='huggingface', - join_learn_process=true, - task="zero-shot-classification", - model_name= "facebook/bart-large-mnli", - input_column = "text_short", - candidate_labels=['travel', 'cooking', 'dancing'] - """ - - model_name = "zero_shot_tcd" - - predict_sql = """ - SELECT h.* - FROM pg.df as t - JOIN mindsdb.zero_shot_tcd as h - """ - self.hf_test_run(mock_handler, model_name, create_sql, predict_sql) - - # fine tune - - fine_tune_sql = """ - FINETUNE mindsdb.zero_shot_tcd - FROM pg (SELECT label, hypothesis FROM df); - """ - - ret = self.command_executor.execute_command( - parse_sql(fine_tune_sql) - ) - - assert ret.error_code is None - - @patch("mindsdb.integrations.handlers.postgres_handler.Handler") - def test_hf_translation_finetune(self, mock_handler): - # create predictor - create_sql = """ - CREATE PREDICTOR mindsdb.translator_en_fr - predict TRANSLATION - USING - engine='huggingface', - join_learn_process=true, - task = "translation", - model_name = "t5-base", - input_column = "text_short", - lang_input = "en", - lang_output = "fr" - """ - - model_name = "translator_en_fr" - - predict_sql = """ - SELECT h.* - FROM pg.df as t - JOIN mindsdb.translator_en_fr as h - """ - self.hf_test_run(mock_handler, model_name, create_sql, predict_sql) - - # fine tune - - fine_tune_sql = """ - FINETUNE mindsdb.translator_en_fr - FROM pg (SELECT text_long, transl FROM df); - """ - - ret = self.command_executor.execute_command( - parse_sql(fine_tune_sql) - ) - - assert ret.error_code is None - - @patch("mindsdb.integrations.handlers.postgres_handler.Handler") - def test_hf_summarization_finetune(self, mock_handler): - # create predictor - create_sql = """ - CREATE MODEL mindsdb.hf_summarization - PREDICT summary - USING - engine = 'huggingface', - task = 'summarization', - model_name = 'sshleifer/distilbart-xsum-12-1', - input_column = 'text_long', - min_output_length = 5, - max_output_length = 20; - """ - - model_name = "hf_summarization" - - predict_sql = """ - SELECT h.* - FROM pg.df as t - JOIN mindsdb.hf_summarization as h - """ - - self.hf_test_run(mock_handler, model_name, create_sql, predict_sql) - - # fine tune - fine_tune_sql = """ - FINETUNE mindsdb.hf_summarization - FROM pg ( - SELECT text, summary FROM df - ); - """ - - ret = self.command_executor.execute_command( - parse_sql(fine_tune_sql) - ) - - assert ret.error_code is None diff --git a/tests/unused/unit/ml_handlers/test_huggingface_api.py b/tests/unused/unit/ml_handlers/test_huggingface_api.py deleted file mode 100644 index 4ee84429123..00000000000 --- a/tests/unused/unit/ml_handlers/test_huggingface_api.py +++ /dev/null @@ -1,46 +0,0 @@ -from unittest.mock import patch -import pandas as pd - -from mindsdb_sql_parser import parse_sql - -from tests.unit.executor_test_base import BaseExecutorTest - - -class TestHuggingFaceAPI(BaseExecutorTest): - def run_sql(self, sql): - ret = self.command_executor.execute_command(parse_sql(sql)) - assert ret.error_code is None - if ret.data is not None: - return ret.data.to_df() - - @patch("mindsdb.integrations.handlers.postgres_handler.Handler") - def test_text_classification(self, mock_handler): - self.run_sql("CREATE DATABASE proj") - - texts = ["I like you. I love you", "I don't like you. I hate you"] - df = pd.DataFrame(texts, columns=['texts']) - - self.set_handler(mock_handler, name="pg", tables={"df": df}) - - self.run_sql( - """ - CREATE MODEL proj.test_hfapi_text_classification - PREDICT sentiment - USING - task = 'text-classification', - engine = 'hf_api_engine', - api_key = '', - input_column = 'text' - """ - ) - - result_df = self.run_sql( - """ - SELECT sentiment - FROM proj.test_hfapi_text_classification - WHERE - text='I like you. I love you' - """ - ) - - assert "positive" in result_df["sentiment"].iloc[0].lower() diff --git a/tests/unused/unit/ml_handlers/test_langchain.py b/tests/unused/unit/ml_handlers/test_langchain.py deleted file mode 100644 index e602a1b1bc0..00000000000 --- a/tests/unused/unit/ml_handlers/test_langchain.py +++ /dev/null @@ -1,162 +0,0 @@ -import os - -import ollama -import pytest - -from ..executor_test_base import BaseExecutorTest - -ANTHROPIC_API_KEY = os.environ.get("ANTHROPIC_API_KEY") -ANYSCALE_API_KEY = os.environ.get("ANYSCALE_API_KEY") -OPENAI_API_KEY = os.environ.get("OPENAI_API_KEY") -GOOGLE_API_KEY = os.environ.get("GOOGLE_API_KEY") - - -def ollama_model_exists(model_name: str) -> bool: - try: - ollama.show(model_name) - return True - except Exception: - return False - - -class TestLangchain(BaseExecutorTest): - """Test Class for Langchain Integration Testing""" - @pytest.fixture(autouse=True, scope="function") - def setup_method(self): - """Setup test environment, creating a project""" - super().setup_method() - self.run_sql("create database proj") - - @pytest.mark.skipif(OPENAI_API_KEY is None, reason='Missing OpenAI API key (OPENAI_API_KEY env variable)') - def test_default_provider(self): - self.run_sql( - f""" - create model proj.test_conversational_model - predict answer - using - engine='langchain', - prompt_template='Answer the user in a useful way: {{{{question}}}}', - openai_api_key='{OPENAI_API_KEY}'; - """ - ) - self.wait_predictor("proj", "test_conversational_model") - - result_df = self.run_sql( - """ - SELECT answer - FROM proj.test_conversational_model - WHERE question='What is the capital of Sweden?' - """ - ) - assert "stockholm" in result_df['answer'].iloc[0].lower() - - @pytest.mark.skipif(ANTHROPIC_API_KEY is None, reason='Missing Anthropic API key (ANTHROPIC_API_KEY env variable)') - def test_anthropic_provider(self): - self.run_sql( - f""" - create model proj.test_anthropic_langchain_model - predict answer - using - engine='langchain', - model_name='claude-2.1', - prompt_template='Answer the user in a useful way: {{{{question}}}}', - anthropic_api_key='{ANTHROPIC_API_KEY}'; - """ - ) - self.wait_predictor("proj", "test_anthropic_langchain_model") - - result_df = self.run_sql( - """ - SELECT answer - FROM proj.test_anthropic_langchain_model - WHERE question='What is the capital of Sweden?' - """ - ) - assert "stockholm" in result_df['answer'].iloc[0].lower() - - @pytest.mark.skipif(not ollama_model_exists('mistral'), reason='Make sure the mistral model is available locally by running `ollama pull mistral`') - def test_ollama_provider(self): - self.run_sql( - """ - create model proj.test_ollama_model - predict answer - using - engine='langchain', - model_name='mistral', - prompt_template='Answer the user in a useful way: {{question}}' - """ - ) - self.wait_predictor("proj", "test_ollama_model") - - result_df = self.run_sql( - """ - SELECT answer - FROM proj.test_ollama_model - WHERE question='What is the capital of British Columbia, Canada?' - """ - ) - assert "victoria" in result_df['answer'].iloc[0].lower() - - - @pytest.mark.skipif(GOOGLE_API_KEY is None, reason='Missing Google API key (GOOGLE_API_KEY env variable)') - def test_google_provider(self): - self.run_sql( - f""" - create model proj.test_google_langchain_model - predict answer - using - engine='langchain', - provider='google', - model_name='gemini-1.5-pro', - prompt_template='Answer the user in a useful way: {{{{question}}}}', - google_api_key='{GOOGLE_API_KEY}'; - """ - ) - self.wait_predictor("proj", "test_google_langchain_model") - - result_df = self.run_sql( - """ - SELECT answer - FROM proj.test_google_langchain_model - WHERE question='What is the capital of Sweden?' - """ - ) - assert "stockholm" in result_df['answer'].iloc[0].lower() - - def test_describe(self): - self.run_sql( - """ - create model proj.test_describe_model - predict answer - using - engine='langchain', - prompt_template='Answer the user in a useful way: {{question}}'; - """ - ) - self.wait_predictor("proj", "test_describe_model") - result_df = self.run_sql('DESCRIBE proj.test_describe_model') - assert not result_df.empty - - @pytest.mark.skipif(OPENAI_API_KEY is None, reason='Missing OpenAI API key (OPENAI_API_KEY env variable)') - def test_prompt_template_args(self): - self.run_sql( - f""" - create model proj.test_prompt_template_model - predict answer - using - engine='langchain', - prompt_template='Your name is {{{{name}}}}. Answer the user in a useful way: {{{{question}}}}', - openai_api_key='{OPENAI_API_KEY}'; - """ - ) - self.wait_predictor("proj", "test_prompt_template_model") - - agent_name = 'professor farnsworth' - result_df = self.run_sql( - f""" - SELECT answer - FROM proj.test_prompt_template_model - WHERE question='What is your name?' AND name='{agent_name}' - """ - ) - assert agent_name in result_df['answer'].iloc[0].lower() diff --git a/tests/unused/unit/ml_handlers/test_langchain_embedding.py b/tests/unused/unit/ml_handlers/test_langchain_embedding.py deleted file mode 100644 index 65029bb2c49..00000000000 --- a/tests/unused/unit/ml_handlers/test_langchain_embedding.py +++ /dev/null @@ -1,362 +0,0 @@ -import os -import time -from unittest.mock import patch - -import pandas as pd -import pytest -from mindsdb_sql_parser import parse_sql - -from ..executor_test_base import BaseExecutorTest - - -class TestLangchainEmbedding(BaseExecutorTest): - def wait_predictor(self, project, name): - # wait - done = False - for _ in range(200): - ret = self.run_sql(f"select * from {project}.models where name='{name}'") - if not ret.empty: - if ret["STATUS"][0] == "complete": - done = True - break - elif ret["STATUS"][0] == "error": - break - time.sleep(0.5) - if not done: - raise RuntimeError("predictor wasn't created") - - def run_sql(self, sql): - ret = self.command_executor.execute_command(parse_sql(sql)) - assert ret.error_code is None - if ret.data is not None: - return ret.data.to_df() - - @patch("mindsdb.integrations.handlers.postgres_handler.Handler") - def test_dummy_embedding(self, mock_handler): - self.run_sql("create database proj") - # create the model - self.run_sql( - """ - CREATE MODEL proj.test_dummy_embedding - PREDICT embeddings_output_column - USING - engine='langchain_embedding', - class = 'FakeEmbeddings', - size = 512, - input_columns = ['content'] - """ - ) - - self.wait_predictor("proj", "test_dummy_embedding") - - # predictions - # one line - ret = self.run_sql( - """ - SELECT * FROM proj.test_dummy_embedding - WHERE content='hello' - """ - ) - assert "content" in ret.columns - assert "embeddings_output_column" in ret.columns - # the embeddings should be a list of 512 floats - assert len(ret["embeddings_output_column"][0]) == 512 - - # multiple lines - # insert data - df = pd.DataFrame( - [ - ["hello"], - ["world"], - ["foo"], - ["bar"], - ], - columns=["content"], - ) - self.set_handler(mock_handler, name="pg", tables={"df": df}) - - # query - ret = self.run_sql( - """ - SELECT * FROM proj.test_dummy_embedding - JOIN pg.df - """ - ) - - assert "content" in ret.columns - assert "embeddings_output_column" in ret.columns - assert ret.shape[0] == 4 - - @patch("mindsdb.integrations.handlers.postgres_handler.Handler") - def test_embed_multiple_columns(self, mock_handler): - self.run_sql("create database proj") - # create the model - # with multiple input columns - self.run_sql( - """ - CREATE MODEL proj.test_dummy_embedding_multiple_columns - PREDICT embeddings - USING - engine='langchain_embedding', - class = 'fake', -- a more user friendly name - size = 512, - input_columns = ['content1', 'content2'] - """ - ) - - self.wait_predictor("proj", "test_dummy_embedding_multiple_columns") - - # predictions - # one line - ret = self.run_sql( - """ - SELECT * FROM proj.test_dummy_embedding_multiple_columns - WHERE content1='hello' - AND content2='world' - """ - ) - - assert "content1" in ret.columns - assert "content2" in ret.columns - assert "embeddings" in ret.columns - - df = pd.DataFrame( - { - "id": [1, 2, 3, 4], - "content1": ["hello", "world", "foo", "bar"], - "content2": ["world", "hello", "bar", "foo"], - } - ) - self.set_handler(mock_handler, name="pg", tables={"df": df}) - - # query - ret = self.run_sql( - """ - SELECT * FROM proj.test_dummy_embedding_multiple_columns - JOIN pg.df - """ - ) - - assert "content1" in ret.columns - assert "content2" in ret.columns - assert "embeddings" in ret.columns - assert ret.shape[0] == 4 - - # if the input missing columns, it should throw an error - with pytest.raises(Exception): - self.run_sql( - """ - SELECT * FROM proj.test_dummy_embedding_multiple_columns - WHERE content1='hello' - """ - ) - - # if the input missing columns, it should throw an error - with pytest.raises(Exception): - df2 = pd.DataFrame( - { - "content1": ["hello", "world", "foo", "bar"], - } - ) - self.set_handler(mock_handler, name="pg", tables={"df": df2}) - self.run_sql( - """ - SELECT * FROM proj.test_dummy_embedding_multiple_columns - JOIN pg.df2 - """ - ) - - @patch("mindsdb.integrations.handlers.postgres_handler.Handler") - def test_no_input_columns(self, mock_handler): - self.run_sql("create database proj") - - df = pd.DataFrame( - { - "id": [1, 2, 3, 4], - "content1": ["hello", "world", "foo", "bar"], - "content2": ["world", "hello", "bar", "foo"], - } - ) - self.save_file("df", df) - - # create the model with no input columns specified should use - # all columns when embedding the documents - self.run_sql( - """ - CREATE MODEL proj.test_dummy_no_input_columns - PREDICT embeddings - USING - engine='langchain_embedding', - class = 'fake', -- a more user friendly name - size = 512 - """ - ) - - self.wait_predictor("proj", "test_dummy_no_input_columns") - - # predictions - # one line - ret = self.run_sql( - """ - SELECT * FROM proj.test_dummy_no_input_columns - WHERE content1='hello' - AND content2='world' - AND id = 1 - """ - ) - - assert "content1" in ret.columns - assert "content2" in ret.columns - assert "id" in ret.columns or "`id`" in ret.columns - assert "embeddings" in ret.columns - - # multiple lines - ret = self.run_sql( - """ - SELECT * FROM proj.test_dummy_no_input_columns - JOIN files.df - """ - ) - - assert "content1" in ret.columns - assert "content2" in ret.columns - assert ret.shape[0] == 4 - - # create the model with no input columns specified, - # but with a given from dataframe should use all the columns - # from the dataframe when embedding the documents - ret = self.run_sql( - """ - CREATE MODEL proj.test_dummy_no_input_columns_from_df - FROM files ( - SELECT *, NULL as embeddings FROM df -- this requires an empty column called embeddings - ) - PREDICT embeddings - USING - engine='langchain_embedding', - class = 'fake', -- a more user friendly name - size = 512 - """ - ) - - self.wait_predictor("proj", "test_dummy_no_input_columns_from_df") - - # input columns == ['id', 'content1', 'content2'] - # predictions - # one line - ret = self.run_sql( - """ - SELECT * FROM proj.test_dummy_no_input_columns_from_df - WHERE content1='hello' - AND content2='world' - AND id = 1 -- looks like 'id' will be quoted - """ - ) - - # missing columns id - with pytest.raises(Exception): - self.run_sql( - """ - SELECT * FROM proj.test_dummy_no_input_columns_from_df - WHERE content1='hello' - AND content2='world' - """ - ) - - # skip if there is no openai key defined in the env - @pytest.mark.skipif( - "OPENAI_API_KEY" not in os.environ, - reason="OPENAI_API_KEY env variable is not defined", - ) - @patch("mindsdb.integrations.handlers.postgres_handler.Handler") - def test_openai_embedding(self, mock_handler): - self.run_sql("create database proj") - # create the model - self.run_sql( - """ - CREATE MODEL proj.test_openai_embedding - PREDICT embeddings - USING - engine='langchain_embedding', - class = 'openai' - """ - ) - - self.wait_predictor("proj", "test_openai_embedding") - - # single line prediction - ret = self.run_sql( - """ - SELECT * FROM proj.test_openai_embedding - WHERE content='hello' - """ - ) - - assert "content" in ret.columns - assert "embeddings" in ret.columns - - # multiple lines - # insert data - df = pd.DataFrame( - [ - ["hello"], - ["world"], - ["foo"], - ["bar"], - ], - columns=["content"], - ) - self.set_handler(mock_handler, name="pg", tables={"df": df}) - - # query - ret = self.run_sql( - """ - SELECT * FROM proj.test_openai_embedding - JOIN pg.df - """ - ) - - assert "content" in ret.columns - assert "embeddings" in ret.columns - assert ret.shape[0] == 4 - - def test_huggingface_embedding(self): - ... - - def test_missing_class_name(self): - self.run_sql("create database proj") - with pytest.raises(Exception): - self.run_sql( - """ - CREATE MODEL proj.test_missing_class_name - USING - engine='langchain_embedding', - size = 512 - """ - ) - - def test_wrong_class_name(self): - self.run_sql("create database proj") - with pytest.raises(Exception): - self.run_sql( - """ - CREATE MODEL proj.test_wrong_class_name - USING - engine='langchain_embedding', - class = 'SomethingDoesNotExist', - size = 512 - """ - ) - - def test_wrong_arguments(self): - self.run_sql("create database proj") - with pytest.raises(Exception): - self.run_sql( - """ - CREATE MODEL proj.test_wrong_arguments - USING - engine='langchain_embedding', - class = 'FakeEmbeddings', - wrong_argument_name = 512 - """ - ) diff --git a/tests/unused/unit/ml_handlers/test_leonardo_ai.py b/tests/unused/unit/ml_handlers/test_leonardo_ai.py deleted file mode 100644 index 635e0c1f90d..00000000000 --- a/tests/unused/unit/ml_handlers/test_leonardo_ai.py +++ /dev/null @@ -1,116 +0,0 @@ -import os -import pytest -import pandas as pd -from unittest.mock import patch - -from .base_ml_test import BaseMLAPITest - - -@pytest.mark.skipif(os.environ.get('LEONARDO_API_KEY') is None, reason='Missing API key!') -class TestLeonardoAI(BaseMLAPITest): - """Test Class for LeonardoAI Integration Testing.""" - - @staticmethod - def get_api_key(): - """Retrieve Leonardo API key from environment variables.""" - return os.environ.get('LEONARDO_API_KEY') - - def setup_method(self): - """Setup test environment, creating a project""" - super().setup_method() - self.run_sql("create database proj") - self.run_sql( - f""" - CREATE ML_ENGINE leo_engine - FROM leonardo_ai - USING - api_key = '{self.get_api_key('LEONARDO_API_KEY')}'; - """ - ) - - def test_invalid_model_parameter(self): - """Test for invalid Leonardo model parameter""" - self.run_sql( - """ - CREATE MODEL proj.test_leonardo_invalid_model - PREDICT url - USING - engine = 'leo_engine', - model = 'invalid-model', - prompt_template = '{{text}}, 8K | highly detailed realistic 3d oil painting style cyberpunk by MAD DOG JONES combined with Van Gogh | cinematic lighting | happy colors'; - """ - ) - with pytest.raises(Exception): - self.wait_predictor("proj", "test_leonardo_invalid_model") - - def test_unknown_model_argument(self): - """Test for unknown argument when creating a Leonardo model""" - self.run_sql( - """ - CREATE MODEL proj.test_leonardo_unknown_argument - PREDICT url - USING - engine = 'leo_engine', - model = 'invalid-model', - prompt_template = '{{text}}, 8K | highly detailed realistic 3d oil painting style cyberpunk by MAD DOG JONES combined with Van Gogh | cinematic lighting | happy colors', - evidently_wrong_argument='wrong value'; - """ - ) - with pytest.raises(Exception): - self.wait_predictor("proj", "test_leonardo_unknown_argument") - - def test_single_qa(self): - """Test for single image generation""" - self.run_sql( - f""" - CREATE MODEL proj.test_leonardo_single_qa - PREDICT url - USING - engine = 'leo_engine', - model = '6bef9f1b-29cb-40c7-b9df-32b51c1f67d3', - api_key = '{self.get_api_key('LEONARDO_API_KEY')}', - prompt_template = '{{text}}, 8K | highly detailed realistic 3d oil painting style cyberpunk by MAD DOG JONES combined with Van Gogh | cinematic lighting | happy colors'; - """ - ) - self.wait_predictor("proj", "test_leonardo_single_qa") - - result_df = self.run_sql( - """ - SELECT * - FROM mindsdb.leo - WHERE text = 'Generate a random ANIME picture'; - """ - ) - assert "stockholm" in result_df["answer"].iloc[0].lower() - - @patch("mindsdb.integrations.handlers.postgres_handler.Handler") - def test_bulk_qa(self, mock_handler): - """Test for bulk image processing""" - df = pd.DataFrame.from_dict({"prompt": [ - "Abstract artwork with vibrant colors and dynamic shapes. Imagine a world where sound is visible, and each element in the image represents a different genre of music.", - "surreal landscape where mountains are made of candy, and rivers flow with liquid gold." - ]}) - self.set_handler(mock_handler, name="pg", tables={"df": df}) - - self.run_sql( - f""" - CREATE MODEL proj.test_leonardo_bulk_qa - PREDICT url - USING - engine = 'leo_engine', - model = '6bef9f1b-29cb-40c7-b9df-32b51c1f67d3', - api_key = '{self.get_api_key('LEONARDO_API_KEY')}', - prompt_template = '{{text}}, 8K | highly detailed realistic 3d oil painting style cyberpunk by MAD DOG JONES combined with Van Gogh | cinematic lighting | happy colors'; - """ - ) - self.wait_predictor("proj", "test_leonardo_bulk_qa") - - result_df = self.run_sql( - """ - SELECT p.answer - FROM pg.df as t - JOIN proj.test_leonardo_bulk_qa as p; - """ - ) - assert "stockholm" in result_df["answer"].iloc[0].lower() - assert "venus" in result_df["answer"].iloc[1].lower() diff --git a/tests/unused/unit/ml_handlers/test_lightfm.py b/tests/unused/unit/ml_handlers/test_lightfm.py deleted file mode 100644 index 6a6eda08d14..00000000000 --- a/tests/unused/unit/ml_handlers/test_lightfm.py +++ /dev/null @@ -1,136 +0,0 @@ -import time -from unittest.mock import patch - -from mindsdb_sql_parser import parse_sql -from unit.executor_test_base import BaseExecutorTest - - -class TestLightFM(BaseExecutorTest): - def wait_predictor(self, project, name): - # wait - done = False - for attempt in range(200): - ret = self.run_sql(f"select * from {project}.models where name='{name}'") - if not ret.empty: - if ret["STATUS"][0] == "complete": - done = True - break - elif ret["STATUS"][0] == "error": - break - time.sleep(0.5) - if not done: - raise RuntimeError("predictor wasn't created") - - def run_sql(self, sql): - ret = self.command_executor.execute_command(parse_sql(sql)) - assert ret.error_code is None - if ret.data is not None: - return ret.data.to_df() - - @patch("mindsdb.integrations.handlers.postgres_handler.Handler") - def test_collaborative_filter_user_item_recommendation_light_fm_handler( - self, mock_handler, lightfm_interaction_data - ): - - self.set_handler( - mock_handler, name="pg", tables={"df": lightfm_interaction_data} - ) - - # create project - self.run_sql("create database proj") - - # create predictor - self.run_sql( - """ - create model proj.useritemtest - from pg (select * from df) - predict movieId - using - engine='lightfm', - item_id='movieId', - user_id='userId', - recommendation_type='{recommender_type}', - threshold=4, - n_recommendations=10 - """ - ) - self.wait_predictor("proj", "useritemtest") - - result_df = self.run_sql( - """ - SELECT p.* - FROM pg.df as t - JOIN proj.useritemtest as p - on p.movieId = t.movieId - where p.recommender_type='user_item' - """ - ) - - # check that the result is the expected shape e.g. 10 recommendations per user * 503 users - assert result_df.shape == (5030, 3) - - @patch("mindsdb.integrations.handlers.postgres_handler.Handler") - def test_collaborative_filter_item_item_recommendation_light_fm_handler( - self, mock_handler, lightfm_interaction_data - ): - - self.set_handler( - mock_handler, name="pg", tables={"df": lightfm_interaction_data} - ) - - # create project - self.run_sql("create database proj") - - # create predictor - self.run_sql( - """ - create model proj.itemitemtest - from pg (select * from df) - predict movieId - using - engine='lightfm', - item_id='movieId', - user_id='userId', - threshold=4, - recommendation_type='{recommender_type}', - n_recommendations=10 - """ - ) - self.wait_predictor("proj", "itemitemtest") - - result_df = self.run_sql( - """ - SELECT p.* - FROM pg.df as t - JOIN proj.itemitemtest as p - on t.movieId = p.movieId - where p.recommender_type='item_item' - """ - ) - - # check that the result is the expected shape e.g. 10 recommendations per user * 89 users - assert result_df.shape == (890, 3) - - @patch("mindsdb.integrations.handlers.postgres_handler.Handler") - def test_collaborative_filter_user_user_recommendation_light_fm_handler_with_item_data( - self, mock_handler, lightfm_interaction_data - ): - ... - - @patch("mindsdb.integrations.handlers.postgres_handler.Handler") - def test_hybrid_user_item_recommendation_light_fm_handler( - self, mock_handler, lightfm_interaction_data - ): - ... - - @patch("mindsdb.integrations.handlers.postgres_handler.Handler") - def test_hybrid_item_item_recommendation_light_fm_handler( - self, mock_handler, lightfm_interaction_data - ): - ... - - @patch("mindsdb.integrations.handlers.postgres_handler.Handler") - def test_hybrid_user_user_recommendation_light_fm_handler( - self, mock_handler, lightfm_interaction_data - ): - ... diff --git a/tests/unused/unit/ml_handlers/test_lightwood.py b/tests/unused/unit/ml_handlers/test_lightwood.py deleted file mode 100644 index 29a80a2c44d..00000000000 --- a/tests/unused/unit/ml_handlers/test_lightwood.py +++ /dev/null @@ -1,132 +0,0 @@ -import time -from unittest.mock import patch -import pandas as pd - -from mindsdb_sql_parser import parse_sql - - -from tests.unit.executor_test_base import BaseExecutorTest - - -class TestLW(BaseExecutorTest): - - def wait_predictor(self, project, name): - # wait - done = False - for attempt in range(200): - ret = self.run_sql( - f"select * from {project}.models where name='{name}'" - ) - if not ret.empty: - if ret['STATUS'][0] == 'complete': - done = True - break - elif ret['STATUS'][0] == 'error': - break - time.sleep(0.5) - if not done: - raise RuntimeError("predictor wasn't created") - - def run_sql(self, sql): - ret = self.command_executor.execute_command( - parse_sql(sql) - ) - assert ret.error_code is None - if ret.data is not None: - return ret.data.to_df() - - @patch('mindsdb.integrations.handlers.postgres_handler.Handler') - def test_simple(self, mock_handler): - - # dataset, string values - df = pd.DataFrame(range(1, 50), columns=['a']) - df['b'] = 50 - df.a - df['c'] = round((df['a']*3 + df['b']) / 50) - - self.set_handler(mock_handler, name='pg', tables={'df': df}) - - # create project - self.run_sql('create database proj') - - # create predictor - self.run_sql(''' - create model proj.modelx - from pg (select * from df) - predict c - using - submodels = [{ - "module": "Regression", - "args": {} - }] - ''') - self.wait_predictor('proj', 'modelx') - - # run predict - ret = self.run_sql(''' - SELECT p.* - FROM pg.df as t - JOIN proj.modelx as p - where t.c=1 - ''') - avg_c = pd.to_numeric(ret.c).mean() - # value is around 1 - assert (avg_c > 0.9) and (avg_c < 1.1) - - # test describe - ret = self.run_sql('describe proj.modelx.info') - assert len(ret) == 1 - for col in ('accuracies', 'column_importances', 'outputs', 'inputs'): - assert col in ret.columns - - ret = self.run_sql('describe proj.modelx.model') - for col in ['name', 'performance', 'training_time', 'selected', 'accuracy_functions']: - assert col in ret.columns - - ret = self.run_sql('describe proj.modelx.features') - for col in ['column', 'type', 'encoder', 'role']: - assert col in ret.columns - - ret = self.run_sql('describe proj.modelx.jsonai') - assert 'ensemble' in ret.columns - - @patch('mindsdb.integrations.handlers.postgres_handler.Handler') - def test_ts(self, mock_handler): - # TS - df2 = pd.DataFrame(pd.date_range(start='1/1/2018', end='1/31/2018'), columns=['t']) - df3 = df2.copy() - - df2['a'] = 'a' - df2['x'] = range(1, 32) - - df3['a'] = 'b' - df3['x'] = range(11, 42) - - df = pd.concat([df2, df3]) - self.set_handler(mock_handler, name='pg', tables={'df': df}) - - # create project - self.run_sql('create database proj') - - # TS predictor - # create predictor - self.run_sql(''' - create model proj.modelx - from pg (select * from df) - predict x - order by t - group by a - window 5 - horizon 3 - ''') - self.wait_predictor('proj', 'modelx') - - # run predict - ret = self.run_sql(''' - SELECT p.* - FROM pg.df as t - JOIN proj.modelx as p - where t.a='b' and t.t > latest - ''') - # LW can predict - # TODO: the result is [37, 36, 33] - # assert map(round, list(ret.x)) == [42, 43, 44] diff --git a/tests/unused/unit/ml_handlers/test_ludwig.py b/tests/unused/unit/ml_handlers/test_ludwig.py deleted file mode 100644 index a7103284290..00000000000 --- a/tests/unused/unit/ml_handlers/test_ludwig.py +++ /dev/null @@ -1,70 +0,0 @@ -import time -from unittest.mock import patch -import pandas as pd - -from mindsdb_sql_parser import parse_sql - - -from tests.unit.executor_test_base import BaseExecutorTest - - -class TestLudwig(BaseExecutorTest): - - def wait_predictor(self, project, name): - # wait - done = False - for attempt in range(200): - ret = self.run_sql( - f"select * from {project}.models where name='{name}'" - ) - if not ret.empty: - if ret['STATUS'][0] == 'complete': - done = True - break - elif ret['STATUS'][0] == 'error': - break - time.sleep(0.5) - if not done: - raise RuntimeError("predictor wasn't created") - - def run_sql(self, sql): - ret = self.command_executor.execute_command( - parse_sql(sql) - ) - assert ret.error_code is None - if ret.data is not None: - return ret.data.to_df() - - @patch('mindsdb.integrations.handlers.postgres_handler.Handler') - def test_simple(self, mock_handler): - - # dataset, string values - df = pd.DataFrame(range(1, 50), columns=['a']) - df['b'] = 50 - df.a - df['c'] = round((df['a']*3 + df['b']) / 50) - - self.set_handler(mock_handler, name='pg', tables={'df': df}) - - # create project - self.run_sql('create database proj') - - # create predictor - self.run_sql(''' - create model proj.modelx - from pg (select * from df) - predict c - using - engine='ludwig'; - ''') - self.wait_predictor('proj', 'modelx') - - # run predict - ret = self.run_sql(''' - SELECT p.* - FROM pg.df as t - JOIN proj.modelx as p - where t.c=1 - ''') - avg_c = pd.to_numeric(ret.c).mean() - # value is around 1 - assert (avg_c > 0.9) and (avg_c < 1.1) diff --git a/tests/unused/unit/ml_handlers/test_merlion_handler.py b/tests/unused/unit/ml_handlers/test_merlion_handler.py deleted file mode 100644 index 7955c16174a..00000000000 --- a/tests/unused/unit/ml_handlers/test_merlion_handler.py +++ /dev/null @@ -1,203 +0,0 @@ -import time -from unittest.mock import patch -import pandas as pd - -from mindsdb_sql_parser import parse_sql - -# How to run: -# env PYTHONPATH=./ pytest tests/unit/test_merlion_handler.py -from mindsdb.integrations.handlers.merlion_handler.adapters import DefaultForecasterAdapter, SarimaForecasterAdapter, \ - ProphetForecasterAdapter, MSESForecasterAdapter, IsolationForestDetectorAdapter, \ - WindStatsDetectorAdapter, ProphetDetectorAdapter -from ..executor_test_base import BaseExecutorTest - - -class TestMerlion(BaseExecutorTest): - def set_project(self): - r = self.db.Project.query.filter_by(name='mindsdb').first() - if r is not None: - self.db.session.delete(r) - - r = self.db.Project( - id=1, - name='mindsdb', - ) - self.db.session.add(r) - self.db.session.commit() - - def get_m4_df(self) -> pd.DataFrame: - train_csv = "https://raw.githubusercontent.com/Mcompetitions/M4-methods/master/Dataset/Train/Hourly-train.csv" - test_csv = "https://raw.githubusercontent.com/Mcompetitions/M4-methods/master/Dataset/Test/Hourly-test.csv" - train_set = pd.read_csv(train_csv).set_index("V1") - test_set = pd.read_csv(test_csv).set_index("V1") - ntrain = train_set.iloc[0, :].dropna().shape[0] - sequence = pd.concat((train_set.iloc[0, :].dropna(), test_set.iloc[0, :].dropna())) - # raw data do not follow consistent timestamp format - sequence.index = pd.date_range(start=0, periods=sequence.shape[0], freq="H") - sequence = sequence.to_frame() - metadata = pd.DataFrame({"trainval": sequence.index < sequence.index[ntrain]}, index=sequence.index) - train = sequence[metadata.trainval] - test = sequence[~metadata.trainval] - train["train"] = 1 - test["train"] = 0 - df = pd.concat([train, test], axis=0) - return df - - def get_nab_df(self) -> pd.DataFrame: - df = pd.read_csv("https://raw.githubusercontent.com/numenta/NAB/master/data/realKnownCause/nyc_taxi.csv") - df.rename(columns={"timestamp": "t", "value": "val"}, inplace=True) - train_len = int(len(df) * 0.5) - df_train = df.iloc[: train_len] - df_test = df.iloc[train_len:] - df_train["train"] = 1 - df_test["train"] = 0 - df = pd.concat([df_train, df_test], axis=0) - return df - - def run_mindsdb_sql(self, sql): - return self.command_executor.execute_command( - parse_sql(sql) - ) - - def test_merlion_forecaster(self): - df = self.get_m4_df() - df_train = df[df["train"] == 1][["H1"]] - df_test = df[df["train"] == 0][["H1"]] - # default adapter - adapter = DefaultForecasterAdapter() - adapter.train(df_train.copy(deep=True), target="H1") - rt_df = adapter.predict(df_test.copy(deep=True), target="H1") - assert rt_df is not None - assert len(rt_df) == len(df_test) - assert "H1__upper" in set(rt_df.columns.values) and "H1__lower" in set(rt_df.columns.values) - # arima adapter - adapter = SarimaForecasterAdapter() - adapter.train(df_train.copy(deep=True), target="H1") - rt_df = adapter.predict(df_test.copy(deep=True), target="H1") - assert rt_df is not None - assert len(rt_df) == len(df_test) - assert "H1__upper" in set(rt_df.columns.values) and "H1__lower" in set(rt_df.columns.values) - # prophet adapter - adapter = ProphetForecasterAdapter() - adapter.train(df_train.copy(deep=True), target="H1") - rt_df = adapter.predict(df_test.copy(deep=True), target="H1") - assert rt_df is not None - assert len(rt_df) == len(df_test) - assert "H1__upper" in set(rt_df.columns.values) and "H1__lower" in set(rt_df.columns.values) - # mses adapter - adapter = MSESForecasterAdapter() - adapter.train(df_train.copy(deep=True), target="H1") - rt_df = adapter.predict(df_test.copy(deep=True), target="H1") - assert rt_df is not None - assert len(rt_df) == len(df_test) - assert "H1__upper" in set(rt_df.columns.values) and "H1__lower" in set(rt_df.columns.values) - - @patch('mindsdb.integrations.handlers.postgres_handler.Handler') - def test_merlion_forecaster_sql(self, mock_handler): - self.set_project() - # prepare data - df = self.get_m4_df() - df["t"] = df.index - self.set_handler(mock_handler, name='pg', tables={'m4': df}) - # test default - self.exec_train_and_forecast(mock_handler=mock_handler, model_name="default", using="") - - def exec_train_and_forecast(self, mock_handler, model_name, using): - # create predictor - create_sql = f''' - CREATE PREDICTOR mindsdb.{model_name}_forecaster - FROM pg - (select t, H1 from m4 where train = 1) - PREDICT H1 - USING engine='merlion'{using} - ''' - ret = self.run_mindsdb_sql(sql=create_sql) - assert ret.error_code is None, "train failed: " + model_name - - self.wait_training(model_name=f'{model_name}_forecaster') - - predict_sql = f''' - select p.t, p.H1 real, t.H1, t.H1__upper, t.H1__lower - from mindsdb.{model_name}_forecaster t - inner join pg.m4 p on t.t = p.t - where p.train = 0 - ''' - ret = self.run_mindsdb_sql(sql=predict_sql) - assert ret.error_code is None, "forecast failed: " + model_name - - def test_merlion_detector(self): - df = self.get_nab_df() - df.index = pd.to_datetime(df["t"]) - df.drop(columns=["t"], inplace=True) - df_train = df[df["train"] == 1][["val"]] - df_test = df[df["train"] == 0][["val"]] - # isolation - adapter = IsolationForestDetectorAdapter() - adapter.train(df_train.copy(deep=True), target="val") - rt_df = adapter.predict(df_test.copy(deep=True), target="val") - assert rt_df is not None - assert len(rt_df[rt_df["val__anomaly_score"] > 0]) > 0 - # windstats - adapter = WindStatsDetectorAdapter() - adapter.train(df_train.copy(deep=True), target="val") - rt_df = adapter.predict(df_test.copy(deep=True), target="val") - assert rt_df is not None - assert len(rt_df[rt_df["val__anomaly_score"] > 0]) > 0 - # prophet - adapter = ProphetDetectorAdapter() - adapter.train(df_train.copy(deep=True), target="val") - rt_df = adapter.predict(df_test.copy(deep=True), target="val") - assert rt_df is not None - assert len(rt_df[rt_df["val__anomaly_score"] > 0]) > 0 - - @patch('mindsdb.integrations.handlers.postgres_handler.Handler') - def test_merlion_detector_sql(self, mock_handler): - self.set_project() - # prepare data - df = self.get_nab_df() - df["t"] = pd.to_datetime(df["t"]) - self.set_handler(mock_handler, name='pg', tables={'nba': df}) - - # test isolation forest - self.exec_train_and_detect(mock_handler=mock_handler, model_name="isolation", using_model=", model_type='isolation'") - - def exec_train_and_detect(self, mock_handler, model_name, using_model): - # create predictor - create_sql = f''' - CREATE PREDICTOR mindsdb.{model_name}_detector - FROM pg - (select t, val from nba where train = 1) - PREDICT val - USING engine='merlion', task='detector'{using_model} - ''' - ret = self.run_mindsdb_sql(sql=create_sql) - assert ret.error_code is None, "train failed: " + model_name - - self.wait_training(model_name=f'{model_name}_detector') - - predict_sql = f''' - select p.t, p.val real, d.val__anomaly_score - from mindsdb.{model_name}_detector d - inner join pg.nba p on d.t = p.t and d.val = p.val - where p.train = 0 - ''' - ret = self.run_mindsdb_sql(sql=predict_sql) - assert ret.error_code is None, "detect failed: " + model_name - - def wait_training(self, model_name): - # wait - done = False - for attempt in range(900): - ret = self.run_mindsdb_sql( - f"select status from mindsdb.predictors where name='{model_name}'" - ) - if len(ret.data) > 0: - data = ret.data.to_lists() - if data[0][0] == 'complete': - done = True - break - elif data[0][0] == 'error': - break - time.sleep(0.5) - if not done: - raise RuntimeError("predictor didn't created: " + model_name) diff --git a/tests/unused/unit/ml_handlers/test_mlflow.py b/tests/unused/unit/ml_handlers/test_mlflow.py deleted file mode 100644 index cc7b5547895..00000000000 --- a/tests/unused/unit/ml_handlers/test_mlflow.py +++ /dev/null @@ -1,57 +0,0 @@ -# How to run: -# env PYTHONPATH=./:$PYTHONPATH pytest tests/unit/ml_handlers/test_mlflow.py -ls - -import time -import pytest -from unittest.mock import patch - -from mindsdb_sql_parser import parse_sql - -from tests.unit.executor_test_base import BaseExecutorTest -from mindsdb.integrations.handlers.mlflow_handler.mlflow_handler import MLflowHandler - - -# TODO: fix patches -class TestMLFlow(BaseExecutorTest): - def run_sql(self, sql): - return self.command_executor.execute_command( - parse_sql(sql) - ) - - @patch('mlflow.tracking.MlflowClient') - @patch.object(MLflowHandler, '_check_model_url') - @patch('mindsdb.integrations.handlers.mlflow_handler.mlflow_handler.requests.post') - def test_mlflow( - self, - mock_internal_post, - mock_handler_url_method, - mock_mlflow_client - ): - mock_mlflow_client.search_registered_models.side_effect = ['test_mlflow'] - mock_internal_post.side_effect = requests.Request(json=['negative_sentiment']) - mock_handler_url_method.side_effect = True - ret = self.run_sql(''' - CREATE PREDICTOR mindsdb.test_mlflow - PREDICT c - USING - engine='mlflow', - model_name='test_mlflow', - mlflow_server_url='http://0.0.0.0:5001/', - mlflow_server_path='sqlite:////mlflow.db', - predict_url='http://localhost:5000/invocations'; - ''') - assert ret.error_code is None - - time.sleep(3) - - ret = self.run_sql(''' - SELECT p.* - FROM mindsdb.test_mlflow as p - WHERE text="The tsunami is coming, seek high ground"; - ''') - assert ret.error_code is None - assert ret.c == '0' # what is it? - - -if __name__ == '__main__': - pytest.main(['test_mlflow.py']) diff --git a/tests/unused/unit/ml_handlers/test_neuralforecast.py b/tests/unused/unit/ml_handlers/test_neuralforecast.py deleted file mode 100644 index 3afcd33fd86..00000000000 --- a/tests/unused/unit/ml_handlers/test_neuralforecast.py +++ /dev/null @@ -1,179 +0,0 @@ -import time -import pytest -from unittest.mock import patch -import pandas as pd - -from mindsdb_sql_parser import parse_sql - -from tests.unit.ml_handlers.test_time_series_utils import create_mock_df -from tests.unit.executor_test_base import BaseExecutorTest - - -class TestNeuralForecast(BaseExecutorTest): - def wait_predictor(self, project, name): - # wait - done = False - for attempt in range(200): - ret = self.run_sql(f"select * from {project}.models where name='{name}'") - if not ret.empty: - if ret["STATUS"][0] == "complete": - done = True - break - elif ret["STATUS"][0] == "error": - break - time.sleep(0.5) - if not done: - raise RuntimeError("predictor wasn't created") - - def run_sql(self, sql): - ret = self.command_executor.execute_command(parse_sql(sql)) - assert ret.error_code is None - if ret.data is not None: - return ret.data.to_df() - - @patch("mindsdb.integrations.handlers.postgres_handler.Handler") - def test_grouped(self, mock_handler): - # create project - self.run_sql("create database proj") - df = create_mock_df() - self.set_handler(mock_handler, name="pg", tables={"df": df}) - - # now add more groups - self.run_sql( - """ - create model proj.model_multi_group - from pg (select * from df) - predict target_col - order by time_col - group by group_col, group_col_2, group_col_3 - window 6 - horizon 3 - using - engine='neuralforecast', - frequency='Q', - train_time=0.01 - """ - ) - self.wait_predictor("proj", "model_multi_group") - - result_df = self.run_sql( - """ - SELECT p.* - FROM pg.df as t - JOIN proj.model_multi_group as p - where t.group_col_2='a2' AND t.time_col > LATEST - """ - ) - assert list(round(result_df["target_col"])) == [32, 33, 34] - - result_df = self.run_sql( - """ - SELECT p.* - FROM pg.df as t - JOIN proj.model_multi_group as p - where t.group_col='b' AND t.time_col > LATEST - """ - ) - assert list(round(result_df["target_col"])) == [42, 43, 44] - - describe_result = self.run_sql("describe proj.model_multi_group") - assert describe_result["inputs"][0] == ["target_col", "time_col", ["group_col", "group_col_2", "group_col_3"]] - assert describe_result["outputs"][0] == "target_col" - # The expected format of the "accuracies" key is - # [(model_1_name, model_1_accuracy), (model_2_name, model_2_accuracy), ...] - assert describe_result["accuracies"][0][0][0] == "NHITS" - assert describe_result["accuracies"][0][0][1] < 1 - - describe_model = self.run_sql("describe proj.model_multi_group.model") - assert describe_model["model_name"][0] == "NHITS" - assert describe_model["frequency"][0] == "Q" - - describe_features = self.run_sql("describe proj.model_multi_group.features") - assert describe_features["ds"][0] == "time_col" - assert describe_features["y"][0] == "target_col" - assert describe_features["unique_id"][0] == ["group_col", "group_col_2", "group_col_3"] - - with pytest.raises(Exception) as e: - self.run_sql("describe proj.modelx.ensemble") - assert "ensemble is not supported" in str(e) - - @patch("mindsdb.integrations.handlers.postgres_handler.Handler") - def test_with_exog_vars(self, mock_handler): - # create project - self.run_sql("create database proj") - df = create_mock_df() - df["exog_var_1"] = 5 * df.index - self.set_handler(mock_handler, name="pg", tables={"df": df}) - - # now add more groups - self.run_sql( - """ - create model proj.model_exog_var - from pg (select * from df) - predict target_col - order by time_col - group by group_col, group_col_2, group_col_3 - window 6 - horizon 3 - using - engine='neuralforecast', - frequency='Q', - train_time=0.01, - exogenous_vars=['exog_var_1'] - """ - ) - self.wait_predictor("proj", "model_exog_var") - - result_df = self.run_sql( - """ - SELECT p.* - FROM pg.df as t - JOIN proj.model_exog_var as p - where t.group_col='b' AND t.time_col > LATEST - """ - ) - assert list(round(result_df["target_col"])) == [42, 43, 44] - - describe_result = self.run_sql("describe proj.model_exog_var") - assert describe_result["inputs"][0] == ["target_col", "time_col", ["group_col", "group_col_2", "group_col_3"], "exog_var_1"] - - describe_features = self.run_sql("describe proj.model_exog_var.features") - assert describe_features["exog_vars"][0] == ["exog_var_1"] - - @patch("mindsdb.integrations.handlers.postgres_handler.Handler") - def test_hierarchical(self, mock_handler): - # create project - self.run_sql("create database proj") - df = pd.read_csv("tests/unit/ml_handlers/data/house_sales.csv") # comes mindsdb docs forecast example - self.set_handler(mock_handler, name="pg", tables={"df": df}) - - self.run_sql( - """ - create model proj.model_1_group - from pg (select * from df) - predict ma - order by saledate - group by type, bedrooms - horizon 4 - window 8 - using - engine='neuralforecast', - hierarchy=['type', 'bedrooms'], - train_time=0.01 - """ - ) - self.wait_predictor("proj", "model_1_group") - - # run predict - mindsdb_result_hier = self.run_sql( - """ - SELECT p.* - FROM pg.df as t - JOIN proj.model_1_group as p - where t.type='house' - """ - ) - assert len(list(round(mindsdb_result_hier["ma"]))) - - describe_result = self.run_sql("describe proj.model_1_group.model") - assert describe_result["hierarchy"][0] == ["type", "bedrooms"] diff --git a/tests/unused/unit/ml_handlers/test_popularity_recommender.py b/tests/unused/unit/ml_handlers/test_popularity_recommender.py deleted file mode 100644 index 1198b8af77f..00000000000 --- a/tests/unused/unit/ml_handlers/test_popularity_recommender.py +++ /dev/null @@ -1,71 +0,0 @@ -import time -from unittest.mock import patch - -from mindsdb_sql_parser import parse_sql -from unit.executor_test_base import BaseExecutorTest - - -# wip -class TestPopularityRecommender(BaseExecutorTest): - def wait_predictor(self, project, name): - # wait - done = False - for attempt in range(200): - ret = self.run_sql(f"select * from {project}.models where name='{name}'") - if not ret.empty: - if ret["STATUS"][0] == "complete": - done = True - break - elif ret["STATUS"][0] == "error": - break - time.sleep(0.5) - if not done: - raise RuntimeError("predictor wasn't created") - - def run_sql(self, sql): - ret = self.command_executor.execute_command(parse_sql(sql)) - assert ret.error_code is None - if ret.data is not None: - return ret.data.to_df() - - @patch("mindsdb.integrations.handlers.postgres_handler.Handler") - def test_popularity_handler(self, mock_handler, lightfm_interaction_data): - - # create project - self.run_sql("create database proj") - self.set_handler( - mock_handler, name="pg", tables={"df": lightfm_interaction_data} - ) - - # create predictor - self.run_sql( - """ - create model proj.modelx - from pg (select * from df) - predict movieId - using - engine='popularity_recommender', - item_id='movieId', - user_id='userId', - n_recommendations=10 - """ - ) - self.wait_predictor("proj", "modelx") - - result_df = self.run_sql( - """ - SELECT p.* - FROM pg.df as t - JOIN proj.modelx as p - """ - ) - - assert not result_df.empty - - # ensure that we have the right number of recommendations per user id - assert result_df.userId.value_counts().isin([10]).all() - - # check we have predictions for all user_ids - assert set(lightfm_interaction_data.userId.unique()) == set( - result_df.userId.unique() - ) diff --git a/tests/unused/unit/ml_handlers/test_rag.py b/tests/unused/unit/ml_handlers/test_rag.py deleted file mode 100644 index f5d7777276a..00000000000 --- a/tests/unused/unit/ml_handlers/test_rag.py +++ /dev/null @@ -1,324 +0,0 @@ -import os -import time - -import pandas as pd -import pytest -from mindsdb_sql_parser import parse_sql - -from tests.unit.executor_test_base import BaseExecutorTest - -OPENAI_API_KEY = os.environ.get("OPENAI_API_KEY") -os.environ["OPENAI_API_KEY"] = OPENAI_API_KEY - -WRITER_API_KEY = os.environ.get("WRITER_API_KEY") -os.environ["WRITER_API_KEY"] = WRITER_API_KEY - -WRITER_ORG_ID = os.environ.get("WRITER_ORG_ID") -os.environ["WRITER_ORG_ID"] = WRITER_ORG_ID - - -class TestRAG(BaseExecutorTest): - def wait_predictor(self, project, name): - # wait - done = False - for attempt in range(200): - ret = self.run_sql(f"select * from {project}.models where name='{name}'") - if not ret.empty: - if ret["STATUS"][0] == "complete": - done = True - break - elif ret["STATUS"][0] == "error": - break - time.sleep(0.5) - if not done: - raise RuntimeError("predictor wasn't created") - - def run_sql(self, sql): - ret = self.command_executor.execute_command(parse_sql(sql)) - assert ret.error_code is None - if ret.data is not None: - return ret.data.to_df() - - def test_missing_required_keys(self): - # create project - self.run_sql("create database proj") - - self.run_sql( - """ - CREATE MODEL proj.test_rag_handler_missing_required_args - PREDICT answer - USING - engine="rag" - """ - ) - with pytest.raises(Exception): - self.wait_predictor("proj", "test_rag_handler_missing_required_args") - - def test_invalid_model_id_parameter(self): - # create project - - self.run_sql("create database proj") - self.run_sql( - f""" - create model proj.test_rag_openai_nonexistant_model - predict answer - using - engine='rag', - llm_type='openai', - model_id='this-model-does-not-exist', - openai_api_key='{OPENAI_API_KEY}'; - """ - ) - with pytest.raises(Exception): - self.wait_predictor("proj", "test_rag_openai_nonexistant_model") - - self.run_sql( - f""" - create model proj.test_rag_writer_nonexistant_model - predict answer - using - engine='rag', - llm_type='writer', - model_id='this-model-does-not-exist', - writer_api_key='{WRITER_API_KEY}', - writer_org_id='{WRITER_ORG_ID}'; - """ - ) - - with pytest.raises(Exception): - self.wait_predictor("proj", "test_rag_writer_nonexistant_model") - - def test_unsupported_llm_type(self): - self.run_sql("create database proj") - self.run_sql( - """ - create model proj.test_unsupported_llm - predict answer - using - engine='rag', - llm_type='unsupported_llm' - """ - ) - with pytest.raises(Exception): - self.wait_predictor("proj", "test_unsupported_llm") - - def test_unsupported_vector_store(self): - self.run_sql("create database proj") - self.run_sql( - f""" - create model proj.test_unsupported_vector_store - predict answer - using - engine='rag', - llm_type='openai', - openai_api_key='{OPENAI_API_KEY}', - vector_store_name='unsupported_vector_store' - """ - ) - - with pytest.raises(Exception): - self.wait_predictor("proj", "test_unsupported_vector_store") - - def test_unknown_arguments(self): - self.run_sql("create database proj") - self.run_sql( - f""" - create model proj.test_openai_unknown_arguments - predict answer - using - engine='rag', - llm_type='openai', - openai_api_key='{OPENAI_API_KEY}', - evidently_wrong_argument='wrong value' --- this is a wrong argument name - """ - ) - with pytest.raises(Exception): - self.wait_predictor("proj", "test_openai_unknown_arguments") - - def test_qa(self): - # create project - self.run_sql("create database proj") - df = pd.DataFrame.from_dict( - { - "context": [ - "For adults and children age 5 and older, OTC decongestants, " - "antihistamines and pain relievers might offer some symptom relief. " - "However, they won't prevent a cold or shorten its duration, and most have some side effects.", - "Paracetamol, also known as acetaminophen and APAP, " - "is a medication used to treat pain and fever as well as colds and flu. " - "It is typically used for mild to moderate pain relief. " - "Evidence is mixed for its use to relieve fever in children. " - "It is often sold in combination with other medications, such as in many cold medications.", - "lemsip is a brand of over-the-counter pharmaceuticals used to treat cold and flu symptoms. " - "The brand is currently owned by Reckitt Benckiser. " - "The original Lemsip product contained paracetamol as its active ingredient. " - "However, other products marketed under the Lemsip " - "brand contain other active ingredients such as ibuprofen," - "pseudoephedrine, phenylephrine, and guaifenesin." - ], - "url": [ - "https://docs.mindsdb.com/sql/tutorials/recommenders/", - "https://docs.mindsdb.com/sql/tutorials/llm-chatbot-ui/", - "https://docs.mindsdb.com/sql/tutorials/house-sales-forecasting/", - ], - } - ) - self.save_file("df", df) - - # test openai qa with chromadb - - self.run_sql( - f""" - create model proj.test_rag_openai_qa - from files (select * from df) - predict answer - using - engine='rag', - llm_type='openai', - openai_api_key='{OPENAI_API_KEY}', - vector_store_folder_name='rag_openai_qa_test', - input_column='question' - """ - ) - self.wait_predictor("proj", "test_rag_openai_qa") - - result_df = self.run_sql( - """ - SELECT p.answer - FROM proj.test_rag_openai_qa as p - WHERE question='What is the best treatment for a cold?' - """ - ) - assert result_df["answer"].iloc[0] - - # test batching with openai qa chroma - - embeddings_batch_size = 1 - - self.run_sql( - f""" - create model proj.test_rag_openai_qa_batch - from files (select * from df) - predict answer - using - engine='rag', - llm_type='openai', - openai_api_key='{OPENAI_API_KEY}', - vector_store_folder_name='rag_openai_qa_test_batch', - embeddings_batch_size={embeddings_batch_size}, - input_column='question' - """ - ) - - self.wait_predictor("proj", "test_rag_openai_qa_batch") - - result_df = self.run_sql( - """ - SELECT p.answer - FROM proj.test_rag_openai_qa_batch as p - WHERE question='What is the best treatment for a cold?' - """ - ) - assert result_df["answer"].iloc[0] - - # test writer qa with FAISS - - self.run_sql( - f""" - create model proj.test_rag_writer_qa - from files (select * from df) - predict answer - using - engine='rag', - llm_type='writer', - vector_store_name='faiss', - writer_api_key='{WRITER_API_KEY}', - writer_org_id='{WRITER_ORG_ID}', - vector_store_folder_name='rag_writer_qa_test', - input_column='question' - """ - ) - self.wait_predictor("proj", "test_rag_writer_qa") - - result_df = self.run_sql( - """ - SELECT p.answer - FROM proj.test_rag_writer_qa as p - WHERE question='What is the best treatment for a cold?' - """ - ) - assert result_df["answer"].iloc[0] - - # test single url parsing - self.run_sql( - f""" - create model proj.test_rag_writer_qa_single_url - predict answer - using - engine='rag', - llm_type='writer', - url='https://docs.mindsdb.com/sql/tutorials/recommenders/', - vector_store_name='faiss', - writer_api_key='{WRITER_API_KEY}', - writer_org_id='{WRITER_ORG_ID}', - vector_store_folder_name='rag_writer_qa_test_single_url', - input_column='question' - """ - ) - self.wait_predictor("proj", "test_rag_writer_qa_single_url") - - result_df = self.run_sql( - """ - SELECT p.answer - FROM proj.test_rag_writer_qa as p - WHERE question='What recommender models does mindsdb support?' - """ - ) - assert result_df["answer"].iloc[0] - - # test multi url parsing - self.run_sql( - f""" - create model proj.test_rag_writer_qa_multi_url - from files (select * from df) - predict answer - using - engine='rag', - llm_type='writer', - vector_store_name='faiss', - url_column_name='url', - writer_api_key='{WRITER_API_KEY}', - writer_org_id='{WRITER_ORG_ID}', - vector_store_folder_name='rag_writer_qa_test_multi_url', - input_column='question' - """ - ) - - self.wait_predictor("proj", "test_rag_writer_qa_multi_url") - - result_df = self.run_sql( - """ - SELECT p.answer - FROM proj.test_rag_writer_qa_multi_url as p - WHERE question='which chat app currently works with mindsdb chatbot?' - """ - ) - - assert result_df["answer"].iloc[0] - - def test_invalid_prompt_template(self): - # create project - self.run_sql("create database proj") - self.run_sql( - f""" - create model proj.test_invalid_prompt_template_format - predict completion - using - engine='rag', - llm_type="openai", - prompt_template="not valid format", - openai_api_key='{OPENAI_API_KEY}'; - """ - ) - with pytest.raises(Exception): - self.wait_predictor("proj", "test_invalid_prompt_template_format") diff --git a/tests/unused/unit/ml_handlers/test_spacy.py b/tests/unused/unit/ml_handlers/test_spacy.py deleted file mode 100644 index 76d464efa7e..00000000000 --- a/tests/unused/unit/ml_handlers/test_spacy.py +++ /dev/null @@ -1,169 +0,0 @@ -from unittest.mock import patch -import pandas as pd - -from mindsdb_sql_parser import parse_sql - -from tests.unit.executor_test_base import BaseExecutorTest - - -class TestSpacy(BaseExecutorTest): - def run_sql(self, sql): - ret = self.command_executor.execute_command(parse_sql(sql)) - assert ret.error_code is None - if ret.data is not None: - return ret.data.to_df() - - @patch("mindsdb.integrations.handlers.postgres_handler.Handler") - def test_spacy_ner(self, mock_handler): - self.run_sql("CREATE DATABASE proj") - - text = ["Apple is looking at buying U.K. startup for $1 billion"] - df = pd.DataFrame(text, columns=['text']) - - self.set_handler(mock_handler, name="pg", tables={"df": df}) - - self.run_sql( - """ - CREATE MODEL proj.spacy__ner__model - PREDICT recognition - USING - engine = 'spacy' - linguistic_feature = 'ner', - target_column = 'text'; - """ - ) - - result_df = self.run_sql( - """ - SELECT recognition - FROM proj.spacy__ner__model - WHERE - text='Apple is looking at buying U.K. startup for $1 billion'; - """ - ) - - assert "{(28, 32, 'GPE'), (45, 55, 'MONEY'), (1, 6, 'ORG')}" in result_df["recognition"].iloc[0] - - @patch("mindsdb.integrations.handlers.postgres_handler.Handler") - def test_spacy_lemmatization(self, mock_handler): - self.run_sql("CREATE DATABASE proj") - - text = ["Apple is looking at buying U.K. startup for $1 billion"] - df = pd.DataFrame(text, columns=['text']) - - self.set_handler(mock_handler, name="pg", tables={"df": df}) - - self.run_sql( - """ - CREATE MODEL proj.spacy__lemmatization__model - PREDICT recognition - USING - engine = 'spacy' - linguistic_feature = 'lemmatization', - target_column = 'text'; - """ - ) - - result_df = self.run_sql( - """ - SELECT recognition - FROM proj.spacy__lemmatization__model - WHERE - text='Apple is looking at buying U.K. startup for $1 billion'; - """ - ) - - assert "{'startup', 'Apple', '1', 'for', 'buy', '$', 'at', 'billion', '"', \'U.K.\', \'be\', \'look\'}' in result_df["recognition"].iloc[0] - - @patch("mindsdb.integrations.handlers.postgres_handler.Handler") - def test_spacy_dependency_parsing(self, mock_handler): - self.run_sql("CREATE DATABASE proj") - - text = ["Apple is looking at buying U.K. startup for $1 billion"] - df = pd.DataFrame(text, columns=['text']) - - self.set_handler(mock_handler, name="pg", tables={"df": df}) - - self.run_sql( - """ - CREATE MODEL proj.spacy__dependency_parsing__model - PREDICT recognition - USING - engine = 'spacy' - linguistic_feature = 'dependency-parsing', - target_column = 'text'; - """ - ) - - result_df = self.run_sql( - """ - SELECT recognition - FROM proj.spacy__dependency_parsing__model - WHERE - text='Apple is looking at buying U.K. startup for $1 billion'; - """ - ) - - assert '{('"', \'punct', 'looking', 'VERB', '[]'), ('for', 'prep', 'startup', 'NOUN', '[billion]'), ('1', 'compound', 'billion', 'NUM', '[]'), ('Apple', 'nsubj', 'looking', 'VERB', '[]'), ('buying', 'pcomp', 'at', 'ADP', '[U.K.]'), ('looking', 'ROOT', 'looking', 'VERB', '[\", Apple, is, at, startup, \"]'), ('$', 'quantmod', 'billion', 'NUM', '[]'), ('is', 'aux', 'looking', 'VERB', '[]'), ('billion', 'pobj', 'for', 'ADP', '[$, 1]'), ('startup', 'dep', 'looking', 'VERB', '[for]'), ('at', 'prep', 'looking', 'VERB', '[buying]'), ('U.K.', 'dobj', 'buying', 'VERB', '[]')}" in result_df["recognition"].iloc[0] - - @patch("mindsdb.integrations.handlers.postgres_handler.Handler") - def test_spacy_pos_tagging(self, mock_handler): - self.run_sql("CREATE DATABASE proj") - - text = ["Apple is looking at buying U.K. startup for $1 billion"] - df = pd.DataFrame(text, columns=['text']) - - self.set_handler(mock_handler, name="pg", tables={"df": df}) - - self.run_sql( - """ - CREATE MODEL proj.spacy__pos_tag__model - PREDICT recognition - USING - engine = 'spacy' - linguistic_feature = 'pos-tag', - target_column = 'text'; - """ - ) - - result_df = self.run_sql( - """ - SELECT recognition - FROM proj.spacy__pos_tag__model - WHERE - text='Apple is looking at buying U.K. startup for $1 billion'; - """ - ) - - assert "{('startup', 'startup', 'NOUN', 'NN', 'dep', 'xxxx', True, False), ('buying', 'buy', 'VERB', 'VBG', 'pcomp', 'xxxx', True, False), ('U.K.', 'U.K.', 'PROPN', 'NNP', 'dobj', 'X.X.', False, False), ('1', '1', 'NUM', 'CD', 'compound', 'd', False, False), ('for', 'for', 'ADP', 'IN', 'prep', 'xxx', True, True), ('$', '$', 'SYM', '$', 'quantmod', '$', False, False), ('Apple', 'Apple', 'PROPN', 'NNP', 'nsubj', 'Xxxxx', True, False), ('billion', 'billion', 'NUM', 'CD', 'pobj', 'xxxx', True, False), ('"', '"', 'PUNCT', "''", 'punct', '"', False, False), (\'looking\', \'look\', \'VERB\', \'VBG\', \'ROOT\', \'xxxx\', True, False), ('"', '"', \'PUNCT\', \'``\', \'punct\', '"', False, False), ('at', 'at', 'ADP', 'IN', 'prep', 'xx', True, True), ('is', 'be', 'AUX', 'VBZ', 'aux', 'xx', True, True)}" in result_df["recognition"].iloc[0] - - @patch("mindsdb.integrations.handlers.postgres_handler.Handler") - def test_spacy_morphology(self, mock_handler): - self.run_sql("CREATE DATABASE proj") - - text = ["Apple is looking at buying U.K. startup for $1 billion"] - df = pd.DataFrame(text, columns=['text']) - - self.set_handler(mock_handler, name="pg", tables={"df": df}) - - self.run_sql( - """ - CREATE MODEL proj.spacy__morphology__model - PREDICT recognition - USING - engine = 'spacy' - linguistic_feature = 'morphology', - target_column = 'text'; - """ - ) - - result_df = self.run_sql( - """ - SELECT recognition - FROM proj.spacy__morphology__model - WHERE - text='Apple is looking at buying U.K. startup for $1 billion'; - """ - ) - - assert "{('"', \'PunctSide=Ini|PunctType=Quot\'), (\'billion\', \'NumType=Card\'), (\'U.K.\', \'Number=Sing\'), (\'at\', ''), (\'Apple\', \'Number=Sing\'), (\'looking\', \'Aspect=Prog|Tense=Pres|VerbForm=Part\'), (\'buying\', \'Aspect=Prog|Tense=Pres|VerbForm=Part\'), ('"', 'PunctSide=Fin|PunctType=Quot'), ('is', 'Mood=Ind|Number=Sing|Person=3|Tense=Pres|VerbForm=Fin'), ('$', ''), ('1', 'NumType=Card'), ('for', ''), ('startup', 'Number=Sing')}" in result_df["recognition"].iloc[0] diff --git a/tests/unused/unit/ml_handlers/test_stabilityai.py b/tests/unused/unit/ml_handlers/test_stabilityai.py deleted file mode 100644 index 0aec623324b..00000000000 --- a/tests/unused/unit/ml_handlers/test_stabilityai.py +++ /dev/null @@ -1,127 +0,0 @@ -import os -import pytest -import pandas as pd -from unittest.mock import patch - -from .base_ml_test import BaseMLAPITest - - -@pytest.mark.skipif(os.environ.get('STABILITY_API_KEY') is None, reason='Missing API key!') -class TestStabilityAI(BaseMLAPITest): - """Test Class for Stability Integration Testing""" - - def setup_method(self): - """Setup test environment, creating a project""" - super().setup_method() - self.run_sql("create database proj") - self.run_sql( - f""" - CREATE ML_ENGINE stability_engine - FROM stabilityai - USING - stabilityai_api_key = '{self.get_api_key('STABILITY_API_KEY')}'; - """ - ) - - def test_invalid_model_parameter(self): - """Test for invalid Stability model parameter""" - self.run_sql( - f""" - CREATE MODEL proj.test_stability_invalid_model - PREDICT answer - USING - engine='stability_engine', - engine_id = 'this-engine-does-not-exist', - task = "text-to-image", - local_directory_path = "tests/unit/ml_handlers/data", - api_key='{self.get_api_key('STABILITY_API_KEY')}'; - """ - ) - with pytest.raises(Exception): - self.wait_predictor("proj", "test_stability_invalid_model") - - def test_missing_task_argument(self): - """Test for unknown argument when creating a stability model""" - self.run_sql( - f""" - CREATE MODEL proj.test_stability_invalid_model - PREDICT answer - USING - engine='stability_engine', - local_directory_path = "tests/unit/ml_handlers/data", - api_key='{self.get_api_key('STABILITY_API_KEY')}'; - """ - ) - with pytest.raises(Exception): - self.wait_predictor("proj", "test_missing_task_argument") - - def test_unknown_task_argument(self): - """Test for unknown argument when creating a stability model""" - self.run_sql( - f""" - CREATE MODEL proj.test_stability_invalid_model - PREDICT answer - USING - engine='stability_engine', - task = "unknown-task", - local_directory_path = "tests/unit/ml_handlers/data", - api_key='{self.get_api_key('STABILITY_API_KEY')}'; - """ - ) - with pytest.raises(Exception): - self.wait_predictor("proj", "test_unknown_task_argument") - - def test_text_image_single(self): - """Test for single text""" - self.run_sql( - f""" - CREATE MODEL proj.test_stability_t2i_single - PREDICT answer - USING - engine='stability_engine', - task = "text-to-image", - local_directory_path = "tests/unit/ml_handlers/data", - api_key='{self.get_api_key('STABILITY_API_KEY')}'; - """ - ) - self.wait_predictor("proj", "test_stability_t2i_single") - - result_df = self.run_sql( - """ - SELECT * - FROM proj.test_stability_t2i_single - WHERE text = 'A blue lagoon'; - """ - ) - assert result_df["answer"].size == 1 - - @patch("mindsdb.integrations.handlers.postgres_handler.Handler") - def test_bulk_text(self, mock_handler): - """Test for bulk question/answer pairs""" - df = pd.DataFrame.from_dict({"text": [ - "A black swan", - "A pink unicorn" - ]}) - self.set_handler(mock_handler, name="pg", tables={"df": df}) - - self.run_sql( - f""" - CREATE MODEL proj.test_stability_bulk_text - PREDICT answer - USING - engine='stability_engine', - task = "text-to-image", - local_directory_path = "tests/unit/ml_handlers/data", - api_key='{self.get_api_key('STABILITY_API_KEY')}'; - """ - ) - self.wait_predictor("proj", "test_stability_bulk_text") - - result_df = self.run_sql( - """ - SELECT p.answer - FROM pg.df as t - JOIN proj.test_stability_bulk_text as p; - """ - ) - assert result_df["answer"].size == 2 diff --git a/tests/unused/unit/ml_handlers/test_statsforecast.py b/tests/unused/unit/ml_handlers/test_statsforecast.py deleted file mode 100644 index fd1a71a7805..00000000000 --- a/tests/unused/unit/ml_handlers/test_statsforecast.py +++ /dev/null @@ -1,302 +0,0 @@ -import time -from unittest.mock import patch -import numpy as np -import pandas as pd -import pytest - -from statsforecast.models import AutoCES -from statsforecast.utils import AirPassengersDF -from statsforecast import StatsForecast -from mindsdb.integrations.utilities.time_series_utils import get_best_model_from_results_df -from mindsdb.integrations.handlers.statsforecast_handler.statsforecast_handler import ( - choose_model, - model_dict, - get_insample_cv_results, -) -from mindsdb_sql_parser import parse_sql -from tests.unit.ml_handlers.test_time_series_utils import create_mock_df -from tests.unit.executor_test_base import BaseExecutorTest - - -def test_choose_model(): - # With this data and settings, AutoTheta should win - model_args = {"horizon": 1, "frequency": "M", "model_name": "auto"} - sample_df = AirPassengersDF.iloc[:100] - results_df = get_insample_cv_results(model_args, sample_df) - best_model = choose_model(model_args, results_df) - assert best_model.__class__.__name__ == "AutoTheta" - - -class TestStatsForecast(BaseExecutorTest): - def wait_predictor(self, project, name): - # wait - done = False - for attempt in range(200): - ret = self.run_sql(f"select * from {project}.models where name='{name}'") - if not ret.empty: - if ret["STATUS"][0] == "complete": - done = True - break - elif ret["STATUS"][0] == "error": - raise RuntimeError("predictor failed", ret["ERROR"][0]) - time.sleep(0.5) - if not done: - raise RuntimeError("predictor wasn't created") - - def run_sql(self, sql): - ret = self.command_executor.execute_command(parse_sql(sql)) - assert ret.error_code is None - if ret.data is not None: - return ret.data.to_df() - - @patch("mindsdb.integrations.handlers.postgres_handler.Handler") - def test_grouped(self, mock_handler): - # create project - self.run_sql("create database proj") - df = create_mock_df() - self.set_handler(mock_handler, name="t", tables={"df": df}, engine='mysql') - - self.run_sql( - """ - create model proj.model_1_group - from t (select * from df) - predict target_col - order by time_col - group by group_col - horizon 3 - using - engine='statsforecast' - """ - ) - self.wait_predictor("proj", "model_1_group") - - # run predict - result_df = self.run_sql( - """ - SELECT p.* - FROM t.df as t - JOIN proj.model_1_group as p - where t.group_col='b' - """ - ) - assert list(round(result_df["target_col"])) == [42, 43, 44] - - describe_result = self.run_sql("describe proj.model_1_group.features") - assert describe_result["unique_id"][0] == ["group_col"] - - # now add more groups - self.run_sql( - """ - create model proj.model_multi_group - from t (select * from df) - predict target_col - order by time_col - group by group_col, group_col_2, group_col_3 - horizon 3 - using - engine='statsforecast' - """ - ) - self.wait_predictor("proj", "model_multi_group") - - result_df = self.run_sql( - """ - SELECT p.* - FROM t.df as t - JOIN proj.model_multi_group as p - where t.group_col_2='a2' - """ - ) - assert list(round(result_df["target_col"])) == [32, 33, 34] - - describe_result = self.run_sql("describe proj.model_multi_group.features") - assert describe_result["unique_id"][0] == ["group_col", "group_col_2", "group_col_3"] - - @patch("mindsdb.integrations.handlers.postgres_handler.Handler") - def test_model_choice(self, mock_handler): - """This tests whether changing the model_name and frequency USING args - will switch the actual model used. - """ - - # create project - self.run_sql("create database proj") - df = pd.read_parquet("https://datasets-nixtla.s3.amazonaws.com/m4-hourly.parquet") - df = df[df.unique_id.isin(["H1", "H2", "H3"])] # subset for speed - n_groups = df["unique_id"].nunique() - self.set_handler(mock_handler, name="pg", tables={"df": df}) - - # generate ground truth predictions from the package - prediction_horizon = 4 - sf = StatsForecast(models=[AutoCES(season_length=24)], freq="H") - sf.fit(df) - forecast_df = sf.predict(prediction_horizon) - package_predictions = forecast_df.reset_index(drop=True).iloc[:, -1] - - # create predictor - self.run_sql( - f""" - create model proj.modelx - from pg (select * from df) - predict y - order by ds - group by unique_id - horizon {prediction_horizon} - using - engine='statsforecast', - model_name='AutoCES', - frequency='H' - """ - ) - self.wait_predictor("proj", "modelx") - - # run predict - result_df = self.run_sql( - """ - SELECT p.* - FROM pg.df as t - JOIN proj.modelx as p - """ - ) - - # check against ground truth - mindsdb_result = result_df.iloc[:, -1] - assert len(mindsdb_result) == prediction_horizon * n_groups - assert np.allclose(mindsdb_result, package_predictions) - - # test describe() method, which should return a df row with keys - # {"inputs": [features], "outputs": , "accuracies": [model_accuracies]} - describe_result = self.run_sql("describe proj.modelx") - assert describe_result["inputs"][0] == ["y", "ds", ["unique_id"]] - assert describe_result["outputs"][0] == "y" - # The expected format of the "accuracies" key is - # [(model_1_name, model_1_accuracy), (model_2_name, model_2_accuracy), ...] - assert describe_result["accuracies"][0][0][0] == "AutoCES" - assert describe_result["accuracies"][0][0][1] < 1 - - describe_model = self.run_sql("describe proj.modelx.model") - assert describe_model["model_name"][0] == "AutoCES" - assert describe_model["frequency"][0] == "H" - assert describe_model["season_length"][0] == 24 - - describe_features = self.run_sql("describe proj.modelx.features") - assert describe_features["ds"][0] == "ds" - assert describe_features["y"][0] == "y" - assert describe_features["unique_id"][0] == ["unique_id"] - - with pytest.raises(Exception) as e: - self.run_sql("describe proj.modelx.ensemble") - assert "ensemble is not supported" in str(e) - - @patch("mindsdb.integrations.handlers.postgres_handler.Handler") - def test_auto_model_selection(self, mock_handler): - """Tests the argument for auto model selection will pick the - model with the lowest error. - """ - # create project - self.run_sql("create database proj") - self.set_handler(mock_handler, name="pg", tables={"df": AirPassengersDF}) - - # generate ground truth predictions from the package - AutoTheta should win here - prediction_horizon = 1 - sf = StatsForecast(models=[m(season_length=12) for m in model_dict.values()], freq="M", df=AirPassengersDF) - sf.cross_validation(prediction_horizon, fitted=True) - sf_results_df = sf.cross_validation_fitted_values() - best_model_name = get_best_model_from_results_df(sf_results_df) - package_predictions = sf.forecast(prediction_horizon)[best_model_name] - - # create predictor - self.run_sql( - f""" - create model proj.modelx - from pg (select * from df) - predict y - order by ds - group by unique_id - horizon {prediction_horizon} - using - engine='statsforecast', - model_name='auto', - frequency='M' - """ - ) - self.wait_predictor("proj", "modelx") - - # run predict - result_df = self.run_sql( - """ - SELECT p.* - FROM pg.df as t - JOIN proj.modelx as p - """ - ) - - # check against ground truth - mindsdb_result = result_df.iloc[:, -1] - assert np.allclose(mindsdb_result, package_predictions) - - describe_result = self.run_sql("describe proj.modelx") - assert len(describe_result["accuracies"][0]) > 1 - assert type(describe_result["accuracies"][0][0][0]) == str - assert describe_result["accuracies"][0][0][1] < 1 - - @patch("mindsdb.integrations.handlers.postgres_handler.Handler") - def test_hierarchical(self, mock_handler): - # create project - self.run_sql("create database proj") - df = pd.read_csv("tests/unit/ml_handlers/data/house_sales.csv") # comes mindsdb docs forecast example - self.set_handler(mock_handler, name="pg", tables={"df": df}) - - self.run_sql( - """ - create model proj.model_1_group - from pg (select * from df) - predict ma - order by saledate - group by type, bedrooms - horizon 4 - using - engine='statsforecast', - hierarchy=['type', 'bedrooms'] - """ - ) - self.wait_predictor("proj", "model_1_group") - - # run predict - mindsdb_result_hier = self.run_sql( - """ - SELECT p.* - FROM pg.df as t - JOIN proj.model_1_group as p - where t.type='house' - """ - ) - assert len(list(round(mindsdb_result_hier["ma"]))) - - describe_result = self.run_sql("describe proj.model_1_group.model") - assert describe_result["hierarchy"][0] == ["type", "bedrooms"] - - # Check results differ from the default settings - self.run_sql( - """ - create model proj.model_1 - from pg (select * from df) - predict ma - order by saledate - group by type, bedrooms - horizon 4 - using - engine='statsforecast' - """ - ) - self.wait_predictor("proj", "model_1") - - mindsdb_result_default = self.run_sql( - """ - SELECT p.* - FROM pg.df as t - JOIN proj.model_1 as p - where t.type='house' - """ - ) - - assert mindsdb_result_hier["ma"].sum() != mindsdb_result_default["ma"].sum() diff --git a/tests/unused/unit/ml_handlers/test_time_series_utils.py b/tests/unused/unit/ml_handlers/test_time_series_utils.py deleted file mode 100644 index 0204339c9d8..00000000000 --- a/tests/unused/unit/ml_handlers/test_time_series_utils.py +++ /dev/null @@ -1,144 +0,0 @@ -import pandas as pd -from statsforecast.utils import AirPassengersDF -from mindsdb.integrations.utilities.time_series_utils import ( - transform_to_nixtla_df, - get_results_from_nixtla_df, - infer_frequency, - get_best_model_from_results_df, - spec_hierarchy_from_list, - get_hierarchy_from_df, - reconcile_forecasts, -) - - -def create_mock_df(freq="Q-DEC"): - df2 = pd.DataFrame(pd.date_range(start="1/1/2010", periods=31, freq=freq), columns=["time_col"]) - df3 = df2.copy() - - df2["target_col"] = range(1, 32) - df2["group_col"] = "a" - df2["group_col_2"] = "a2" - df2["group_col_3"] = "a3" - - df3["target_col"] = range(11, 42) - df3["group_col"] = "b" - df3["group_col_2"] = "b2" - df3["group_col_3"] = "b3" - - return pd.concat([df2, df3]).reset_index(drop=True) - - -def test_infer_frequency(): - df = create_mock_df() - assert infer_frequency(df, "time_col") == "Q-DEC" - - df = create_mock_df(freq="M") - assert infer_frequency(df, "time_col") == "M" - - # Should still work if we pass string dates - df["time_col"] = df["time_col"].astype(str) - assert infer_frequency(df, "time_col") == "M" - - # Should still work if we pass unordered dates - unordered_df = pd.concat([df.iloc[:3, :], df.iloc[3:, :]]) - assert infer_frequency(unordered_df, "time_col") == "M" - - -def test_statsforecast_df_transformations(): - df = create_mock_df() - model_name = "ARIMA" - settings_dict = { - "order_by": "time_col", - "group_by": ["group_col"], - "target": "target_col", - "model_name": model_name, - } - - # Test transform for single groupby - nixtla_df = transform_to_nixtla_df(df, settings_dict) - assert [nixtla_df["unique_id"].iloc[i] == df["group_col"].iloc[i] for i in range(len(nixtla_df))] - assert [nixtla_df["y"].iloc[i] == df["target_col"].iloc[i] for i in range(len(nixtla_df))] - assert [nixtla_df["ds"].iloc[i] == df["time_col"].iloc[i] for i in range(len(nixtla_df))] - # Test reversing the transformation - nixtla_results_df = nixtla_df.rename({"y": model_name}, axis=1).set_index("unique_id") - mindsdb_results_df = get_results_from_nixtla_df(nixtla_results_df, settings_dict) - pd.testing.assert_frame_equal(mindsdb_results_df, df[["time_col", "target_col", "group_col"]]) - - # Test for multiple groups - settings_dict["group_by"] = ["group_col", "group_col_2", "group_col_3"] - nixtla_df = transform_to_nixtla_df(df, settings_dict) - assert nixtla_df["unique_id"][0] == "a/a2/a3" - # Test reversing the transformation - nixtla_results_df = nixtla_df.rename({"y": model_name}, axis=1).set_index("unique_id") - mindsdb_results_df = get_results_from_nixtla_df(nixtla_results_df, settings_dict) - pd.testing.assert_frame_equal(mindsdb_results_df, df) - - # Test with exogenous vars - settings_dict["group_by"] = ["group_col"] - settings_dict["exogenous_vars"] = ["group_col_2", "group_col_3"] - nixtla_df = transform_to_nixtla_df(df, settings_dict, exog_vars=["group_col_2", "group_col_3"]) - assert nixtla_df.columns.tolist() == ["unique_id", "ds", "y", "group_col_2", "group_col_3"] - - -def test_get_best_model_from_results_df(): - nixtla_df = AirPassengersDF.copy() - nixtla_df["AutoARIMA"] = nixtla_df["y"] + 1 - nixtla_df["AutoCES"] = nixtla_df["y"] - nixtla_df["AutoBadModel"] = nixtla_df["y"] - 2 - - assert get_best_model_from_results_df(nixtla_df) == "AutoCES" - - -def test_spec_hierarchy_from_list(): - hierachy_cols = ["col1", "col2"] - hierarchy_spec = spec_hierarchy_from_list(hierachy_cols) - - assert len(hierarchy_spec) == 3 - assert hierarchy_spec[0] == ["Total"] - assert hierarchy_spec[1] == ["Total", "col1"] - assert hierarchy_spec[2] == ["Total", "col1", "col2"] - - -def test_get_hierarchy_from_df(): - df = pd.DataFrame({"col1": [1, 2], "col2": [3, 4], "target": [5, 6]}) - df["time_col"] = pd.date_range(start="1/1/2010", freq="M", periods=2) - model_args = { - "order_by": "time_col", - "group_by": ["col1", "col2"], - "target": "target", - "hierarchy": ["col1", "col2"], - } - - training_df, hier_df, hier_dict = get_hierarchy_from_df(df, model_args) - assert training_df.columns.tolist() == ["ds", "y"] - assert training_df.index.name == "unique_id" - # checks shape of hierarchy matrix, which is a [0, 1] matrix - assert hier_df.columns.tolist() == ["total/1/3", "total/2/4"] - assert hier_df.index.tolist() == ["total", "total/1", "total/2", "total/1/3", "total/2/4"] - - assert hier_dict["Total"].tolist() == ["total"] - assert hier_dict["Total/col1"].tolist() == ["total/1", "total/2"] - assert hier_dict["Total/col1/col2"] == ["total/1/3", "total/2/4"] - - -def test_reconcile_forecasts(): - df = pd.DataFrame({"col1": [1, 2], "col2": [3, 4], "target": [5, 6]}) - df["time_col"] = pd.date_range(start="1/1/2010", freq="M", periods=1)[0] - model_args = { - "order_by": "time_col", - "group_by": ["col1", "col2"], - "target": "target", - "hierarchy": ["col1", "col2"], - } - - training_df, hier_df, hier_dict = get_hierarchy_from_df(df, model_args) - forecast_df = pd.DataFrame( - {"ARIMA": [15, 8, 7, 8, 7]}, index=["total", "total/1", "total/2", "total/1/3", "total/2/4"] - ) - forecast_df["ds"] = pd.date_range(start="1/3/2010", freq="M", periods=1)[0] - forecast_df.index.name = "unique_id" - results_df = reconcile_forecasts(training_df, forecast_df, hier_df, hier_dict) - - # Check we keep the hierarchically reconciled results, not the original forecast - assert "ARIMA/BottomUp" in results_df.columns - assert "ARIMA" not in results_df.columns diff --git a/tests/unused/unit/ml_handlers/test_unify.py b/tests/unused/unit/ml_handlers/test_unify.py deleted file mode 100644 index 8ec749c71ae..00000000000 --- a/tests/unused/unit/ml_handlers/test_unify.py +++ /dev/null @@ -1,156 +0,0 @@ -import unittest -from unittest.mock import patch, MagicMock -import pandas as pd -from collections import OrderedDict - -from mindsdb.integrations.handlers.unify_handler.unify_handler import UnifyHandler # Replace with the actual import path - - -class TestUnify(unittest.TestCase): - """ - Unit tests for the Unify handler. - """ - - dummy_connection_data = OrderedDict( - unify_api_key='dummy_api_key', - ) - - def setUp(self): - # Mock model storage and engine storage - mock_engine_storage = MagicMock() - mock_model_storage = MagicMock() - - # Define a return value for the `get_connection_args` method of the mock engine storage - mock_engine_storage.get_connection_args.return_value = self.dummy_connection_data - - # Assign mock engine storage to instance variable for create validation tests - self.mock_engine_storage = mock_engine_storage - - self.handler = UnifyHandler(mock_model_storage, mock_engine_storage) - - def test_create_without_using_clause_raises_exception(self): - """ - Test if model creation raises an exception without a USING clause. - """ - with self.assertRaisesRegex(Exception, "Unify engine requires a USING clause!"): - self.handler.create('target', args={}) - - def test_create_with_valid_arguments_runs_no_errors(self): - """ - Test if model creation is validated correctly with valid arguments. - """ - args = { - 'using': { - 'model': 'dummy_model', - 'provider': 'dummy_provider', - 'column': 'dummy_column' - } - } - self.handler.create('target', args=args) - self.assertTrue(self.handler.generative) - self.handler.model_storage.json_set.assert_called_once_with('args', args) - - @patch('unify.utils.list_endpoints') - @patch('unify.Unify') - def test_predict_with_valid_arguments_runs_no_errors(self, mock_unify, mock_list_endpoints): - """ - Test if model prediction returns the expected result with valid arguments. - """ - # Mock the necessary methods and attributes - self.handler.model_storage.json_get.return_value = { - 'using': { - 'model': 'dummy_model', - 'provider': 'dummy_provider', - 'column': 'input_text' - }, - 'target': 'output_text' - } - mock_list_endpoints.return_value = ['dummy_model@dummy_provider'] - - mock_client = MagicMock() - mock_client.generate.return_value = 'Generated text' - mock_unify.return_value = mock_client - - # Create a dummy DataFrame - df = pd.DataFrame({'input_text': ['Test input']}) - - result = self.handler.predict(df) - - self.assertIsInstance(result, pd.DataFrame) - self.assertEqual(list(result.columns), ['output_text']) - self.assertEqual(result['output_text'][0], 'Generated text') - - def test_predict_with_missing_model_raises_exception(self): - """ - Test if model prediction raises an exception when 'model' is missing from the USING clause. - """ - self.handler.model_storage.json_get.return_value = { - 'using': { - 'provider': 'dummy_provider', - 'column': 'input_text' - } - } - with self.assertRaisesRegex(Exception, "Unify requires an model parameter in the USING clause!"): - self.handler.predict(pd.DataFrame()) - - def test_predict_with_missing_provider_raises_exception(self): - """ - Test if model prediction raises an exception when 'provider' is missing from the USING clause. - """ - self.handler.model_storage.json_get.return_value = { - 'using': { - 'model': 'dummy_model', - 'column': 'input_text' - } - } - with self.assertRaisesRegex(Exception, "Unify requires a provider parameter in the USING clause!"): - self.handler.predict(pd.DataFrame()) - - @patch('unify.utils.list_endpoints') - def test_predict_with_unsupported_endpoint_raises_exception(self, mock_list_endpoints): - """ - Test if model prediction raises an exception when the endpoint is not supported by Unify. - """ - self.handler.model_storage.json_get.return_value = { - 'using': { - 'model': 'dummy_model', - 'provider': 'dummy_provider', - 'column': 'input_text' - } - } - mock_list_endpoints.return_value = ['other_model@other_provider'] - - with self.assertRaisesRegex(Exception, "The model, provider or their combination is not supported by Unify!"): - self.handler.predict(pd.DataFrame()) - - @patch('mindsdb.integrations.handlers.unify_handler.unify_handler.unify.utils.list_endpoints') - @patch('mindsdb.integrations.handlers.unify_handler.unify_handler.get_api_key') - def test_predict_with_missing_input_column_raises_exception(self, mock_get_api_key, mock_list_endpoints): - # Mock the necessary methods and attributes - mock_get_api_key.return_value = 'dummy_api_key' - mock_list_endpoints.return_value = ['dummy_model@dummy_provider'] - - self.handler.model_storage.json_get.return_value = { - 'using': { - 'model': 'dummy_model', - 'provider': 'dummy_provider', - 'column': 'non_existent_column' - }, - 'target': 'output_column' - } - - # Create a DataFrame without the expected input column - df = pd.DataFrame({'other_column': ['Test input']}) - - # Assert that the correct exception is raised - with self.assertRaisesRegex(RuntimeError, 'Column "non_existent_column" not found in input data'): - self.handler.predict(df) - - # Verify that the mocked methods were called - self.handler.model_storage.json_get.assert_called_once_with('args') - mock_get_api_key.assert_called_once() - mock_list_endpoints.assert_called_once() - - -if __name__ == '__main__': - unittest.main() diff --git a/tests/unused/unit/ml_handlers/test_vertex.py b/tests/unused/unit/ml_handlers/test_vertex.py deleted file mode 100644 index fd360f53443..00000000000 --- a/tests/unused/unit/ml_handlers/test_vertex.py +++ /dev/null @@ -1,247 +0,0 @@ -import time -import json - -import pandas as pd - -import pytest -from unittest.mock import Mock, patch -from mindsdb_sql_parser import parse_sql - -from tests.unit.executor_test_base import BaseExecutorTest -from mindsdb.integrations.handlers.vertex_handler.vertex_client import VertexClient - -path = "mindsdb.integrations.handlers.vertex_handler.vertex_client" - - -@pytest.fixture -def vertex_client(): - with patch(f"{path}.service_account.Credentials.from_service_account_file"), patch(f"{path}.aiplatform.init"): - client = VertexClient("fake_path", "fake_project_id") - return client - - -# Mocks -def mock_datasets(): - dataset_1 = Mock(display_name="Dataset1", name="ID1") - dataset_2 = Mock(display_name="Dataset2", name="ID2") - - # Set concrete return values for attributes - dataset_1.display_name = "Dataset1" - dataset_1.name = "ID1" - - dataset_2.display_name = "Dataset2" - dataset_2.name = "ID2" - - return [dataset_1, dataset_2] - - -def mock_endpoints(): - endpoint_1 = Mock(display_name="Endpoint1", name="EndpointID1") - endpoint_2 = Mock(display_name="Endpoint2", name="EndpointID2") - - # Set concrete return values for attributes - endpoint_1.display_name = "Endpoint1" - endpoint_1.name = "EndpointID1" - - endpoint_2.display_name = "Endpoint2" - endpoint_2.name = "EndpointID2" - - return [endpoint_1, endpoint_2] - - -def mock_models(): - model_1 = Mock(display_name="Model1", name="ModelID1") - model_2 = Mock(display_name="Model2", name="ModelID2") - - # Set concrete return values for attributes - model_1.display_name = "Model1" - model_1.name = "ModelID1" - - model_2.display_name = "Model2" - model_2.name = "ModelID2" - - return [model_1, model_2] - - -# Test of Vertex client class -def test_get_model_by_display_name(vertex_client): - with patch(f"{path}.aiplatform.Model.list", return_value=mock_models()): - model = vertex_client.get_model_by_display_name("Model1") - assert model.display_name == "Model1" - assert model.name == "ModelID1" - - -def test_get_endpoint_by_display_name(vertex_client): - with patch(f"{path}.aiplatform.Endpoint.list", return_value=mock_endpoints()): - endpoint = vertex_client.get_endpoint_by_display_name("Endpoint1") - assert endpoint.display_name == "Endpoint1" - assert endpoint.name == "EndpointID1" - - -def test_get_model_by_id(vertex_client): - with patch(f"{path}.aiplatform.Model", return_value=mock_models()[0]): - model = vertex_client.get_model_by_id("ModelID1") - assert model.display_name == "Model1" - assert model.name == "ModelID1" - - -def test_deploy_model(vertex_client): - mock_model = mock_models()[0] - with patch.object(mock_model, "deploy", return_value=mock_endpoints()[0]): - endpoint = vertex_client.deploy_model(mock_model) - assert endpoint.display_name == "Endpoint1" - assert endpoint.name == "EndpointID1" - - -def test_predict_from_csv(vertex_client, mocker): - mock_endpoint = mocker.MagicMock() - mock_endpoint.predict.return_value = "CSV Predictions" - - mocker.patch(f"{path}.pd.read_csv", return_value=pd.DataFrame({"col1": ["data1", "data2"]})) - mocker.patch(f"{path}.VertexClient.get_endpoint_by_display_name", return_value=mock_endpoint) - - predictions = vertex_client.predict_from_csv("Endpoint1", "path_to_csv") - assert predictions == "CSV Predictions" - - -def test_predict_from_json(vertex_client, mocker): - mock_endpoint = mocker.MagicMock() - mock_endpoint.predict.return_value = "JSON Predictions" - - mock_open = mocker.mock_open(read_data='{"col1": ["data1", "data2"]}') - mocker.patch("builtins.open", mock_open) - - mocker.patch(f"{path}.json.load", return_value={"col1": ["data1", "data2"]}) - mocker.patch(f"{path}.VertexClient.get_endpoint_by_display_name", return_value=mock_endpoint) - - """Make a prediction from a JSON file""" - with open("path_to_json", "r") as f: - data = json.load(f) - - predictions = vertex_client.predict_from_dict("Endpoint1", data) - assert predictions == "JSON Predictions" - - -# Test of Vertex handler - - -class TestVertex(BaseExecutorTest): - def wait_predictor(self, project, name): - # wait - done = False - for attempt in range(200): - ret = self.run_sql(f"select * from {project}.models where name='{name}'") - if not ret.empty: - if ret["STATUS"][0] == "complete": - done = True - break - elif ret["STATUS"][0] == "error": - break - time.sleep(0.5) - if not done: - raise RuntimeError("predictor wasn't created") - - def run_sql(self, sql): - ret = self.command_executor.execute_command(parse_sql(sql)) - assert ret.error_code is None - if ret.data is not None: - return ret.data.to_df() - - @patch("mindsdb.integrations.handlers.postgres_handler.Handler") - def test_anomaly_detection_model(self, mock_handler): - # create project - self.run_sql("create database proj") - df = pd.read_csv("tests/unit/ml_handlers/data/vertex_anomaly_detection.csv") - self.set_handler(mock_handler, name="pg", tables={"df": df}) - - # create predictor - self.run_sql( - """ - create model proj.modelx - from pg (select * from df) - predict cut - using - engine='vertex', - model_name='diamonds_anomaly_detection', - custom_model='True', - vertex_args_path='tests/unit/ml_handlers/data/vertex_args.json', - service_key_path='tests/unit/ml_handlers/data/vertex_service_key.json' - """ - ) - self.wait_predictor("proj", "modelx") - - # run predict - ret = self.run_sql( - """ - SELECT p.* - FROM pg.df as t - JOIN proj.modelx as p - """ - ) - assert len(ret) == len(df) - - @patch("mindsdb.integrations.handlers.postgres_handler.Handler") - def test_regression_model(self, mock_handler): - # create database - self.run_sql("create database proj") - df = pd.read_csv("tests/unit/ml_handlers/data/vertex_regression.csv") - self.set_handler(mock_handler, name="pg", tables={"df": df}) - - # create predictor - self.run_sql( - """ - create model proj.modelx - from pg (select * from df) - predict actual_productivity - using - engine='vertex', - model_name='productivity_regression', - vertex_args_path='tests/unit/ml_handlers/data/vertex_args.json', - service_key_path='tests/unit/ml_handlers/data/vertex_service_key.json' - """ - ) - self.wait_predictor("proj", "modelx") - - # run predict - ret = self.run_sql( - """ - SELECT p.* - FROM pg.df as t - JOIN proj.modelx as p - """ - ) - assert len(ret) == len(df) - - @patch("mindsdb.integrations.handlers.postgres_handler.Handler") - def test_classification_model(self, mock_handler): - # dataset, string values - df = pd.read_csv("tests/unit/ml_handlers/data/vertex_classification.csv") - self.set_handler(mock_handler, name="pg", tables={"df": df}) - - # create project - self.run_sql("create database proj") - - # create predictor - self.run_sql( - """ - create model proj.modelx - from pg (select * from df) - predict Class - using - engine='vertex', - model_name='fraud_detection', - vertex_args_path='tests/unit/ml_handlers/data/vertex_args.json', - service_key_path='tests/unit/ml_handlers/data/vertex_service_key.json' - """ - ) - self.wait_predictor("proj", "modelx") - - # run predict - ret = self.run_sql( - """ - SELECT p.* - FROM pg.df as t - JOIN proj.modelx as p - """ - ) - assert len(ret) == len(df) diff --git a/tests/unused/unit/ml_handlers/test_writer.py b/tests/unused/unit/ml_handlers/test_writer.py deleted file mode 100644 index 8a7e4686e9e..00000000000 --- a/tests/unused/unit/ml_handlers/test_writer.py +++ /dev/null @@ -1,143 +0,0 @@ -import os -import time -from unittest.mock import patch - -import pandas as pd -import pytest -from mindsdb_sql_parser import parse_sql - -from tests.unit.executor_test_base import BaseExecutorTest - -WRITER_API_KEY = os.environ.get("WRITER_API_KEY") -os.environ["WRITER_API_KEY"] = WRITER_API_KEY - -WRITER_ORG_ID = os.environ.get("WRITER_ORG_ID") -os.environ["WRITER_ORG_ID"] = WRITER_ORG_ID - - -class TestWriter(BaseExecutorTest): - def wait_predictor(self, project, name): - # wait - done = False - for attempt in range(200): - ret = self.run_sql(f"select * from {project}.models where name='{name}'") - if not ret.empty: - if ret["STATUS"][0] == "complete": - done = True - break - elif ret["STATUS"][0] == "error": - break - time.sleep(0.5) - if not done: - raise RuntimeError("predictor wasn't created") - - def run_sql(self, sql): - ret = self.command_executor.execute_command(parse_sql(sql)) - assert ret.error_code is None - if ret.data is not None: - return ret.data.to_df() - - def test_missing_required_keys(self): - # create project - self.run_sql("create database proj") - - self.run_sql( - """ - CREATE MODEL proj.test_writer_handler_missing_required_args - PREDICT answer - USING - engine="writer" - """ - ) - with pytest.raises(Exception): - self.wait_predictor("proj", "test_writer_handler_missing_required_args") - - def test_unsupported_vector_store(self): - self.run_sql("create database proj") - self.run_sql( - f""" - create model proj.test_unsupported_vector_store - predict answer - using - engine='writer', - writer_api_key='{WRITER_API_KEY}', - writer_org_id='{WRITER_ORG_ID}', - vector_store_name='unsupported_vector_store' - """ - ) - - with pytest.raises(Exception): - self.wait_predictor("proj", "test_unsupported_vector_store") - - def test_unknown_arguments(self): - self.run_sql("create database proj") - self.run_sql( - f""" - create model proj.test_writer_unknown_arguments - predict answer - using - engine='writer', - writer_api_key='{WRITER_API_KEY}', - writer_org_id='{WRITER_ORG_ID}', - evidently_wrong_argument='wrong value' --- this is a wrong argument name - """ - ) - with pytest.raises(Exception): - self.wait_predictor("proj", "test_writer_unknown_arguments") - - @pytest.mark.xfail( - reason="there seems to be an issue with running inner queries, it appears to be a potential bug in the mock handler" - ) - @patch("mindsdb.integrations.handlers.postgres_handler.Handler") - def test_qa(self, postgres_mock_handler): - # create project - self.run_sql("create database proj") - df = pd.DataFrame.from_dict( - { - "context": [ - "For adults and children age 5 and older, OTC decongestants, " - "antihistamines and pain relievers might offer some symptom relief. " - "However, they won't prevent a cold or shorten its duration, and most have some side effects.", - ] - } - ) - self.set_handler(postgres_mock_handler, name="pg", tables={"df": df}) - - self.run_sql( - f""" - create model proj.test_writer_writer_qa - from pg (select * from df) - predict answer - using - engine='writer', - writer_api_key='{WRITER_API_KEY}', - writer_org_id='{WRITER_ORG_ID}'; - """ - ) - self.wait_predictor("proj", "test_writer_writer_qa") - - result_df = self.run_sql( - """ - SELECT p.answer - FROM proj.test_writer_writer_qa as p - WHERE question='What is the best treatment for a cold?' - """ - ) - assert "cold" in result_df["answer"].iloc[0].lower() - - def test_invalid_prompt_template(self): - # create project - self.run_sql("create database proj") - self.run_sql( - f""" - create model proj.test_invalid_prompt_template_format - predict completion - using - engine='writer', - prompt_template="not valid format", - writer_api_key='{WRITER_API_KEY}', - writer_org_id='{WRITER_ORG_ID}'; - """ - ) - with pytest.raises(Exception): - self.wait_predictor("proj", "test_invalid_prompt_template_format")