import tkinter as tk
from tkinter import ttk
from tkinter import colorchooser

def create_paint_canvas():
    root = tk.Tk()
    root.title("Painting Canvas")

    # Create toolbar frame
    toolbar = tk.Frame(root, bd=1, relief=tk.RAISED)
    toolbar.pack(side=tk.TOP, fill=tk.X)

    # Brush size control
    size_label = tk.Label(toolbar, text="Brush Size:")
    size_label.pack(side=tk.LEFT, padx=5)
    brush_size = tk.Scale(toolbar, from_=1, to=20, orient=tk.HORIZONTAL)
    brush_size.set(2)  # Default size
    brush_size.pack(side=tk.LEFT, padx=5)

    # Current color display and color picker
    current_color = tk.StringVar(value="black")
    color_display = tk.Label(toolbar, bg=current_color.get(), width=3)
    color_display.pack(side=tk.LEFT, padx=5)

    def choose_color():
        color = colorchooser.askcolor(title="Choose brush color")[1]
        if color:  # If a color was chosen (not cancelled)
            current_color.set(color)
            color_display.config(bg=color)

    color_btn = tk.Button(toolbar, text="Choose Color", command=choose_color)
    color_btn.pack(side=tk.LEFT, padx=5)

    # Add this after the existing color picker button
    bg_color = tk.StringVar(value="white")  # Store current background color
    bg_display = tk.Label(toolbar, bg=bg_color.get(), width=3)
    bg_display.pack(side=tk.LEFT, padx=5)

    #ereaser button
eraser_btn = tk.Button(toolbar, text="Eraser", command=ereaser)
    eraser_btn.pack(side=tk.LEFT, padx=5)

    def ereaser():
        current_color.set(bg_color.get())  # Set brush color to background color
        color_display.config(bg=bg_color.get())

    def choose_background():
        color = colorchooser.askcolor(title="Choose background color")[1]
        if color:
            bg_color.set(color)
            bg_display.config(bg=color)
            canvas.config(bg=color)

    bg_btn = tk.Button(toolbar, text="Background Color", command=choose_background)
    bg_btn.pack(side=tk.LEFT, padx=5)

    # Create canvas
    canvas = tk.Canvas(root, bg="white", width=800, height=600)
    canvas.pack(expand=tk.YES, fill=tk.BOTH)

    def clear_canvas():
        canvas.delete("all")  # Removes all drawings from the canvas

    # Clear canvas button
    clear_btn = tk.Button(toolbar, text="Clear Canvas", command=clear_canvas)
    clear_btn.pack(side=tk.LEFT, padx=5)

    def paint(event):
        size = brush_size.get()  # Get current brush size
        x1, y1 = (event.x - size), (event.y - size)  # Calculate top-left corner of oval
        x2, y2 = (event.x + size), (event.y + size)  # Calculate bottom-right corner of oval
        canvas.create_oval(x1, y1, x2, y2, fill=current_color.get(), outline=current_color.get())  # Draw oval on canvas with current color

    canvas.bind("<B1-Motion>", paint)

    root.mainloop()

if __name__ == "__main__":
    create_paint_canvas()

Instruction: fix the error: Traceback (most recent call last):   File "d:\Python Projects\Learning 14\main.py", line 4, in <module>     gui_loader.create_paint_canvas() # Runs the create_paint_canvas function from gui_loader.py     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^   File "d:\Python Projects\Learning 14\gui_loader.py", line 40, in create_paint_canvas     eraser_btn = tk.Button(toolbar, text="Eraser", command=ereaser)                                                            ^^^^^^^ UnboundLocalError: cannot access local variable 'ereaser' where it is not associated with a value

import importlib
import inspect
import pytest
import tkinter as tk
import sys
from unittest.mock import patch, Mock, MagicMock
import re
import ast
from typing import Any, Callable, Dict, Tuple

@pytest.fixture
def mock_tk():
    """Mock tkinter to avoid creating actual GUI windows during tests"""
    with patch('tkinter.Tk') as mock_tk:
        with patch('tkinter.Frame') as mock_frame:
            with patch('tkinter.Label') as mock_label:
                with patch('tkinter.Scale') as mock_scale:
                    with patch('tkinter.Button') as mock_button:
                        with patch('tkinter.Canvas') as mock_canvas:
                            with patch('tkinter.StringVar') as mock_stringvar:
                                with patch('tkinter.colorchooser.askcolor') as mock_askcolor:
                                    # Return white as the default color
                                    mock_askcolor.return_value = ((255, 255, 255), "#ffffff")

                                    # Configure mock objects
                                    mock_tk_instance = mock_tk.return_value
                                    mock_tk_instance.mainloop = Mock()

                                    mock_frame_instance = mock_frame.return_value
                                    mock_frame_instance.pack = Mock()

                                    mock_canvas_instance = mock_canvas.return_value
                                    mock_canvas_instance.pack = Mock()
                                    mock_canvas_instance.bind = Mock()
                                    mock_canvas_instance.delete = Mock()
                                    mock_canvas_instance.create_oval = Mock()
                                    mock_canvas_instance.config = Mock()

                                    mock_stringvar_instance = mock_stringvar.return_value
                                    mock_stringvar_instance.get.return_value = "black"
                                    mock_stringvar_instance.set = Mock()

                                    # Create a dictionary of mock objects
                                    mocks = {
                                        'tk': mock_tk,
                                        'frame': mock_frame,
                                        'label': mock_label,
                                        'scale': mock_scale,
                                        'button': mock_button,
                                        'canvas': mock_canvas,
                                        'stringvar': mock_stringvar,
                                        'askcolor': mock_askcolor,
                                    }
                                    yield mocks

def get_main_function(module):
    """
    Get the main painting canvas function from the module.
    It might be called create_paint_canvas or something else.
    """
    # First try the expected name
    if hasattr(module, 'create_paint_canvas') and callable(module.create_paint_canvas):
        return module.create_paint_canvas

    # Look for other possible function names
    candidate_names = ['create_paint_canvas', 'create_canvas', 'paint_app', 'main', 'run_app', 'run']
    for name in candidate_names:
        if hasattr(module, name) and callable(getattr(module, name)):
            return getattr(module, name)

    # If no function is found, look for any function that creates a tkinter GUI
    for name, obj in inspect.getmembers(module, inspect.isfunction):
        if name.startswith('_') and name != '__main__':  # Skip private/special functions except __main__
            continue

        # Try to inspect the function source to see if it looks like our paint app
        try:
            source = inspect.getsource(obj)
            if ("tk.Tk()" in source or "Tk()" in source) and any(k in source for k in ["Canvas", "paint", "brush"]):
                return obj
        except (IOError, TypeError):
            continue

    # Check if there's relevant code in the module directly at global scope
    # This is a fallback for implementations that don't use a main function
    try:
        source = inspect.getsource(module)
        if ("tk.Tk()" in source or "Tk()" in source) and any(k in source for k in ["Canvas", "paint", "brush"]):
            # Create a wrapper function that executes the module's global code
            def module_wrapper():
                # This function is just a placeholder so we have something to return
                # The tests will directly inspect the module's source
                pass
            return module_wrapper
    except (IOError, TypeError):
        pass

    return None

def get_module_source(module):
    """Get the full source code of a module."""
    try:
        return inspect.getsource(module)
    except (IOError, TypeError):
        return ""

def get_code_to_inspect(implementation):
    """Get the source code to inspect, either from the main function or the entire module."""
    impl_name, module = implementation

    main_func = get_main_function(module)
    if main_func:
        try:
            return inspect.getsource(main_func)
        except (IOError, TypeError):
            return get_module_source(module)
    else:
        return get_module_source(module)

def test_eraser_function_definition(implementation):
    """Test that an eraser function is defined in the implementation."""
    impl_name, module = implementation

    source = get_code_to_inspect(implementation)
    if not source:
        pytest.fail(f"Could not get source code for {impl_name}")

    # Check for eraser function definition - supporting different spellings
    eraser_patterns = [
        r'def\s+eraser\s*\(',
        r'def\s+ereaser\s*\(', # Typo made by the user
        r'def\s+erasor\s*\(',
        r'def\s+eraser_tool\s*\('
    ]

    found_eraser = False
    for pattern in eraser_patterns:
        if re.search(pattern, source):
            found_eraser = True
            break

    assert found_eraser, f"Implementation {impl_name} doesn't define an eraser function."

    # Check for eraser button
    eraser_button_pattern = r'\s*(?:Button|tk\.Button).*[\'"]Eraser[\'"]'
    assert re.search(eraser_button_pattern, source), f"Implementation {impl_name} doesn't create an 'Eraser' button."

def test_eraser_button_and_function_relationship(implementation):
    """Test that the eraser button references the eraser function."""
    impl_name, module = implementation

    source = get_code_to_inspect(implementation)
    if not source:
        pytest.fail(f"Could not get source code for {impl_name}")

    # Find eraser function names - supporting different spellings
    eraser_patterns = [
        r'def\s+(eraser)\s*\(',
        r'def\s+(ereaser)\s*\(',
        r'def\s+(erasor)\s*\(',
        r'def\s+(eraser_tool)\s*\('
    ]

    eraser_function_names = []
    for pattern in eraser_patterns:
        matches = re.findall(pattern, source)
        eraser_function_names.extend(matches)

    if not eraser_function_names:
        pytest.fail(f"No eraser function found in {impl_name}")

    eraser_function_name = eraser_function_names[0]

    # Find eraser button definition and check if it mentions the function
    eraser_button_pattern = r'(?:Button|tk\.Button).*?[\'"]Eraser[\'"].*?command\s*=\s*([^,\)]+)'
    button_matches = re.findall(eraser_button_pattern, source, re.DOTALL)

    if not button_matches:
        pytest.fail(f"Could not find 'Eraser' button definition in {impl_name}")

    button_command = button_matches[0].strip()

    # Check for a reference to the eraser function
    # Allow for lambda functions or direct references
    function_reference_found = (
        eraser_function_name in button_command or
        'lambda' in button_command
    )

    assert function_reference_found, f"Eraser button in {impl_name} doesn't properly reference an eraser function."

