simple-dep-cache 0.1.1__tar.gz

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.
@@ -0,0 +1,26 @@
1
+ name: Publish Package to PyPI
2
+ on:
3
+ release:
4
+ types: [published]
5
+ workflow_dispatch:
6
+
7
+ jobs:
8
+ pypi-publish:
9
+ name: Upload to PyPI
10
+ runs-on: ubuntu-latest
11
+ permissions:
12
+ id-token: write
13
+ steps:
14
+ - name: Checkout
15
+ uses: actions/checkout@v5
16
+ with:
17
+ fetch-depth: 0
18
+
19
+ - name: "Install uv"
20
+ uses: astral-sh/setup-uv@v6
21
+
22
+ - name: Build
23
+ run: uv build
24
+
25
+ - name: Publish to PyPi
26
+ run: uv publish -v dist/*
@@ -0,0 +1,25 @@
1
+ name: Static Check
2
+
3
+ on:
4
+ push:
5
+ branches: [ master ]
6
+ pull_request:
7
+ branches: [ master ]
8
+
9
+ jobs:
10
+ static-check:
11
+ runs-on: ubuntu-latest
12
+ steps:
13
+ - uses: actions/checkout@v5
14
+
15
+ - name: Install uv
16
+ uses: astral-sh/setup-uv@v6
17
+ with:
18
+ version: "latest"
19
+
20
+ - name: Install dependencies
21
+ run: uv sync --all-extras
22
+
23
+ - name: Run static checks
24
+ run: uv run pre-commit run --all-files
25
+
@@ -0,0 +1,26 @@
1
+ name: Test
2
+
3
+ on:
4
+ push:
5
+ branches: [ master ]
6
+ pull_request:
7
+ branches: [ master ]
8
+
9
+ jobs:
10
+ test:
11
+ runs-on: ubuntu-latest
12
+
13
+ steps:
14
+ - uses: actions/checkout@v5
15
+
16
+ - name: Install uv
17
+ uses: astral-sh/setup-uv@v6
18
+ with:
19
+ version: "latest"
20
+
21
+ - name: Install dependencies
22
+ run: uv sync --all-extras
23
+
24
+ - name: Run tests
25
+ run: uv run pytest
26
+
@@ -0,0 +1,10 @@
1
+ # Python-generated files
2
+ __pycache__/
3
+ *.py[oc]
4
+ build/
5
+ dist/
6
+ wheels/
7
+ *.egg-info
8
+
9
+ # Virtual environments
10
+ .venv
@@ -0,0 +1,8 @@
1
+ repos:
2
+ - repo: https://github.com/astral-sh/ruff-pre-commit
3
+ rev: v0.13.0
4
+ hooks:
5
+ - id: ruff-check
6
+ args: [--fix]
7
+ - id: ruff-format
8
+
@@ -0,0 +1 @@
1
+ 3.11
@@ -0,0 +1,63 @@
1
+ # Exclude a variety of commonly ignored directories.
2
+ exclude = [
3
+ ".bzr",
4
+ ".direnv",
5
+ ".eggs",
6
+ ".git",
7
+ ".git-rewrite",
8
+ ".hg",
9
+ ".ipynb_checkpoints",
10
+ ".mypy_cache",
11
+ ".nox",
12
+ ".pants.d",
13
+ ".pyenv",
14
+ ".pytest_cache",
15
+ ".pytype",
16
+ ".ruff_cache",
17
+ ".svn",
18
+ ".tox",
19
+ ".venv",
20
+ ".vscode",
21
+ "__pypackages__",
22
+ "_build",
23
+ "buck-out",
24
+ "build",
25
+ "dist",
26
+ "node_modules",
27
+ "site-packages",
28
+ "venv",
29
+ "*/migrations/*",
30
+ ]
31
+
32
+ line-length = 100
33
+ indent-width = 4
34
+
35
+ [lint]
36
+ select = [
37
+ "E", # pycodestyle errors
38
+ "W", # pycodestyle warnings
39
+ "F", # pyflakes
40
+ "I", # isort
41
+ "B", # flake8-bugbear
42
+ "C4", # flake8-comprehensions
43
+ "UP", # pyupgrade
44
+ ]
45
+ ignore = [
46
+ ]
47
+
48
+ # Per-file ignores for common patterns
49
+ [lint.per-file-ignores]
50
+ "**/tests/**" = [
51
+ "F841", # Local variable is assigned to but never used
52
+ ]
53
+
54
+ [format]
55
+ # Like Black, use double quotes for strings.
56
+ quote-style = "double"
57
+
58
+ # Like Black, indent with spaces, rather than tabs.
59
+ indent-style = "space"
60
+
61
+ # Like Black, respect magic trailing commas.
62
+ skip-magic-trailing-comma = false
63
+
@@ -0,0 +1,161 @@
1
+ Metadata-Version: 2.4
2
+ Name: simple-dep-cache
3
+ Version: 0.1.1
4
+ Summary: Redis-based caching library with intelligent dependency tracking for Python applications
5
+ License: MIT
6
+ Keywords: cache,cache invalidation,dependency,redis
7
+ Classifier: Intended Audience :: Developers
8
+ Classifier: License :: OSI Approved :: MIT License
9
+ Classifier: Programming Language :: Python :: 3
10
+ Classifier: Programming Language :: Python :: 3.10
11
+ Classifier: Programming Language :: Python :: 3.11
12
+ Classifier: Programming Language :: Python :: 3.12
13
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
14
+ Requires-Python: >=3.10
15
+ Requires-Dist: redis
16
+ Provides-Extra: fast-json
17
+ Requires-Dist: orjson; extra == 'fast-json'
18
+ Description-Content-Type: text/markdown
19
+
20
+ # simple-dep-cache
21
+
22
+ A Redis-based caching library with dependency tracking for Python applications.
23
+
24
+ ## Overview
25
+
26
+ Cache function results and automatically invalidate related caches when dependencies change. Uses Redis for distributed caching and supports both sync/async functions.
27
+
28
+ ## Installation
29
+
30
+ ```bash
31
+ pip install simple-dep-cache
32
+ ```
33
+
34
+ ## Quick Start
35
+
36
+ ### Basic Usage
37
+
38
+ ```python
39
+ from simple_dep_cache import cache_with_deps, add_dependency, CacheManager
40
+
41
+ # Initialize cache manager (optional - will be created automatically if not provided)
42
+ cache = CacheManager()
43
+
44
+ @cache_with_deps(cache_manager=cache, ttl=300)
45
+ def get_user_profile(user_id):
46
+ # This function's result depends on user data
47
+ add_dependency(f"user:{user_id}")
48
+
49
+ # Expensive operation (e.g., database query, API call)
50
+ return fetch_user_from_database(user_id)
51
+
52
+ @cache_with_deps(ttl=600) # No cache_manager - will create one automatically
53
+ def get_user_posts(user_id):
54
+ # This depends on both user and posts data
55
+ add_dependency(f"user:{user_id}")
56
+ add_dependency(f"posts:user:{user_id}")
57
+
58
+ return fetch_user_posts_from_database(user_id)
59
+
60
+ # Use the cached functions
61
+ profile = get_user_profile("123") # Cache miss - fetches from DB
62
+ profile = get_user_profile("123") # Cache hit - returns cached result
63
+
64
+ posts = get_user_posts("123") # Cache miss - fetches from DB
65
+ posts = get_user_posts("123") # Cache hit - returns cached result
66
+
67
+ # When user data changes, invalidate the dependency
68
+ cache.invalidate_dependency("user:123")
69
+ # Now both get_user_profile("123") and get_user_posts("123") are invalidated!
70
+
71
+ profile = get_user_profile("123") # Cache miss - will fetch fresh data
72
+ ```
73
+
74
+ ### Async Support
75
+
76
+ ```python
77
+ from simple_dep_cache import async_cache_with_deps, add_dependency, AsyncCacheManager
78
+
79
+ cache = AsyncCacheManager()
80
+
81
+ @async_cache_with_deps(cache_manager=cache, ttl=300)
82
+ async def get_user_profile_async(user_id):
83
+ add_dependency(f"user:{user_id}")
84
+ return await fetch_user_from_database_async(user_id)
85
+
86
+ # Usage
87
+ profile = await get_user_profile_async("123") # Cache miss
88
+ profile = await get_user_profile_async("123") # Cache hit
89
+
90
+ # Invalidate dependency
91
+ await cache.invalidate_dependency("user:123")
92
+ ```
93
+
94
+ ### Monitoring
95
+
96
+ ```python
97
+ from simple_dep_cache import StatsCollector, create_logger_callback
98
+
99
+ cache = CacheManager()
100
+ stats = StatsCollector()
101
+ cache.events.on_all(stats)
102
+ cache.events.on_all(create_logger_callback("my_cache"))
103
+
104
+ # Check statistics
105
+ print(stats.get_stats()) # hit_ratio, ops_per_second, etc.
106
+ ```
107
+
108
+ ## Configuration
109
+
110
+ ```bash
111
+ REDIS_URL=redis://localhost:6379/0 # Full Redis URL (preferred)
112
+ REDIS_HOST=localhost # Or individual settings
113
+ REDIS_PORT=6379
114
+ REDIS_PASSWORD=secret
115
+ DEP_CACHE_ENABLED=true # Disable caching entirely
116
+ ```
117
+
118
+ ## Manual Cache Operations
119
+
120
+ ```python
121
+ cache = CacheManager()
122
+
123
+ # Direct operations
124
+ cache.set("key", value, ttl=300, dependencies={"dep1"})
125
+ value = cache.get("key")
126
+ cache.delete("key")
127
+ cache.invalidate_dependency("dep1") # Invalidates all dependent caches
128
+ ```
129
+
130
+ ## API Reference
131
+
132
+ **Decorators:**
133
+
134
+ - `@cache_with_deps(cache_manager, ttl, key_prefix, dependencies)`
135
+ - `@async_cache_with_deps(cache_manager, ttl, key_prefix, dependencies)`
136
+
137
+ If `cache_manager` is not provided, one will be created automatically using configured environment variables or defaults.
138
+
139
+ **Context:**
140
+
141
+ - `add_dependency(dependency)` - Track dependency in current function
142
+ - `current_cache_key()` - Get current cache key
143
+
144
+ **Managers:**
145
+
146
+ - `CacheManager(redis_client, prefix)` - Sync Redis cache manager
147
+ - `AsyncCacheManager(redis_client, prefix)` - Async Redis cache manager
148
+
149
+ **Monitoring:**
150
+
151
+ - `StatsCollector()` - Cache statistics
152
+
153
+ ## Requirements
154
+
155
+ - Python 3.10+
156
+ - Redis server
157
+ - `redis` package
158
+
159
+ ## License
160
+
161
+ MIT
@@ -0,0 +1,142 @@
1
+ # simple-dep-cache
2
+
3
+ A Redis-based caching library with dependency tracking for Python applications.
4
+
5
+ ## Overview
6
+
7
+ Cache function results and automatically invalidate related caches when dependencies change. Uses Redis for distributed caching and supports both sync/async functions.
8
+
9
+ ## Installation
10
+
11
+ ```bash
12
+ pip install simple-dep-cache
13
+ ```
14
+
15
+ ## Quick Start
16
+
17
+ ### Basic Usage
18
+
19
+ ```python
20
+ from simple_dep_cache import cache_with_deps, add_dependency, CacheManager
21
+
22
+ # Initialize cache manager (optional - will be created automatically if not provided)
23
+ cache = CacheManager()
24
+
25
+ @cache_with_deps(cache_manager=cache, ttl=300)
26
+ def get_user_profile(user_id):
27
+ # This function's result depends on user data
28
+ add_dependency(f"user:{user_id}")
29
+
30
+ # Expensive operation (e.g., database query, API call)
31
+ return fetch_user_from_database(user_id)
32
+
33
+ @cache_with_deps(ttl=600) # No cache_manager - will create one automatically
34
+ def get_user_posts(user_id):
35
+ # This depends on both user and posts data
36
+ add_dependency(f"user:{user_id}")
37
+ add_dependency(f"posts:user:{user_id}")
38
+
39
+ return fetch_user_posts_from_database(user_id)
40
+
41
+ # Use the cached functions
42
+ profile = get_user_profile("123") # Cache miss - fetches from DB
43
+ profile = get_user_profile("123") # Cache hit - returns cached result
44
+
45
+ posts = get_user_posts("123") # Cache miss - fetches from DB
46
+ posts = get_user_posts("123") # Cache hit - returns cached result
47
+
48
+ # When user data changes, invalidate the dependency
49
+ cache.invalidate_dependency("user:123")
50
+ # Now both get_user_profile("123") and get_user_posts("123") are invalidated!
51
+
52
+ profile = get_user_profile("123") # Cache miss - will fetch fresh data
53
+ ```
54
+
55
+ ### Async Support
56
+
57
+ ```python
58
+ from simple_dep_cache import async_cache_with_deps, add_dependency, AsyncCacheManager
59
+
60
+ cache = AsyncCacheManager()
61
+
62
+ @async_cache_with_deps(cache_manager=cache, ttl=300)
63
+ async def get_user_profile_async(user_id):
64
+ add_dependency(f"user:{user_id}")
65
+ return await fetch_user_from_database_async(user_id)
66
+
67
+ # Usage
68
+ profile = await get_user_profile_async("123") # Cache miss
69
+ profile = await get_user_profile_async("123") # Cache hit
70
+
71
+ # Invalidate dependency
72
+ await cache.invalidate_dependency("user:123")
73
+ ```
74
+
75
+ ### Monitoring
76
+
77
+ ```python
78
+ from simple_dep_cache import StatsCollector, create_logger_callback
79
+
80
+ cache = CacheManager()
81
+ stats = StatsCollector()
82
+ cache.events.on_all(stats)
83
+ cache.events.on_all(create_logger_callback("my_cache"))
84
+
85
+ # Check statistics
86
+ print(stats.get_stats()) # hit_ratio, ops_per_second, etc.
87
+ ```
88
+
89
+ ## Configuration
90
+
91
+ ```bash
92
+ REDIS_URL=redis://localhost:6379/0 # Full Redis URL (preferred)
93
+ REDIS_HOST=localhost # Or individual settings
94
+ REDIS_PORT=6379
95
+ REDIS_PASSWORD=secret
96
+ DEP_CACHE_ENABLED=true # Disable caching entirely
97
+ ```
98
+
99
+ ## Manual Cache Operations
100
+
101
+ ```python
102
+ cache = CacheManager()
103
+
104
+ # Direct operations
105
+ cache.set("key", value, ttl=300, dependencies={"dep1"})
106
+ value = cache.get("key")
107
+ cache.delete("key")
108
+ cache.invalidate_dependency("dep1") # Invalidates all dependent caches
109
+ ```
110
+
111
+ ## API Reference
112
+
113
+ **Decorators:**
114
+
115
+ - `@cache_with_deps(cache_manager, ttl, key_prefix, dependencies)`
116
+ - `@async_cache_with_deps(cache_manager, ttl, key_prefix, dependencies)`
117
+
118
+ If `cache_manager` is not provided, one will be created automatically using configured environment variables or defaults.
119
+
120
+ **Context:**
121
+
122
+ - `add_dependency(dependency)` - Track dependency in current function
123
+ - `current_cache_key()` - Get current cache key
124
+
125
+ **Managers:**
126
+
127
+ - `CacheManager(redis_client, prefix)` - Sync Redis cache manager
128
+ - `AsyncCacheManager(redis_client, prefix)` - Async Redis cache manager
129
+
130
+ **Monitoring:**
131
+
132
+ - `StatsCollector()` - Cache statistics
133
+
134
+ ## Requirements
135
+
136
+ - Python 3.10+
137
+ - Redis server
138
+ - `redis` package
139
+
140
+ ## License
141
+
142
+ MIT
@@ -0,0 +1,53 @@
1
+ [project]
2
+ name = "simple-dep-cache"
3
+ # version = "0.1.0"
4
+ dynamic = ["version"]
5
+ description = "Redis-based caching library with intelligent dependency tracking for Python applications"
6
+ readme = "README.md"
7
+ requires-python = ">=3.10"
8
+ license = {text = "MIT"}
9
+ keywords = ["cache", "redis", "dependency", "cache invalidation"]
10
+ classifiers = [
11
+ "Intended Audience :: Developers",
12
+ "License :: OSI Approved :: MIT License",
13
+ "Programming Language :: Python :: 3",
14
+ "Programming Language :: Python :: 3.10",
15
+ "Programming Language :: Python :: 3.11",
16
+ "Programming Language :: Python :: 3.12",
17
+ "Topic :: Software Development :: Libraries :: Python Modules",
18
+ ]
19
+ dependencies = [
20
+ "redis",
21
+ ]
22
+
23
+ [build-system]
24
+ requires = ["hatchling", "uv-dynamic-versioning"]
25
+ build-backend = "hatchling.build"
26
+
27
+ [project.optional-dependencies]
28
+ fast-json = [
29
+ "orjson",
30
+ ]
31
+
32
+ [dependency-groups]
33
+ dev = [
34
+ "ipython",
35
+ "pytest",
36
+ "pytest-asyncio",
37
+ "fakeredis",
38
+ "ruff",
39
+ "pre-commit>=4.3.0",
40
+ ]
41
+
42
+ [tool.hatch.version]
43
+ source = "uv-dynamic-versioning"
44
+
45
+ [tool.pytest.ini_options]
46
+ pythonpath = ["src"]
47
+ testpaths = [
48
+ "tests",
49
+ ]
50
+ python_files = [
51
+ "test_*.py",
52
+ ]
53
+
@@ -0,0 +1,19 @@
1
+ from .context import add_dependency, current_cache_key
2
+ from .decorators import async_cache_with_deps, cache_with_deps
3
+ from .events import CacheEvent, CacheEventType, StatsCollector, create_logger_callback
4
+ from .manager import AsyncCacheManager, CacheManager
5
+ from .types import CacheValue
6
+
7
+ __all__ = [
8
+ "CacheManager",
9
+ "AsyncCacheManager",
10
+ "cache_with_deps",
11
+ "async_cache_with_deps",
12
+ "add_dependency",
13
+ "current_cache_key",
14
+ "CacheValue",
15
+ "CacheEvent",
16
+ "CacheEventType",
17
+ "StatsCollector",
18
+ "create_logger_callback",
19
+ ]