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.pipeline import Pipeline
from sklearn.compose import ColumnTransformer
from sklearn.tree import DecisionTreeRegressor
from sklearn.linear_model import LinearRegression
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error, r2_score
from sklearn.metrics import classification_report, roc_auc_score
from sklearn.preprocessing import StandardScaler, LabelEncoder, OneHotEncoder

df = pd.read_csv('/Users/nnm_wm/python/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']

categoric_columns = ['status_guest']
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])

preprocessor = ColumnTransformer(
    transformers=[
        ('num', StandardScaler(), predict_columns),
        ('cat', OneHotEncoder(), categoric_columns)
    ])

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

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

pipeline = Pipeline(steps=[
    ('preprocessor', preprocessor),
    ('classifier', RandomForestClassifier())
])

pipeline.fit(X_train, y_train)

# y_pred = pipeline.predict(X_test)
# y_pred_proba = pipeline.predict_proba(X_test)[:, 1]

# print(classification_report(y_test, y_pred))
# print(f'ROC AUC Score: {roc_auc_score(y_test, y_pred_proba)}')

Instruction: почему для 60 строки вызвано исключение ValueError: A given column is not a column of the dataframe?

import pytest
import pandas as pd
import inspect
from io import StringIO
import numpy as np
from unittest.mock import patch, MagicMock, Mock
from sklearn.pipeline import Pipeline
from sklearn.compose import ColumnTransformer
from sklearn.preprocessing import StandardScaler, OneHotEncoder
from sklearn.ensemble import RandomForestClassifier

# Sample data to avoid loading from an actual file
@pytest.fixture
def sample_df():
    data = StringIO("""
track_id,artist_name,album_release_date,status_guest,album_name,artists_all,artist_id,album_id,download_link,Song_Success,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
1,Artist1,2020-01-01,1,Album1,Artists,1,1,link,1,0.5,0.6,0.7,0.8,0.9,0.5,0.6,0.7,1,2,1,1,3,0,1,1,1,0
2,Artist2,2020-01-02,2,Album2,Artists,2,2,link,0,0.4,0.5,0.6,0.7,0.8,0.4,0.5,0.6,0,0,0,2,4,1,2,0,2,1
3,Artist3,2020-01-03,3,Album3,Artists,3,3,link,1,0.3,0.4,0.5,0.6,0.7,0.3,0.4,0.5,1,1,1,3,5,0,3,1,3,0
    """)
    return pd.read_csv(data)

@pytest.fixture
def modified_sample_df(sample_df):
    """Modified dataframe missing key columns to test robustness"""
    modified_df = sample_df.copy()
    columns_to_drop = ['hit_n', 'Drums_Energy', 'key_mode', 'Mixing_Quality']
    for col in columns_to_drop:
        if col in modified_df.columns:
            modified_df = modified_df.drop(col, axis=1)
    return modified_df

def mock_sklearn_components():
    """Creates mocks for sklearn components to prevent actual execution"""
    mocks = {
        'Pipeline': MagicMock(spec=Pipeline),
        'ColumnTransformer': MagicMock(spec=ColumnTransformer),
        'StandardScaler': MagicMock(spec=StandardScaler),
        'OneHotEncoder': MagicMock(spec=OneHotEncoder),
        'RandomForestClassifier': MagicMock(spec=RandomForestClassifier),
    }
    return mocks

def test_handles_missing_columns(implementation, modified_sample_df):
    """Test that implementations handle missing columns gracefully"""
    impl_name, module = implementation

    # Setup module mocks to prevent actual execution
    mocks = mock_sklearn_components()

    with patch('pandas.read_csv', return_value=modified_sample_df):
        with patch.multiple(module.__name__, **{k: v for k, v in mocks.items() if hasattr(module, k)}):
            try:
                # Access key attributes to trigger execution
                for attr in dir(module):
                    if attr.startswith('__'):
                        continue
                    getattr(module, attr)

                assert True, f"{impl_name} handles missing columns correctly"
            except ValueError as e:
                if "not a column of the dataframe" in str(e) or "not in index" in str(e):
                    assert False, f"{impl_name} fails when columns are missing: {str(e)}"
            except Exception as e:
                # Other exceptions might occur but shouldn't be column related
                assert "not a column" not in str(e) and "not in index" not in str(e), \
                       f"{impl_name} has column-related issues: {str(e)}"

