Skip to content

Commit 7da5fa0

Browse files
adhami3310masenf
andauthored
implement a global var cache (#4691)
* implement a global var cache * fix misisng types --------- Co-authored-by: Masen Furer <[email protected]>
1 parent 8663dbc commit 7da5fa0

File tree

1 file changed

+81
-5
lines changed

1 file changed

+81
-5
lines changed

reflex/vars/base.py

Lines changed: 81 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import random
1313
import re
1414
import string
15+
import uuid
1516
import warnings
1617
from types import CodeType, FunctionType
1718
from typing import (
@@ -1666,17 +1667,92 @@ def figure_out_type(value: Any) -> types.GenericType:
16661667
return type(value)
16671668

16681669

1669-
class cached_property_no_lock(functools.cached_property): # noqa: N801
1670-
"""A special version of functools.cached_property that does not use a lock."""
1670+
GLOBAL_CACHE = {}
1671+
1672+
1673+
class cached_property: # noqa: N801
1674+
"""A cached property that caches the result of the function."""
16711675

16721676
def __init__(self, func: Callable):
1673-
"""Initialize the cached_property_no_lock.
1677+
"""Initialize the cached_property.
16741678
16751679
Args:
16761680
func: The function to cache.
16771681
"""
1678-
super().__init__(func)
1679-
self.lock = contextlib.nullcontext()
1682+
self._func = func
1683+
self._attrname = None
1684+
1685+
def __set_name__(self, owner: Any, name: str):
1686+
"""Set the name of the cached property.
1687+
1688+
Args:
1689+
owner: The owner of the cached property.
1690+
name: The name of the cached property.
1691+
1692+
Raises:
1693+
TypeError: If the cached property is assigned to two different names.
1694+
"""
1695+
if self._attrname is None:
1696+
self._attrname = name
1697+
1698+
original_del = getattr(owner, "__del__", None)
1699+
1700+
def delete_property(this: Any):
1701+
"""Delete the cached property.
1702+
1703+
Args:
1704+
this: The object to delete the cached property from.
1705+
"""
1706+
cached_field_name = "_reflex_cache_" + name
1707+
try:
1708+
unique_id = object.__getattribute__(this, cached_field_name)
1709+
except AttributeError:
1710+
if original_del is not None:
1711+
original_del(this)
1712+
return
1713+
if unique_id in GLOBAL_CACHE:
1714+
del GLOBAL_CACHE[unique_id]
1715+
1716+
if original_del is not None:
1717+
original_del(this)
1718+
1719+
owner.__del__ = delete_property
1720+
1721+
elif name != self._attrname:
1722+
raise TypeError(
1723+
"Cannot assign the same cached_property to two different names "
1724+
f"({self._attrname!r} and {name!r})."
1725+
)
1726+
1727+
def __get__(self, instance: Any, owner: Type | None = None):
1728+
"""Get the cached property.
1729+
1730+
Args:
1731+
instance: The instance to get the cached property from.
1732+
owner: The owner of the cached property.
1733+
1734+
Returns:
1735+
The cached property.
1736+
1737+
Raises:
1738+
TypeError: If the class does not have __set_name__.
1739+
"""
1740+
if self._attrname is None:
1741+
raise TypeError(
1742+
"Cannot use cached_property on a class without __set_name__."
1743+
)
1744+
cached_field_name = "_reflex_cache_" + self._attrname
1745+
try:
1746+
unique_id = object.__getattribute__(instance, cached_field_name)
1747+
except AttributeError:
1748+
unique_id = uuid.uuid4().int
1749+
object.__setattr__(instance, cached_field_name, unique_id)
1750+
if unique_id not in GLOBAL_CACHE:
1751+
GLOBAL_CACHE[unique_id] = self._func(instance)
1752+
return GLOBAL_CACHE[unique_id]
1753+
1754+
1755+
cached_property_no_lock = cached_property
16801756

16811757

16821758
class CachedVarOperation:

0 commit comments

Comments
 (0)