cache

On-disk result cache to avoid redundant API calls.

bib_checker.cache

On-disk JSON cache for InspireHEP lookup results.

Caches CheckResult objects keyed by texkey. Each cached entry stores a short hash of the local bib entry's fields; if the local entry changes the cached result is treated as stale and discarded.

CheckCache

Persistent on-disk cache mapping texkey → :class:~bib_checker.models.CheckResult.

Parameters:
  • path (str or Path) –

    Path to the JSON cache file. The file is created on first :meth:save.

Source code in src/bib_checker/cache.py
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
class CheckCache:
    """Persistent on-disk cache mapping texkey → :class:`~bib_checker.models.CheckResult`.

    Parameters
    ----------
    path : str or Path
        Path to the JSON cache file.  The file is created on first
        :meth:`save`.
    """

    def __init__(self, path: str | Path) -> None:
        self._path = Path(path)
        self._data: dict[str, Any] = {}
        self._dirty = False
        self._load()

    # ------------------------------------------------------------------
    # Private helpers
    # ------------------------------------------------------------------

    def _load(self) -> None:
        """Load cache from disk, silently ignoring corrupt files."""
        if not self._path.exists():
            return
        try:
            raw = json.loads(self._path.read_text(encoding="utf-8"))
            if raw.get("version") == _CACHE_VERSION:
                self._data = raw.get("entries", {})
        except (json.JSONDecodeError, KeyError, OSError):
            self._data = {}

    # ------------------------------------------------------------------
    # Public interface
    # ------------------------------------------------------------------

    def get(self, texkey: str, entry_fields: dict[str, str]) -> CheckResult | None:
        """Return a cached result if the local entry hasn't changed, else ``None``.

        Parameters
        ----------
        texkey : str
            Citation key to look up.
        entry_fields : dict[str, str]
            Current field values from the local bib entry.

        Returns
        -------
        result : CheckResult or None
            Cached result, or ``None`` if not cached or stale.
        """
        slot = self._data.get(texkey)
        if slot is None:
            return None
        if slot.get("entry_hash") != _entry_hash(entry_fields):
            return None
        return _result_from_dict(slot["result"])

    def put(self, texkey: str, entry_fields: dict[str, str], result: CheckResult) -> None:
        """Store a result in the in-memory cache.

        Parameters
        ----------
        texkey : str
            Citation key.
        entry_fields : dict[str, str]
            Field values of the local bib entry at check time.
        result : CheckResult
            The result to cache.
        """
        self._data[texkey] = {
            "entry_hash": _entry_hash(entry_fields),
            "result": result.to_dict(),
        }
        self._dirty = True

    def save(self) -> None:
        """Write the cache to disk (only when entries have been added/updated)."""
        if not self._dirty:
            return
        payload = {"version": _CACHE_VERSION, "entries": self._data}
        self._path.write_text(json.dumps(payload, indent=2, ensure_ascii=False), encoding="utf-8")
        self._dirty = False

    @staticmethod
    def default_path(bib_path: str | Path) -> Path:
        """Return the default cache file path next to *bib_path*.

        Parameters
        ----------
        bib_path : str or Path
            Path to the ``.bib`` file being checked.

        Returns
        -------
        path : Path
            A hidden file named ``.{stem}-cache.json`` in the same directory.
        """
        bib = Path(bib_path)
        return bib.with_name(f".{bib.stem}-cache.json")

default_path staticmethod

default_path(bib_path)

Return the default cache file path next to bib_path.

Parameters:
  • bib_path (str or Path) –

    Path to the .bib file being checked.

Returns:
  • path( Path ) –

    A hidden file named .{stem}-cache.json in the same directory.

Source code in src/bib_checker/cache.py
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
@staticmethod
def default_path(bib_path: str | Path) -> Path:
    """Return the default cache file path next to *bib_path*.

    Parameters
    ----------
    bib_path : str or Path
        Path to the ``.bib`` file being checked.

    Returns
    -------
    path : Path
        A hidden file named ``.{stem}-cache.json`` in the same directory.
    """
    bib = Path(bib_path)
    return bib.with_name(f".{bib.stem}-cache.json")

get

get(texkey, entry_fields)

Return a cached result if the local entry hasn't changed, else None.

Parameters:
  • texkey (str) –

    Citation key to look up.

  • entry_fields (dict[str, str]) –

    Current field values from the local bib entry.

Returns:
  • result( CheckResult or None ) –

    Cached result, or None if not cached or stale.

Source code in src/bib_checker/cache.py
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
def get(self, texkey: str, entry_fields: dict[str, str]) -> CheckResult | None:
    """Return a cached result if the local entry hasn't changed, else ``None``.

    Parameters
    ----------
    texkey : str
        Citation key to look up.
    entry_fields : dict[str, str]
        Current field values from the local bib entry.

    Returns
    -------
    result : CheckResult or None
        Cached result, or ``None`` if not cached or stale.
    """
    slot = self._data.get(texkey)
    if slot is None:
        return None
    if slot.get("entry_hash") != _entry_hash(entry_fields):
        return None
    return _result_from_dict(slot["result"])

put

put(texkey, entry_fields, result)

Store a result in the in-memory cache.

Parameters:
  • texkey (str) –

    Citation key.

  • entry_fields (dict[str, str]) –

    Field values of the local bib entry at check time.

  • result (CheckResult) –

    The result to cache.

Source code in src/bib_checker/cache.py
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
def put(self, texkey: str, entry_fields: dict[str, str], result: CheckResult) -> None:
    """Store a result in the in-memory cache.

    Parameters
    ----------
    texkey : str
        Citation key.
    entry_fields : dict[str, str]
        Field values of the local bib entry at check time.
    result : CheckResult
        The result to cache.
    """
    self._data[texkey] = {
        "entry_hash": _entry_hash(entry_fields),
        "result": result.to_dict(),
    }
    self._dirty = True

save

save()

Write the cache to disk (only when entries have been added/updated).

Source code in src/bib_checker/cache.py
144
145
146
147
148
149
150
def save(self) -> None:
    """Write the cache to disk (only when entries have been added/updated)."""
    if not self._dirty:
        return
    payload = {"version": _CACHE_VERSION, "entries": self._data}
    self._path.write_text(json.dumps(payload, indent=2, ensure_ascii=False), encoding="utf-8")
    self._dirty = False