fix: annotate redis_client param and formalize Args in RedisCredentialStore.__init__; refresh MCP docs

This commit is contained in:
2026-09-14 00:05:34 +05:30
parent 085fe5e03e
commit 089aad24c3
4 changed files with 47 additions and 39 deletions

View File

@@ -247,6 +247,13 @@
"signature": "<bound method Alias.signature of Alias('Callable', 'collections.abc.Callable')>", "signature": "<bound method Alias.signature of Alias('Callable', 'collections.abc.Callable')>",
"docstring": null "docstring": null
}, },
"Any": {
"name": "Any",
"kind": "alias",
"path": "mail_intake.credentials.redis.Any",
"signature": "<bound method Alias.signature of Alias('Any', 'typing.Any')>",
"docstring": null
},
"TypeVar": { "TypeVar": {
"name": "TypeVar", "name": "TypeVar",
"kind": "alias", "kind": "alias",
@@ -295,7 +302,7 @@
"name": "RedisCredentialStore", "name": "RedisCredentialStore",
"kind": "class", "kind": "class",
"path": "mail_intake.credentials.redis.RedisCredentialStore", "path": "mail_intake.credentials.redis.RedisCredentialStore",
"signature": "<bound method Class.signature of Class('RedisCredentialStore', 35, 137)>", "signature": "<bound method Class.signature of Class('RedisCredentialStore', 35, 145)>",
"docstring": "Redis-backed implementation of `CredentialStore`.\n\nThis store persists credentials in Redis and is suitable for\ndistributed and horizontally scaled deployments where credentials\nmust be shared across multiple processes or nodes.\n\nNotes:\n **Responsibilities:**\n\n - This class is responsible only for persistence and retrieval.\n - It does not interpret, validate, refresh, or otherwise manage the\n lifecycle of the credentials being stored.\n\n **Guarantees:**\n\n - The store is intentionally generic and delegates all serialization\n concerns to caller-provided functions.\n - This avoids unsafe mechanisms such as `pickle` and allows\n credential formats to be explicitly controlled and audited.", "docstring": "Redis-backed implementation of `CredentialStore`.\n\nThis store persists credentials in Redis and is suitable for\ndistributed and horizontally scaled deployments where credentials\nmust be shared across multiple processes or nodes.\n\nNotes:\n **Responsibilities:**\n\n - This class is responsible only for persistence and retrieval.\n - It does not interpret, validate, refresh, or otherwise manage the\n lifecycle of the credentials being stored.\n\n **Guarantees:**\n\n - The store is intentionally generic and delegates all serialization\n concerns to caller-provided functions.\n - This avoids unsafe mechanisms such as `pickle` and allows\n credential formats to be explicitly controlled and audited.",
"members": { "members": {
"redis": { "redis": {
@@ -337,31 +344,24 @@
"name": "load", "name": "load",
"kind": "function", "kind": "function",
"path": "mail_intake.credentials.redis.RedisCredentialStore.load", "path": "mail_intake.credentials.redis.RedisCredentialStore.load",
"signature": "<bound method Function.signature of Function('load', 80, 105)>", "signature": "<bound method Function.signature of Function('load', 88, 113)>",
"docstring": "Load credentials from Redis.\n\nReturns:\n T | None:\n An instance of type `T` if credentials are present and\n successfully deserialized; otherwise `None`.\n\nNotes:\n **Guarantees:**\n\n - If no value exists for the configured key, or if the stored\n payload cannot be successfully deserialized, this method\n returns `None`.\n - The store does not attempt to validate the returned\n credentials or determine whether they are expired or\n otherwise usable." "docstring": "Load credentials from Redis.\n\nReturns:\n T | None:\n An instance of type `T` if credentials are present and\n successfully deserialized; otherwise `None`.\n\nNotes:\n **Guarantees:**\n\n - If no value exists for the configured key, or if the stored\n payload cannot be successfully deserialized, this method\n returns `None`.\n - The store does not attempt to validate the returned\n credentials or determine whether they are expired or\n otherwise usable."
}, },
"save": { "save": {
"name": "save", "name": "save",
"kind": "function", "kind": "function",
"path": "mail_intake.credentials.redis.RedisCredentialStore.save", "path": "mail_intake.credentials.redis.RedisCredentialStore.save",
"signature": "<bound method Function.signature of Function('save', 107, 125)>", "signature": "<bound method Function.signature of Function('save', 115, 133)>",
"docstring": "Persist credentials to Redis.\n\nArgs:\n credentials (T):\n The credential object to persist.\n\nNotes:\n **Responsibilities:**\n\n - Any previously stored credentials under the same key are overwritten\n - If a TTL is configured, the credentials will expire automatically after the specified duration" "docstring": "Persist credentials to Redis.\n\nArgs:\n credentials (T):\n The credential object to persist.\n\nNotes:\n **Responsibilities:**\n\n - Any previously stored credentials under the same key are overwritten\n - If a TTL is configured, the credentials will expire automatically after the specified duration"
}, },
"clear": { "clear": {
"name": "clear", "name": "clear",
"kind": "function", "kind": "function",
"path": "mail_intake.credentials.redis.RedisCredentialStore.clear", "path": "mail_intake.credentials.redis.RedisCredentialStore.clear",
"signature": "<bound method Function.signature of Function('clear', 127, 137)>", "signature": "<bound method Function.signature of Function('clear', 135, 145)>",
"docstring": "Remove stored credentials from Redis.\n\nNotes:\n **Lifecycle:**\n\n - This operation deletes the configured Redis key if it exists\n - Implementations should treat this method as idempotent" "docstring": "Remove stored credentials from Redis.\n\nNotes:\n **Lifecycle:**\n\n - This operation deletes the configured Redis key if it exists\n - Implementations should treat this method as idempotent"
} }
} }
},
"Any": {
"name": "Any",
"kind": "alias",
"path": "mail_intake.credentials.redis.Any",
"signature": "<bound method Alias.signature of Alias('Any', 'typing.Any')>",
"docstring": null
} }
} }
}, },