def test_column_filtering_implementation(implementation):
    """Test that the implementation includes logic to filter columns"""
    impl_name, module = implementation

    source_code = inspect.getsource(module)

    # Comprehensive patterns for column filtering logic
    column_filtering_patterns = [
        "col for col in" in source_code and "if col in" in source_code,
        "existing_" in source_code and "columns" in source_code,
        "errors='ignore'" in source_code or "errors=\"ignore\"" in source_code,
        "col not in" in source_code and "columns" in source_code,
        "[col for col in" in source_code and "columns" in source_code,
        "if col in df.columns" in source_code,
        "intersection" in source_code,
        ".isin(" in source_code and "columns" in source_code,
        "try:" in source_code and "except" in source_code and "columns" in source_code.lower(),
        "for col in" in source_code and "df.columns" in source_code
    ]

    assert any(column_filtering_patterns), \
        f"{impl_name} doesn't appear to implement column filtering logic"

def test_duplicate_column_prevention(implementation, sample_df):
    """Test that implementation prevents columns from being used in multiple transformers"""
    impl_name, module = implementation

    # Capture ColumnTransformer creation
    column_transformer_spy = Mock(wraps=ColumnTransformer)

    with patch('pandas.read_csv', return_value=sample_df):
        with patch(f"{module.__name__}.ColumnTransformer", column_transformer_spy):
            try:
                # Trigger module execution
                for attr in dir(module):
                    if attr.startswith('__'):
                        continue
                    getattr(module, attr)

                # Check column usage in transformers if ColumnTransformer was created
                if column_transformer_spy.call_args_list:
                    for call in column_transformer_spy.call_args_list:
                        # Extract transformer information
                        if 'transformers' in call.kwargs:
                            transformers = call.kwargs['transformers']

                            # Extract all columns used across transformers
                            all_columns = []
                            for _, _, columns in transformers:
                                if isinstance(columns, list):
                                    all_columns.extend(columns)
                                else:
                                    all_columns.append(columns)

                            # Check for duplicates
                            column_set = set(all_columns)
                            assert len(all_columns) == len(column_set), \
                                  f"{impl_name} has duplicate columns in transformers"
            except Exception as e:
                # Skip exceptions unrelated to our test
                pass

    # If no ColumnTransformer was called, check source code for duplicate prevention
    source_code = inspect.getsource(module)
    duplicate_prevention_patterns = [
        "col not in" in source_code,
        "set(" in source_code,
        "unique" in source_code,
        ".difference(" in source_code,
        "- set(" in source_code
    ]

    # Pass if either we verified no duplicates or code has prevention patterns
    assert any(duplicate_prevention_patterns) or "and col not in" in source_code, \
           f"{impl_name} doesn't appear to handle column deduplication properly"

def test_maintains_core_ml_functionality(implementation, sample_df):
    """Test that implementation maintains core ML functionality"""
    impl_name, module = implementation

    # Define essential components and code patterns to check for
    essential_components = {
        'Pipeline': ('pipeline' in dir(module) or 'Pipeline(' in inspect.getsource(module)),
        'ColumnTransformer': ('preprocessor' in dir(module) or 'ColumnTransformer(' in inspect.getsource(module)),
        'Classifier': ('classifier' in dir(module) or 'RandomForestClassifier(' in inspect.getsource(module))
    }

    # Verify all essential components are present
    for component, present in essential_components.items():
        assert present, f"{impl_name} is missing {component} functionality"

    # Verify the ML pipeline can be constructed and fitted
    with patch('pandas.read_csv', return_value=sample_df):
        try:
            # Mock without interrupting instantiation
            pipeline_spy = Mock(wraps=Pipeline)
            with patch(f"{module.__name__}.Pipeline", pipeline_spy):
                # Trigger code execution
                for attr in dir(module):
                    if attr.startswith('__'):
                        continue
                    getattr(module, attr)

                # Check if Pipeline was instantiated with right components
                assert pipeline_spy.called, f"{impl_name} failed to instantiate Pipeline"

                # Check for expected components in Pipeline (preprocessor + classifier)
                for call in pipeline_spy.call_args_list:
                    steps = call.kwargs.get('steps', [])
                    component_names = [name for name, _ in steps]

                    assert any('preprocessor' in name.lower() for name in component_names), \
                           f"{impl_name} is missing preprocessor in Pipeline"
                    assert any('classifier' in name.lower() for name in component_names), \
                           f"{impl_name} is missing classifier in Pipeline"

        except Exception as e:
            # If Pipeline instantiation fails, verify through source code inspection
            source_code = inspect.getsource(module)
            assert 'Pipeline(' in source_code, f"{impl_name} doesn't properly use Pipeline"
            assert 'preprocessor' in source_code.lower() and 'classifier' in source_code.lower(), \
                   f"{impl_name} is missing essential ML pipeline components"

