Repository: ManimCommunity/manim
File: manim/utils/hashing.py (Python)

Code before:
            )
            and obj not in [None, cls.ALREADY_PROCESSED_PLACEHOLDER]
        ):
            # It makes no sense (and it'd slower) to memoize objects of these primitive types.
            # Hence, we simply return the object.
            return obj
        if isinstance(obj, collections.abc.Hashable):
            try:
                return cls._return(obj, hash, default_function)
            except TypeError:
                # In case of an error with the hash (eg an object is marked as hashable but contains a non hashable within it)
                # Fallback to use the built-in function id instead.
                pass
        return cls._return(obj, id, default_function)

    @classmethod
    def _return(
        cls,
        obj: typing.Any,
        obj_to_membership_sign: typing.Callable[[Any], int],
        default_func,
        memoizing=True,
    ) -> typing.Union[str, Any]:
        if len(cls._already_processed) == cls.THRESHOLD_WARNING:
            logger.warning(
                "It looks like the scene contains a lot of sub-mobjects. Caching mecanism is not suited to handle such large scenes, you might consider disabling caching with\
                           --disable_caching to speed up the rendering process."
            )
        obj_membership_sign = obj_to_membership_sign(obj)
        if obj_membership_sign in cls._already_processed:
            return cls.ALREADY_PROCESSED_PLACEHOLDER
        if memoizing:
            cls._already_processed.add(obj_membership_sign)
        return default_func(obj)


class _CustomEncoder(json.JSONEncoder):
    def default(self, obj):
        """
        This method is used to serialize objects to JSON format.

        If obj is a function, then it will return a dict with two keys : 'code', for the code source, and 'nonlocals' for all nonlocalsvalues. (including nonlocals functions, that will be serialized as this is recursive.)
        if obj is a np.darray, it converts it into a list.
        if obj is an object with __dict__ attribute, it returns its __dict__.
        Else, will let the JSONEncoder do the stuff, and throw an error if the type is not suitable for JSONEncoder.

        Parameters
        ----------
        obj : Any
            Arbitrary object to convert


Review comment (suggestion):
```suggestion
                "It looks like the scene contains a lot of sub-mobjects. Caching is not suited to handle such large scenes, you might consider disabling caching with\
```

Code after:
            )
            and obj not in [None, cls.ALREADY_PROCESSED_PLACEHOLDER]
        ):
            # It makes no sense (and it'd slower) to memoize objects of these primitive types.
            # Hence, we simply return the object.
            return obj
        if isinstance(obj, collections.abc.Hashable):
            try:
                return cls._return(obj, hash, default_function)
            except TypeError:
                # In case of an error with the hash (eg an object is marked as hashable but contains a non hashable within it)
                # Fallback to use the built-in function id instead.
                pass
        return cls._return(obj, id, default_function)

    @classmethod
    def _return(
        cls,
        obj: typing.Any,
        obj_to_membership_sign: typing.Callable[[Any], int],
        default_func,
        memoizing=True,
    ) -> typing.Union[str, Any]:
        obj_membership_sign = obj_to_membership_sign(obj)
        if obj_membership_sign in cls._already_processed:
            return cls.ALREADY_PROCESSED_PLACEHOLDER
        if memoizing:
            if (
                not config.disable_caching_warning
                and len(cls._already_processed) == cls.THRESHOLD_WARNING
            ):
                logger.warning(
                    "It looks like the scene contains a lot of sub-mobjects. Caching is sometimes not suited to handle such large scenes, you might consider disabling caching with\
                            --disable_caching to potentially speed up the rendering process."
                )
                logger.warning(
                    "You can disable this warning by setting disable_caching_warning to True in your config file."
                )

            cls._already_processed.add(obj_membership_sign)
        return default_func(obj)


class _CustomEncoder(json.JSONEncoder):
    def default(self, obj):
        """
        This method is used to serialize objects to JSON format.

        If obj is a function, then it will return a dict with two keys : 'code', for the code source, and 'nonlocals' for all nonlocalsvalues. (including nonlocals functions, that will be serialized as this is recursive.)
        if obj is a np.darray, it converts it into a list.
        if obj is an object with __dict__ attribute, it returns its __dict__.