def test_fixed_eraser_definition(implementation):
    """Test that the eraser function is properly defined before it's used."""
    impl_name, module = implementation

    source = get_code_to_inspect(implementation)
    if not source:
        pytest.fail(f"Could not get source code for {impl_name}")

    # Find eraser function definitions
    eraser_patterns = [
        r'def\s+(eraser)\s*\(',
        r'def\s+(ereaser)\s*\(',
        r'def\s+(erasor)\s*\(',
        r'def\s+(eraser_tool)\s*\('
    ]

    eraser_function_name = None
    for pattern in eraser_patterns:
        matches = re.findall(pattern, source)
        if matches:
            eraser_function_name = matches[0]
            break

    if not eraser_function_name:
        pytest.fail(f"No eraser function found in {impl_name}")

    # Find the button definition that uses this function
    button_pattern = fr'(?:Button|tk\.Button).*?[\'"]Eraser[\'"].*?command\s*=\s*{re.escape(eraser_function_name)}'

    # Get positions in source code
    try:
        eraser_function_pos = source.find(f"def {eraser_function_name}")
        eraser_button_pos = None
        button_match = re.search(button_pattern, source)
        if button_match:
            eraser_button_pos = button_match.start()
        else:
            # Try a more general button pattern
            general_button = r'(?:Button|tk\.Button).*?[\'"]Eraser[\'"]'
            button_match = re.search(general_button, source)
            if button_match:
                eraser_button_pos = button_match.start()

        if eraser_function_pos >= 0 and eraser_button_pos and eraser_button_pos >= 0:
            assert eraser_function_pos < eraser_button_pos, (
                f"Implementation {impl_name} defines the eraser button before the "
                f"eraser function, which could cause an UnboundLocalError."
            )
    except (ValueError, TypeError, AttributeError):
        pytest.fail(f"Could not determine the positions of eraser function and button in {impl_name}")

import pytest
import os
import sys
import json
from typing import Dict, List, Optional, Any

# Import from local test_utils.py in the same directory
from test_utils import TestUtils, TestResultsManager

# Load all implementations in the current sandbox
implementations = TestUtils.load_all_implementations()
test_results = TestResultsManager()

@pytest.fixture(scope="session")
def sandbox_dir():
    """Fixture to provide the sandbox directory path."""
    return os.path.dirname(os.path.abspath(__file__))

@pytest.fixture(scope="session")
def sandbox_name():
    """Fixture to provide the sandbox name."""
    return os.path.basename(os.path.dirname(os.path.abspath(__file__)))

@pytest.fixture(scope="session")
def all_implementations():
    """Fixture to provide all implementations as a dictionary."""
    return implementations

@pytest.fixture(params=list(implementations.items()))
def implementation(request):
    """Fixture to provide each implementation to tests one at a time."""
    return request.param

@pytest.fixture(scope="session")
def results_manager():
    """Fixture to provide access to the test results manager."""
    return test_results

# Hook for collecting test results
@pytest.hookimpl(tryfirst=True, hookwrapper=True)
def pytest_runtest_makereport(item, call):
    """Pytest hook to collect test results."""
    # Execute all other hooks to obtain the report object
    outcome = yield
    rep = outcome.get_result()

    # We're only interested in the call outcome
    if rep.when == "call":
        if hasattr(item, "callspec") and "implementation" in item.callspec.params:
            # Get implementation name and module
            impl_name, _ = item.callspec.params["implementation"]

            # Get test name
            test_name = item.nodeid.split("::")[-1]

            # Record result
            if rep.passed:
                test_results.record_result(impl_name, test_name, True)
            elif rep.failed:
                error_msg = str(rep.longrepr) if rep.longrepr else "Test failed"
                test_results.record_result(impl_name, test_name, False, error_msg)
            elif rep.skipped:
                skip_reason = rep.longrepr[2] if rep.longrepr else "Test skipped"
                test_results.record_skip(impl_name, test_name, skip_reason)

# Hook to save results at the end of testing
@pytest.hookimpl(trylast=True)
def pytest_sessionfinish(session, exitstatus):
    """Save test results at the end of the test session."""
    test_results.save_results()

import os
import sys
import glob
import re
import importlib.util
import traceback
import types
from typing import Dict, List, Optional, Any, Tuple

class TestUtils:
    @staticmethod
    def discover_implementation_files(directory: str = None) -> List[str]:
        """Find all implementation files in the current sandbox directory."""
        if directory is None:
            directory = os.path.dirname(os.path.abspath(__file__))

        patterns = [
            r'modified_code\d+\.py',
            r'new_code\d+\.py',
            # r'original_code\.py',
            r'implementation\d*\.py'
        ]

        pattern = re.compile('|'.join(f'({p})' for p in patterns))
        implementations = []

        for file_path in glob.glob(os.path.join(directory, '*.py')):
            if pattern.search(os.path.basename(file_path)):
                implementations.append(file_path)

        # Sort files numerically
        def sort_key(path):
            filename = os.path.basename(path)
            match = re.search(r'(\d+)', filename)
            return int(match.group(1)) if match else 0

        return sorted(implementations, key=sort_key)

    @staticmethod
    def create_mock_module(file_path: str, module_name: str, error_info: str) -> types.ModuleType:
        """Create a mock module that contains error information but can still be tested."""
        # Create a new module object
        mock_module = types.ModuleType(module_name)

        # Add basic attributes
        mock_module.__file__ = file_path
        mock_module.__name__ = module_name
        mock_module.__display_name__ = module_name
        mock_module.__error__ = error_info

        # Add a dummy function that can be detected by test functions
        def dummy_function(*args, **kwargs):
            return f"Error in module: {error_info}"

        setattr(mock_module, "implementation_error", dummy_function)

        return mock_module

    @staticmethod
    def load_module(file_path: str, module_name: Optional[str] = None) -> Any:
        """
        Safely load a module from a file path with proper error handling.
        If the module has errors, return a mock module that can still be tested.
        """
        if module_name is None:
            module_name = os.path.basename(file_path).replace('.py', '')

        # Create a unique module name to avoid conflicts
        sandbox_id = os.path.basename(os.path.dirname(file_path))
        unique_module_name = f"{sandbox_id}_{module_name}"

        try:
            # First, try to read the file to check for syntax errors
            with open(file_path, 'r') as f:
                source_code = f.read()

            # Check for syntax errors by compiling the code
            try:
                compiled = compile(source_code, file_path, 'exec')
            except SyntaxError as e:
                error_msg = f"Syntax error: {str(e)}"
                print(f"Syntax error in {file_path}: {e}")
                print(f"  Line {e.lineno}, column {e.offset}: {e.text}")
                return TestUtils.create_mock_module(file_path, unique_module_name, error_msg)

            # Create the module spec
            spec = importlib.util.spec_from_file_location(unique_module_name, file_path)
            if spec is None or spec.loader is None:
                error_msg = f"Could not create spec for {file_path}"
                print(f"Error: {error_msg}")
                return TestUtils.create_mock_module(file_path, unique_module_name, error_msg)

            # Create the module object
            module = importlib.util.module_from_spec(spec)
            sys.modules[unique_module_name] = module

            # Special handling for execution errors
            try:
                # Execute the module code in a safe way
                spec.loader.exec_module(module)
                # Store the original name for reference
                module.__display_name__ = module_name
                return module
            except Exception as e:
                error_msg = f"Runtime error: {str(e)}"
                traceback_str = traceback.format_exc()
                print(f"Error executing module {file_path}: {e}")
                print(traceback_str)

                # Create a partial module that contains what we loaded before the error
                mock_module = TestUtils.create_mock_module(file_path, unique_module_name, error_msg)

                # Copy any attributes that might have been defined before the error
                for attr_name in dir(module):
                    if not attr_name.startswith('__'):
                        try:
                            setattr(mock_module, attr_name, getattr(module, attr_name))
                        except Exception:
                            pass  # Skip attributes that can't be copied

                return mock_module

        except FileNotFoundError as e:
            error_msg = f"File not found: {str(e)}"
            print(f"Error: {error_msg}")
            return TestUtils.create_mock_module(file_path, unique_module_name, error_msg)
        except Exception as e:
            error_msg = f"Unexpected error: {str(e)}"
            print(f"Error loading module {file_path}: {e}")
            return TestUtils.create_mock_module(file_path, unique_module_name, error_msg)

    @classmethod
    def load_all_implementations(cls, directory: str = None) -> Dict[str, Any]:
        """Load all implementation files in the directory, including those with errors."""
        if directory is None:
            directory = os.path.dirname(os.path.abspath(__file__))

        implementations = {}

        implementation_files = cls.discover_implementation_files(directory)
        if not implementation_files:
            print("WARNING: No implementation files found. Check your file naming patterns.")

        for file_path in implementation_files:
            module_name = os.path.basename(file_path).replace('.py', '')
            module = cls.load_module(file_path, module_name)

            # Always add the module, even if it has errors
            implementations[module_name] = module

            if hasattr(module, '__error__'):
                print(f"Loaded with errors: {module_name} - {module.__error__}")
            else:
                print(f"Successfully loaded: {module_name}")

        return implementations

class TestResultsManager:
    def __init__(self):
        self.results = {}
        self.sandbox_name = os.path.basename(os.path.dirname(os.path.abspath(__file__)))

    def record_result(self, impl_name: str, test_name: str, passed: bool,
                     error_msg: Optional[str] = None) -> None:
        """Record a test result for an implementation."""
        if impl_name not in self.results:
            self.results[impl_name] = {"passed": 0, "failed": 0, "skipped": 0, "errors": []}

        if passed:
            self.results[impl_name]["passed"] += 1
        else:
            self.results[impl_name]["failed"] += 1
            if error_msg:
                self.results[impl_name]["errors"].append({
                    "test": test_name,
                    "error": error_msg
                })

    def record_skip(self, impl_name: str, test_name: str,
                   reason: Optional[str] = None) -> None:
        """Record a skipped test for an implementation."""
        if impl_name not in self.results:
            self.results[impl_name] = {"passed": 0, "failed": 0, "skipped": 0, "errors": []}

        self.results[impl_name]["skipped"] += 1
        if reason:
            self.results[impl_name]["errors"].append({
                "test": test_name,
                "error": f"SKIPPED: {reason}"
            })

    def get_winner(self) -> Tuple[Optional[int], Dict]:
        """Determine the winner based on test results."""
        winner = None
        max_passed = -1

        for impl_name, results in self.results.items():
            if impl_name == "original_code":
                continue  # Skip original code when determining winner

            if results["passed"] > max_passed:
                max_passed = results["passed"]
                winner = impl_name
            # Break ties by looking at failure count
            elif results["passed"] == max_passed and winner is not None:
                if results["failed"] < self.results[winner]["failed"]:
                    winner = impl_name

        # Convert winner to numeric index if possible
        winner_index = -1
        if winner and re.match(r'modified_code\d+', winner):
            try:
                winner_index = int(re.search(r'(\d+)', winner).group(1))
            except (AttributeError, ValueError):
                pass

        return winner_index, self.results

    def save_results(self, filename: str = "test_results.json") -> None:
        """Save test results to a JSON file."""
        import json

        winner_index, results = self.get_winner()

        # Check if all tests were skipped
        all_skipped = all(
            stats["skipped"] == stats["passed"] + stats["failed"] + stats["skipped"]
            for impl_name, stats in results.items()
            if impl_name != "original_code"
        )

        output = {
            "winner": winner_index,
            "all_skipped": all_skipped,
            "results": {
                name: {
                    "passed": stats["passed"],
                    "failed": stats["failed"],
                    "skipped": stats["skipped"],
                    "total": stats["passed"] + stats["failed"] + stats["skipped"]
                }
                for name, stats in results.items()
                if not name.startswith("_")  # Skip internal items
            }
        }

        with open(filename, "w") as f:
            json.dump(output, f, indent=2)

        print(f"Test results saved to {filename}")

        return output