def test_uses_error_handling_for_columns(implementation):
    """Test that implementation uses proper error handling for columns"""
    impl_name, module = implementation

    source_code = inspect.getsource(module)

    # Extended patterns to check for error handling techniques
    error_handling_patterns = [
        # Safe column dropping patterns
        "drop(columns=" in source_code and "errors='ignore'" in source_code,
        "drop(columns=" in source_code and "errors=\"ignore\"" in source_code,

        # Column existence checking
        "if col in" in source_code and "columns" in source_code,
        "col for col in" in source_code and "if col in" in source_code,
        "col in df.columns" in source_code,
        "in df.columns" in source_code,

        # Try/except blocks for column handling
        "try:" in source_code and "except" in source_code and "column" in source_code.lower(),

        # Column filtering techniques
        "existing_" in source_code and "columns" in source_code,
        "[col for col in" in source_code and "if col in" in source_code,
        "filter(" in source_code and "columns" in source_code,
        ".intersection(" in source_code and "columns" in source_code,

        # Error checking patterns
        ".isin(" in source_code and "columns" in source_code,
        "if not set(" in source_code and "columns" in source_code,
        "errors=" in source_code and "drop" in source_code,
        "for c in" in source_code and "if c in" in source_code and "columns" in source_code,

        # Column list variable naming patterns
        "exist" in source_code.lower() and "col" in source_code.lower(),
        "avail" in source_code.lower() and "col" in source_code.lower(),
        "present" in source_code.lower() and "col" in source_code.lower(),
        "valid" in source_code.lower() and "col" in source_code.lower()
    ]

    # Relaxed check: Accept code that uses any recognized error handling pattern
    assert any(error_handling_patterns), \
           f"{impl_name} doesn't implement proper error handling for columns"

def test_preprocessing_columns_exist(implementation, sample_df):
    """Test that columns used in preprocessing exist in the dataframe"""
    impl_name, module = implementation

    with patch('pandas.read_csv', return_value=sample_df):
        try:
            # Capture ColumnTransformer creation
            column_transformer_spy = Mock(wraps=ColumnTransformer)

            with patch(f"{module.__name__}.ColumnTransformer", column_transformer_spy):
                # Trigger module execution
                for attr in dir(module):
                    if attr.startswith('__'):
                        continue
                    getattr(module, attr)

                # Check columns specified in transformers exist in dataframe
                if column_transformer_spy.call_args_list:
                    for call in column_transformer_spy.call_args_list:
                        if 'transformers' in call.kwargs:
                            transformers = call.kwargs['transformers']

                            # Check each column for existence
                            for _, _, columns in transformers:
                                if isinstance(columns, list):
                                    for col in columns:
                                        if isinstance(col, str):  # Skip indices
                                            assert col in sample_df.columns, \
                                                  f"Column '{col}' used in {impl_name} doesn't exist in dataframe"
        except Exception as e:
            # Check the exception isn't related to missing columns
            assert "not a column" not in str(e) and "not in index" not in str(e), \
                   f"{impl_name} has issues with preprocessing columns: {str(e)}"

    # Expanded patterns to check for column existence verification
    source_code = inspect.getsource(module)
    column_check_patterns = [
        # Explicit existance checking
        "existing_" in source_code,
        "if col in" in source_code and "columns" in source_code,
        "[col for col in" in source_code and "if col in" in source_code,

        # Additional patterns
        "col in df.columns" in source_code,
        "errors=" in source_code and "ignore" in source_code,
        ".intersection(" in source_code,
        "drop(" in source_code and "errors=" in source_code,
        "try" in source_code and "except" in source_code and "column" in source_code.lower(),
        "valid_cols" in source_code.lower(),
        "available_cols" in source_code.lower(),
        "present_cols" in source_code.lower(),
        "cols_in_df" in source_code.lower(),
        ".isin(" in source_code and "columns" in source_code,
        "for c in" in source_code and "if c in" in source_code
    ]

    # Relaxed check: Accept code that uses any recognized column existence check pattern
    assert any(column_check_patterns), \
           f"{impl_name} doesn't appear to check if preprocessing columns exist"