View File

@@ -11,6 +11,13 @@
"signature": "<bound method Alias.signature of Alias('Callable', 'collections.abc.Callable')>", "signature": "<bound method Alias.signature of Alias('Callable', 'collections.abc.Callable')>",
"docstring": null "docstring": null
}, },
"Any": {
"name": "Any",
"kind": "alias",
"path": "mail_intake.credentials.redis.Any",
"signature": "<bound method Alias.signature of Alias('Any', 'typing.Any')>",
"docstring": null
},
"TypeVar": { "TypeVar": {
"name": "TypeVar", "name": "TypeVar",
"kind": "alias", "kind": "alias",
@@ -59,7 +66,7 @@
"name": "RedisCredentialStore", "name": "RedisCredentialStore",
"kind": "class", "kind": "class",
"path": "mail_intake.credentials.redis.RedisCredentialStore", "path": "mail_intake.credentials.redis.RedisCredentialStore",
"signature": "<bound method Class.signature of Class('RedisCredentialStore', 35, 137)>", "signature": "<bound method Class.signature of Class('RedisCredentialStore', 35, 145)>",
"docstring": "Redis-backed implementation of `CredentialStore`.\n\nThis store persists credentials in Redis and is suitable for\ndistributed and horizontally scaled deployments where credentials\nmust be shared across multiple processes or nodes.\n\nNotes:\n **Responsibilities:**\n\n - This class is responsible only for persistence and retrieval.\n - It does not interpret, validate, refresh, or otherwise manage the\n lifecycle of the credentials being stored.\n\n **Guarantees:**\n\n - The store is intentionally generic and delegates all serialization\n concerns to caller-provided functions.\n - This avoids unsafe mechanisms such as `pickle` and allows\n credential formats to be explicitly controlled and audited.", "docstring": "Redis-backed implementation of `CredentialStore`.\n\nThis store persists credentials in Redis and is suitable for\ndistributed and horizontally scaled deployments where credentials\nmust be shared across multiple processes or nodes.\n\nNotes:\n **Responsibilities:**\n\n - This class is responsible only for persistence and retrieval.\n - It does not interpret, validate, refresh, or otherwise manage the\n lifecycle of the credentials being stored.\n\n **Guarantees:**\n\n - The store is intentionally generic and delegates all serialization\n concerns to caller-provided functions.\n - This avoids unsafe mechanisms such as `pickle` and allows\n credential formats to be explicitly controlled and audited.",
"members": { "members": {
"redis": { "redis": {
@@ -101,31 +108,24 @@
"name": "load", "name": "load",
"kind": "function", "kind": "function",
"path": "mail_intake.credentials.redis.RedisCredentialStore.load", "path": "mail_intake.credentials.redis.RedisCredentialStore.load",
"signature": "<bound method Function.signature of Function('load', 80, 105)>", "signature": "<bound method Function.signature of Function('load', 88, 113)>",
"docstring": "Load credentials from Redis.\n\nReturns:\n T | None:\n An instance of type `T` if credentials are present and\n successfully deserialized; otherwise `None`.\n\nNotes:\n **Guarantees:**\n\n - If no value exists for the configured key, or if the stored\n payload cannot be successfully deserialized, this method\n returns `None`.\n - The store does not attempt to validate the returned\n credentials or determine whether they are expired or\n otherwise usable." "docstring": "Load credentials from Redis.\n\nReturns:\n T | None:\n An instance of type `T` if credentials are present and\n successfully deserialized; otherwise `None`.\n\nNotes:\n **Guarantees:**\n\n - If no value exists for the configured key, or if the stored\n payload cannot be successfully deserialized, this method\n returns `None`.\n - The store does not attempt to validate the returned\n credentials or determine whether they are expired or\n otherwise usable."
}, },
"save": { "save": {
"name": "save", "name": "save",
"kind": "function", "kind": "function",
"path": "mail_intake.credentials.redis.RedisCredentialStore.save", "path": "mail_intake.credentials.redis.RedisCredentialStore.save",
"signature": "<bound method Function.signature of Function('save', 107, 125)>", "signature": "<bound method Function.signature of Function('save', 115, 133)>",
"docstring": "Persist credentials to Redis.\n\nArgs:\n credentials (T):\n The credential object to persist.\n\nNotes:\n **Responsibilities:**\n\n - Any previously stored credentials under the same key are overwritten\n - If a TTL is configured, the credentials will expire automatically after the specified duration" "docstring": "Persist credentials to Redis.\n\nArgs:\n credentials (T):\n The credential object to persist.\n\nNotes:\n **Responsibilities:**\n\n - Any previously stored credentials under the same key are overwritten\n - If a TTL is configured, the credentials will expire automatically after the specified duration"
}, },
"clear": { "clear": {
"name": "clear", "name": "clear",
"kind": "function", "kind": "function",
"path": "mail_intake.credentials.redis.RedisCredentialStore.clear", "path": "mail_intake.credentials.redis.RedisCredentialStore.clear",
"signature": "<bound method Function.signature of Function('clear', 127, 137)>", "signature": "<bound method Function.signature of Function('clear', 135, 145)>",
"docstring": "Remove stored credentials from Redis.\n\nNotes:\n **Lifecycle:**\n\n - This operation deletes the configured Redis key if it exists\n - Implementations should treat this method as idempotent" "docstring": "Remove stored credentials from Redis.\n\nNotes:\n **Lifecycle:**\n\n - This operation deletes the configured Redis key if it exists\n - Implementations should treat this method as idempotent"
} }
} }
},
"Any": {
"name": "Any",
"kind": "alias",
"path": "mail_intake.credentials.redis.Any",
"signature": "<bound method Alias.signature of Alias('Any', 'typing.Any')>",
"docstring": null
} }
} }
} }

