浏览代码

Merge branch 'main' into add-validation-to-function-vars

Khaleel Al-Adhami 3 月之前
父节点
当前提交
1bb8ba5585
共有 1 个文件被更改,包括 81 次插入5 次删除
  1. 81 5
      reflex/vars/base.py

+ 81 - 5
reflex/vars/base.py

@@ -12,6 +12,7 @@ import json
 import random
 import random
 import re
 import re
 import string
 import string
+import uuid
 import warnings
 import warnings
 from types import CodeType, EllipsisType, FunctionType
 from types import CodeType, EllipsisType, FunctionType
 from typing import (
 from typing import (
@@ -1942,17 +1943,92 @@ def figure_out_type(value: Any) -> types.GenericType:
     return type(value)
     return type(value)
 
 
 
 
-class cached_property_no_lock(functools.cached_property):  # noqa: N801
-    """A special version of functools.cached_property that does not use a lock."""
+GLOBAL_CACHE = {}
+
+
+class cached_property:  # noqa: N801
+    """A cached property that caches the result of the function."""
 
 
     def __init__(self, func: Callable):
     def __init__(self, func: Callable):
-        """Initialize the cached_property_no_lock.
+        """Initialize the cached_property.
 
 
         Args:
         Args:
             func: The function to cache.
             func: The function to cache.
         """
         """
-        super().__init__(func)
-        self.lock = contextlib.nullcontext()
+        self._func = func
+        self._attrname = None
+
+    def __set_name__(self, owner: Any, name: str):
+        """Set the name of the cached property.
+
+        Args:
+            owner: The owner of the cached property.
+            name: The name of the cached property.
+
+        Raises:
+            TypeError: If the cached property is assigned to two different names.
+        """
+        if self._attrname is None:
+            self._attrname = name
+
+            original_del = getattr(owner, "__del__", None)
+
+            def delete_property(this: Any):
+                """Delete the cached property.
+
+                Args:
+                    this: The object to delete the cached property from.
+                """
+                cached_field_name = "_reflex_cache_" + name
+                try:
+                    unique_id = object.__getattribute__(this, cached_field_name)
+                except AttributeError:
+                    if original_del is not None:
+                        original_del(this)
+                    return
+                if unique_id in GLOBAL_CACHE:
+                    del GLOBAL_CACHE[unique_id]
+
+                if original_del is not None:
+                    original_del(this)
+
+            owner.__del__ = delete_property
+
+        elif name != self._attrname:
+            raise TypeError(
+                "Cannot assign the same cached_property to two different names "
+                f"({self._attrname!r} and {name!r})."
+            )
+
+    def __get__(self, instance: Any, owner: Type | None = None):
+        """Get the cached property.
+
+        Args:
+            instance: The instance to get the cached property from.
+            owner: The owner of the cached property.
+
+        Returns:
+            The cached property.
+
+        Raises:
+            TypeError: If the class does not have __set_name__.
+        """
+        if self._attrname is None:
+            raise TypeError(
+                "Cannot use cached_property on a class without __set_name__."
+            )
+        cached_field_name = "_reflex_cache_" + self._attrname
+        try:
+            unique_id = object.__getattribute__(instance, cached_field_name)
+        except AttributeError:
+            unique_id = uuid.uuid4().int
+            object.__setattr__(instance, cached_field_name, unique_id)
+        if unique_id not in GLOBAL_CACHE:
+            GLOBAL_CACHE[unique_id] = self._func(instance)
+        return GLOBAL_CACHE[unique_id]
+
+
+cached_property_no_lock = cached_property
 
 
 
 
 class CachedVarOperation:
 class CachedVarOperation: