Skip to main content

PyperCache Docs

PyperCache is a durable, file-backed cache for JSON-like Python data.

Features

  • API wrapper base class: build synchronous requests clients with URL joining, optional caching, response decoding, file downloads, SSE parsing, and typed response casting
  • File-backed storage backends: choose Pickle, JSON, chunked manifest, or SQLite storage by file extension (.pkl, .json, .manifest, .db)
  • Expiry-aware cache records: store records with optional TTLs, check freshness, and refetch stale ApiWrapper GET/JSON responses instead of serving expired data
  • Typed API models: decorate classes with @apimodel for dict constructors, nested hydration, raw field aliases, timestamp parsing, lazy fields, shallow lazy validation, and optional validation
  • JSON navigation: query loaded dict/list payloads with JsonInjester selectors for dotted paths, existence checks, filters, plucks, defaults, and casting
  • Request logging: append thread-safe JSONL request records and inspect recent entries by time window

Installation

Install from PyPI:

pip install pypercache

Or install from source:

git clone https://github.com/BrandonBahret/PyperCache.git
cd PyperCache
pip install .

Quick Start

See the full documentation, examples, and API reference:

Read the docs webpage

Find api wrapper examples

At a glance

At the center is Cache, which stores keyed records to disk and returns CacheRecord objects. Each record exposes .query, which gives you a JsonInjester over the loaded payload so you can navigate nested data without writing long chains of dict.get(...) calls.

@apimodel sits on top of that. Decorate a class and it gains a dict-accepting constructor, nested hydration, aliases, timestamp parsing, and lazy fields. Store with cast=MyModel, then retrieve a typed object later with cache.get_object().

ApiWrapper composes requests, Cache, and optionally RequestLogger into a higher-level base class for HTTP clients. Subclass it, add thin endpoint methods, and let the wrapper handle URL joining, cache lookup, response decoding, and model hydration.

API Wrapper

pypercache.api_wrapper.ApiWrapper provides a base class for building small synchronous API clients on top of requests, Cache, and RequestLogger.

from pypercache.api_wrapper import ApiWrapper
from pypercache.models.apimodel import apimodel


@apimodel
class Widget:
    id: int
    name: str


class WidgetClient(ApiWrapper):
    ...

    def list_widgets(self) -> list[Widget]:
        return self.request("GET", "/widgets", expected="json", cast=list[Widget])

Example

The snippet below demonstrates every major feature in one pass: choosing a backend, TTL, typed objects, query navigation, and request logging.

import math
from datetime import datetime
from typing import Annotated

from pypercache import Cache, RequestLogger
from pypercache.models.apimodel import Alias, Timestamp, apimodel
 
# ── 1. Backend is chosen by file extension ──────────────────────────────────
cache = Cache(filepath="api-cache.db")   # .pkl / .json / .manifest / .db
log   = RequestLogger("api_requests.log")
 
# ── 2. Define a typed model ──────────────────────────────────────────────────
@apimodel
class SearchResult:
    total: int
    next_page: Annotated[str | None, Alias("nextPage")]
    fetched_at: Annotated[datetime, Alias("fetchedAt"), Timestamp()]
    hits:  list
 
# ── 3. Fetch-or-cache pattern ────────────────────────────────────────────────
KEY = "search:v1:python"
 
if not cache.is_data_fresh(KEY):
    payload = {
        "total": 3,
        "nextPage": None,
        "fetchedAt": "2026-04-19T12:34:56Z",
        "hits": [
            {"name": "Alice", "role": "staff",  "score": 92},
            {"name": "Bob",   "role": "guest",  "score": 74},
            {"name": "Carol", "role": "staff",  "score": 88},
        ],
    }
    cache.store(KEY, payload, expiry=3600, cast=SearchResult)
    log.log(uri="/api/search?q=python", status=200)
 
# ── 4. Retrieve a typed object ───────────────────────────────────────────────
result: SearchResult = cache.get_object(KEY)  # SearchResult instance
print(result.total)                           # 3
print(result.next_page)                       # None
print(result.fetched_at.isoformat())          # 2026-04-19T12:34:56+00:00
 
# ── 5. Query without mutating the payload ───────────────────────────────────
q = cache.get(KEY).query
 
print(q.get("total"))                           # 3
print(q.get("hits?role=staff.name"))            # [Alice, Carol]
print(q.get("hits?name*"))                      # ['Alice', 'Bob', 'Carol']
print(q.get("hits?role=staff", select_first=True)["name"])  # 'Alice'

member: StaffMember = q.get("hits?role=staff", select_first=True, cast=StaffMember)
 
# ── 6. Inspect the request log ───────────────────────────────────────────────
for entry in log.get_logs_from_last_seconds(60):
    print(entry.data["uri"], entry.data["status"])

License

MIT

Metadata

Release files for pypercache 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for pypercache 0.2.0
File Size Uploaded Provenance Actions
pypercache-0.2.0.tar.gz 103.1 kB Without provenance Details for pypercache-0.2.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for pypercache 0.2.0
File Interpreter ABI Platform Actions
pypercache-0.2.0-py3-none-any.whl Python 3 none any Details for pypercache-0.2.0-py3-none-any.whl

Total release size: 154.6 kB

Release files / pypercache-0.2.0.tar.gz

Download URL pypercache-0.2.0.tar.gz
Size 103.1 kB
Tags Source
SHA-256 checksum
How to use checksums
566b5889406663d54d9847e10a35b33d8d33a073dc30cbb0b561b5332655ba8b
BLAKE2b-256 checksum
How to use checksums
a26c837b03e0129689b0722108f377e438c4737df35f50a4e3e0d400b7c30bca
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.13.13

Release files / pypercache-0.2.0-py3-none-any.whl

Download URL pypercache-0.2.0-py3-none-any.whl
Size 51.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
9eb6c8ae7b7e3df465fa975b9718716de472d2a8c463eeb5f12918c6825fe243
BLAKE2b-256 checksum
How to use checksums
53905837407b24cd601e0679825cd8dbba3d477299253b4ad79c74b26aa12936
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.13.13

Security for pypercache 0.2.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page