METADATA 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. Metadata-Version: 2.4
  2. Name: async-lru
  3. Version: 2.3.0
  4. Summary: Simple LRU cache for asyncio
  5. Home-page: https://github.com/aio-libs/async-lru
  6. Maintainer: aiohttp team <team@aiohttp.org>
  7. Maintainer-email: team@aiohttp.org
  8. License: MIT License
  9. Project-URL: Chat: Matrix, https://matrix.to/#/#aio-libs:matrix.org
  10. Project-URL: Chat: Matrix Space, https://matrix.to/#/#aio-libs-space:matrix.org
  11. Project-URL: CI: GitHub Actions, https://github.com/aio-libs/async-lru/actions
  12. Project-URL: GitHub: repo, https://github.com/aio-libs/async-lru
  13. Keywords: asyncio,lru,lru_cache
  14. Classifier: License :: OSI Approved :: MIT License
  15. Classifier: Intended Audience :: Developers
  16. Classifier: Programming Language :: Python
  17. Classifier: Programming Language :: Python :: 3
  18. Classifier: Programming Language :: Python :: 3 :: Only
  19. Classifier: Programming Language :: Python :: 3.10
  20. Classifier: Programming Language :: Python :: 3.11
  21. Classifier: Programming Language :: Python :: 3.12
  22. Classifier: Programming Language :: Python :: 3.13
  23. Classifier: Programming Language :: Python :: 3.14
  24. Classifier: Development Status :: 5 - Production/Stable
  25. Classifier: Framework :: AsyncIO
  26. Requires-Python: >=3.10
  27. Description-Content-Type: text/x-rst
  28. License-File: LICENSE
  29. Requires-Dist: typing_extensions>=4.0.0; python_version < "3.11"
  30. Dynamic: license-file
  31. async-lru
  32. =========
  33. :info: Simple lru cache for asyncio
  34. .. image:: https://github.com/aio-libs/async-lru/actions/workflows/ci-cd.yml/badge.svg?event=push
  35. :target: https://github.com/aio-libs/async-lru/actions/workflows/ci-cd.yml?query=event:push
  36. :alt: GitHub Actions CI/CD workflows status
  37. .. image:: https://img.shields.io/pypi/v/async-lru.svg?logo=Python&logoColor=white
  38. :target: https://pypi.org/project/async-lru
  39. :alt: async-lru @ PyPI
  40. .. image:: https://codecov.io/gh/aio-libs/async-lru/branch/master/graph/badge.svg
  41. :target: https://codecov.io/gh/aio-libs/async-lru
  42. .. image:: https://img.shields.io/matrix/aio-libs:matrix.org?label=Discuss%20on%20Matrix%20at%20%23aio-libs%3Amatrix.org&logo=matrix&server_fqdn=matrix.org&style=flat
  43. :target: https://matrix.to/#/%23aio-libs:matrix.org
  44. :alt: Matrix Room — #aio-libs:matrix.org
  45. .. image:: https://img.shields.io/matrix/aio-libs-space:matrix.org?label=Discuss%20on%20Matrix%20at%20%23aio-libs-space%3Amatrix.org&logo=matrix&server_fqdn=matrix.org&style=flat
  46. :target: https://matrix.to/#/%23aio-libs-space:matrix.org
  47. :alt: Matrix Space — #aio-libs-space:matrix.org
  48. Installation
  49. ------------
  50. .. code-block:: shell
  51. pip install async-lru
  52. Usage
  53. -----
  54. This package is a port of Python's built-in `functools.lru_cache <https://docs.python.org/3/library/functools.html#functools.lru_cache>`_ function for `asyncio <https://docs.python.org/3/library/asyncio.html>`_. To better handle async behaviour, it also ensures multiple concurrent calls will only result in 1 call to the wrapped function, with all ``await``\s receiving the result of that call when it completes.
  55. .. code-block:: python
  56. import asyncio
  57. import aiohttp
  58. from async_lru import alru_cache
  59. @alru_cache(maxsize=32)
  60. async def get_pep(num):
  61. resource = 'http://www.python.org/dev/peps/pep-%04d/' % num
  62. async with aiohttp.ClientSession() as session:
  63. try:
  64. async with session.get(resource) as s:
  65. return await s.read()
  66. except aiohttp.ClientError:
  67. return 'Not Found'
  68. async def main():
  69. for n in 8, 290, 308, 320, 8, 218, 320, 279, 289, 320, 9991:
  70. pep = await get_pep(n)
  71. print(n, len(pep))
  72. print(get_pep.cache_info())
  73. # CacheInfo(hits=3, misses=8, maxsize=32, currsize=8)
  74. # closing is optional, but highly recommended
  75. await get_pep.cache_close()
  76. asyncio.run(main())
  77. TTL (time-to-live in seconds, expiration on timeout) is supported by accepting `ttl` configuration
  78. parameter (off by default):
  79. .. code-block:: python
  80. @alru_cache(ttl=5)
  81. async def func(arg):
  82. return arg * 2
  83. To prevent thundering herd issues when many cache entries expire simultaneously,
  84. you can add ``jitter`` to randomize the TTL for each entry:
  85. .. code-block:: python
  86. @alru_cache(ttl=3600, jitter=1800)
  87. async def func(arg):
  88. return arg * 2
  89. With ``ttl=3600, jitter=1800``, each cache entry will have a random TTL
  90. between 3600 and 5400 seconds, spreading out invalidations over time.
  91. The library supports explicit invalidation for specific function call by
  92. `cache_invalidate()`:
  93. .. code-block:: python
  94. @alru_cache(ttl=5)
  95. async def func(arg1, arg2):
  96. return arg1 + arg2
  97. func.cache_invalidate(1, arg2=2)
  98. The method returns `True` if corresponding arguments set was cached already, `False`
  99. otherwise.
  100. To check whether a specific set of arguments is present in the cache without
  101. affecting hit/miss counters or LRU ordering, use `cache_contains()`:
  102. .. code-block:: python
  103. @alru_cache(maxsize=32)
  104. async def func(arg1, arg2):
  105. return arg1 + arg2
  106. await func(1, arg2=2)
  107. func.cache_contains(1, arg2=2) # True
  108. func.cache_contains(3, arg2=4) # False
  109. The method returns `True` if the result for the given arguments is cached, `False`
  110. otherwise.
  111. Limitations
  112. -----------
  113. **Event Loop Affinity**: ``alru_cache`` enforces that a cache instance is used with only
  114. one event loop. If you attempt to use a cached function from a different event loop than
  115. where it was first called, a ``RuntimeError`` will be raised:
  116. .. code-block:: text
  117. RuntimeError: alru_cache is not safe to use across event loops: this cache
  118. instance was first used with a different event loop.
  119. Use separate cache instances per event loop.
  120. For typical asyncio applications using a single event loop, this is automatic and requires
  121. no configuration. If your application uses multiple event loops, create separate cache
  122. instances per loop:
  123. .. code-block:: python
  124. import threading
  125. _local = threading.local()
  126. def get_cached_fetcher():
  127. if not hasattr(_local, 'fetcher'):
  128. @alru_cache(maxsize=100)
  129. async def fetch_data(key):
  130. ...
  131. _local.fetcher = fetch_data
  132. return _local.fetcher
  133. You can also reuse the logic of an already decorated function in a new loop by accessing ``__wrapped__``:
  134. .. code-block:: python
  135. @alru_cache(maxsize=32)
  136. async def my_task(x):
  137. ...
  138. # In Loop 1:
  139. # my_task() uses the default global cache instance
  140. # In Loop 2 (or a new thread):
  141. # Create a fresh cache instance for the same logic
  142. cached_task_loop2 = alru_cache(maxsize=32)(my_task.__wrapped__)
  143. await cached_task_loop2(x)
  144. Benchmarks
  145. ----------
  146. async-lru uses `CodSpeed <https://codspeed.io/>`_ for performance regression testing.
  147. To run the benchmarks locally:
  148. .. code-block:: shell
  149. pip install -r requirements-dev.txt
  150. pytest --codspeed benchmark.py
  151. The benchmark suite covers both bounded (with maxsize) and unbounded (no maxsize) cache configurations. Scenarios include:
  152. - Cache hit
  153. - Cache miss
  154. - Cache fill/eviction (cycling through more keys than maxsize)
  155. - Cache clear
  156. - TTL expiry
  157. - Cache invalidation
  158. - Cache info retrieval
  159. - Concurrent cache hits
  160. - Baseline (uncached async function)
  161. On CI, benchmarks are run automatically via GitHub Actions on Python 3.13, and results are uploaded to CodSpeed (if a `CODSPEED_TOKEN` is configured). You can view performance history and detect regressions on the CodSpeed dashboard.
  162. Thanks
  163. ------
  164. The library was donated by `Ocean S.A. <https://ocean.io/>`_
  165. Thanks to the company for contribution.