Repository navigation
Changes
🚀 Features
- Sync schemas with latest Metron API @bpepple (#193)
- Rework SqliteCache with per-resource TTLs @bpepple (#184)
- Remove the backwards-compatibility re-exports from mokkari.session @bpepple (#178)
- Switch the string schema enums to StrEnum @bpepple (#175)
- Remove Basic auth support @bpepple (#174)
🐛 Bug Fixes
- Invalidate only the cache entries a PATCH or POST can change @bpepple (#190)
- Read send times as they're logged in the send-log limiter test @bpepple (#182)
- Fix flaky send-log rate limiter test on macOS @bpepple (#180)
- Stop a netrc entry from replacing the Bearer token @bpepple (#176)
- Quiet cache contention logging and drop SqliteCache.con @bpepple (#196)
🧰 Maintenance
- Update dev dependencies and pre-commit hooks @bpepple (#197)
- Bump uv from 0.13.1 to 0.13.4 @dependabot[bot] (#194)
- Bump certifi from 2026.7.22 to 2026.10.19 @dependabot[bot] (#195)
- Import datetime as dt in the tests @bpepple (#192)
- Draft releases separately for main and 4.x @bpepple (#183)
- Drop Python 3.10 and add Python 3.15 support @bpepple (#172)
🗄️ Using the reworked SqliteCache
SqliteCache now sets how long entries are kept per resource, rather than one expiry for everything:
from datetime import timedelta
import mokkari
from mokkari.sqlite_cache import SqliteCache # no longer loaded by `import mokkari`
cache = SqliteCache(
"mokkari_cache.db",
default_ttl=timedelta(days=7), # anything not listed below
ttl={
"issue:list": timedelta(hours=6), # issue list/search results
"issue": timedelta(days=2), # issue detail and list entries
"role": SqliteCache.NEVER, # never expires
"series:list": SqliteCache.NO_CACHE, # never cached
"pull_list": timedelta(minutes=10), # not cached by default; opt in
"*:list": timedelta(days=1), # every other list endpoint
},
empty_list_ttl=timedelta(minutes=30), # searches with no results
)
with mokkari.api(api_token="your-token", cache=cache) as m:
issue = m.issue(1)Lookups go from "resource:kind" to "resource" to "*:kind", then fall back to default_ttl. A TTL can be a timedelta, SqliteCache.NEVER (None) or SqliteCache.NO_CACHE. collection, pull_list and wish_list aren't cached unless you add them to ttl, and empty lists aren't cached unless you set empty_list_ttl.
A PATCH or POST through the session now removes only the cache entries that write could have changed. You can also remove entries yourself with cache.invalidate("issue"), cache.invalidate("issue", "list") or cache.clear().
Upgrading from 4.x: an existing 4.x cache database is emptied the first time 5.0 opens it, so the first requests after upgrading will go to Metron.