View File

@@ -891,6 +891,13 @@
"signature": "<bound method Alias.signature of Alias('Callable', 'collections.abc.Callable')>", "signature": "<bound method Alias.signature of Alias('Callable', 'collections.abc.Callable')>",
"docstring": null "docstring": null
}, },
"Any": {
"name": "Any",
"kind": "alias",
"path": "mail_intake.credentials.redis.Any",
"signature": "<bound method Alias.signature of Alias('Any', 'typing.Any')>",
"docstring": null
},
"TypeVar": { "TypeVar": {
"name": "TypeVar", "name": "TypeVar",
"kind": "alias", "kind": "alias",
@@ -939,7 +946,7 @@
"name": "RedisCredentialStore", "name": "RedisCredentialStore",
"kind": "class", "kind": "class",
"path": "mail_intake.credentials.redis.RedisCredentialStore", "path": "mail_intake.credentials.redis.RedisCredentialStore",
"signature": "<bound method Class.signature of Class('RedisCredentialStore', 35, 137)>", "signature": "<bound method Class.signature of Class('RedisCredentialStore', 35, 145)>",
"docstring": "Redis-backed implementation of `CredentialStore`.\n\nThis store persists credentials in Redis and is suitable for\ndistributed and horizontally scaled deployments where credentials\nmust be shared across multiple processes or nodes.\n\nNotes:\n **Responsibilities:**\n\n - This class is responsible only for persistence and retrieval.\n - It does not interpret, validate, refresh, or otherwise manage the\n lifecycle of the credentials being stored.\n\n **Guarantees:**\n\n - The store is intentionally generic and delegates all serialization\n concerns to caller-provided functions.\n - This avoids unsafe mechanisms such as `pickle` and allows\n credential formats to be explicitly controlled and audited.", "docstring": "Redis-backed implementation of `CredentialStore`.\n\nThis store persists credentials in Redis and is suitable for\ndistributed and horizontally scaled deployments where credentials\nmust be shared across multiple processes or nodes.\n\nNotes:\n **Responsibilities:**\n\n - This class is responsible only for persistence and retrieval.\n - It does not interpret, validate, refresh, or otherwise manage the\n lifecycle of the credentials being stored.\n\n **Guarantees:**\n\n - The store is intentionally generic and delegates all serialization\n concerns to caller-provided functions.\n - This avoids unsafe mechanisms such as `pickle` and allows\n credential formats to be explicitly controlled and audited.",
"members": { "members": {
"redis": { "redis": {
@@ -981,31 +988,24 @@
"name": "load", "name": "load",
"kind": "function", "kind": "function",
"path": "mail_intake.credentials.redis.RedisCredentialStore.load", "path": "mail_intake.credentials.redis.RedisCredentialStore.load",
"signature": "<bound method Function.signature of Function('load', 80, 105)>", "signature": "<bound method Function.signature of Function('load', 88, 113)>",
"docstring": "Load credentials from Redis.\n\nReturns:\n T | None:\n An instance of type `T` if credentials are present and\n successfully deserialized; otherwise `None`.\n\nNotes:\n **Guarantees:**\n\n - If no value exists for the configured key, or if the stored\n payload cannot be successfully deserialized, this method\n returns `None`.\n - The store does not attempt to validate the returned\n credentials or determine whether they are expired or\n otherwise usable." "docstring": "Load credentials from Redis.\n\nReturns:\n T | None:\n An instance of type `T` if credentials are present and\n successfully deserialized; otherwise `None`.\n\nNotes:\n **Guarantees:**\n\n - If no value exists for the configured key, or if the stored\n payload cannot be successfully deserialized, this method\n returns `None`.\n - The store does not attempt to validate the returned\n credentials or determine whether they are expired or\n otherwise usable."
}, },
"save": { "save": {
"name": "save", "name": "save",
"kind": "function", "kind": "function",
"path": "mail_intake.credentials.redis.RedisCredentialStore.save", "path": "mail_intake.credentials.redis.RedisCredentialStore.save",
"signature": "<bound method Function.signature of Function('save', 107, 125)>", "signature": "<bound method Function.signature of Function('save', 115, 133)>",
"docstring": "Persist credentials to Redis.\n\nArgs:\n credentials (T):\n The credential object to persist.\n\nNotes:\n **Responsibilities:**\n\n - Any previously stored credentials under the same key are overwritten\n - If a TTL is configured, the credentials will expire automatically after the specified duration" "docstring": "Persist credentials to Redis.\n\nArgs:\n credentials (T):\n The credential object to persist.\n\nNotes:\n **Responsibilities:**\n\n - Any previously stored credentials under the same key are overwritten\n - If a TTL is configured, the credentials will expire automatically after the specified duration"
}, },
"clear": { "clear": {
"name": "clear", "name": "clear",
"kind": "function", "kind": "function",
"path": "mail_intake.credentials.redis.RedisCredentialStore.clear", "path": "mail_intake.credentials.redis.RedisCredentialStore.clear",
"signature": "<bound method Function.signature of Function('clear', 127, 137)>", "signature": "<bound method Function.signature of Function('clear', 135, 145)>",
"docstring": "Remove stored credentials from Redis.\n\nNotes:\n **Lifecycle:**\n\n - This operation deletes the configured Redis key if it exists\n - Implementations should treat this method as idempotent" "docstring": "Remove stored credentials from Redis.\n\nNotes:\n **Lifecycle:**\n\n - This operation deletes the configured Redis key if it exists\n - Implementations should treat this method as idempotent"
} }
} }
},
"Any": {
"name": "Any",
"kind": "alias",
"path": "mail_intake.credentials.redis.Any",
"signature": "<bound method Alias.signature of Alias('Any', 'typing.Any')>",
"docstring": null
} }
} }
}, },