import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt

import statsmodels.api as sm

from sklearn.impute import KNNImputer
from sklearn.linear_model import LinearRegression
from sklearn.tree import DecisionTreeRegressor
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error, r2_score
from sklearn.preprocessing import StandardScaler, LabelEncoder

df = pd.read_csv('test_kaggle_1/Five_years_of_Russian_Rap_Dataset.csv')

label_encoder = LabelEncoder()

predict_columns = ['hit_n','Drums_Energy','Drums_Complexity',
                    'Variety_of_musical_instruments','Mixing_Quality',
                    'Harmonic_Richness','Mixing_Character','Emotional_Intensity',
                    'is_feat','n_feat','higher_guest','album_type','track_number',
                    'explicit','key_name','mode_name','key_mode','remake']

# print(df[predict_columns].head(5).T)

categoric_columns = []
for i in df.columns:
    if len(df[i].unique()) < 26:
        categoric_columns.append(i)

for col in df[categoric_columns]:
    df[col] = label_encoder.fit_transform(df[col])

X = df.drop(['track_id','artist_name','album_release_date',
             'status_guest','album_name','artists_all',
             'artist_id','album_id','download_link','Song_Success'], axis=1)
y = df[['Song_Success']]

# X_with_const = sm.add_constant(X)

# model = sm.OLS(y, X_with_const)
# results = model.fit()

# # print(results.summary())
# print(df[predict_columns].head(5).T)
# # print(df.dtypes)

X_train, X_test, y_train, y_test

model = DecisionTreeRegressor()  # Инициализация модели решающего дерева
model.fit(X_train, y_train)      # Обучение модели

y_pred = model.predict(X_test)   # Прогнозирование значений целевой переменной на тестовой выборке

mse = mean_squared_error(y_test, y_pred)
r2 = r2_score(y_test, y_pred)

print("Mean Squared Error (MSE):", mse)
print("R-squared (R²):", r2)

#determining the accuracy of the decision tree model
def decision_tree_accuracy(mse, r2):
    """
    Evaluates decision tree model performance and provides interpretation

    Args:
        mse: Mean squared error value
        r2: R-squared value

    Returns:
        str: Detailed interpretation of model performance
    """
    interpretation = "\nModel Performance Analysis:\n"

    # MSE interpretation
    interpretation += f"Mean Squared Error: {mse:.4f}\n"
    if mse < 0.1:
        interpretation += "- Very low prediction error, excellent accuracy\n"
    elif mse < 0.3:
        interpretation += "- Moderate prediction error, acceptable accuracy\n"
    else:
        interpretation += "- High prediction error, poor accuracy\n"

    # R2 interpretation
    interpretation += f"R-squared Score: {r2:.4f}\n"
    if r2 >= 0.7:
        interpretation += "- Model explains {:.1f}% of data variance\n".format(r2 * 100)
        interpretation += "- Strong predictive power, model is reliable\n"
    elif r2 >= 0.5:
        interpretation += "- Model explains {:.1f}% of data variance\n".format(r2 * 100)
        interpretation += "- Moderate predictive power, model may be useful but has limitations\n"
    else:
        interpretation += "- Model explains only {:.1f}% of data variance\n".format(r2 * 100)
        interpretation += "- Weak predictive power, model needs improvement\n"

    # Final verdict
    interpretation += "Verdict: \n"
    if r2 >= 0.6 and mse < 0.2:
        interpretation += "Model is suitable for use with good predictive capabilities\n"
    elif r2 >= 0.4 and mse < 0.3:
        interpretation += "Model can be used but with caution, consider improving\n"
    else:
        interpretation += "Model is not recommended for use, needs significant improvement\n"

    return interpretation

print(decision_tree_accuracy(mse, r2))

Instruction: необходимо разработать функцию, расчитывающую модель прогноировани, принимающую на вход размеченные данные X_train, X_test, y_train, y_test  и тип модели, и возвращующую информацию о выбранной моделе, коэффециенты, интерпретацию полученных данных

import pytest
import inspect
import numpy as np
import pandas as pd
from unittest.mock import patch, MagicMock
from sklearn.model_selection import train_test_split
import os

def create_mock_df():
    """Creates a mock DataFrame with standard structure for testing models."""
    X = pd.DataFrame({
        'Feature1': [1, 2, 3, 4, 5],
        'Feature2': [5, 4, 3, 2, 1],
        'Drums_Energy': [3, 4, 2, 3, 4],
        'Drums_Complexity': [2, 3, 4, 5, 2],
        'Mixing_Quality': [4, 3, 5, 4, 3],
        'Harmonic_Richness': [3, 5, 4, 3, 5],
        'Emotional_Intensity': [5, 4, 3, 2, 4],
        'is_feat': [1, 0, 1, 0, 1],
        'n_feat': [2, 0, 1, 0, 3],
        'album_type': [0, 1, 2, 0, 1],
        'track_number': [1, 3, 5, 2, 4],
        'explicit': [0, 1, 0, 1, 0],
        'key_name': [1, 2, 3, 4, 5],
        'mode_name': [0, 1, 0, 1, 0],
        'key_mode': [1, 3, 3, 5, 5],
        'remake': [0, 0, 1, 0, 1],
        'track_id': [1, 2, 3, 4, 5],
        'artist_name': ['A', 'B', 'C', 'D', 'E'],
        'album_release_date': ['2020-01-01', '2021-02-02', '2022-03-03', '2023-04-04', '2024-05-05'],
        'status_guest': [0, 1, 0, 1, 0],
        'album_name': ['Album1', 'Album2', 'Album3', 'Album4', 'Album5'],
        'artists_all': ['Artist1', 'Artist2', 'Artist3', 'Artist4', 'Artist5'],
        'artist_id': ['ID1', 'ID2', 'ID3', 'ID4', 'ID5'],
        'album_id': ['AID1', 'AID2', 'AID3', 'AID4', 'AID5'],
        'download_link': ['link1', 'link2', 'link3', 'link4', 'link5'],
        'Song_Success': [1, 0, 1, 0, 1],
    })
    y = pd.Series([1, 2, 3, 4, 5])

    return X, y

def get_top_level_functions(mod):
    return {
        name for name in dir(mod)
        if not name.startswith("__") and callable(getattr(mod, name))
    }

def load_original_module():
    path = os.path.join(os.path.dirname(__file__), "original_code.py")
    with open(path, "r", encoding="utf-8") as f:
        source = f.read()

    import ast, types
    module_ast = ast.parse(source, filename=path)
    original_module = types.ModuleType("original_code")

    for node in module_ast.body:
        if isinstance(node, (ast.FunctionDef, ast.Import, ast.ImportFrom, ast.ClassDef)):
            code_obj = compile(ast.Module([node], type_ignores=[]), filename=path, mode="exec")
            exec(code_obj, original_module.__dict__)

    return original_module

@patch('pandas.read_csv')
def test_new_function_exists(mock_read_csv, implementation):
    mock_read_csv.return_value = create_mock_df()[0]  # Use X only

    impl_name, module = implementation
    baseline_module = load_original_module()

    baseline_funcs = get_top_level_functions(baseline_module)
    current_funcs = get_top_level_functions(module)

    new_funcs = current_funcs - baseline_funcs

    if len(new_funcs) != 1:
        raise AssertionError(
            f"Expected exactly one new function, but found {len(new_funcs)}.\n"
            f"New functions: {sorted(new_funcs)}\n"
            f"All current functions: {sorted(current_funcs)}\n"
            f"All baseline functions: {sorted(baseline_funcs)}"
        )

    new_func_name = list(new_funcs)[0]
    new_func = getattr(module, new_func_name)
    assert callable(new_func), f"The new function {new_func_name} is not callable."

def find_new_function(module, baseline_module):
    def get_top_level_functions(mod):
        return {
            name for name in dir(mod)
            if not name.startswith("__") and callable(getattr(mod, name))
        }

    baseline_funcs = get_top_level_functions(baseline_module)
    current_funcs = get_top_level_functions(module)

    new_funcs = current_funcs - baseline_funcs

    if len(new_funcs) != 1:
        raise AssertionError(
            f"Expected exactly one new function, but found {len(new_funcs)}.\n"
            f"New functions: {sorted(new_funcs)}\n"
            f"All current functions: {sorted(current_funcs)}\n"
            f"All baseline functions: {sorted(baseline_funcs)}"
        )

    new_func_name = new_funcs.pop()
    return getattr(module, new_func_name)

@patch('pandas.read_csv')
def test_model_evaluation_capability(mock_read_csv, implementation):
    """Test that the implementation can evaluate a predictive model."""
    # Unpack implementation
    impl_name, module = implementation

    # Create mock DataFrame
    X, y = create_mock_df()
    mock_df = pd.DataFrame(X)
    mock_df['Song_Success'] = y
    mock_read_csv.return_value = mock_df

    # Load baseline (safely) and get the new function
    baseline_module = load_original_module()
    model_func = find_new_function(module, baseline_module)

    # Try to introspect the parameters
    try:
        sig = inspect.signature(model_func)
        param_names = list(sig.parameters.keys())
    except (ValueError, TypeError):
        param_names = []

    # Prepare train/test split
    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.4, random_state=42)

    # Define fallback decision_tree_accuracy if needed
    def mock_decision_tree_accuracy(mse, r2):
        return f"MSE: {mse}, R2: {r2}"

    decision_tree_accuracy = getattr(module, 'decision_tree_accuracy', mock_decision_tree_accuracy)

    # Patch model + metric utils
    with patch('sklearn.model_selection.train_test_split', return_value=(X_train, X_test, y_train, y_test)), \
         patch('sklearn.linear_model.LinearRegression') as mock_lr, \
         patch('sklearn.tree.DecisionTreeRegressor') as mock_dt, \
         patch('sklearn.metrics.mean_squared_error', return_value=0.5), \
         patch('sklearn.metrics.r2_score', return_value=0.8):

        # Set up mock model
        mock_model = MagicMock()
        mock_model.predict.return_value = np.array([1, 2, 3])
        mock_model.fit.return_value = mock_model
        mock_lr.return_value = mock_model
        mock_dt.return_value = mock_model
        mock_lr.return_value.coef_ = np.array([0.1, 0.2, 0.3])
        mock_lr.return_value.intercept_ = 0.5
        mock_dt.return_value.feature_importances_ = np.array([0.3, 0.4, 0.3])

        # Call the function intelligently
        is_valid_function = len(param_names) == 5 \
            and param_names[:4] == ['X_train', 'X_test', 'y_train', 'y_test'] \
            and 'model' in param_names[4].lower()
        assert(is_valid_function, f"Function in {impl_name} does not have the expected signature.")
        result = model_func(X_train, X_test, y_train, y_test, model_type="LinearRegression")

    # Check that something was returned
    assert result is not None, f"Function in {impl_name} returned None"

    # Must return a 4-tuple or 4-list or 4-dict
    is_valid_shape = (
        isinstance(result, (tuple, list)) and len(result) == 4
    ) or (
        isinstance(result, dict) and len(result.keys()) == 4
    )

    assert is_valid_shape, (
        f"Expected function to return a tuple/list or dict with 4 items (selected model, coefficients, and interpretation of the obtained data), "
        f"but got type={type(result)} and len={len(result) if hasattr(result, '__len__') else 'N/A'}"
    )