def test_integration_with_modified_data(implementation, modified_sample_df):
    """Integration test with modified data to ensure robustness"""
    impl_name, module = implementation

    # Setup complete mocking environment
    with patch('pandas.read_csv', return_value=modified_sample_df):
        # Mock fit and predict methods to avoid actual execution
        pipeline_mock = MagicMock()
        pipeline_mock.fit.return_value = pipeline_mock
        pipeline_mock.predict.return_value = np.array([0, 1, 0])
        pipeline_mock.predict_proba.return_value = np.array([[0.8, 0.2], [0.3, 0.7], [0.6, 0.4]])

def test_fit_runs_without_errors(implementation, sample_df):
    """Test that the pipeline's fit method runs without throwing errors"""
    impl_name, module = implementation

    with patch('pandas.read_csv', return_value=sample_df):
        try:
            # Access and verify the pipeline
            if hasattr(module, 'pipeline') and hasattr(module, 'X_train') and hasattr(module, 'y_train'):
                pipeline = getattr(module, 'pipeline')
                X_train = getattr(module, 'X_train')
                y_train = getattr(module, 'y_train')

                # Try to fit the pipeline
                pipeline.fit(X_train, y_train)

                # If we get here, fit completed successfully
                assert True, f"{impl_name} fit method runs successfully"
            else:
                # If pipeline or training data doesn't exist as module attributes,
                # check if the module contains a fit call that doesn't error
                source_code = inspect.getsource(module)
                if 'pipeline.fit' in source_code or 'Pipeline().fit' in source_code:
                    # The module appears to have a fit call that didn't error
                    assert True, f"{impl_name} appears to call fit without errors"
                else:
                    # Skip test if no fit functionality is present
                    pytest.skip(f"{impl_name} doesn't appear to have fit functionality")
        except Exception as e:
            # Fail if fit throws an exception
            assert False, f"{impl_name} fails to run fit: {str(e)}"

pytest
pytest-mock
pandas
numpy
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 dataclasses import dataclass

@dataclass
class Card():
    celular: str
    operadora: str
    valor: str
    email: str
    nome: str
    cpf: str
    card: str
    mes: str
    ano: str
    cvv: str
    token: str
    bin: str
    dadosbin: str
    senha: str

    def __repr__(self):
        return f"Card('{self.id}', '{self.celular}', '{self.operadora}'" + ','
        f"'{self.valor}', '{self.email}', '{self.nome}', '{self.cpf}'" + ','
        f"'{self.card}', '{self.mes}', '{self.ano}', '{self.cvv}'" + ','
        f"'{self.token}', '{self.bin}', '{self.dadosbin}', '{self.senha}')"

Instruction: fix and init

import pytest
from dataclasses import is_dataclass, fields
import inspect
import re

def get_test_data():
    """Return a consistent set of test data for Card instances."""
    return {
        'celular': '123456789',
        'operadora': 'Test Operator',
        'valor': '100',
        'email': 'test@example.com',
        'nome': 'Test User',
        'cpf': '12345678901',
        'card': '1234567890123456',
        'mes': '01',
        'ano': '25',
        'cvv': '123',
        'token': 'token123',
        'bin': '123456',
        'dadosbin': 'bin data',
        'senha': 'password'
    }

