<commit_before>"""
Base and utility classes for pandas objects.
"""

import builtins
import textwrap
from typing import (
    TYPE_CHECKING,
    Any,
    Callable,
    Dict,
    FrozenSet,
    Optional,
    TypeVar,
    Union,
    cast,
)

import numpy as np

import pandas._libs.lib as lib
from pandas._typing import (
    Dtype,
    DtypeObj,
    IndexLabel,
)
from pandas.compat import PYPY
from pandas.compat.numpy import function as nv
from pandas.errors import AbstractMethodError
from pandas.util._decorators import (
    cache_readonly,
    doc,
)

from pandas.core.dtypes.common import (
    is_categorical_dtype,
    is_dict_like,
    is_extension_array_dtype,
    is_object_dtype,
    is_scalar,
)
from pandas.core.dtypes.generic import (
    ABCDataFrame,
    ABCIndex,
    ABCSeries,
)
from pandas.core.dtypes.missing import (
    isna,
    remove_na_arraylike,
)

from pandas.core import algorithms
from pandas.core.accessor import DirNamesMixin
from pandas.core.algorithms import (
    duplicated,
    unique1d,
    value_counts,
)
from pandas.core.arraylike import OpsMixin
from pandas.core.arrays import ExtensionArray
from pandas.core.construction import create_series_with_explicit_dtype
import pandas.core.nanops as nanops

if TYPE_CHECKING:
    from pandas import Categorical

_shared_docs: Dict[str, str] = {}
_indexops_doc_kwargs = {
    "klass": "IndexOpsMixin",
    "inplace": "",
    "unique": "IndexOpsMixin",
    "duplicated": "IndexOpsMixin",
}

_T = TypeVar("_T", bound="IndexOpsMixin")


class PandasObject(DirNamesMixin):
    """
    Baseclass for various pandas objects.
    """

    # results from calls to methods decorated with cache_readonly get added to _cache
    _cache: Dict[str, Any]

    @property
    def _constructor(self):
        """
        Class constructor (for this class it's just `__class__`.
        """
        return type(self)

    def __repr__(self) -> str:
        """
        Return a string representation for a particular object.
        """
        # Should be overwritten by base classes
        return object.__repr__(self)

    def _reset_cache(self, key: Optional[str] = None) -> None:
        """
        Reset cached properties. If ``key`` is passed, only clears that key.
        """
        if not hasattr(self, "_cache"):
            return
        if key is None:
            self._cache.clear()
        else:
            self._cache.pop(key, None)

    def __sizeof__(self) -> int:
        """
        Generates the total memory usage for an object that returns
        either a value or Series of values
        """
        if hasattr(self, "memory_usage"):
            # error: "PandasObject" has no attribute "memory_usage"
            mem = self.memory_usage(deep=True)  # type: ignore[attr-defined]
            return int(mem if is_scalar(mem) else mem.sum())

        # no memory_usage attribute, so fall back to object's 'sizeof'
        return super().__sizeof__()


class NoNewAttributesMixin:
    """
    Mixin which prevents adding new attributes.

    Prevents additional attributes via xxx.attribute = "something" after a
    call to `self.__freeze()`. Mainly used to prevent the user from using
    wrong attributes on an accessor (`Series.cat/.str/.dt`).

    If you really want to add a new attribute at a later time, you need to use<commit_msg>TYP: remove ignore from PandasObject.__sizeof__ (#40271)<commit_after>"""
Base and utility classes for pandas objects.
"""

import builtins
import textwrap
from typing import (
    TYPE_CHECKING,
    Any,
    Callable,
    Dict,
    FrozenSet,
    Optional,
    TypeVar,
    Union,
    cast,
)

import numpy as np

import pandas._libs.lib as lib
from pandas._typing import (
    Dtype,
    DtypeObj,
    IndexLabel,
)
from pandas.compat import PYPY
from pandas.compat.numpy import function as nv
from pandas.errors import AbstractMethodError
from pandas.util._decorators import (
    cache_readonly,
    doc,
)

from pandas.core.dtypes.common import (
    is_categorical_dtype,
    is_dict_like,
    is_extension_array_dtype,
    is_object_dtype,
    is_scalar,
)
from pandas.core.dtypes.generic import (
    ABCDataFrame,
    ABCIndex,
    ABCSeries,
)
from pandas.core.dtypes.missing import (
    isna,
    remove_na_arraylike,
)

from pandas.core import algorithms
from pandas.core.accessor import DirNamesMixin
from pandas.core.algorithms import (
    duplicated,
    unique1d,
    value_counts,
)
from pandas.core.arraylike import OpsMixin
from pandas.core.arrays import ExtensionArray
from pandas.core.construction import create_series_with_explicit_dtype
import pandas.core.nanops as nanops

if TYPE_CHECKING:
    from pandas import Categorical

_shared_docs: Dict[str, str] = {}
_indexops_doc_kwargs = {
    "klass": "IndexOpsMixin",
    "inplace": "",
    "unique": "IndexOpsMixin",
    "duplicated": "IndexOpsMixin",
}

_T = TypeVar("_T", bound="IndexOpsMixin")


class PandasObject(DirNamesMixin):
    """
    Baseclass for various pandas objects.
    """

    # results from calls to methods decorated with cache_readonly get added to _cache
    _cache: Dict[str, Any]

    @property
    def _constructor(self):
        """
        Class constructor (for this class it's just `__class__`.
        """
        return type(self)

    def __repr__(self) -> str:
        """
        Return a string representation for a particular object.
        """
        # Should be overwritten by base classes
        return object.__repr__(self)

    def _reset_cache(self, key: Optional[str] = None) -> None:
        """
        Reset cached properties. If ``key`` is passed, only clears that key.
        """
        if not hasattr(self, "_cache"):
            return
        if key is None:
            self._cache.clear()
        else:
            self._cache.pop(key, None)

    def __sizeof__(self) -> int:
        """
        Generates the total memory usage for an object that returns
        either a value or Series of values
        """
        memory_usage = getattr(self, "memory_usage", None)
        if memory_usage:
            mem = memory_usage(deep=True)
            return int(mem if is_scalar(mem) else mem.sum())

        # no memory_usage attribute, so fall back to object's 'sizeof'
        return super().__sizeof__()


class NoNewAttributesMixin:
    """
    Mixin which prevents adding new attributes.

    Prevents additional attributes via xxx.attribute = "something" after a
    call to `self.__freeze()`. Mainly used to prevent the user from using
    wrong attributes on an accessor (`Series.cat/.str/.dt`).

    If you really want to add a new attribute at a later time, you need to use
{'fraction_non_alphanumeric': 0.08644016837041492, 'fraction_numerical': 0.0010523150932050512, 'mean_word_length': 2.8235632183908046, 'pattern_counts': {'":': 8, '<': 3, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3350678', 'n_tokens_mistral': 2019, 'n_tokens_neox': 1952, 'n_words': 619}