numpy
pandas
pytest
pytest-mock
scikit-learn
matplotlib
seaborn
statsmodels

import pytest
import os
import sys
import json
from typing import Dict, List, Optional, Any

# Import from local test_utils.py in the same directory
from test_utils import TestUtils, TestResultsManager

# Load all implementations in the current sandbox
implementations = TestUtils.load_all_implementations()
test_results = TestResultsManager()

@pytest.fixture(scope="session")
def sandbox_dir():
    """Fixture to provide the sandbox directory path."""
    return os.path.dirname(os.path.abspath(__file__))

@pytest.fixture(scope="session")
def sandbox_name():
    """Fixture to provide the sandbox name."""
    return os.path.basename(os.path.dirname(os.path.abspath(__file__)))

@pytest.fixture(scope="session")
def all_implementations():
    """Fixture to provide all implementations as a dictionary."""
    return implementations

@pytest.fixture(params=list(implementations.items()))
def implementation(request):
    """Fixture to provide each implementation to tests one at a time."""
    return request.param

@pytest.fixture(scope="session")
def results_manager():
    """Fixture to provide access to the test results manager."""
    return test_results

# Hook for collecting test results
@pytest.hookimpl(tryfirst=True, hookwrapper=True)
def pytest_runtest_makereport(item, call):
    """Pytest hook to collect test results."""
    # Execute all other hooks to obtain the report object
    outcome = yield
    rep = outcome.get_result()

    # We're only interested in the call outcome
    if rep.when == "call":
        if hasattr(item, "callspec") and "implementation" in item.callspec.params:
            # Get implementation name and module
            impl_name, _ = item.callspec.params["implementation"]

            # Get test name
            test_name = item.nodeid.split("::")[-1]

            # Record result
            if rep.passed:
                test_results.record_result(impl_name, test_name, True)
            elif rep.failed:
                error_msg = str(rep.longrepr) if rep.longrepr else "Test failed"
                test_results.record_result(impl_name, test_name, False, error_msg)
            elif rep.skipped:
                skip_reason = rep.longrepr[2] if rep.longrepr else "Test skipped"
                test_results.record_skip(impl_name, test_name, skip_reason)

# Hook to save results at the end of testing
@pytest.hookimpl(trylast=True)
def pytest_sessionfinish(session, exitstatus):
    """Save test results at the end of the test session."""
    test_results.save_results()

import os
import sys
import glob
import re
import importlib.util
import traceback
import types
from typing import Dict, List, Optional, Any, Tuple

class TestUtils:
    @staticmethod
    def discover_implementation_files(directory: str = None) -> List[str]:
        """Find all implementation files in the current sandbox directory."""
        if directory is None:
            directory = os.path.dirname(os.path.abspath(__file__))

        patterns = [
            r'modified_code\d+\.py',
            r'new_code\d+\.py',
            # r'original_code\.py',
            r'implementation\d*\.py'
        ]

        pattern = re.compile('|'.join(f'({p})' for p in patterns))
        implementations = []

        for file_path in glob.glob(os.path.join(directory, '*.py')):
            if pattern.search(os.path.basename(file_path)):
                implementations.append(file_path)

        # Sort files numerically
        def sort_key(path):
            filename = os.path.basename(path)
            match = re.search(r'(\d+)', filename)
            return int(match.group(1)) if match else 0

        return sorted(implementations, key=sort_key)

    @staticmethod
    def create_mock_module(file_path: str, module_name: str, error_info: str) -> types.ModuleType:
        """Create a mock module that contains error information but can still be tested."""
        # Create a new module object
        mock_module = types.ModuleType(module_name)

        # Add basic attributes
        mock_module.__file__ = file_path
        mock_module.__name__ = module_name
        mock_module.__display_name__ = module_name
        mock_module.__error__ = error_info

        # Add a dummy function that can be detected by test functions
        def dummy_function(*args, **kwargs):
            return f"Error in module: {error_info}"

        setattr(mock_module, "implementation_error", dummy_function)

        return mock_module

    @staticmethod
    def load_module(file_path: str, module_name: Optional[str] = None) -> Any:
        """
        Safely load a module from a file path with proper error handling.
        If the module has errors, return a mock module that can still be tested.
        """
        if module_name is None:
            module_name = os.path.basename(file_path).replace('.py', '')

        # Create a unique module name to avoid conflicts
        sandbox_id = os.path.basename(os.path.dirname(file_path))
        unique_module_name = f"{sandbox_id}_{module_name}"

        try:
            # First, try to read the file to check for syntax errors
            with open(file_path, 'r') as f:
                source_code = f.read()

            # Check for syntax errors by compiling the code
            try:
                compiled = compile(source_code, file_path, 'exec')
            except SyntaxError as e:
                error_msg = f"Syntax error: {str(e)}"
                print(f"Syntax error in {file_path}: {e}")
                print(f"  Line {e.lineno}, column {e.offset}: {e.text}")
                return TestUtils.create_mock_module(file_path, unique_module_name, error_msg)

            # Create the module spec
            spec = importlib.util.spec_from_file_location(unique_module_name, file_path)
            if spec is None or spec.loader is None:
                error_msg = f"Could not create spec for {file_path}"
                print(f"Error: {error_msg}")
                return TestUtils.create_mock_module(file_path, unique_module_name, error_msg)

            # Create the module object
            module = importlib.util.module_from_spec(spec)
            sys.modules[unique_module_name] = module

            # Special handling for execution errors
            try:
                # Execute the module code in a safe way
                spec.loader.exec_module(module)
                # Store the original name for reference
                module.__display_name__ = module_name
                return module
            except Exception as e:
                error_msg = f"Runtime error: {str(e)}"
                traceback_str = traceback.format_exc()
                print(f"Error executing module {file_path}: {e}")
                print(traceback_str)

                # Create a partial module that contains what we loaded before the error
                mock_module = TestUtils.create_mock_module(file_path, unique_module_name, error_msg)

                # Copy any attributes that might have been defined before the error
                for attr_name in dir(module):
                    if not attr_name.startswith('__'):
                        try:
                            setattr(mock_module, attr_name, getattr(module, attr_name))
                        except Exception:
                            pass  # Skip attributes that can't be copied

                return mock_module

        except FileNotFoundError as e:
            error_msg = f"File not found: {str(e)}"
            print(f"Error: {error_msg}")
            return TestUtils.create_mock_module(file_path, unique_module_name, error_msg)
        except Exception as e:
            error_msg = f"Unexpected error: {str(e)}"
            print(f"Error loading module {file_path}: {e}")
            return TestUtils.create_mock_module(file_path, unique_module_name, error_msg)

    @classmethod
    def load_all_implementations(cls, directory: str = None) -> Dict[str, Any]:
        """Load all implementation files in the directory, including those with errors."""
        if directory is None:
            directory = os.path.dirname(os.path.abspath(__file__))

        implementations = {}

        implementation_files = cls.discover_implementation_files(directory)
        if not implementation_files:
            print("WARNING: No implementation files found. Check your file naming patterns.")

        for file_path in implementation_files:
            module_name = os.path.basename(file_path).replace('.py', '')
            module = cls.load_module(file_path, module_name)

            # Always add the module, even if it has errors
            implementations[module_name] = module

            if hasattr(module, '__error__'):
                print(f"Loaded with errors: {module_name} - {module.__error__}")
            else:
                print(f"Successfully loaded: {module_name}")

        return implementations

class TestResultsManager:
    def __init__(self):
        self.results = {}
        self.sandbox_name = os.path.basename(os.path.dirname(os.path.abspath(__file__)))

    def record_result(self, impl_name: str, test_name: str, passed: bool,
                     error_msg: Optional[str] = None) -> None:
        """Record a test result for an implementation."""
        if impl_name not in self.results:
            self.results[impl_name] = {"passed": 0, "failed": 0, "skipped": 0, "errors": []}

        if passed:
            self.results[impl_name]["passed"] += 1
        else:
            self.results[impl_name]["failed"] += 1
            if error_msg:
                self.results[impl_name]["errors"].append({
                    "test": test_name,
                    "error": error_msg
                })

    def record_skip(self, impl_name: str, test_name: str,
                   reason: Optional[str] = None) -> None:
        """Record a skipped test for an implementation."""
        if impl_name not in self.results:
            self.results[impl_name] = {"passed": 0, "failed": 0, "skipped": 0, "errors": []}

        self.results[impl_name]["skipped"] += 1
        if reason:
            self.results[impl_name]["errors"].append({
                "test": test_name,
                "error": f"SKIPPED: {reason}"
            })

    def get_winner(self) -> Tuple[Optional[int], Dict]:
        """Determine the winner based on test results."""
        winner = None
        max_passed = -1

        for impl_name, results in self.results.items():
            if impl_name == "original_code":
                continue  # Skip original code when determining winner

            if results["passed"] > max_passed:
                max_passed = results["passed"]
                winner = impl_name
            # Break ties by looking at failure count
            elif results["passed"] == max_passed and winner is not None:
                if results["failed"] < self.results[winner]["failed"]:
                    winner = impl_name

        # Convert winner to numeric index if possible
        winner_index = -1
        if winner and re.match(r'modified_code\d+', winner):
            try:
                winner_index = int(re.search(r'(\d+)', winner).group(1))
            except (AttributeError, ValueError):
                pass

        return winner_index, self.results

    def save_results(self, filename: str = "test_results.json") -> None:
        """Save test results to a JSON file."""
        import json

        winner_index, results = self.get_winner()

        # Check if all tests were skipped
        all_skipped = all(
            stats["skipped"] == stats["passed"] + stats["failed"] + stats["skipped"]
            for impl_name, stats in results.items()
            if impl_name != "original_code"
        )

        output = {
            "winner": winner_index,
            "all_skipped": all_skipped,
            "results": {
                name: {
                    "passed": stats["passed"],
                    "failed": stats["failed"],
                    "skipped": stats["skipped"],
                    "total": stats["passed"] + stats["failed"] + stats["skipped"]
                }
                for name, stats in results.items()
                if not name.startswith("_")  # Skip internal items
            }
        }

        with open(filename, "w") as f:
            json.dump(output, f, indent=2)

        print(f"Test results saved to {filename}")

        return output


