Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions docs/usage/getting-started/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,15 @@ Controls how githubkit caches **tokens** (e.g., GitHub App installation tokens)

You can provide any built-in strategy or implement a custom one by subclassing `BaseCacheStrategy`.

!!! note "Migrating to Hishel 2.0"

githubkit now depends on Hishel `>=2.0`. If you implement a custom `BaseCacheStrategy` or use githubkit's cache clients directly, note these breaking changes:

- `get_hishel_policy()` has been replaced by `get_hishel_options()`, which returns a `hishel.CacheOptions` instead of a `CachePolicy`. Hishel 2.0 removed `CachePolicy` and `SpecificationPolicy`.
- `get_hishel_storage()` must return a `hishel.BaseStorage` (formerly `SyncBaseStorage`). `SyncSqliteStorage` is now `SqliteStorage`.
- The `policy` argument of `SyncCacheClient` / `AsyncCacheClient` has been renamed to `rfc` to align with Hishel 2.0. It accepts `CacheOptions | bool` and defaults to `True` (RFC 9111 caching, same behavior as before).
- `SyncMemoryStorage` / `AsyncMemoryStorage` no longer accept `refresh_ttl_on_access`.

#### Built-in Cache Strategies

**`MemCacheStrategy`** — In-memory cache (default)
Expand Down
6 changes: 3 additions & 3 deletions githubkit/_httpx.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@

