Skip to content

Commit cf7d52a

Browse files
committed
Add cache for import
1 parent 2b4cc17 commit cf7d52a

1 file changed

Lines changed: 17 additions & 5 deletions

File tree

src/semble/stats.py

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,10 @@
33
from collections import defaultdict
44
from dataclasses import dataclass
55
from datetime import datetime, timedelta, timezone
6+
from functools import cache
7+
from importlib import import_module
68
from pathlib import Path
9+
from types import ModuleType
710

811
from semble.cache import resolve_cache_folder
912
from semble.types import CallType, SearchResult
@@ -37,6 +40,15 @@ class SavingsSummary:
3740
call_type_counts: dict[str, int]
3841

3942

43+
@cache
44+
def _import_fcntl() -> ModuleType | None:
45+
"""Return fcntl when available, otherwise None."""
46+
try:
47+
return import_module("fcntl")
48+
except ImportError: # pragma: no cover
49+
return None
50+
51+
4052
def save_search_stats(
4153
results: list[SearchResult],
4254
call_type: CallType,
@@ -59,12 +71,12 @@ def save_search_stats(
5971
stats_file = _get_stats_file()
6072
stats_file.parent.mkdir(parents=True, exist_ok=True)
6173
with stats_file.open("a") as f:
74+
fcntl = _import_fcntl()
6275
try:
63-
import fcntl
64-
65-
fcntl.flock(f, fcntl.LOCK_EX | fcntl.LOCK_NB)
66-
except ImportError: # pragma: no cover
67-
pass # Windows has no fcntl, write unlocked
76+
if fcntl is not None:
77+
fcntl.flock(f, fcntl.LOCK_EX | fcntl.LOCK_NB)
78+
except BlockingIOError: # pragma: no cover
79+
return # another process holds the lock; skip this record
6880
except OSError: # pragma: no cover
6981
return # lock contention or unsupported filesystem; skip
7082
f.write(json.dumps(record) + "\n")

0 commit comments

Comments
 (0)