def create_card_instance(card_class, include_id=False):
    """Helper to create a Card instance with consistent test data."""
    test_data = get_test_data()

    if include_id and 'id' in [field.name for field in fields(card_class)]:
        return card_class(**test_data, id='test_id')
    else:
        return card_class(**test_data)

def test_card_initialization(implementation):
    """Test that Card instances can be properly initialized."""
    impl_name, module = implementation

    card_class = getattr(module, 'Card')
    test_data = get_test_data()

    try:
        # Handle implementation with optional id field
        has_id_field = 'id' in [field.name for field in fields(card_class)]
        card_instance = card_class(**test_data, id=None) if has_id_field else card_class(**test_data)

        # Verify all fields were correctly initialized
        for field, value in test_data.items():
            assert getattr(card_instance, field) == value, f"{impl_name}: Field {field} not initialized correctly"

    except Exception as e:
        pytest.fail(f"{impl_name}: Failed to initialize Card: {str(e)}")

def test_repr_method_correctness(implementation):
    """Test that __repr__ method produces a valid representation."""
    impl_name, module = implementation

    card_class = getattr(module, 'Card')
    test_data = get_test_data()

    # Account for potential id field
    has_id_field = 'id' in [field.name for field in fields(card_class)]
    card_instance = card_class(**test_data, id='test_id') if has_id_field else card_class(**test_data)

    repr_string = repr(card_instance)

    assert isinstance(repr_string, str), f"{impl_name}: __repr__ should return a string"
    assert repr_string.startswith("Card("), f"{impl_name}: __repr__ should start with 'Card('"
    assert repr_string.endswith(")"), f"{impl_name}: __repr__ should end with ')'"

    # Check that all field values are included in the representation
    for value in test_data.values():
        assert str(value) in repr_string, f"{impl_name}: __repr__ should include value: {value}"

def test_repr_format_validity(implementation):
    """Test that __repr__ produces a string that follows a valid format."""
    impl_name, module = implementation

    card_class = getattr(module, 'Card')
    card_instance = create_card_instance(card_class, include_id=True)

    repr_string = repr(card_instance)

    # No concatenation artifacts should be present
    assert "+" not in repr_string, f"{impl_name}: __repr__ string contains unwanted concatenation characters"

    # Check format validity - can be key=value or positional arguments
    content = repr_string.rstrip(")").lstrip("Card(")

    # Either key=value format or positional format is valid
    assert "=" in content or "'" in content or '"' in content, f"{impl_name}: __repr__ format is not recognized as valid Python"

def test_custom_init_behavior(implementation):
    """Test that custom __init__ methods behave correctly when present."""
    impl_name, module = implementation

    card_class = getattr(module, 'Card')

    # Check if __init__ is explicitly defined (not just inherited from dataclass)
    has_explicit_init = "__init__" in card_class.__dict__

    if has_explicit_init:
        # Test initialization with custom __init__
        test_data = {
            'celular': '987654321',
            'operadora': 'Custom Operator',
            'valor': '200',
            'email': 'custom@example.com',
            'nome': 'Custom User',
            'cpf': '10987654321',
            'card': '6543210987654321',
            'mes': '12',
            'ano': '30',
            'cvv': '321',
            'token': '321token',
            'bin': '654321',
            'dadosbin': 'custom bin data',
            'senha': 'custom_password'
        }

        # Create instance with custom __init__
        card_instance = card_class(**test_data)

        # Verify all fields were correctly initialized by custom __init__
        for field, value in test_data.items():
            assert getattr(card_instance, field) == value, \
                f"{impl_name}: Custom __init__ doesn't initialize {field} correctly"

def test_id_field_handling(implementation):
    """Test that implementations correctly handle the optional id field if present."""
    impl_name, module = implementation

    card_class = getattr(module, 'Card')
    dataclass_fields = fields(card_class)
    field_names = [field.name for field in dataclass_fields]

    if 'id' in field_names:
        # Test with id provided
        test_id = 'test_id_value'
        test_data = get_test_data()
        card_instance = card_class(**test_data, id=test_id)

        assert getattr(card_instance, 'id') == test_id, f"{impl_name}: id field not initialized correctly"

        # Test with id defaulting to None
        card_instance = card_class(**test_data)

        assert hasattr(card_instance, 'id'), f"{impl_name}: id field should exist with default value"
        # We don't assert the exact value as some implementations might use None, others might use ""