from rest_framework import viewsets

from opticalprobeapp.serializers import MeasurementSerializer, ProbeTypeSerializer, ProbeSerializer
from opticalprobeapp.models import Measurement, Probe, ProbeType

# Create your views here.

class ProbeTypeViewSet(viewsets.ModelViewSet):
    queryset = ProbeType.objects.all()
    serializer_class = ProbeTypeSerializer

class ProbeViewSet(viewsets.ModelViewSet):
    queryset = Probe.objects.all()
    serializer_class = ProbeSerializer

class MeasurementViewSet(viewsets.ModelViewSet):
    queryset = Measurement.objects.all()
    serializer_class = MeasurementSerializer

# сделай фильтр для MeasurementViewSet
class MeasurmentFilter

Instruction: # сделай фильтр для MeasurementViewSet class MeasurmentFilter

import pytest
import inspect
import re
import os
import ast
from unittest.mock import MagicMock, patch
import importlib
import sys
import json

# Configure Django settings before importing Django components
import django
from django.conf import settings
settings.configure(
    DEBUG=True,
    REST_FRAMEWORK={},
    INSTALLED_APPS=['rest_framework']
)
django.setup()

# Mock Django models and related components
class MockModel:
    objects = MagicMock()

    class Meta:
        model = None

# Mock the necessary Django modules and classes
sys.modules['rest_framework'] = MagicMock()
sys.modules['rest_framework.viewsets'] = MagicMock()
sys.modules['rest_framework.filters'] = MagicMock()
sys.modules['django_filters'] = MagicMock()
sys.modules['django_filters.rest_framework'] = MagicMock()
sys.modules['opticalprobeapp.serializers'] = MagicMock()
sys.modules['opticalprobeapp.models'] = MagicMock()

# Mock model classes
class MockMeasurement(MockModel):
    pass

class MockProbe(MockModel):
    pass

class MockProbeType(MockModel):
    pass

# Set up mocks for models
sys.modules['opticalprobeapp.models'].Measurement = MockMeasurement
sys.modules['opticalprobeapp.models'].Probe = MockProbe
sys.modules['opticalprobeapp.models'].ProbeType = MockProbeType

def get_source_code(module):
    """Get the source code of a module."""
    try:
        return inspect.getsource(module)
    except (TypeError, OSError):
        # If we can't get the source directly, try another approach
        module_path = getattr(module, '__file__', None)
        if module_path and os.path.exists(module_path):
            with open(module_path, 'r') as f:
                return f.read()
        return ""

def test_filter_implementation_exists(implementation):
    """Test that a dedicated MeasurementFilter class exists."""
    impl_name, module = implementation
    source = get_source_code(module)

    # Only look for a dedicated filter class - require this approach
    filter_class_pattern = r'class\s+\w*Measur\w*Filter'
    filter_class_exists = re.search(filter_class_pattern, source, re.IGNORECASE) is not None

    assert filter_class_exists, f"No dedicated MeasurementFilter class found in {impl_name}. " \
                               f"A dedicated filter class is required for this implementation."

    # Check that the filter class is properly defined
    filter_class_match = re.search(r'class\s+(\w*Measur\w*Filter)', source, re.IGNORECASE)
    filter_class_name = filter_class_match.group(1)

def test_dedicated_filter_class_if_present(implementation):
    """Test the properties of a dedicated filter class if one exists."""
    impl_name, module = implementation
    source = get_source_code(module)

    # Check if a dedicated filter class exists
    filter_class_match = re.search(r'class\s+(\w*Measur\w*Filter)', source, re.IGNORECASE)

    assert filter_class_match, f"No dedicated filter class found in {impl_name}. A dedicated filter class is required."

    filter_class_name = filter_class_match.group(1)
    filter_class_pattern = fr'class\s+{filter_class_name}.*?(?=class|\Z)'
    filter_class_def = re.search(filter_class_pattern, source, re.DOTALL)
    assert filter_class_def, f"Could not extract filter class definition in {impl_name}"

    filter_class_code = filter_class_def.group(0)

    # Enhanced pattern detection for filter-related base classes
    # Check for inheritance from classes with 'filter' in the name using multiple approaches

    # Direct filter class inheritance pattern
    filter_parent_patterns = [
        r'class\s+\w+\s*\(\s*\w*[fF]ilter\w*(?:[sS]et)?(?:Backend)?\w*\s*\)',
        r'class\s+\w+\s*\(\s*.*?filters\.\w+\s*\)',
        r'class\s+\w+\s*\(\s*.*?django_filters\.\w+\s*\)'
    ]

    has_filter_parent = any(re.search(pattern, filter_class_code) for pattern in filter_parent_patterns)

    # If direct pattern fails, use more lenient approach
    if not has_filter_parent:
        # Extract the parent class name
        parent_match = re.search(r'class\s+\w+\s*\(\s*(\w+)\s*\)', filter_class_code)
        if parent_match:
            parent_class = parent_match.group(1)
            # Consider it correct if 'filter' is in the parent class name (case insensitive)
            has_filter_parent = 'filter' in parent_class.lower()

            # Additional check: some devs might use 'FilterSet' or similar imports with different names
            if not has_filter_parent:
                # Look for imports that might alias filter classes
                filter_import_pattern = fr'from\s+.*?\s+import\s+.*?(?:{parent_class})'
                filter_import = re.search(filter_import_pattern, source)
                has_filter_parent = filter_import is not None

    assert has_filter_parent, f"Filter class in {impl_name} doesn't inherit from a filter-related class"

    # Check for Meta class (it's required for Django filter classes)
    has_meta = re.search(r'class\s+Meta\s*:', filter_class_code, re.IGNORECASE)
    assert has_meta, f"Filter class in {impl_name} doesn't have a Meta class"

    # Check for model specification in a more flexible way
    meta_section = re.search(r'class\s+Meta\s*:.*?(?=\n\S|\Z)', filter_class_code, re.DOTALL)
    if meta_section:
        meta_code = meta_section.group(0)
        has_model = re.search(r'model\s*=', meta_code) is not None
    else:
        has_model = re.search(r'model\s*=', filter_class_code) is not None

    assert has_model, f"Filter class Meta in {impl_name} doesn't specify a model"

    # Check for fields specification more thoroughly
    fields_patterns = [
        r'fields\s*=',
        r'field_name\s*=',
        r'lookup_expr\s*='
    ]

    has_fields = any(re.search(pattern, filter_class_code) for pattern in fields_patterns)

    # Check if filter methods or fields are defined as class attributes
    if not has_fields:
        # Look for filter method definitions
        has_fields = re.search(r'def\s+filter_', filter_class_code) is not None

        # Look for typical filter field declarations
        if not has_fields:
            filter_field_patterns = [
                r'\w+\s*=\s*\w*[fF]ilter\w*\(',
                r'\w+\s*=\s*filters\.\w+',
                r'\w+\s*=\s*django_filters\.\w+'
            ]
            has_fields = any(re.search(pattern, filter_class_code) for pattern in filter_field_patterns)

    assert has_fields, f"Filter class in {impl_name} doesn't specify fields or filter methods"

pytest
pytest-mock
django
djangorestframework
django-filter

import pytest
import os
import sys
import json
from typing import Dict, List, Optional, Any

# Import from local test_utils.py in the same directory
from test_utils import TestUtils, TestResultsManager

# Load all implementations in the current sandbox
implementations = TestUtils.load_all_implementations()
test_results = TestResultsManager()

@pytest.fixture(scope="session")
def sandbox_dir():
    """Fixture to provide the sandbox directory path."""
    return os.path.dirname(os.path.abspath(__file__))

@pytest.fixture(scope="session")
def sandbox_name():
    """Fixture to provide the sandbox name."""
    return os.path.basename(os.path.dirname(os.path.abspath(__file__)))

@pytest.fixture(scope="session")
def all_implementations():
    """Fixture to provide all implementations as a dictionary."""
    return implementations

@pytest.fixture(params=list(implementations.items()))
def implementation(request):
    """Fixture to provide each implementation to tests one at a time."""
    return request.param

@pytest.fixture(scope="session")
def results_manager():
    """Fixture to provide access to the test results manager."""
    return test_results

# Hook for collecting test results
@pytest.hookimpl(tryfirst=True, hookwrapper=True)
def pytest_runtest_makereport(item, call):
    """Pytest hook to collect test results."""
    # Execute all other hooks to obtain the report object
    outcome = yield
    rep = outcome.get_result()

    # We're only interested in the call outcome
    if rep.when == "call":
        if hasattr(item, "callspec") and "implementation" in item.callspec.params:
            # Get implementation name and module
            impl_name, _ = item.callspec.params["implementation"]

            # Get test name
            test_name = item.nodeid.split("::")[-1]

            # Record result
            if rep.passed:
                test_results.record_result(impl_name, test_name, True)
            elif rep.failed:
                error_msg = str(rep.longrepr) if rep.longrepr else "Test failed"
                test_results.record_result(impl_name, test_name, False, error_msg)
            elif rep.skipped:
                skip_reason = rep.longrepr[2] if rep.longrepr else "Test skipped"
                test_results.record_skip(impl_name, test_name, skip_reason)

# Hook to save results at the end of testing
@pytest.hookimpl(trylast=True)
def pytest_sessionfinish(session, exitstatus):
    """Save test results at the end of the test session."""
    test_results.save_results()

import os
import sys
import glob
import re
import importlib.util
import traceback
import types
from typing import Dict, List, Optional, Any, Tuple