if TYPE_CHECKING:
from hishel.httpx2 import AsyncCacheTransport as AsyncCacheTransport
from hishel.httpx2 import SyncCacheTransport as SyncCacheTransport
from hishel.httpx2 import CacheTransport as CacheTransport
import httpx2 as httpx
else:
httpx = None
if not os.getenv(GITHUBKIT_HTTPX2_DISABLE_FLAG):
try:
from hishel.httpx2 import AsyncCacheTransport, SyncCacheTransport
from hishel.httpx2 import AsyncCacheTransport, CacheTransport
import httpx2 as httpx
except ImportError:
# Hishel wraps a missing HTTP client in ImportError.
Expand All @@ -21,7 +21,7 @@
if httpx is None:
try:
from hishel.httpx import AsyncCacheTransport as AsyncCacheTransport
from hishel.httpx import SyncCacheTransport as SyncCacheTransport
from hishel.httpx import CacheTransport as CacheTransport
import httpx as httpx
except ImportError:
raise RuntimeError(
Expand Down
16 changes: 5 additions & 11 deletions githubkit/cache/base.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,7 @@
import abc
from datetime import timedelta

from hishel import (
AsyncBaseStorage,
CacheOptions,
CachePolicy,
SpecificationPolicy,
SyncBaseStorage,
)
from hishel import AsyncBaseStorage, BaseStorage, CacheOptions


class BaseCache(abc.ABC):
Expand Down Expand Up @@ -47,12 +41,12 @@ async def get_async_cache_storage(self) -> AsyncBaseCache:
"""
raise NotImplementedError

def get_hishel_policy(self) -> CachePolicy:
"""Get the hishel cache policy instance"""
return SpecificationPolicy(cache_options=CacheOptions(shared=False))
def get_hishel_options(self) -> CacheOptions:
"""Get the hishel cache options instance"""
return CacheOptions(shared=False)

@abc.abstractmethod
def get_hishel_storage(self) -> SyncBaseStorage:
def get_hishel_storage(self) -> BaseStorage:
"""Get the hishel storage instance used in sync context"""
raise NotImplementedError

Expand Down
4 changes: 2 additions & 2 deletions githubkit/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,7 @@ def _create_sync_client(self) -> httpx.Client:
transport=self.config.transport,
event_hooks=self.config.event_hooks,
storage=self.config.cache_strategy.get_hishel_storage(),
policy=self.config.cache_strategy.get_hishel_policy(),
rfc=self.config.cache_strategy.get_hishel_options(),
)

return httpx.Client(
Expand Down Expand Up @@ -303,7 +303,7 @@ async def _create_async_client(self) -> httpx.AsyncClient:
transport=self.config.async_transport,
event_hooks=self.config.async_event_hooks,
storage=await self.config.cache_strategy.get_async_hishel_storage(),
policy=self.config.cache_strategy.get_hishel_policy(),
rfc=self.config.cache_strategy.get_hishel_options(),
)

return httpx.AsyncClient(
Expand Down
40 changes: 17 additions & 23 deletions githubkit/hishel.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,63 +6,60 @@
from hishel import (
AsyncBaseStorage,
AsyncSqliteStorage,
CachePolicy,
SyncBaseStorage,
SyncSqliteStorage,
BaseStorage,
CacheOptions,
SqliteStorage,
)

from ._httpx import AsyncCacheTransport, SyncCacheTransport, httpx
from ._httpx import AsyncCacheTransport, CacheTransport, httpx


class SyncCacheClient(httpx.Client):
def __init__(self, *args: Any, **kwargs: Any):
self.storage: SyncBaseStorage | None = kwargs.pop("storage", None)
self.policy: CachePolicy | None = kwargs.pop("policy", None)
self.storage: BaseStorage | None = kwargs.pop("storage", None)
self.rfc: CacheOptions | bool = kwargs.pop("rfc", True)
super().__init__(*args, **kwargs)

def _init_transport(self, *args, **kwargs) -> httpx.BaseTransport:
_transport = super()._init_transport(*args, **kwargs)
return SyncCacheTransport(
next_transport=_transport, storage=self.storage, policy=self.policy
return CacheTransport(
next_transport=_transport, storage=self.storage, rfc=self.rfc
)

def _init_proxy_transport(self, *args, **kwargs) -> httpx.BaseTransport:
_transport = super()._init_proxy_transport(*args, **kwargs)
return SyncCacheTransport(
next_transport=_transport, storage=self.storage, policy=self.policy
return CacheTransport(
next_transport=_transport, storage=self.storage, rfc=self.rfc
)


class AsyncCacheClient(httpx.AsyncClient):
def __init__(self, *args: Any, **kwargs: Any):
self.storage: AsyncBaseStorage | None = kwargs.pop("storage", None)
self.policy: CachePolicy | None = kwargs.pop("policy", None)
self.rfc: CacheOptions | bool = kwargs.pop("rfc", True)
super().__init__(*args, **kwargs)

def _init_transport(self, *args, **kwargs) -> httpx.AsyncBaseTransport:
_transport = super()._init_transport(*args, **kwargs)
return AsyncCacheTransport(
next_transport=_transport, storage=self.storage, policy=self.policy
next_transport=_transport, storage=self.storage, rfc=self.rfc
)

def _init_proxy_transport(self, *args, **kwargs) -> httpx.AsyncBaseTransport:
_transport = super()._init_proxy_transport(*args, **kwargs)
return AsyncCacheTransport(
next_transport=_transport, storage=self.storage, policy=self.policy
next_transport=_transport, storage=self.storage, rfc=self.rfc
)


class SyncMemoryStorage(SyncSqliteStorage):
class SyncMemoryStorage(SqliteStorage):
def __init__(
self,
*,
default_ttl: float | None = None,
refresh_ttl_on_access: bool | None = None,
keep_unclosed: bool = False,
) -> None:
super().__init__(
default_ttl=default_ttl, refresh_ttl_on_access=refresh_ttl_on_access
)
super().__init__(default_ttl=default_ttl)
# NOTE: hishel close the storage when the client transport is closed.
# but for in-memory sqlite,
# we may want to keep it unclosed to preserve the data for the next client.
Expand Down Expand Up @@ -91,12 +88,9 @@ def __init__(
self,
*,
default_ttl: float | None = None,
refresh_ttl_on_access: bool | None = None,
keep_unclosed: bool = False,
) -> None:
super().__init__(
default_ttl=default_ttl, refresh_ttl_on_access=refresh_ttl_on_access
)
super().__init__(default_ttl=default_ttl)
# NOTE: hishel close the storage when the client transport is closed.
# but for in-memory sqlite,
# we may want to keep it unclosed to preserve the data for the next client.
Expand All @@ -117,7 +111,7 @@ async def _ensure_connection(self) -> anysqlite.Connection:
async def close(self) -> None:
if self.keep_unclosed:
# Do not close the connection, but drain all pending writes
async with self._write_lock:
async with self._init_lock:
return
return await super().close()

Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ requires-python = ">=3.10, <4.0"
dependencies = [
"anyio >=3.6.1, <5.0.0",
"httpx >=0.23.0, <1.0.0",
"hishel[async,httpx] >=1.4.0, <2.0.0",
"hishel[async,httpx] >=2.0.0, <3.0.0",
"typing-extensions >=4.13.0, <5.0.0",
"pydantic >=1.9.1, <3.0.0, !=2.5.0, !=2.5.1",
"githubkit-schemas >=26.5.7",
Expand Down
8 changes: 4 additions & 4 deletions uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading