cachify 0.1.0__py3-none-any.whl → 0.2.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,44 +1,44 @@
1
- import inspect
2
- from typing import Callable
3
-
4
- from cachify._async import async_decorator
5
- from cachify._sync import sync_decorator
6
- from cachify.types import CacheConfig, CacheKeyFunction, F, Number
7
-
8
-
9
- def create_cache_decorator(
10
- ttl: Number,
11
- never_die: bool,
12
- cache_key_func: CacheKeyFunction | None,
13
- ignore_fields: tuple[str, ...],
14
- config: CacheConfig,
15
- ) -> Callable[[F], F]:
16
- """
17
- Create a cache decorator with the given configuration.
18
-
19
- This is a shared factory used by both memory_cache and redis_cache
20
- to avoid code duplication.
21
- """
22
- if cache_key_func and ignore_fields:
23
- raise ValueError("Either cache_key_func or ignore_fields can be provided, but not both")
24
-
25
- def decorator(function: F) -> F:
26
- if inspect.iscoroutinefunction(function):
27
- return async_decorator(
28
- function=function,
29
- ttl=ttl,
30
- never_die=never_die,
31
- cache_key_func=cache_key_func,
32
- ignore_fields=ignore_fields,
33
- config=config,
34
- )
35
- return sync_decorator(
36
- function=function,
37
- ttl=ttl,
38
- never_die=never_die,
39
- cache_key_func=cache_key_func,
40
- ignore_fields=ignore_fields,
41
- config=config,
42
- )
43
-
44
- return decorator
1
+ import inspect
2
+ from typing import Callable
3
+
4
+ from cachify._async import async_decorator
5
+ from cachify._sync import sync_decorator
6
+ from cachify.types import CacheConfig, CacheKeyFunction, F, Number
7
+
8
+
9
+ def create_cache_decorator(
10
+ ttl: Number,
11
+ never_die: bool,
12
+ cache_key_func: CacheKeyFunction | None,
13
+ ignore_fields: tuple[str, ...],
14
+ config: CacheConfig,
15
+ ) -> Callable[[F], F]:
16
+ """
17
+ Create a cache decorator with the given configuration.
18
+
19
+ This is a shared factory used by both memory_cache and redis_cache
20
+ to avoid code duplication.
21
+ """
22
+ if cache_key_func and ignore_fields:
23
+ raise ValueError("Either cache_key_func or ignore_fields can be provided, but not both")
24
+
25
+ def decorator(function: F) -> F:
26
+ if inspect.iscoroutinefunction(function):
27
+ return async_decorator(
28
+ function=function,
29
+ ttl=ttl,
30
+ never_die=never_die,
31
+ cache_key_func=cache_key_func,
32
+ ignore_fields=ignore_fields,
33
+ config=config,
34
+ )
35
+ return sync_decorator(
36
+ function=function,
37
+ ttl=ttl,
38
+ never_die=never_die,
39
+ cache_key_func=cache_key_func,
40
+ ignore_fields=ignore_fields,
41
+ config=config,
42
+ )
43
+
44
+ return decorator
@@ -1,10 +1,10 @@
1
- import functools
2
- from typing import Any, Callable
3
-
4
-
5
- @functools.cache
6
- def get_function_id(function: Callable[..., Any]) -> str:
7
- """
8
- Returns the unique identifier for the function, which is a combination of its module and qualified name.
9
- """
10
- return f"{function.__module__}.{function.__qualname__}"
1
+ import functools
2
+ from typing import Any, Callable
3
+
4
+
5
+ @functools.cache
6
+ def get_function_id(function: Callable[..., Any]) -> str:
7
+ """
8
+ Returns the unique identifier for the function, which is a combination of its module and qualified name.
9
+ """
10
+ return f"{function.__module__}.{function.__qualname__}"
cachify/utils/locks.py CHANGED
@@ -1,6 +1,6 @@
1
- import asyncio
2
- import threading
3
- from collections import defaultdict
4
-
5
- ASYNC_LOCKS: defaultdict[str, asyncio.Lock] = defaultdict(asyncio.Lock)
6
- SYNC_LOCKS: defaultdict[str, threading.Lock] = defaultdict(threading.Lock)
1
+ import asyncio
2
+ import threading
3
+ from collections import defaultdict
4
+
5
+ ASYNC_LOCKS: defaultdict[str, asyncio.Lock] = defaultdict(asyncio.Lock)
6
+ SYNC_LOCKS: defaultdict[str, threading.Lock] = defaultdict(threading.Lock)
@@ -1,9 +1,9 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: cachify
3
- Version: 0.1.0
3
+ Version: 0.2.1
4
4
  Summary: A simple cache library with sync/async support, Memory and Redis backend