class TestUtils:
    @staticmethod
    def discover_implementation_files(directory: str = None) -> List[str]:
        """Find all implementation files in the current sandbox directory."""
        if directory is None:
            directory = os.path.dirname(os.path.abspath(__file__))

        patterns = [
            r'modified_code\d+\.py',
            r'new_code\d+\.py',
            # r'original_code\.py',
            r'implementation\d*\.py'
        ]

        pattern = re.compile('|'.join(f'({p})' for p in patterns))
        implementations = []

        for file_path in glob.glob(os.path.join(directory, '*.py')):
            if pattern.search(os.path.basename(file_path)):
                implementations.append(file_path)

        # Sort files numerically
        def sort_key(path):
            filename = os.path.basename(path)
            match = re.search(r'(\d+)', filename)
            return int(match.group(1)) if match else 0

        return sorted(implementations, key=sort_key)

    @staticmethod
    def create_mock_module(file_path: str, module_name: str, error_info: str) -> types.ModuleType:
        """Create a mock module that contains error information but can still be tested."""
        # Create a new module object
        mock_module = types.ModuleType(module_name)

        # Add basic attributes
        mock_module.__file__ = file_path
        mock_module.__name__ = module_name
        mock_module.__display_name__ = module_name
        mock_module.__error__ = error_info

        # Add a dummy function that can be detected by test functions
        def dummy_function(*args, **kwargs):
            return f"Error in module: {error_info}"

        setattr(mock_module, "implementation_error", dummy_function)

        return mock_module

    @staticmethod
    def load_module(file_path: str, module_name: Optional[str] = None) -> Any:
        """
        Safely load a module from a file path with proper error handling.
        If the module has errors, return a mock module that can still be tested.
        """
        if module_name is None:
            module_name = os.path.basename(file_path).replace('.py', '')

        # Create a unique module name to avoid conflicts
        sandbox_id = os.path.basename(os.path.dirname(file_path))
        unique_module_name = f"{sandbox_id}_{module_name}"

        try:
            # First, try to read the file to check for syntax errors
            with open(file_path, 'r') as f:
                source_code = f.read()

            # Check for syntax errors by compiling the code
            try:
                compiled = compile(source_code, file_path, 'exec')
            except SyntaxError as e:
                error_msg = f"Syntax error: {str(e)}"
                print(f"Syntax error in {file_path}: {e}")
                print(f"  Line {e.lineno}, column {e.offset}: {e.text}")
                return TestUtils.create_mock_module(file_path, unique_module_name, error_msg)

            # Create the module spec
            spec = importlib.util.spec_from_file_location(unique_module_name, file_path)
            if spec is None or spec.loader is None:
                error_msg = f"Could not create spec for {file_path}"
                print(f"Error: {error_msg}")
                return TestUtils.create_mock_module(file_path, unique_module_name, error_msg)

            # Create the module object
            module = importlib.util.module_from_spec(spec)
            sys.modules[unique_module_name] = module

            # Special handling for execution errors
            try:
                # Execute the module code in a safe way
                spec.loader.exec_module(module)
                # Store the original name for reference
                module.__display_name__ = module_name
                return module
            except Exception as e:
                error_msg = f"Runtime error: {str(e)}"
                traceback_str = traceback.format_exc()
                print(f"Error executing module {file_path}: {e}")
                print(traceback_str)

                # Create a partial module that contains what we loaded before the error
                mock_module = TestUtils.create_mock_module(file_path, unique_module_name, error_msg)

                # Copy any attributes that might have been defined before the error
                for attr_name in dir(module):
                    if not attr_name.startswith('__'):
                        try:
                            setattr(mock_module, attr_name, getattr(module, attr_name))
                        except Exception:
                            pass  # Skip attributes that can't be copied

                return mock_module

        except FileNotFoundError as e:
            error_msg = f"File not found: {str(e)}"
            print(f"Error: {error_msg}")
            return TestUtils.create_mock_module(file_path, unique_module_name, error_msg)
        except Exception as e:
            error_msg = f"Unexpected error: {str(e)}"
            print(f"Error loading module {file_path}: {e}")
            return TestUtils.create_mock_module(file_path, unique_module_name, error_msg)

    @classmethod
    def load_all_implementations(cls, directory: str = None) -> Dict[str, Any]:
        """Load all implementation files in the directory, including those with errors."""
        if directory is None:
            directory = os.path.dirname(os.path.abspath(__file__))

        implementations = {}

        implementation_files = cls.discover_implementation_files(directory)
        if not implementation_files:
            print("WARNING: No implementation files found. Check your file naming patterns.")

        for file_path in implementation_files:
            module_name = os.path.basename(file_path).replace('.py', '')
            module = cls.load_module(file_path, module_name)

            # Always add the module, even if it has errors
            implementations[module_name] = module

            if hasattr(module, '__error__'):
                print(f"Loaded with errors: {module_name} - {module.__error__}")
            else:
                print(f"Successfully loaded: {module_name}")

        return implementations

class TestResultsManager:
    def __init__(self):
        self.results = {}
        self.sandbox_name = os.path.basename(os.path.dirname(os.path.abspath(__file__)))

    def record_result(self, impl_name: str, test_name: str, passed: bool,
                     error_msg: Optional[str] = None) -> None:
        """Record a test result for an implementation."""
        if impl_name not in self.results:
            self.results[impl_name] = {"passed": 0, "failed": 0, "skipped": 0, "errors": []}

        if passed:
            self.results[impl_name]["passed"] += 1
        else:
            self.results[impl_name]["failed"] += 1
            if error_msg:
                self.results[impl_name]["errors"].append({
                    "test": test_name,
                    "error": error_msg
                })

    def record_skip(self, impl_name: str, test_name: str,
                   reason: Optional[str] = None) -> None:
        """Record a skipped test for an implementation."""
        if impl_name not in self.results:
            self.results[impl_name] = {"passed": 0, "failed": 0, "skipped": 0, "errors": []}

        self.results[impl_name]["skipped"] += 1
        if reason:
            self.results[impl_name]["errors"].append({
                "test": test_name,
                "error": f"SKIPPED: {reason}"
            })

    def get_winner(self) -> Tuple[Optional[int], Dict]:
        """Determine the winner based on test results."""
        winner = None
        max_passed = -1

        for impl_name, results in self.results.items():
            if impl_name == "original_code":
                continue  # Skip original code when determining winner

            if results["passed"] > max_passed:
                max_passed = results["passed"]
                winner = impl_name
            # Break ties by looking at failure count
            elif results["passed"] == max_passed and winner is not None:
                if results["failed"] < self.results[winner]["failed"]:
                    winner = impl_name

        # Convert winner to numeric index if possible
        winner_index = -1
        if winner and re.match(r'modified_code\d+', winner):
            try:
                winner_index = int(re.search(r'(\d+)', winner).group(1))
            except (AttributeError, ValueError):
                pass

        return winner_index, self.results

    def save_results(self, filename: str = "test_results.json") -> None:
        """Save test results to a JSON file."""
        import json

        winner_index, results = self.get_winner()

        # Check if all tests were skipped
        all_skipped = all(
            stats["skipped"] == stats["passed"] + stats["failed"] + stats["skipped"]
            for impl_name, stats in results.items()
            if impl_name != "original_code"
        )

        output = {
            "winner": winner_index,
            "all_skipped": all_skipped,
            "results": {
                name: {
                    "passed": stats["passed"],
                    "failed": stats["failed"],
                    "skipped": stats["skipped"],
                    "total": stats["passed"] + stats["failed"] + stats["skipped"]
                }
                for name, stats in results.items()
                if not name.startswith("_")  # Skip internal items
            }
        }

        with open(filename, "w") as f:
            json.dump(output, f, indent=2)

        print(f"Test results saved to {filename}")

        return output


from sklearn.cluster import KMeans
from sklearn.metrics import silhouette_score

def cluster_data(features_transformed, cluster_feature_name, n_clusters=2, clustering_method='kmeans'):
    """
    Выполняет кластеризацию данных.

    Args:
        features_transformed (pandas.DataFrame): Преобразованный DataFrame с параметрами.
        cluster_feature_name (str): Имя столбца, в который будут записаны метки кластеров.
        n_clusters (int): Количество кластеров.
        clustering_method (str): Метод кластеризации ('kmeans').

    Returns:
        pandas.DataFrame: DataFrame с добавленным столбцом меток кластеров.
    """
    if features_transformed is None:
        print("Сначала выполните преобразование данных (этап 5).")
        return None

    features_for_clustering = features_transformed.copy()

    if clustering_method == 'kmeans':
        model = KMeans(n_clusters=n_clusters, random_state=42, n_init=10)
        cluster_labels = model.fit_predict(features_for_clustering)

        # Оценка качества кластеризации (например, с помощью коэффициента силуэта)
        if len(np.unique(cluster_labels)) > 1: # Проверка на случай, когда все точки отнесены к одному кластеру
            silhouette_avg = silhouette_score(features_for_clustering, cluster_labels)
            print(f"Коэффициент силуэта для {n_clusters} кластеров: {silhouette_avg:.4f}")
        else:
            print(f"Невозможно рассчитать коэффициент силуэта для {n_clusters} кластера (все точки в одном кластере).")

    else:
        print("Неподдерживаемый метод кластеризации.")
        return None

    features_transformed[cluster_feature_name] = cluster_labels
    print(f"Кластеризация выполнена. Метки кластеров добавлены в столбец '{cluster_feature_name}'.")
    return features_transformed

# Выполнение кластеризации (после этапа 5 и до этапа 6)
if 'features_transformed' in locals() and features_transformed is not None:
    cluster_feature_name = 'cluster'  # Имя столбца для меток кластеров
    n_clusters = 3  # Количество кластеров (подберите оптимальное значение)
    features_transformed = cluster_data(features_transformed, cluster_feature_name, n_clusters)

    # Визуализация кластеров (пример для случая, когда есть 2 числовых признака)
    numerical_features = features_transformed.select_dtypes(include=np.number)
    if numerical_features.shape[1] >= 2:
        plt.figure(figsize=(8, 6))
        plt.scatter(numerical_features.iloc[:, 0], numerical_features.iloc[:, 1], c=features_transformed[cluster_feature_name], cmap='viridis')
        plt.xlabel(numerical_features.columns[0])
        plt.ylabel(numerical_features.columns[1])
        plt.title('Результаты кластеризации')
        plt.colorbar(label='Номер кластера')
        plt.show()
    else:
        print("Недостаточно числовых признаков для визуализации кластеров на плоскости.")
else:
    print("Сначала выполните этап 5 (Преобразование данных).")

Instruction: Давай сделаем так, чтобы кластеризация проводилась независимо для указанных наборов столбцов, допустим если я передаю список вида {Кластер1: (столбец1, столбец2), Кластер2: (столбец3)}, значит я хочу, чтобы процедура кластеризации проводилась отдельно для пары первых столбцов и третьего столбца. Там же задаются имена новых колонок как ключи словаря.

import pytest
import pandas as pd
import numpy as np
from unittest.mock import patch, Mock
from sklearn.metrics import silhouette_score
from sklearn.cluster import KMeans

