def search(self, **kwargs: str) -> pd.DataFrame:
        """
        Search for specific data based on provided criteria.

        Allows searching the database based on column names and queries,
        with optional case sensitivity.

        Args:
            **kwargs: Column names and search queries.
                For example, symbol="TSLA" or sector="Technology".
            case_sensitive (bool): Whether the search should be case-sensitive.
                Defaults to False.
            only_primary_listing (bool): Whether to exclude secondary listings.
                Defaults to False.
            index (str): Search within the DataFrame index.
                Defaults to None.

        Returns:
            DataFrame with filtered data based on the input criteria.
        """
        data_filter = self.data.copy()

        if "case_sensitive" in kwargs:
            case_sensitive = bool(kwargs["case_sensitive"] in [True, "True"])
            kwargs = {k: v for k, v in kwargs.items() if k != "case_sensitive"}
        else:
            case_sensitive = False

        for key, value in kwargs.items():
            if key == "only_primary_listing":
                if value is True:
                    # Filter data if exclude exchanges is set to True
                    data_filter = data_filter[
                        ~data_filter.index.str.contains(r"\.", na=False)
                    ]
            elif key == "index":
                # Look into the index of the DataFrame and search accordingly
                if isinstance(value, list | pd.Index):
                    data_filter = data_filter[data_filter.index.isin(value)]
                else:
                    data_filter = data_filter[
                        data_filter.index.str.contains(value, na=False)
                    ]
            elif key not in data_filter.columns:
                print(f"{key} is not a valid column.")
            elif isinstance(value, list):
                if case_sensitive:
                    # For case-sensitive search, use string comparison that preserves case
                    data_filter = data_filter[data_filter[key].isin(value)]
                else:
                    # For case-insensitive search, convert both sides to lowercase
                    # Create a mask that matches if any value in the list is found in the column
                    mask = (
                        data_filter[key]
                        .str.lower()
                        .apply(
                            lambda x, vals=value: (
                                any(val.lower() in str(x).lower() for val in vals)
                                if pd.notna(x)
                                else False
                            )
                        )
                    )
                    data_filter = data_filter[mask]
            else:
                data_filter = data_filter[
                    data_filter[key].str.contains(value, case=case_sensitive, na=False)
                ]

        return FinanceFrame(data_filter)

        Search for specific data based on provided criteria.

        Allows searching the database based on column names and queries,
        with optional case sensitivity.

        Args:
            **kwargs: Column names and search queries.
                For example, symbol="TSLA" or sector="Technology".
            case_sensitive (bool): Whether the search should be case-sensitive.
                Defaults to False.
            only_primary_listing (bool): Whether to exclude secondary listings.
                Defaults to False.
            index (str): Search within the DataFrame index.
                Defaults to None.

        Returns:
            DataFrame with filtered data based on the input criteria.
        
financedatabase/helpers.py