5
- Home-page: https://github.com/PulsarDataSolutions/cachify
6
5
  License: MIT
6
+ License-File: LICENSE
7
7
  Keywords: cachify,cache,caching,redis,async,decorator,memoization
8
8
  Author: dynalz
9
9
  Author-email: git@pulsar.finance
@@ -20,6 +20,7 @@ Classifier: Programming Language :: Python :: 3.14
20
20
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
21
21
  Classifier: Typing :: Typed
22
22
  Requires-Dist: redis[hiredis] (>5.0.0)
23
+ Project-URL: Homepage, https://github.com/PulsarDataSolutions/cachify
23
24
  Project-URL: Repository, https://github.com/PulsarDataSolutions/cachify
24
25
  Description-Content-Type: text/markdown
25
26
 
@@ -27,6 +28,19 @@ Description-Content-Type: text/markdown
27
28
 
28
29
  A simple and robust caching library for Python functions, supporting both synchronous and asynchronous code.
29
30
 
31
+ ## Table of Contents
32
+
33
+ - [Features](#features)
34
+ - [Installation](#installation)
35
+ - [Usage](#usage)
36
+ - [Basic Usage](#basic-usage)
37
+ - [Redis Cache](#redis-cache)
38
+ - [Never Die Cache](#never-die-cache)
39
+ - [Skip Cache](#skip-cache)
40
+ - [Testing](#testing)
41
+ - [Contributing](#contributing)
42
+ - [License](#license)
43
+
30
44
  ## Features
31
45
 
32
46
  - Cache function results based on function ID and arguments
@@ -40,12 +54,14 @@ A simple and robust caching library for Python functions, supporting both synchr
40
54
  ## Installation
41
55
 
42
56
  ```bash
43
- # Clone the repository
44
- git clone https://github.com/PulsarDefi/cachify.git
45
- cd cachify
57
+ # Using pip
58
+ pip install cachify
59
+
60
+ # Using poetry
61
+ poetry add cachify
46
62
 
47
- # Install the package
48
- poetry install
63
+ # Using uv
64
+ uv add cachify
49
65
  ```
50
66
 
51
67
  ## Usage
@@ -56,18 +72,57 @@ poetry install
56
72
  from cachify import cache
57
73
 
58
74
  # Cache function in sync functions
59
- @cache(ttl=60) # ttl in seconds
75
+ @cache(ttl=60) # ttl in seconds
60
76
  def expensive_calculation(a, b):
61
77
  # Some expensive operation
62
78
  return a + b
63
79
 
64
80
  # And async functions
65
- @cache(ttl=3600) # ttl in seconds
81
+ @cache(ttl=3600) # ttl in seconds
66
82
  async def another_calculation(url):
67
83
  # Some expensive IO call
68
84
  return await httpx.get(url).json()
69
85
  ```
70
86
 
87
+ ### Decorator Parameters
88
+
89
+ | Parameter | Type | Default | Description |
90
+ | ---------------- | ----------------- | ------- | ---------------------------------------------------- |
91
+ | `ttl` | `int \| float` | `300` | Time to live for cached items in seconds |
92
+ | `never_die` | `bool` | `False` | If True, cache refreshes automatically in background |
93
+ | `cache_key_func` | `Callable` | `None` | Custom function to generate cache keys |
94
+ | `ignore_fields` | `tuple[str, ...]` | `()` | Function parameters to exclude from cache key |
95
+
96
+ ### Custom Cache Key Function
97
+
98
+ Use `cache_key_func` when you need custom control over how cache keys are generated:
99
+
100
+ ```python
101
+ from cachify import cache
102
+
103
+ def custom_key(args: tuple, kwargs: dict) -> str:
104
+ user_id = kwargs.get("user_id") or args[0]
105
+ return f"user:{user_id}"
106
+
107
+ @cache(ttl=60, cache_key_func=custom_key)
108
+ def get_user_profile(user_id: int):
109
+ return fetch_from_database(user_id)
110
+ ```
111
+
112
+ ### Ignore Fields
113
+
114
+ Use `ignore_fields` to exclude specific parameters from the cache key. Useful when some arguments don't affect the result:
115
+
116
+ ```python
117
+ from cachify import cache
118
+
119
+ @cache(ttl=300, ignore_fields=("logger", "request_id"))
120
+ def fetch_data(query: str, logger: Logger, request_id: str):
121
+ # Cache key only uses 'query', ignoring logger and request_id
122
+ logger.info(f"Fetching data for request {request_id}")
123
+ return database.execute(query)
124
+ ```
125
+
71
126
  ### Redis Cache
72
127
 
73
128
  For distributed caching across multiple processes or machines, use `rcache`:
@@ -79,7 +134,7 @@ from cachify import setup_redis_config, rcache
79
134
  # Configure Redis (call once at startup)
80
135
  setup_redis_config(
81
136
  sync_client=redis.from_url("redis://localhost:6379/0"),
82
- key_prefix="myapp", # default: "key_prefix", prefix searchable on redis "PREFIX:*"
137
+ key_prefix="myapp", # default: "cachify", prefix searchable on redis "PREFIX:*"
83
138
  lock_timeout=10, # default: 10, maximum lock lifetime in seconds
84
139
  on_error="silent", # "silent" (default) or "raise" in case of redis errors
85
140
  )
@@ -94,7 +149,7 @@ import redis.asyncio as aredis
94
149
  setup_redis_config(async_client=aredis.from_url("redis://localhost:6379/0"))
95
150
 
96
151
  @rcache(ttl=300)
97
- def get_user_async(user_id: int) -> dict:
152
+ async def get_user_async(user_id: int) -> dict:
98
153
  return await fetch_from_database(user_id)
99
154
  ```
100
155
 
@@ -165,7 +220,11 @@ Run the test scripts
165
220
  poetry run python -m pytest
166
221
  ```
167
222
 
223
+ ## Contributing
224
+
225
+ Contributions are welcome! Feel free to open an issue or submit a pull request.
226
+
168
227
  ## License
169
228
 
170
- MIT
229
+ This project is licensed under the MIT License - see the [LICENSE](https://github.com/PulsarDataSolutions/cachify/blob/master/LICENSE) file for details.
171
230
 
@@ -0,0 +1,24 @@
1
+ cachify/__init__.py,sha256=OvqM85Qq3rO6-KilFjq4MO0rm_NBdTfzAo2uhBVksdU,550
2
+ cachify/cache.py,sha256=zJM9J4DdBXyGquQUTDJJ_voC51p-RM_CQcC-4DM92Gg,4021
3
+ cachify/config/__init__.py,sha256=ZvLLEsprTbKai3-uUTbZ6Axbgf-xw-7sxmz8Y62YdT4,98
4
+ cachify/features/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
+ cachify/features/never_die.py,sha256=NJvCJhHMjxxaVZCC5xrUATcBBm4OXXHdipOg6wjOfV4,7111
6
+ cachify/memory_cache.py,sha256=2UEnYXSJJ0XlqVM7sJ2GkPW1reU7DRtfifHEdbJQrYY,1328
7
+ cachify/redis/__init__.py,sha256=geuYVjwJdddlhrnt45cHzkJ7Anrhttm2F3Q3r0TTMLk,410
8
+ cachify/redis/config.py,sha256=Gvlj_hrUlsIGYqu50dghrv83R5UEOMJa4jVeK-nBAOs,3558
9
+ cachify/redis/lock.py,sha256=XbE5GHZIWUs9gqyfgle3Bur5CfKJ1pLhgtLctmZLB94,7281
10
+ cachify/redis_cache.py,sha256=WVc26EpAVSyQptD3guDD2LuPDgnuL72BCvhln-n84hc,873
11
+ cachify/storage/__init__.py,sha256=8FJOYwjg8LHVoNkyupdgKOR61LPfX5Bpz_mvnn-T-oU,250
12
+ cachify/storage/memory_storage.py,sha256=rsQqoymWczzkfXisF-9Tc9UGQem936U6_vd9Uo-sWnU,1481
13
+ cachify/storage/redis_storage.py,sha256=wZaKg7h98cmESpqiOmh906D5wfNBxYN80x-LQDLtb-c,4767
14
+ cachify/types/__init__.py,sha256=OataAgBEQXxpc376uZFM6cmdzJLUkzkj_H8XiKq5zpU,2641
15
+ cachify/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
16
+ cachify/utils/arguments.py,sha256=7NcuntqxK7G1UV4wrIaLNfxE0E7Gr-MmPWi9U-JyQ9o,2000
17
+ cachify/utils/decorator_factory.py,sha256=brraPKR7ZJqdTbp8s5tEk6D517CKOlo9z1ZLoqhoz_s,1325
18
+ cachify/utils/functions.py,sha256=AA1GXJEEBsIr2NX9h6AslAdmqKaWUcjnf1q5kA216uY,312
19
+ cachify/utils/locks.py,sha256=7x-4XK27NiM_Eu04pftUgEgu91w8B3rE15jjAl0g1AE,216
20
+ cachify-0.2.1.dist-info/METADATA,sha256=pl450wfErW4M_deswdy9thDYahuDHno6p1LfJ3kdmHU,7432
21
+ cachify-0.2.1.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
22
+ cachify-0.2.1.dist-info/entry_points.txt,sha256=a8B7GSYgDPfUClqct0o7yyBbJ61AWgSSy1idL6YZLUM,45
23
+ cachify-0.2.1.dist-info/licenses/LICENSE,sha256=zUzOFiuoPIQzGktjk4kL78hpi57iWD6-Kug_96OgUO0,1071
24
+ cachify-0.2.1.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: poetry-core 1.9.1
2
+ Generator: poetry-core 2.2.1
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
@@ -1,21 +1,21 @@
1
- MIT License
2
-
3
- Copyright (c) 2025 Pulsar Finance
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Pulsar Finance
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -1,24 +0,0 @@
1
- cachify/__init__.py,sha256=5Q5eK7Pyty7-eSF99DBSa79FnKq27MGNiCYPkhY3uxo,553
2
- cachify/cache.py,sha256=Y1hh3t9DlcaG8KoVi3gZHevPzZf59WPIdDb_VsooHqo,4137
3
- cachify/config/__init__.py,sha256=xWH80AN6A2O2DlrY3ITkLYEkqnNv8WqGWhNAszVZq5w,102
4
- cachify/features/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
- cachify/features/never_die.py,sha256=A8sVAgVP-s6hlEs8FqrmHFg_-TJ8Bu8E8M_d3gwBpdg,7330
6
- cachify/memory_cache.py,sha256=9bDgV0Lb7ZB_ieARQmiKyi0nrn7E-cqQX9lH4d9xFFk,1365
7
- cachify/redis/__init__.py,sha256=4ZCbpo1tfU1O06pvIjerCuSR7XfopJly7mWgp9NZ_tg,429
8
- cachify/redis/config.py,sha256=ShaNvP6-vRnxWtFk3cD6lzMcPigpCM8FnFVBv21jxk4,3673
9
- cachify/redis/lock.py,sha256=NwrCa-z9fcXLvuaUrTsdCeNqoHIhR-Rm0J56fZ_0kT4,7513
10
- cachify/redis_cache.py,sha256=roQ3ENdqUe6n03nX4RFB0wrOKowUEcEY96BJV48hzRQ,900
11
- cachify/storage/__init__.py,sha256=p62r3EJPidhkHtw2OgV-gAH4U-wDtB8ZU_IbE5e3CdQ,259
12
- cachify/storage/memory_storage.py,sha256=lwSbCYqT4NyRwgPs8TMSjHIp5aTJs6bXmQmMKFOIhVM,1533
13
- cachify/storage/redis_storage.py,sha256=NOwWaSjca6591pMbLaHMmtelutXkAhxuWbFkoWChRnA,4905
14
- cachify/types/__init__.py,sha256=VpDvMLFAxVo-J9MISzE-liT-wiZzo4AYHG7cQgVi-TI,2736
15
- cachify/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
16
- cachify/utils/arguments.py,sha256=m4TMXmZ5nC9tDyS4BBDjsW41Q7L2LOx6zEWFN70ux70,2065
17
- cachify/utils/decorator_factory.py,sha256=5Cqz_QQDc7jVvVb_yscF41EC5o8mOda2nDeR6NvPGh8,1369
18
- cachify/utils/functions.py,sha256=QqpdJVvmwkPtHnPhFj5xpouJL_jQ29ySOjPkgvNg-Y0,322
19
- cachify/utils/locks.py,sha256=nvNnFuu3ooGpptH4-5tpaUU2YJmXlVqZ_GTQRWmKX7g,222
20
- cachify-0.1.0.dist-info/entry_points.txt,sha256=a8B7GSYgDPfUClqct0o7yyBbJ61AWgSSy1idL6YZLUM,45
21
- cachify-0.1.0.dist-info/LICENSE,sha256=nOY-lEC7Zaqf05sDxPYQ8iOGaShYMB2zf1Kr-M5hE-w,1092
22
- cachify-0.1.0.dist-info/METADATA,sha256=pkPXhJ5vOrtH8qi56CaESR_gI4B7c_iaZbg-ZNrlNVc,5340
23
- cachify-0.1.0.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
24
- cachify-0.1.0.dist-info/RECORD,,