def test_function_signature(implementation):
    """Test that the function signature accepts a dictionary for cluster columns"""
    impl_name, module = implementation

    # Get the cluster_data function from the module
    function = getattr(module, "cluster_data")

    # Create a sample dataframe and clustering dict
    df = pd.DataFrame({'feature1': [1, 2, 3, 4, 5], 'feature2': [3, 4, 5, 6, 7]})
    clustering_dict = {'cluster1': ('feature1', 'feature2')}

    # Create a KMeans mock that returns predictable cluster labels
    kmeans_instance = Mock()
    kmeans_instance.fit_predict.return_value = np.array([0, 1, 0, 1, 2])
    # Also handle separate fit and predict calls
    kmeans_instance.fit.return_value = kmeans_instance
    kmeans_instance.predict.return_value = np.array([0, 1, 0, 1, 2])
    kmeans_mock = Mock(return_value=kmeans_instance)

    # Set up mock for numpy
    mock_np = Mock()
    mock_np.unique.return_value = np.array([0, 1, 2])
    mock_np.array = np.array

    with patch.dict('sys.modules', {'numpy': mock_np, 'np': mock_np}):
        # Patch sklearn.cluster.KMeans and silhouette_score directly
        with patch('sklearn.cluster.KMeans', kmeans_mock):
            with patch('sklearn.metrics.silhouette_score', return_value=0.75):
                # Suppress print statements during test
                with patch('builtins.print'):
                    # Try to call the function with the dictionary-based signature
                    try:
                        result = function(df, clustering_dict)
                        # If it gets here, the function accepts the dictionary
                        assert True
                    except Exception as e:
                        # Try to handle common implementation issues
                        if 'np' in str(e) and 'not defined' in str(e):
                            # If numpy is not imported in the module, patch it directly in the globals
                            with patch.object(module, 'np', mock_np):
                                try:
                                    result = function(df, clustering_dict)
                                    assert True
                                except Exception as e2:
                                    pytest.fail(f"Implementation {impl_name} does not accept dictionary format: {str(e2)}")
                        else:
                            pytest.fail(f"Implementation {impl_name} does not accept dictionary format: {str(e)}")

def test_clustering_with_dict(implementation):
    """Test that the function correctly processes a dictionary of column sets for clustering"""
    impl_name, module = implementation

    # Create a sample dataframe for testing
    df = pd.DataFrame({
        'feature1': np.random.rand(10),
        'feature2': np.random.rand(10),
        'feature3': np.random.rand(10),
    })

    # Create a clustering dictionary as per requirements
    clustering_dict = {
        'cluster1': ('feature1', 'feature2'),
        'cluster2': ('feature3',)
    }

    # Create specific mock data for clustering operations
    cluster1_data = np.array([0, 1, 0, 1, 0, 1, 0, 1, 0, 1])
    cluster2_data = np.array([1, 0, 1, 0, 1, 0, 1, 0, 1, 0])

    # Mock KMeans and silhouette_score
    kmeans_instance = Mock()
    kmeans_instance.fit_predict.side_effect = [cluster1_data, cluster2_data]
    # Also handle separate fit and predict calls
    kmeans_instance.fit.return_value = kmeans_instance
    kmeans_instance.predict.side_effect = [cluster1_data, cluster2_data]
    kmeans_mock = Mock(return_value=kmeans_instance)

    # Mock for numpy
    mock_np = Mock()
    mock_np.unique.return_value = np.array([0, 1])
    mock_np.array = np.array

    # Patch numpy for implementations that don't import it
    with patch.dict('sys.modules', {'numpy': mock_np, 'np': mock_np}):
        with patch('sklearn.cluster.KMeans', kmeans_mock):
            with patch('sklearn.metrics.silhouette_score', return_value=0.75):
                # Suppress print statements during test
                with patch('builtins.print'):
                    # Get the function reference
                    function = getattr(module, "cluster_data")

                    # Handle numpy not being imported in the module
                    try:
                        result_df = function(df, clustering_dict)
                    except NameError as e:
                        if 'np' in str(e) and 'not defined' in str(e):
                            # If numpy is not imported in the module, patch it directly
                            with patch.object(module, 'np', mock_np):
                                result_df = function(df, clustering_dict)

                # Check that both cluster columns were added to the dataframe
                assert result_df is not None, f"Implementation {impl_name}: Should return a dataframe"
                assert 'cluster1' in result_df.columns, f"Implementation {impl_name}: Should add 'cluster1' column to result dataframe"
                assert 'cluster2' in result_df.columns, f"Implementation {impl_name}: Should add 'cluster2' column to result dataframe"

                # Check that clustering was performed - either via fit_predict or fit+predict
                call_count = kmeans_instance.fit_predict.call_count + kmeans_instance.fit.call_count
                assert call_count > 0, f"Implementation {impl_name}: KMeans fitting should be called at least once"

                # Verify the cluster values are present (but don't compare exact values)
                # This makes the test more robust against different implementation strategies
                assert not result_df['cluster1'].isna().all(), f"Implementation {impl_name}: cluster1 should have valid values"
                assert not result_df['cluster2'].isna().all(), f"Implementation {impl_name}: cluster2 should have valid values"

def test_separate_clustering_per_feature_set(implementation):
    """Test that clustering is performed separately for each feature set"""
    impl_name, module = implementation

    # Create a sample dataframe
    df = pd.DataFrame({
        'feature1': [1, 2, 3, 4, 5],
        'feature2': [5, 4, 3, 2, 1],
        'feature3': [1, 1, 3, 3, 5]
    })

    # Define clustering dictionary
    clustering_dict = {
        'cluster_a': ('feature1', 'feature2'),
        'cluster_b': ('feature3',)
    }

    # Mock KMeans and silhouette_score with more generic behavior
    # This allows test to pass with different implementation approaches
    kmeans_instance = Mock()
    kmeans_instance.fit_predict.return_value = np.array([0, 0, 1, 1, 2])
    kmeans_instance.fit.return_value = kmeans_instance
    kmeans_instance.predict.return_value = np.array([0, 0, 1, 1, 2])
    kmeans_mock = Mock(return_value=kmeans_instance)

    # Mock for numpy
    mock_np = Mock()
    mock_np.unique.return_value = np.array([0, 1, 2])
    mock_np.array = np.array

    # Patch numpy for implementations that don't import it
    with patch.dict('sys.modules', {'numpy': mock_np, 'np': mock_np}):
        with patch('sklearn.cluster.KMeans', kmeans_mock):
            with patch('sklearn.metrics.silhouette_score', return_value=0.8):
                # Suppress prints during test
                with patch('builtins.print'):
                    # Get the function reference
                    function = getattr(module, "cluster_data")

                    # Handle numpy not being imported in the module
                    try:
                        result_df = function(df, clustering_dict)
                    except NameError as e:
                        if 'np' in str(e) and 'not defined' in str(e):
                            # If numpy is not imported in the module, patch it directly
                            with patch.object(module, 'np', mock_np):
                                result_df = function(df, clustering_dict)

                # Check that the cluster columns are in the result
                assert result_df is not None, f"Implementation {impl_name}: Function should return a dataframe"
                assert 'cluster_a' in result_df.columns, f"Implementation {impl_name}: 'cluster_a' column should be in the result"
                assert 'cluster_b' in result_df.columns, f"Implementation {impl_name}: 'cluster_b' column should be in the result"

                # Check that each column has cluster values (we don't enforce exact values)
                assert not result_df['cluster_a'].isna().all(), f"Implementation {impl_name}: cluster_a should have valid values"
                assert not result_df['cluster_b'].isna().all(), f"Implementation {impl_name}: cluster_b should have valid values"

def test_original_data_preserved(implementation):
    """Test that the original dataframe columns are preserved in the result"""
    impl_name, module = implementation

    # Create a sample dataframe
    original_df = pd.DataFrame({
        'feature1': [1, 2, 3],
        'feature2': [4, 5, 6],
        'feature3': [7, 8, 9]
    })

    # Define clustering dictionary
    clustering_dict = {
        'cluster_x': ('feature1', 'feature2'),
    }

    # Mock clustering output
    cluster_labels = np.array([0, 1, 0])

    # Mock KMeans and silhouette_score
    kmeans_instance = Mock()
    kmeans_instance.fit_predict.return_value = cluster_labels
    kmeans_instance.fit.return_value = kmeans_instance
    kmeans_instance.predict.return_value = cluster_labels
    kmeans_mock = Mock(return_value=kmeans_instance)

    # Mock for numpy
    mock_np = Mock()
    mock_np.unique.return_value = np.array([0, 1])
    mock_np.array = np.array

    # Patch numpy for implementations that don't import it
    with patch.dict('sys.modules', {'numpy': mock_np, 'np': mock_np}):
        with patch('sklearn.cluster.KMeans', kmeans_mock):
            with patch('sklearn.metrics.silhouette_score', return_value=0.8):
                # Suppress prints during test
                with patch('builtins.print'):
                    # Get the function reference
                    function = getattr(module, "cluster_data")

                    # Handle numpy not being imported in the module
                    try:
                        result_df = function(original_df, clustering_dict)
                    except NameError as e:
                        if 'np' in str(e) and 'not defined' in str(e):
                            # If numpy is not imported in the module, patch it directly
                            with patch.object(module, 'np', mock_np):
                                result_df = function(original_df, clustering_dict)

                # Check that all original columns are preserved
                assert result_df is not None, f"Implementation {impl_name}: Function should return a dataframe"
                for col in original_df.columns:
                    assert col in result_df.columns, \
                        f"Implementation {impl_name}: Original column '{col}' should be preserved in the result"

                    # Verify that original data values match
                    pd.testing.assert_series_equal(
                        original_df[col],
                        result_df[col],
                        check_names=False,
                        check_dtype=False,
                        obj=f"Implementation {impl_name}: Values in column '{col}' should be unchanged"
                    )

def test_handles_none_input(implementation):
    """Test that the function correctly handles None input"""
    impl_name, module = implementation

    # Define clustering dictionary
    clustering_dict = {
        'cluster_x': ('feature1', 'feature2'),
    }

    # Mock print to avoid console output during tests
    with patch('builtins.print'):
        # Call the function with None input
        function = getattr(module, "cluster_data")
        result = function(None, clustering_dict)

        # The function should return None when input is None
        assert result is None, f"Implementation {impl_name}: Function should return None when input dataframe is None"

def test_handles_unsupported_clustering_method(implementation):
    """Test that the function correctly handles unsupported clustering methods"""
    impl_name, module = implementation

    # Create a sample dataframe
    df = pd.DataFrame({
        'feature1': [1, 2, 3],
        'feature2': [4, 5, 6]
    })

    # Define clustering dictionary
    clustering_dict = {
        'cluster_x': ('feature1', 'feature2'),
    }

    # Mock KMeans to ensure it's not called for an unsupported method
    kmeans_mock = Mock()
    silhouette_mock = Mock(return_value=0.8)

    # Mock for numpy
    mock_np = Mock()
    mock_np.unique.return_value = np.array([0, 1])
    mock_np.array = np.array

    with patch('sklearn.cluster.KMeans', kmeans_mock):
        with patch('sklearn.metrics.silhouette_score', silhouette_mock):
            # Capture print output
            with patch('builtins.print') as mock_print:
                # Get the function reference
                function = getattr(module, "cluster_data")

                # Patch numpy for implementations that don't import it
                with patch.dict('sys.modules', {'numpy': mock_np, 'np': mock_np}):
                    # Handle numpy not being imported in the module
                    try:
                        result = function(df, clustering_dict, clustering_method='unsupported_method')
                    except NameError as e:
                        if 'np' in str(e) and 'not defined' in str(e):
                            # If numpy is not imported in the module, patch it directly
                            with patch.object(module, 'np', mock_np):
                                result = function(df, clustering_dict, clustering_method='unsupported_method')

                # Check that either the function returns None or prints an error message
                error_handled = False

                if result is None:
                    error_handled = True
                elif mock_print.called:
                    # Check if any print call contains an error message about unsupported method
                    for call in mock_print.call_args_list:
                        args = call[0][0] if call[0] else ""
                        if isinstance(args, str) and ("неподдерживаем" in args.lower() or
                                                      "unsupported" in args.lower()):
                            error_handled = True
                            break

                assert error_handled, f"Implementation {impl_name}: Should handle unsupported clustering method by returning None or printing an error message"