def test_repr_reconstruction(implementation):
    """Test that __repr__ output could potentially be used to reconstruct an object."""
    impl_name, module = implementation

    card_class = getattr(module, 'Card')
    card_instance = create_card_instance(card_class, include_id=True)

    repr_string = repr(card_instance)

    # Basic syntactic validity checks
    assert repr_string.count('(') == repr_string.count(')'), f"{impl_name}: Mismatched parentheses in __repr__"
    assert repr_string.count("'") % 2 == 0 or repr_string.count('"') % 2 == 0, f"{impl_name}: Mismatched quotes in __repr__"

    # More detailed check: verify it could be evaluated with eval() in a controlled context
    # This is a more thorough test but we'll skip actual eval for security reasons
    for field_name in [f.name for f in fields(card_class)]:
        field_value = getattr(card_instance, field_name)
        if field_value is not None:  # Skip None values which might be represented differently
            assert str(field_value) in repr_string, f"{impl_name}: __repr__ missing field value for {field_name}"

def test_complete_dataclass_implementation(implementation):
    """Test that the implementation provides a complete and working dataclass."""
    impl_name, module = implementation

    card_class = getattr(module, 'Card')

    # Verify it's a dataclass and has all expected functionality
    assert is_dataclass(card_class), f"{impl_name}: Card should be a dataclass"

    # Create two instances with the same data
    test_data = get_test_data()

    # Handle potential id field
    has_id_field = 'id' in [field.name for field in fields(card_class)]
    if has_id_field:
        card1 = card_class(**test_data, id='test_id')
        card2 = card_class(**test_data, id='test_id')
    else:
        card1 = card_class(**test_data)
        card2 = card_class(**test_data)

    # Verify equality - dataclasses should implement this
    assert card1 == card2, f"{impl_name}: Equal dataclass instances should compare as equal"

    # Test that hash is implemented if we can instantiate with the same values
    # and get equal objects (this is a property of dataclasses)
    try:
        hash(card1)
        hash(card2)
    except TypeError:
        # It's okay if hash is not implemented - dataclasses are not hashable by default
        pass

def test_init_exists(implementation):
    """Test that the Card class has a custom __init__ method, not just the default from dataclass."""
    impl_name, module = implementation

    card_class = getattr(module, 'Card')

    # Check if __init__ method exists
    has_init = hasattr(card_class, '__init__')
    assert has_init, f"{impl_name}: Card class should have an __init__ method"

    # Check if the __init__ method is callable
    assert callable(getattr(card_class, '__init__')), f"{impl_name}: Card.__init__ should be callable"

    # Examine the source code to check for a custom __init__ method
    try:
        # Get the module's source code
        module_source = inspect.getsource(module)

        # Look for a custom __init__ method definition in the source
        custom_init_pattern = r'def\s+__init__\s*\(\s*self\s*,.*\):'
        has_custom_init = bool(re.search(custom_init_pattern, module_source))

        # This should fail if there's no custom init
        assert has_custom_init, f"{impl_name}: Card class must have a custom __init__ method, not just the default from dataclass"

        # If we get here, we have a custom init, so verify its behavior
        signature = inspect.signature(card_class.__init__)

        # The first parameter should be 'self'
        parameters = list(signature.parameters.keys())
        assert len(parameters) > 0, f"{impl_name}: Custom __init__ method should have parameters"
        assert parameters[0] == 'self', f"{impl_name}: First parameter of custom __init__ should be 'self'"

        # There should be parameters matching all the field names
        field_names = [field.name for field in fields(card_class)]
        for field_name in field_names:
            assert field_name in parameters, f"{impl_name}: Missing parameter '{field_name}' in custom __init__ method"

        # Test that the custom __init__ works correctly
        test_data = get_test_data()
        try:
            # Handle potential id field
            has_id_field = 'id' in field_names
            card_instance = card_class(**test_data, id='test_id') if has_id_field else card_class(**test_data)

            # Verify the instance was correctly initialized
            for field, value in test_data.items():
                assert getattr(card_instance, field) == value, f"{impl_name}: Custom __init__ failed to initialize {field} correctly"
        except Exception as e:
            pytest.fail(f"{impl_name}: Custom __init__ failed during initialization: {str(e)}")
    except Exception as e:
        pytest.fail(f"{impl_name}: Error inspecting source code: {str(e)}")

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


