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

Code before:
import inspect
import json
import typing
import zlib
from time import perf_counter
from types import FunctionType, MappingProxyType, MethodType, ModuleType
from typing import Any

import numpy as np

from .. import logger

# Sometimes there are elements that are not suitable for hashing (too long or run-dependent)
# This is used to filter them out.
KEYS_TO_FILTER_OUT = set(
    ["original_id", "background", "pixel_array", "pixel_array_to_cairo_context"]
)


class _Memoizer:
    """Implements the memoization logic to optimize the hashing procedure and prevent the circular references within iterable processed.

    Keeps a record of all the processed objects, and handle the logic to return a place holder instead of the original object if the object has already been processed
    by the hashing logic (i.e, recusively checked, converted to JSON, etc..).

    This class used two signatures functions to keep a track of processed objects : hash or id. Whenever possible, hash is used to ensure a broader object content-equality detection.
    """

    _already_processed = set()

    # Can be changed to whatever string to help debugging the JSon generation.
    ALREADY_PROCESSED_PLACEHOLDER = "ALREADY PROCESSED"

    @classmethod
    def reset_already_processed(cls):
        cls._already_processed.clear()

    @classmethod
    def check_already_processed_decorator(cls: "_Memoizer", is_method=False):
        """Decorator to handle the arguments that goes through the decorated function. Returns _ALREADY_PROCESSED_PLACEHOLDER if the obj has been processed, or lets the decorated function call go ahead.

        Parameters
        ----------
        is_method : bool, optional
            Whether the function passed is a method, by default Falsep
        """

        def layer(func):
            # NOTE : There is probably a better to separate both case when func is a method or a function.
            if is_method:
                return lambda self, obj: cls._handle_already_processed(

Review comment (suggestion):
```suggestion
    This class uses two signatures functions to keep a track of processed objects : hash or id. Whenever possible, hash is used to ensure a broader object content-equality detection.
```

Code after:
import inspect
import json
import typing
import zlib
from time import perf_counter
from types import FunctionType, MappingProxyType, MethodType, ModuleType
from typing import Any

import numpy as np

from .. import logger

# Sometimes there are elements that are not suitable for hashing (too long or run-dependent)
# This is used to filter them out.
KEYS_TO_FILTER_OUT = set(
    ["original_id", "background", "pixel_array", "pixel_array_to_cairo_context"]
)


class _Memoizer:
    """Implements the memoization logic to optimize the hashing procedure and prevent the circular references within iterable processed.

    Keeps a record of all the processed objects, and handle the logic to return a place holder instead of the original object if the object has already been processed
    by the hashing logic (i.e, recursively checked, converted to JSON, etc..).

    This class uses two signatures functions to keep a track of processed objects : hash or id. Whenever possible, hash is used to ensure a broader object content-equality detection.
    """

    _already_processed = set()

    # Can be changed to whatever string to help debugging the JSon generation.
    ALREADY_PROCESSED_PLACEHOLDER = "ALREADY PROCESSED"

    @classmethod
    def reset_already_processed(cls):
        cls._already_processed.clear()

    @classmethod
    def check_already_processed_decorator(cls: "_Memoizer", is_method=False):
        """Decorator to handle the arguments that goes through the decorated function. Returns _ALREADY_PROCESSED_PLACEHOLDER if the obj has been processed, or lets the decorated function call go ahead.

        Parameters
        ----------
        is_method : bool, optional
            Whether the function passed is a method, by default False.
        """

        def layer(func):
            # NOTE : There is probably a better way to separate both case when func is a method or a function.
            if is_method:
                return lambda self, obj: cls._handle_already_processed(