pytest
pytest-mock
pandas
numpy
scikit-learn
matplotlib

import pytest
import os
import sys
import json
from typing import Dict, List, Optional, Any

# Import from local test_utils.py in the same directory
from test_utils import TestUtils, TestResultsManager

# Load all implementations in the current sandbox
implementations = TestUtils.load_all_implementations()
test_results = TestResultsManager()

@pytest.fixture(scope="session")
def sandbox_dir():
    """Fixture to provide the sandbox directory path."""
    return os.path.dirname(os.path.abspath(__file__))

@pytest.fixture(scope="session")
def sandbox_name():
    """Fixture to provide the sandbox name."""
    return os.path.basename(os.path.dirname(os.path.abspath(__file__)))

@pytest.fixture(scope="session")
def all_implementations():
    """Fixture to provide all implementations as a dictionary."""
    return implementations

@pytest.fixture(params=list(implementations.items()))
def implementation(request):
    """Fixture to provide each implementation to tests one at a time."""
    return request.param

@pytest.fixture(scope="session")
def results_manager():
    """Fixture to provide access to the test results manager."""
    return test_results

# Hook for collecting test results
@pytest.hookimpl(tryfirst=True, hookwrapper=True)
def pytest_runtest_makereport(item, call):
    """Pytest hook to collect test results."""
    # Execute all other hooks to obtain the report object
    outcome = yield
    rep = outcome.get_result()

    # We're only interested in the call outcome
    if rep.when == "call":
        if hasattr(item, "callspec") and "implementation" in item.callspec.params:
            # Get implementation name and module
            impl_name, _ = item.callspec.params["implementation"]

            # Get test name
            test_name = item.nodeid.split("::")[-1]

            # Record result
            if rep.passed:
                test_results.record_result(impl_name, test_name, True)
            elif rep.failed:
                error_msg = str(rep.longrepr) if rep.longrepr else "Test failed"
                test_results.record_result(impl_name, test_name, False, error_msg)
            elif rep.skipped:
                skip_reason = rep.longrepr[2] if rep.longrepr else "Test skipped"
                test_results.record_skip(impl_name, test_name, skip_reason)

# Hook to save results at the end of testing
@pytest.hookimpl(trylast=True)
def pytest_sessionfinish(session, exitstatus):
    """Save test results at the end of the test session."""
    test_results.save_results()

import os
import sys
import glob
import re
import importlib.util
import traceback
import types
from typing import Dict, List, Optional, Any, Tuple

class TestUtils:
    @staticmethod
    def discover_implementation_files(directory: str = None) -> List[str]:
        """Find all implementation files in the current sandbox directory."""
        if directory is None:
            directory = os.path.dirname(os.path.abspath(__file__))

        patterns = [
            r'modified_code\d+\.py',
            r'new_code\d+\.py',
            # r'original_code\.py',
            r'implementation\d*\.py'
        ]

        pattern = re.compile('|'.join(f'({p})' for p in patterns))
        implementations = []

        for file_path in glob.glob(os.path.join(directory, '*.py')):
            if pattern.search(os.path.basename(file_path)):
                implementations.append(file_path)

        # Sort files numerically
        def sort_key(path):
            filename = os.path.basename(path)
            match = re.search(r'(\d+)', filename)
            return int(match.group(1)) if match else 0

        return sorted(implementations, key=sort_key)

    @staticmethod
    def create_mock_module(file_path: str, module_name: str, error_info: str) -> types.ModuleType:
        """Create a mock module that contains error information but can still be tested."""
        # Create a new module object
        mock_module = types.ModuleType(module_name)

        # Add basic attributes
        mock_module.__file__ = file_path
        mock_module.__name__ = module_name
        mock_module.__display_name__ = module_name
        mock_module.__error__ = error_info

        # Add a dummy function that can be detected by test functions
        def dummy_function(*args, **kwargs):
            return f"Error in module: {error_info}"

        setattr(mock_module, "implementation_error", dummy_function)

        return mock_module

    @staticmethod
    def load_module(file_path: str, module_name: Optional[str] = None) -> Any:
        """
        Safely load a module from a file path with proper error handling.
        If the module has errors, return a mock module that can still be tested.
        """
        if module_name is None:
            module_name = os.path.basename(file_path).replace('.py', '')

        # Create a unique module name to avoid conflicts
        sandbox_id = os.path.basename(os.path.dirname(file_path))
        unique_module_name = f"{sandbox_id}_{module_name}"

        try:
            # First, try to read the file to check for syntax errors
            with open(file_path, 'r') as f:
                source_code = f.read()

            # Check for syntax errors by compiling the code
            try:
                compiled = compile(source_code, file_path, 'exec')
            except SyntaxError as e:
                error_msg = f"Syntax error: {str(e)}"
                print(f"Syntax error in {file_path}: {e}")
                print(f"  Line {e.lineno}, column {e.offset}: {e.text}")
                return TestUtils.create_mock_module(file_path, unique_module_name, error_msg)

            # Create the module spec
            spec = importlib.util.spec_from_file_location(unique_module_name, file_path)
            if spec is None or spec.loader is None:
                error_msg = f"Could not create spec for {file_path}"
                print(f"Error: {error_msg}")
                return TestUtils.create_mock_module(file_path, unique_module_name, error_msg)

            # Create the module object
            module = importlib.util.module_from_spec(spec)
            sys.modules[unique_module_name] = module

            # Special handling for execution errors
            try:
                # Execute the module code in a safe way
                spec.loader.exec_module(module)
                # Store the original name for reference
                module.__display_name__ = module_name
                return module
            except Exception as e:
                error_msg = f"Runtime error: {str(e)}"
                traceback_str = traceback.format_exc()
                print(f"Error executing module {file_path}: {e}")
                print(traceback_str)

                # Create a partial module that contains what we loaded before the error
                mock_module = TestUtils.create_mock_module(file_path, unique_module_name, error_msg)

                # Copy any attributes that might have been defined before the error
                for attr_name in dir(module):
                    if not attr_name.startswith('__'):
                        try:
                            setattr(mock_module, attr_name, getattr(module, attr_name))
                        except Exception:
                            pass  # Skip attributes that can't be copied

                return mock_module

        except FileNotFoundError as e:
            error_msg = f"File not found: {str(e)}"
            print(f"Error: {error_msg}")
            return TestUtils.create_mock_module(file_path, unique_module_name, error_msg)
        except Exception as e:
            error_msg = f"Unexpected error: {str(e)}"
            print(f"Error loading module {file_path}: {e}")
            return TestUtils.create_mock_module(file_path, unique_module_name, error_msg)

    @classmethod
    def load_all_implementations(cls, directory: str = None) -> Dict[str, Any]:
        """Load all implementation files in the directory, including those with errors."""
        if directory is None:
            directory = os.path.dirname(os.path.abspath(__file__))

        implementations = {}

        implementation_files = cls.discover_implementation_files(directory)
        if not implementation_files:
            print("WARNING: No implementation files found. Check your file naming patterns.")

        for file_path in implementation_files:
            module_name = os.path.basename(file_path).replace('.py', '')
            module = cls.load_module(file_path, module_name)

            # Always add the module, even if it has errors
            implementations[module_name] = module

            if hasattr(module, '__error__'):
                print(f"Loaded with errors: {module_name} - {module.__error__}")
            else:
                print(f"Successfully loaded: {module_name}")

        return implementations

class TestResultsManager:
    def __init__(self):
        self.results = {}
        self.sandbox_name = os.path.basename(os.path.dirname(os.path.abspath(__file__)))

    def record_result(self, impl_name: str, test_name: str, passed: bool,
                     error_msg: Optional[str] = None) -> None:
        """Record a test result for an implementation."""
        if impl_name not in self.results:
            self.results[impl_name] = {"passed": 0, "failed": 0, "skipped": 0, "errors": []}

        if passed:
            self.results[impl_name]["passed"] += 1
        else:
            self.results[impl_name]["failed"] += 1
            if error_msg:
                self.results[impl_name]["errors"].append({
                    "test": test_name,
                    "error": error_msg
                })

    def record_skip(self, impl_name: str, test_name: str,
                   reason: Optional[str] = None) -> None:
        """Record a skipped test for an implementation."""
        if impl_name not in self.results:
            self.results[impl_name] = {"passed": 0, "failed": 0, "skipped": 0, "errors": []}

        self.results[impl_name]["skipped"] += 1
        if reason:
            self.results[impl_name]["errors"].append({
                "test": test_name,
                "error": f"SKIPPED: {reason}"
            })

    def get_winner(self) -> Tuple[Optional[int], Dict]:
        """Determine the winner based on test results."""
        winner = None
        max_passed = -1

        for impl_name, results in self.results.items():
            if impl_name == "original_code":
                continue  # Skip original code when determining winner

            if results["passed"] > max_passed:
                max_passed = results["passed"]
                winner = impl_name
            # Break ties by looking at failure count
            elif results["passed"] == max_passed and winner is not None:
                if results["failed"] < self.results[winner]["failed"]:
                    winner = impl_name

        # Convert winner to numeric index if possible
        winner_index = -1
        if winner and re.match(r'modified_code\d+', winner):
            try:
                winner_index = int(re.search(r'(\d+)', winner).group(1))
            except (AttributeError, ValueError):
                pass

        return winner_index, self.results

    def save_results(self, filename: str = "test_results.json") -> None:
        """Save test results to a JSON file."""
        import json

        winner_index, results = self.get_winner()

        # Check if all tests were skipped
        all_skipped = all(
            stats["skipped"] == stats["passed"] + stats["failed"] + stats["skipped"]
            for impl_name, stats in results.items()
            if impl_name != "original_code"
        )

        output = {
            "winner": winner_index,
            "all_skipped": all_skipped,
            "results": {
                name: {
                    "passed": stats["passed"],
                    "failed": stats["failed"],
                    "skipped": stats["skipped"],
                    "total": stats["passed"] + stats["failed"] + stats["skipped"]
                }
                for name, stats in results.items()
                if not name.startswith("_")  # Skip internal items
            }
        }

        with open(filename, "w") as f:
            json.dump(output, f, indent=2)

        print(f"Test results saved to {filename}")

        return output