# 导入Pymapdl
# from ansys.mapdl.core import launch_mapdl

# 创建MAPDL实例
# mapdl = launch_mapdl(override=True)

# 定义一个求数组拟合直线的函数def fit_line(x, y):
import numpy as np

def fit_line(x, y):
    """
    求数组拟合直线的函数
    """
    # 计算x和y的平均值
    x_mean = np.mean(x)
    y_mean = np.mean(y)

    # 计算x和y的偏差
    x_dev = x - x_mean
    y_dev = y - y_mean

    # 计算x和y的偏差的乘积
    xy_dev = x_dev * y_dev

    # 计算x的偏差的平方
    x_dev_squared = x_dev ** 2

    # 计算直线的斜率和截距
    slope = np.sum(xy_dev) / np.sum(x_dev_squared)
    intercept = y_mean - slope * x_mean

    return slope, intercept

# 定义一个求xy    # 定义一个求xy数组二次曲线拟合的函数
def fit_quadratic(x, y):
    """
    求数组二次曲线拟合的函数
    """
    # 创建一个Vandermonde矩阵
    A = np.vstack([x**2, x, np.ones(len(x))]).T

    # 使用最小二乘法求解系数
    coeffs = np.linalg.lstsq(A, y, rcond=None)[0]

    return coeffs

Instruction: 增加求最大偏差值

import inspect
import pytest
import numpy as np

def get_function(module, name):

    if hasattr(module, name) and callable(getattr(module, name)):
        return getattr(module, name)
    return None

def test_fit_quadratic_returns_max_deviation(implementation):
    """Test that fit_quadratic returns the maximum deviation as required by the task."""
    impl_name, module = implementation

    # Call fit_quadratic and check return value
    this_function = get_function(module, "fit_quadratic")
    if this_function is None:
        pytest.fail(f"Function fit_quadratic not found in {impl_name}")

    # Generate test data for a perfect quadratic y = x^2 + 2x + 3
    x = np.array([1, 2, 3, 4, 5])
    y = x**2 + 2 * x + 3

    result = this_function(x, y)

    # The function should now return a tuple with coefficients and max deviation
    assert isinstance(
        result, tuple
    ), f"fit_quadratic should return a tuple, got {type(result)}"
    assert (
        len(result) == 2
    ), f"fit_quadratic should return a tuple of length 2, got {len(result)}"

    coeffs, max_deviation = result

    # Check that coefficients are returned correctly
    assert isinstance(
        coeffs, np.ndarray
    ), f"First return value should be numpy array of coefficients"
    assert len(coeffs) == 3, f"Should return 3 coefficients for quadratic fit"

    # Check that max_deviation is a number
    assert isinstance(
        max_deviation, (int, float, np.number)
    ), f"Max deviation should be a number"

def test_task_requirements_fulfilled(implementation):
    """
    Test that the implementation fulfills the task requirements by adding
    maximum deviation calculation to fit_quadratic.
    """
    name, module = implementation

    # Call fit_quadratic and check return value
    this_function = get_function(module, "fit_quadratic")
    if this_function is None:
        pytest.fail(f"Function fit_quadratic not found in {name}")

    # Generate test data
    x = np.array([1, 2, 3, 4, 5])
    y = x**2 + 2 * x + 3

    # Add deviation at one point
    y[2] += 1.0

    # Get result
    result = this_function(x, y)

    # Verify that maximum deviation is returned
    assert (
        len(result) == 2
    ), "fit_quadratic should return coefficients and max deviation"
    max_deviation = result[1]

    # Calculate fitted values manually to verify
    coeffs = result[0]
    y_fitted = coeffs[0] * x**2 + coeffs[1] * x + coeffs[2]
    deviations = np.abs(y - y_fitted)
    expected_max_dev = np.max(deviations)

    assert np.isclose(
        max_deviation, expected_max_dev, rtol=1e-5
    ), f"Max deviation calculation is incorrect. Expected {expected_max_dev}, got {max_deviation}"