View File

@@ -25,7 +25,7 @@ responsibility of authentication provider implementations.
""" """
from collections.abc import Callable from collections.abc import Callable
from typing import TypeVar from typing import Any, TypeVar
from mail_intake.credentials.store import CredentialStore from mail_intake.credentials.store import CredentialStore
@@ -57,7 +57,7 @@ class RedisCredentialStore(CredentialStore[T]):
def __init__( def __init__(
self, self,
redis_client, redis_client: Any,
key: str, key: str,
serialize: Callable[[T], bytes], serialize: Callable[[T], bytes],
deserialize: Callable[[bytes], T], deserialize: Callable[[bytes], T],
@@ -66,10 +66,18 @@ class RedisCredentialStore(CredentialStore[T]):
""" """
Initialize a Redis-backed credential store. Initialize a Redis-backed credential store.
Callers supply all runtime dependencies: ``redis_client`` is an Args:
initialized Redis client instance, ``key`` names the storage key, redis_client (Any):
``serialize``/``deserialize`` are the encoding and decoding callables, Initialized Redis client instance used for persistence.
and ``ttl_seconds`` optionally limits credential lifetime. key (str):
Storage key under which credentials are persisted.
serialize (Callable[[T], bytes]):
Callable that encodes credentials to bytes for storage.
deserialize (Callable[[bytes], T]):
Callable that decodes stored bytes back into credentials.
ttl_seconds (int | None):
Optional time-to-live in seconds after which stored
credentials expire automatically. ``None`` disables expiry.
""" """
self.redis = redis_client self.redis = redis_client
self.key = key self.key = key