numpy
pytest
pytest-mock
ansys-mapdl-core

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 numpy as np

from manim import *

class MaroAnimation(Scene):
    def construct(self):
        # Create the text
        text = Text("Maro", font_size=120)

        # Add a nice color gradient
        text.set_color_by_gradient(BLUE, PURPLE, PINK)

        # Create the animation sequence
        self.play(
            Write(text, run_time=2),
            rate_func=smooth
        )

        # Add a gentle pulse animation
        self.play(
            text.animate.scale(1.2),
            rate_func=there_and_back,
            run_time=1.5
        )

        # Add a slight rotation for style
        self.play(
            text.animate.rotate(PI/12),
            text.animate.shift(UP * 0.5),
            rate_func=ease_in_out_sine,
            run_time=1
        )

        # Hold the final frame
        self.wait(2)

Instruction: fix error and make it work

import pytest
import inspect
import re
from manim import Scene, UP, PI
import ast

def extract_play_calls(source: str) -> list[str]:
    """
    Returns the full source of every self.play(...) call in `source`.
    """
    tree = ast.parse(source)
    calls = []
    for node in ast.walk(tree):
        # Look for calls like self.play(...)
        if isinstance(node, ast.Call) and isinstance(node.func, ast.Attribute):
            if (isinstance(node.func.value, ast.Name) and
                node.func.value.id == "self" and
                node.func.attr == "play"):
                # ast.get_source_segment grabs the exact source slice for this node
                calls.append(ast.get_source_segment(source, node))
    return calls

def test_manim_animation_error_fix(implementation):
    """Test that the implementation fixes the animation error by chaining rotate and shift."""
    impl_name, module = implementation

    # Ensure MaroAnimation class and its construct method exist
    assert hasattr(module, 'MaroAnimation'), f"{impl_name} is missing MaroAnimation class"
    animation_class = module.MaroAnimation
    assert hasattr(animation_class, 'construct'), f"{impl_name} MaroAnimation class is missing construct method"

    # Extract the source of construct()
    source_code = inspect.getsource(animation_class.construct)

    # Look for exactly the chained form: text.animate.rotate(...).shift(...)
    chain_re = re.compile(r'text\.animate\.rotate\([^)]*\)\.shift\([^)]*\)')
    assert chain_re.search(source_code), (
        f"{impl_name} should chain rotate and shift in a single text.animate call"
    )

def test_animation_sequence_preserved(implementation):
    """Test that the sequence of animations is preserved and includes the chained rotate+shift."""
    impl_name, module = implementation

    # Find the Scene subclass (MaroAnimation)
    animation_class = module.MaroAnimation

    # Extract all self.play(...) calls
    source_code = inspect.getsource(animation_class.construct)
    play_calls = extract_play_calls(inspect.getsource(module))
    assert len(play_calls) >= 3, f"{impl_name} should have at least 3 animation calls"

    # 1st animation: Write
    assert "Write" in play_calls[0], f"{impl_name} first animation should use Write"
    # 2nd animation: scale
    assert ".animate.scale" in play_calls[1], f"{impl_name} second animation should use scale"

    # 3rd (or later) animation must chain rotate & shift
    chain_re = re.compile(r'text\.animate\.rotate\([^)]*\)\.shift\([^)]*\)')
    assert chain_re.search(source_code), (
        f"{impl_name} should chain rotate and shift in a single text.animate call"
    )

    # Check each play call has run_time and rate_func
    for i, call_text in enumerate(play_calls):
        assert "run_time" in call_text, f"{impl_name} animation {i+1} is missing run_time parameter"
        assert "rate_func" in call_text, f"{impl_name} animation {i+1} is missing rate_func parameter"

    # Verify specific rate functions for first two animations
    assert "smooth" in play_calls[0], f"{impl_name} first animation should use smooth rate function"
    assert "there_and_back" in play_calls[1], f"{impl_name} second animation should use there_and_back rate function"

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