From 5ca4703c3f2c835b028c669de43fb5d5cbf27689 Mon Sep 17 00:00:00 2001 From: Yujong Lee Date: Thu, 5 Nov 2026 07:02:20 +0900 Subject: [PATCH] docs(config): record redis-py kwargs per version against the Rust settings table Co-Authored-By: Claude Opus 5.5 --- litellm-rust/crates/config/AGENTS.md | 2 +- .../crates/config/redis-py-kwargs.json | 2865 +++++++++++++++++ 2 files changed, 2866 insertions(+), 1 deletion(-) create mode 100644 litellm-rust/crates/config/redis-py-kwargs.json diff --git a/litellm-rust/crates/config/AGENTS.md b/litellm-rust/crates/config/AGENTS.md index 7d89ee8d4ff..f0846c81e49 100644 --- a/litellm-rust/crates/config/AGENTS.md +++ b/litellm-rust/crates/config/AGENTS.md @@ -5,7 +5,7 @@ - `resolve` follows `litellm/_redis.py` `_get_redis_client_logic` plus `_credential_provider_auth_kwargs` and the per-client allowlists of `get_redis_async_client` (redis-py 5.3.1). Python and Rust pods share one Redis during the switch, so a change there is a change to a wire contract - That contract is `resolves_like_python_redis` in `tests/redis.rs` and its mirror `test_redis_settings_resolve_like_the_rust_resolver_expects` in `tests/unit/test_redis.py`. Both hold the same named cases with the expected view written next to the input, the Python side reading the effective redis-py 5.3.1 connection objects without connecting. A new resolution rule is a new case in both files, never a generated fixture - `resolve` takes a `SecretSnapshot` and an environment `Lookup`. The snapshot holds every name `ConfiguredRedis::secret_names` lists, read the way Python's `get_secret` reads it (secret manager, then environment). The host fills it once before resolving, python-bridge through `get_secret` and rust-proxy from its environment, so the resolver never calls back into the host. The environment lookup is only for what Python reads straight from `os.environ` (`REDIS_USERNAME` for Azure). Reading a name the snapshot does not list fails a debug assertion -- Every Redis setting Python reads is one row in `SETTINGS` in `src/redis/keys.rs`: how Rust handles it (read, or warn and drop), whether `_get_redis_env_kwarg_mapping` reads it as `REDIS_`, and the names `_get_redis_client_logic` falls back to. The env layer, the ignored list and `secret_names` all come from that table. A read row is also a field of `Options` +- Every Redis setting Python reads is one row in `SETTINGS` in `src/redis/keys.rs`: how Rust handles it (read, or warn and drop), whether `_get_redis_env_kwarg_mapping` reads it as `REDIS_`, and the names `_get_redis_client_logic` falls back to. The env layer, the ignored list and `secret_names` all come from that table. A read row is also a field of `Options`. `redis-py-kwargs.json` records which redis-py version accepts each kwarg next to its row, so check it when adding or changing a row - Lookups go through `litellm_core_utils::settings::Lookup`, never a closure type of our own - A url carries its own TLS. redis-py's url allowlist is the plain `Connection` signature, so every `ssl_*` setting outside the url is dropped, and a credential provider strips the url's userinfo. A `rediss://` url's `ssl_cert_reqs`, `ssl_ca_certs`, `ssl_ca_data`, `ssl_ca_path`, `ssl_certfile`, `ssl_keyfile`, `ssl_password` and `ssl_check_hostname` query parameters are read like `parse_url` reads them - TLS options and `db` are only read for the endpoint that uses them, so a bad `ssl_cert_reqs` never fails a url target. A cluster with a non-zero `db`, and Sentinel with a `host` or `port`, are errors because redis-py raises building those clients diff --git a/litellm-rust/crates/config/redis-py-kwargs.json b/litellm-rust/crates/config/redis-py-kwargs.json new file mode 100644 index 00000000000..aad9bc8550f --- /dev/null +++ b/litellm-rust/crates/config/redis-py-kwargs.json @@ -0,0 +1,2865 @@ +{ + "meta": { + "description": "Every kwarg litellm/_redis.py can pass to redis-py, by tested redis-py version, next to how SETTINGS in src/redis/keys.rs handles it", + "generated": "2026-11-05", + "redis_py_versions": [ + "5.3.1", + "6.4.0", + "7.4.1", + "8.0.1" + ], + "redis_py_locked": "5.3.1", + "python": "3.12", + "method": "uv run --no-project --python 3.12 --with redis== python -I, reading inspect.getfullargspec(inspect.unwrap(cls.__init__)) args and kwonlyargs, minus self", + "signatures": { + "sync": "redis.Redis.__init__. _get_redis_kwargs uses it as the config allowlist and the REDIS_ environment mapping", + "async": "redis.asyncio.Redis.__init__, which the proxy constructs. A kwarg in sync but not async raises TypeError when the client is built", + "connection": "redis.Connection or redis.asyncio.Connection MRO, the url allowlist from _get_redis_url_kwargs", + "cluster": "redis.asyncio.RedisCluster.__init__, the allowlist from _get_redis_cluster_kwargs" + }, + "rust": { + "supported": "true when the Rust client honors the setting, which is only the Read rows", + "handling": { + "Read": "modeled by the resolver", + "Warn": "dropped and returned as an Ignored warning naming the consequence", + "Reject": "fails with RedisError::Unenforceable when set to true", + "unlisted": "no SETTINGS row, so it lands in passthrough for a redis-py host and the Rust client never uses it, without a warning", + "unlisted_host_object": "no SETTINGS row and listed in HOST_OBJECTS, so it lands in host_objects and the Rust client never uses it, without a warning" + }, + "field": "the Options field in src/redis/options.rs that a Read row fills, null otherwise" + }, + "versions": "each entry is a redis-py version whose signatures name the arg, with which ones. An empty array means no signature names it, so it only reaches Python as a litellm key" + }, + "args": { + "address_remap": { + "versions": [ + { + "redis_py": "5.3.1", + "signatures": [ + "cluster" + ] + }, + { + "redis_py": "6.4.0", + "signatures": [ + "cluster" + ] + }, + { + "redis_py": "7.4.1", + "signatures": [ + "cluster" + ] + }, + { + "redis_py": "8.0.1", + "signatures": [ + "cluster" + ] + } + ], + "rust": { + "supported": false, + "handling": "unlisted_host_object", + "field": null + }, + "note": "Cluster-only and no SETTINGS row, so a Rust cluster store drops it without a warning" + }, + "auto_close_connection_pool": { + "versions": [ + { + "redis_py": "5.3.1", + "signatures": [ + "async" + ] + }, + { + "redis_py": "6.4.0", + "signatures": [ + "async" + ] + }, + { + "redis_py": "7.4.1", + "signatures": [ + "async" + ] + }, + { + "redis_py": "8.0.1", + "signatures": [ + "async" + ] + } + ], + "rust": { + "supported": false, + "handling": "unlisted", + "field": null + }, + "note": "Async-only and outside the config allowlist, so Python never passes it from config" + }, + "aws_iam_auth": { + "versions": [], + "rust": { + "supported": true, + "handling": "Read", + "field": "Options.aws.auth" + } + }, + "aws_iam_cache_name": { + "versions": [], + "rust": { + "supported": true, + "handling": "Read", + "field": "Options.aws.cache_name" + } + }, + "aws_iam_region": { + "versions": [], + "rust": { + "supported": true, + "handling": "Read", + "field": "Options.aws.region" + } + }, + "aws_iam_serverless": { + "versions": [], + "rust": { + "supported": true, + "handling": "Read", + "field": "Options.aws.serverless" + } + }, + "aws_iam_user_name": { + "versions": [], + "rust": { + "supported": true, + "handling": "Read", + "field": "Options.aws.user_name" + } + }, + "azure_client_id": { + "versions": [], + "rust": { + "supported": true, + "handling": "Read", + "field": "Options.azure.client_id" + } + }, + "azure_client_secret": { + "versions": [], + "rust": { + "supported": true, + "handling": "Read", + "field": "Options.azure.client_secret" + } + }, + "azure_redis_ad_token": { + "versions": [], + "rust": { + "supported": true, + "handling": "Read", + "field": "Options.azure.ad_token" + } + }, + "azure_tenant_id": { + "versions": [], + "rust": { + "supported": true, + "handling": "Read", + "field": "Options.azure.tenant_id" + } + }, + "cache": { + "versions": [ + { + "redis_py": "5.3.1", + "signatures": [ + "sync" + ] + }, + { + "redis_py": "6.4.0", + "signatures": [ + "sync" + ] + }, + { + "redis_py": "7.4.1", + "signatures": [ + "sync" + ] + }, + { + "redis_py": "8.0.1", + "signatures": [ + "sync" + ] + } + ], + "rust": { + "supported": false, + "handling": "Warn", + "field": null + }, + "note": "Sync-only on every tested version, so the proxy's async path raises TypeError on it in Python too" + }, + "cache_config": { + "versions": [ + { + "redis_py": "5.3.1", + "signatures": [ + "sync" + ] + }, + { + "redis_py": "6.4.0", + "signatures": [ + "sync" + ] + }, + { + "redis_py": "7.4.1", + "signatures": [ + "sync" + ] + }, + { + "redis_py": "8.0.1", + "signatures": [ + "sync" + ] + } + ], + "rust": { + "supported": false, + "handling": "Warn", + "field": null + }, + "note": "Sync-only on every tested version, so the proxy's async path raises TypeError on it in Python too" + }, + "charset": { + "versions": [ + { + "redis_py": "5.3.1", + "signatures": [ + "sync" + ] + } + ], + "rust": { + "supported": false, + "handling": "Warn", + "field": null + }, + "note": "Removed in redis-py 6.0, so the Warn row only matters for 5.3.1 configs" + }, + "client_name": { + "versions": [ + { + "redis_py": "5.3.1", + "signatures": [ + "sync", + "async", + "connection", + "cluster" + ] + }, + { + "redis_py": "6.4.0", + "signatures": [ + "sync", + "async", + "connection", + "cluster" + ] + }, + { + "redis_py": "7.4.1", + "signatures": [ + "sync", + "async", + "connection", + "cluster" + ] + }, + { + "redis_py": "8.0.1", + "signatures": [ + "sync", + "async", + "connection", + "cluster" + ] + } + ], + "rust": { + "supported": false, + "handling": "Warn", + "field": null + } + }, + "cluster_error_retry_attempts": { + "versions": [ + { + "redis_py": "5.3.1", + "signatures": [ + "cluster" + ] + }, + { + "redis_py": "6.4.0", + "signatures": [ + "cluster" + ] + }, + { + "redis_py": "7.4.1", + "signatures": [ + "cluster" + ] + }, + { + "redis_py": "8.0.1", + "signatures": [ + "cluster" + ] + } + ], + "rust": { + "supported": false, + "handling": "unlisted", + "field": null + }, + "note": "Cluster-only and no SETTINGS row, so a Rust cluster store drops it without a warning" + }, + "command_packer": { + "versions": [ + { + "redis_py": "5.3.1", + "signatures": [ + "connection" + ] + }, + { + "redis_py": "6.4.0", + "signatures": [ + "connection" + ] + }, + { + "redis_py": "7.4.1", + "signatures": [ + "connection" + ] + }, + { + "redis_py": "8.0.1", + "signatures": [ + "connection" + ] + } + ], + "rust": { + "supported": false, + "handling": "unlisted", + "field": null + }, + "note": "Connection internal that only the url allowlist admits, not a setting anyone configures" + }, + "connection_error_retry_attempts": { + "versions": [ + { + "redis_py": "5.3.1", + "signatures": [ + "cluster" + ] + } + ], + "rust": { + "supported": false, + "handling": "unlisted", + "field": null + }, + "note": "Cluster-only and no SETTINGS row, so a Rust cluster store drops it without a warning. Only exists in 5.3.1" + }, + "connection_pool": { + "versions": [ + { + "redis_py": "5.3.1", + "signatures": [ + "sync", + "async" + ] + }, + { + "redis_py": "6.4.0", + "signatures": [ + "sync", + "async" + ] + }, + { + "redis_py": "7.4.1", + "signatures": [ + "sync", + "async" + ] + }, + { + "redis_py": "8.0.1", + "signatures": [ + "sync", + "async" + ] + } + ], + "rust": { + "supported": false, + "handling": "Warn", + "field": null + } + }, + "credential_provider": { + "versions": [ + { + "redis_py": "5.3.1", + "signatures": [ + "sync", + "async", + "connection", + "cluster" + ] + }, + { + "redis_py": "6.4.0", + "signatures": [ + "sync", + "async", + "connection", + "cluster" + ] + }, + { + "redis_py": "7.4.1", + "signatures": [ + "sync", + "async", + "connection", + "cluster" + ] + }, + { + "redis_py": "8.0.1", + "signatures": [ + "sync", + "async", + "connection", + "cluster" + ] + } + ], + "rust": { + "supported": true, + "handling": "Read", + "field": "Options.credential_provider" + } + }, + "db": { + "versions": [ + { + "redis_py": "5.3.1", + "signatures": [ + "sync", + "async", + "connection", + "cluster" + ] + }, + { + "redis_py": "6.4.0", + "signatures": [ + "sync", + "async", + "connection", + "cluster" + ] + }, + { + "redis_py": "7.4.1", + "signatures": [ + "sync", + "async", + "connection", + "cluster" + ] + }, + { + "redis_py": "8.0.1", + "signatures": [ + "sync", + "async", + "connection", + "cluster" + ] + } + ], + "rust": { + "supported": true, + "handling": "Read", + "field": "Options.db" + } + }, + "decode_responses": { + "versions": [ + { + "redis_py": "5.3.1", + "signatures": [ + "sync", + "async", + "connection", + "cluster" + ] + }, + { + "redis_py": "6.4.0", + "signatures": [ + "sync", + "async", + "connection", + "cluster" + ] + }, + { + "redis_py": "7.4.1", + "signatures": [ + "sync", + "async", + "connection", + "cluster" + ] + }, + { + "redis_py": "8.0.1", + "signatures": [ + "sync", + "async", + "connection", + "cluster" + ] + } + ], + "rust": { + "supported": false, + "handling": "Warn", + "field": null + } + }, + "driver_info": { + "versions": [ + { + "redis_py": "7.4.1", + "signatures": [ + "sync", + "async", + "connection", + "cluster" + ] + }, + { + "redis_py": "8.0.1", + "signatures": [ + "sync", + "async", + "connection", + "cluster" + ] + } + ], + "rust": { + "supported": false, + "handling": "unlisted_host_object", + "field": null + }, + "note": "No SETTINGS row, so a Rust store drops it without a warning" + }, + "dynamic_startup_nodes": { + "versions": [ + { + "redis_py": "6.4.0", + "signatures": [ + "cluster" + ] + }, + { + "redis_py": "7.4.1", + "signatures": [ + "cluster" + ] + }, + { + "redis_py": "8.0.1", + "signatures": [ + "cluster" + ] + } + ], + "rust": { + "supported": false, + "handling": "unlisted", + "field": null + }, + "note": "Cluster-only and no SETTINGS row, so a Rust cluster store drops it without a warning" + }, + "encoder_class": { + "versions": [ + { + "redis_py": "5.3.1", + "signatures": [ + "connection" + ] + }, + { + "redis_py": "6.4.0", + "signatures": [ + "connection" + ] + }, + { + "redis_py": "7.4.1", + "signatures": [ + "connection" + ] + }, + { + "redis_py": "8.0.1", + "signatures": [ + "connection" + ] + } + ], + "rust": { + "supported": false, + "handling": "unlisted", + "field": null + }, + "note": "Connection internal that only the url allowlist admits, not a setting anyone configures" + }, + "encoding": { + "versions": [ + { + "redis_py": "5.3.1", + "signatures": [ + "sync", + "async", + "connection", + "cluster" + ] + }, + { + "redis_py": "6.4.0", + "signatures": [ + "sync", + "async", + "connection", + "cluster" + ] + }, + { + "redis_py": "7.4.1", + "signatures": [ + "sync", + "async", + "connection", + "cluster" + ] + }, + { + "redis_py": "8.0.1", + "signatures": [ + "sync", + "async", + "connection", + "cluster" + ] + } + ], + "rust": { + "supported": false, + "handling": "Warn", + "field": null + } + }, + "encoding_errors": { + "versions": [ + { + "redis_py": "5.3.1", + "signatures": [ + "sync", + "async", + "connection", + "cluster" + ] + }, + { + "redis_py": "6.4.0", + "signatures": [ + "sync", + "async", + "connection", + "cluster" + ] + }, + { + "redis_py": "7.4.1", + "signatures": [ + "sync", + "async", + "connection", + "cluster" + ] + }, + { + "redis_py": "8.0.1", + "signatures": [ + "sync", + "async", + "connection", + "cluster" + ] + } + ], + "rust": { + "supported": false, + "handling": "Warn", + "field": null + } + }, + "errors": { + "versions": [ + { + "redis_py": "5.3.1", + "signatures": [ + "sync" + ] + } + ], + "rust": { + "supported": false, + "handling": "Warn", + "field": null + }, + "note": "Removed in redis-py 6.0, so the Warn row only matters for 5.3.1 configs" + }, + "event_dispatcher": { + "versions": [ + { + "redis_py": "5.3.1", + "signatures": [ + "sync", + "async", + "connection", + "cluster" + ] + }, + { + "redis_py": "6.4.0", + "signatures": [ + "sync", + "async", + "connection", + "cluster" + ] + }, + { + "redis_py": "7.4.1", + "signatures": [ + "sync", + "async", + "connection", + "cluster" + ] + }, + { + "redis_py": "8.0.1", + "signatures": [ + "sync", + "async", + "connection", + "cluster" + ] + } + ], + "rust": { + "supported": false, + "handling": "Warn", + "field": null + } + }, + "gcp_service_account": { + "versions": [], + "rust": { + "supported": true, + "handling": "Read", + "field": "Options.gcp.service_account" + } + }, + "gcp_ssl_ca_certs": { + "versions": [], + "rust": { + "supported": true, + "handling": "Read", + "field": "Options.gcp.ssl_ca_certs" + } + }, + "health_check_interval": { + "versions": [ + { + "redis_py": "5.3.1", + "signatures": [ + "sync", + "async", + "connection", + "cluster" + ] + }, + { + "redis_py": "6.4.0", + "signatures": [ + "sync", + "async", + "connection", + "cluster" + ] + }, + { + "redis_py": "7.4.1", + "signatures": [ + "sync", + "async", + "connection", + "cluster" + ] + }, + { + "redis_py": "8.0.1", + "signatures": [ + "sync", + "async", + "connection", + "cluster" + ] + } + ], + "rust": { + "supported": true, + "handling": "Read", + "field": "Options.health_check_interval" + } + }, + "host": { + "versions": [ + { + "redis_py": "5.3.1", + "signatures": [ + "sync", + "async", + "connection", + "cluster" + ] + }, + { + "redis_py": "6.4.0", + "signatures": [ + "sync", + "async", + "connection", + "cluster" + ] + }, + { + "redis_py": "7.4.1", + "signatures": [ + "sync", + "async", + "connection", + "cluster" + ] + }, + { + "redis_py": "8.0.1", + "signatures": [ + "sync", + "async", + "connection", + "cluster" + ] + } + ], + "rust": { + "supported": true, + "handling": "Read", + "field": "Options.host" + } + }, + "legacy_responses": { + "versions": [ + { + "redis_py": "8.0.1", + "signatures": [ + "sync", + "async", + "connection", + "cluster" + ] + } + ], + "rust": { + "supported": false, + "handling": "unlisted", + "field": null + }, + "note": "No SETTINGS row, so a Rust store drops it without a warning" + }, + "lib_name": { + "versions": [ + { + "redis_py": "5.3.1", + "signatures": [ + "sync", + "async", + "connection", + "cluster" + ] + }, + { + "redis_py": "6.4.0", + "signatures": [ + "sync", + "async", + "connection", + "cluster" + ] + }, + { + "redis_py": "7.4.1", + "signatures": [ + "sync", + "async", + "connection", + "cluster" + ] + }, + { + "redis_py": "8.0.1", + "signatures": [ + "sync", + "async", + "connection", + "cluster" + ] + } + ], + "rust": { + "supported": false, + "handling": "Warn", + "field": null + } + }, + "lib_version": { + "versions": [ + { + "redis_py": "5.3.1", + "signatures": [ + "sync", + "async", + "connection", + "cluster" + ] + }, + { + "redis_py": "6.4.0", + "signatures": [ + "sync", + "async", + "connection", + "cluster" + ] + }, + { + "redis_py": "7.4.1", + "signatures": [ + "sync", + "async", + "connection", + "cluster" + ] + }, + { + "redis_py": "8.0.1", + "signatures": [ + "sync", + "async", + "connection", + "cluster" + ] + } + ], + "rust": { + "supported": false, + "handling": "Warn", + "field": null + } + }, + "load_balancing_strategy": { + "versions": [ + { + "redis_py": "5.3.1", + "signatures": [ + "cluster" + ] + }, + { + "redis_py": "6.4.0", + "signatures": [ + "cluster" + ] + }, + { + "redis_py": "7.4.1", + "signatures": [ + "cluster" + ] + }, + { + "redis_py": "8.0.1", + "signatures": [ + "cluster" + ] + } + ], + "rust": { + "supported": false, + "handling": "unlisted", + "field": null + }, + "note": "Cluster-only and no SETTINGS row, so a Rust cluster store drops it without a warning. It changes which node serves a read" + }, + "maint_notifications_config": { + "versions": [ + { + "redis_py": "7.4.1", + "signatures": [ + "sync", + "connection" + ] + }, + { + "redis_py": "8.0.1", + "signatures": [ + "sync", + "connection" + ] + } + ], + "rust": { + "supported": false, + "handling": "unlisted_host_object", + "field": null + }, + "note": "No SETTINGS row, so a Rust store drops it without a warning" + }, + "maint_notifications_pool_handler": { + "versions": [ + { + "redis_py": "7.4.1", + "signatures": [ + "connection" + ] + }, + { + "redis_py": "8.0.1", + "signatures": [ + "connection" + ] + } + ], + "rust": { + "supported": false, + "handling": "unlisted", + "field": null + }, + "note": "Connection internal that only the url allowlist admits, not a setting anyone configures" + }, + "maintenance_notification_hash": { + "versions": [ + { + "redis_py": "7.4.1", + "signatures": [ + "connection" + ] + }, + { + "redis_py": "8.0.1", + "signatures": [ + "connection" + ] + } + ], + "rust": { + "supported": false, + "handling": "unlisted", + "field": null + }, + "note": "Connection internal that only the url allowlist admits, not a setting anyone configures" + }, + "maintenance_state": { + "versions": [ + { + "redis_py": "7.4.1", + "signatures": [ + "connection" + ] + }, + { + "redis_py": "8.0.1", + "signatures": [ + "connection" + ] + } + ], + "rust": { + "supported": false, + "handling": "unlisted", + "field": null + }, + "note": "Connection internal that only the url allowlist admits, not a setting anyone configures" + }, + "max_connections": { + "versions": [ + { + "redis_py": "5.3.1", + "signatures": [ + "sync", + "async", + "cluster" + ] + }, + { + "redis_py": "6.4.0", + "signatures": [ + "sync", + "async", + "cluster" + ] + }, + { + "redis_py": "7.4.1", + "signatures": [ + "sync", + "async", + "cluster" + ] + }, + { + "redis_py": "8.0.1", + "signatures": [ + "sync", + "async", + "cluster" + ] + } + ], + "rust": { + "supported": false, + "handling": "Warn", + "field": null + }, + "note": "Warned with the generic consequence, though Rust having no connection cap can push a low maxclients server over its limit" + }, + "namespace": { + "versions": [], + "rust": { + "supported": true, + "handling": "Read", + "field": "Options.namespace" + } + }, + "orig_host_address": { + "versions": [ + { + "redis_py": "7.4.1", + "signatures": [ + "connection" + ] + }, + { + "redis_py": "8.0.1", + "signatures": [ + "connection" + ] + } + ], + "rust": { + "supported": false, + "handling": "unlisted", + "field": null + }, + "note": "Connection internal that only the url allowlist admits, not a setting anyone configures" + }, + "orig_socket_connect_timeout": { + "versions": [ + { + "redis_py": "7.4.1", + "signatures": [ + "connection" + ] + }, + { + "redis_py": "8.0.1", + "signatures": [ + "connection" + ] + } + ], + "rust": { + "supported": false, + "handling": "unlisted", + "field": null + }, + "note": "Connection internal that only the url allowlist admits, not a setting anyone configures" + }, + "orig_socket_timeout": { + "versions": [ + { + "redis_py": "7.4.1", + "signatures": [ + "connection" + ] + }, + { + "redis_py": "8.0.1", + "signatures": [ + "connection" + ] + } + ], + "rust": { + "supported": false, + "handling": "unlisted", + "field": null + }, + "note": "Connection internal that only the url allowlist admits, not a setting anyone configures" + }, + "oss_cluster_maint_notifications_handler": { + "versions": [ + { + "redis_py": "7.4.1", + "signatures": [ + "sync", + "connection" + ] + }, + { + "redis_py": "8.0.1", + "signatures": [ + "sync", + "connection" + ] + } + ], + "rust": { + "supported": false, + "handling": "unlisted", + "field": null + }, + "note": "No SETTINGS row, so a Rust store drops it without a warning. It takes an object but is missing from HOST_OBJECTS" + }, + "parser": { + "versions": [ + { + "redis_py": "7.4.1", + "signatures": [ + "connection" + ] + }, + { + "redis_py": "8.0.1", + "signatures": [ + "connection" + ] + } + ], + "rust": { + "supported": false, + "handling": "unlisted", + "field": null + }, + "note": "Connection internal that only the url allowlist admits, not a setting anyone configures" + }, + "parser_class": { + "versions": [ + { + "redis_py": "5.3.1", + "signatures": [ + "connection" + ] + }, + { + "redis_py": "6.4.0", + "signatures": [ + "connection" + ] + }, + { + "redis_py": "7.4.1", + "signatures": [ + "connection" + ] + }, + { + "redis_py": "8.0.1", + "signatures": [ + "connection" + ] + } + ], + "rust": { + "supported": false, + "handling": "unlisted_host_object", + "field": null + }, + "note": "Connection internal that only the url allowlist admits, not a setting anyone configures" + }, + "password": { + "versions": [ + { + "redis_py": "5.3.1", + "signatures": [ + "sync", + "async", + "connection", + "cluster" + ] + }, + { + "redis_py": "6.4.0", + "signatures": [ + "sync", + "async", + "connection", + "cluster" + ] + }, + { + "redis_py": "7.4.1", + "signatures": [ + "sync", + "async", + "connection", + "cluster" + ] + }, + { + "redis_py": "8.0.1", + "signatures": [ + "sync", + "async", + "connection", + "cluster" + ] + } + ], + "rust": { + "supported": true, + "handling": "Read", + "field": "Options.password" + } + }, + "path": { + "versions": [ + { + "redis_py": "5.3.1", + "signatures": [ + "cluster" + ] + }, + { + "redis_py": "6.4.0", + "signatures": [ + "cluster" + ] + }, + { + "redis_py": "7.4.1", + "signatures": [ + "cluster" + ] + }, + { + "redis_py": "8.0.1", + "signatures": [ + "cluster" + ] + } + ], + "rust": { + "supported": false, + "handling": "unlisted", + "field": null + }, + "note": "Cluster-only and no SETTINGS row, so a Rust cluster store drops it without a warning" + }, + "policy_resolver": { + "versions": [ + { + "redis_py": "7.4.1", + "signatures": [ + "cluster" + ] + }, + { + "redis_py": "8.0.1", + "signatures": [ + "cluster" + ] + } + ], + "rust": { + "supported": false, + "handling": "unlisted", + "field": null + }, + "note": "Cluster-only and no SETTINGS row, so a Rust cluster store drops it without a warning" + }, + "port": { + "versions": [ + { + "redis_py": "5.3.1", + "signatures": [ + "sync", + "async", + "connection", + "cluster" + ] + }, + { + "redis_py": "6.4.0", + "signatures": [ + "sync", + "async", + "connection", + "cluster" + ] + }, + { + "redis_py": "7.4.1", + "signatures": [ + "sync", + "async", + "connection", + "cluster" + ] + }, + { + "redis_py": "8.0.1", + "signatures": [ + "sync", + "async", + "connection", + "cluster" + ] + } + ], + "rust": { + "supported": true, + "handling": "Read", + "field": "Options.port" + } + }, + "protocol": { + "versions": [ + { + "redis_py": "5.3.1", + "signatures": [ + "sync", + "async", + "connection", + "cluster" + ] + }, + { + "redis_py": "6.4.0", + "signatures": [ + "sync", + "async", + "connection", + "cluster" + ] + }, + { + "redis_py": "7.4.1", + "signatures": [ + "sync", + "async", + "connection", + "cluster" + ] + }, + { + "redis_py": "8.0.1", + "signatures": [ + "sync", + "async", + "connection", + "cluster" + ] + } + ], + "rust": { + "supported": false, + "handling": "Warn", + "field": null + } + }, + "read_from_replicas": { + "versions": [ + { + "redis_py": "5.3.1", + "signatures": [ + "cluster" + ] + }, + { + "redis_py": "6.4.0", + "signatures": [ + "cluster" + ] + }, + { + "redis_py": "7.4.1", + "signatures": [ + "cluster" + ] + }, + { + "redis_py": "8.0.1", + "signatures": [ + "cluster" + ] + } + ], + "rust": { + "supported": false, + "handling": "unlisted", + "field": null + }, + "note": "Cluster-only and no SETTINGS row, so a Rust cluster store drops it without a warning. It changes which node serves a read" + }, + "redis_connect_func": { + "versions": [ + { + "redis_py": "5.3.1", + "signatures": [ + "sync", + "async", + "connection" + ] + }, + { + "redis_py": "6.4.0", + "signatures": [ + "sync", + "async", + "connection" + ] + }, + { + "redis_py": "7.4.1", + "signatures": [ + "sync", + "async", + "connection" + ] + }, + { + "redis_py": "8.0.1", + "signatures": [ + "sync", + "async", + "connection" + ] + } + ], + "rust": { + "supported": false, + "handling": "Warn", + "field": null + } + }, + "reinitialize_steps": { + "versions": [ + { + "redis_py": "5.3.1", + "signatures": [ + "cluster" + ] + }, + { + "redis_py": "6.4.0", + "signatures": [ + "cluster" + ] + }, + { + "redis_py": "7.4.1", + "signatures": [ + "cluster" + ] + }, + { + "redis_py": "8.0.1", + "signatures": [ + "cluster" + ] + } + ], + "rust": { + "supported": false, + "handling": "unlisted", + "field": null + }, + "note": "Cluster-only and no SETTINGS row, so a Rust cluster store drops it without a warning" + }, + "require_full_coverage": { + "versions": [ + { + "redis_py": "5.3.1", + "signatures": [ + "cluster" + ] + }, + { + "redis_py": "6.4.0", + "signatures": [ + "cluster" + ] + }, + { + "redis_py": "7.4.1", + "signatures": [ + "cluster" + ] + }, + { + "redis_py": "8.0.1", + "signatures": [ + "cluster" + ] + } + ], + "rust": { + "supported": false, + "handling": "unlisted", + "field": null + }, + "note": "Cluster-only and no SETTINGS row, so a Rust cluster store drops it without a warning" + }, + "retry": { + "versions": [ + { + "redis_py": "5.3.1", + "signatures": [ + "sync", + "async", + "connection", + "cluster" + ] + }, + { + "redis_py": "6.4.0", + "signatures": [ + "sync", + "async", + "connection", + "cluster" + ] + }, + { + "redis_py": "7.4.1", + "signatures": [ + "sync", + "async", + "connection", + "cluster" + ] + }, + { + "redis_py": "8.0.1", + "signatures": [ + "sync", + "async", + "connection", + "cluster" + ] + } + ], + "rust": { + "supported": false, + "handling": "Warn", + "field": null + } + }, + "retry_on_error": { + "versions": [ + { + "redis_py": "5.3.1", + "signatures": [ + "sync", + "async", + "connection", + "cluster" + ] + }, + { + "redis_py": "6.4.0", + "signatures": [ + "sync", + "async", + "connection", + "cluster" + ] + }, + { + "redis_py": "7.4.1", + "signatures": [ + "sync", + "async", + "connection", + "cluster" + ] + }, + { + "redis_py": "8.0.1", + "signatures": [ + "sync", + "async", + "connection", + "cluster" + ] + } + ], + "rust": { + "supported": false, + "handling": "Warn", + "field": null + } + }, + "retry_on_timeout": { + "versions": [ + { + "redis_py": "5.3.1", + "signatures": [ + "sync", + "async", + "connection" + ] + }, + { + "redis_py": "6.4.0", + "signatures": [ + "sync", + "async", + "connection" + ] + }, + { + "redis_py": "7.4.1", + "signatures": [ + "sync", + "async", + "connection" + ] + }, + { + "redis_py": "8.0.1", + "signatures": [ + "sync", + "async", + "connection" + ] + } + ], + "rust": { + "supported": false, + "handling": "Warn", + "field": null + } + }, + "sentinel_nodes": { + "versions": [], + "rust": { + "supported": true, + "handling": "Read", + "field": "Options.sentinel.nodes" + } + }, + "sentinel_password": { + "versions": [], + "rust": { + "supported": true, + "handling": "Read", + "field": "Options.sentinel.password" + } + }, + "service_name": { + "versions": [], + "rust": { + "supported": true, + "handling": "Read", + "field": "Options.sentinel.service_name" + } + }, + "single_connection_client": { + "versions": [ + { + "redis_py": "5.3.1", + "signatures": [ + "sync", + "async" + ] + }, + { + "redis_py": "6.4.0", + "signatures": [ + "sync", + "async" + ] + }, + { + "redis_py": "7.4.1", + "signatures": [ + "sync", + "async" + ] + }, + { + "redis_py": "8.0.1", + "signatures": [ + "sync", + "async" + ] + } + ], + "rust": { + "supported": false, + "handling": "Warn", + "field": null + } + }, + "socket_connect_timeout": { + "versions": [ + { + "redis_py": "5.3.1", + "signatures": [ + "sync", + "async", + "connection", + "cluster" + ] + }, + { + "redis_py": "6.4.0", + "signatures": [ + "sync", + "async", + "connection", + "cluster" + ] + }, + { + "redis_py": "7.4.1", + "signatures": [ + "sync", + "async", + "connection", + "cluster" + ] + }, + { + "redis_py": "8.0.1", + "signatures": [ + "sync", + "async", + "connection", + "cluster" + ] + } + ], + "rust": { + "supported": true, + "handling": "Read", + "field": "Options.socket_connect_timeout" + } + }, + "socket_keepalive": { + "versions": [ + { + "redis_py": "5.3.1", + "signatures": [ + "sync", + "async", + "connection", + "cluster" + ] + }, + { + "redis_py": "6.4.0", + "signatures": [ + "sync", + "async", + "connection", + "cluster" + ] + }, + { + "redis_py": "7.4.1", + "signatures": [ + "sync", + "async", + "connection", + "cluster" + ] + }, + { + "redis_py": "8.0.1", + "signatures": [ + "sync", + "async", + "connection", + "cluster" + ] + } + ], + "rust": { + "supported": false, + "handling": "Warn", + "field": null + } + }, + "socket_keepalive_options": { + "versions": [ + { + "redis_py": "5.3.1", + "signatures": [ + "sync", + "async", + "connection", + "cluster" + ] + }, + { + "redis_py": "6.4.0", + "signatures": [ + "sync", + "async", + "connection", + "cluster" + ] + }, + { + "redis_py": "7.4.1", + "signatures": [ + "sync", + "async", + "connection", + "cluster" + ] + }, + { + "redis_py": "8.0.1", + "signatures": [ + "sync", + "async", + "connection", + "cluster" + ] + } + ], + "rust": { + "supported": false, + "handling": "Warn", + "field": null + } + }, + "socket_read_size": { + "versions": [ + { + "redis_py": "5.3.1", + "signatures": [ + "connection" + ] + }, + { + "redis_py": "6.4.0", + "signatures": [ + "connection" + ] + }, + { + "redis_py": "7.4.1", + "signatures": [ + "connection" + ] + }, + { + "redis_py": "8.0.1", + "signatures": [ + "sync", + "async", + "connection", + "cluster" + ] + } + ], + "rust": { + "supported": false, + "handling": "unlisted", + "field": null + }, + "note": "No SETTINGS row, so a Rust store drops it without a warning" + }, + "socket_timeout": { + "versions": [ + { + "redis_py": "5.3.1", + "signatures": [ + "sync", + "async", + "connection", + "cluster" + ] + }, + { + "redis_py": "6.4.0", + "signatures": [ + "sync", + "async", + "connection", + "cluster" + ] + }, + { + "redis_py": "7.4.1", + "signatures": [ + "sync", + "async", + "connection", + "cluster" + ] + }, + { + "redis_py": "8.0.1", + "signatures": [ + "sync", + "async", + "connection", + "cluster" + ] + } + ], + "rust": { + "supported": true, + "handling": "Read", + "field": "Options.socket_timeout" + } + }, + "socket_type": { + "versions": [ + { + "redis_py": "5.3.1", + "signatures": [ + "connection" + ] + }, + { + "redis_py": "6.4.0", + "signatures": [ + "connection" + ] + }, + { + "redis_py": "7.4.1", + "signatures": [ + "connection" + ] + }, + { + "redis_py": "8.0.1", + "signatures": [ + "connection" + ] + } + ], + "rust": { + "supported": false, + "handling": "unlisted", + "field": null + }, + "note": "Connection internal that only the url allowlist admits, not a setting anyone configures" + }, + "ssl": { + "versions": [ + { + "redis_py": "5.3.1", + "signatures": [ + "sync", + "async", + "cluster" + ] + }, + { + "redis_py": "6.4.0", + "signatures": [ + "sync", + "async", + "cluster" + ] + }, + { + "redis_py": "7.4.1", + "signatures": [ + "sync", + "async", + "cluster" + ] + }, + { + "redis_py": "8.0.1", + "signatures": [ + "sync", + "async", + "cluster" + ] + } + ], + "rust": { + "supported": true, + "handling": "Read", + "field": "Options.ssl" + } + }, + "ssl_ca_certs": { + "versions": [ + { + "redis_py": "5.3.1", + "signatures": [ + "sync", + "async", + "cluster" + ] + }, + { + "redis_py": "6.4.0", + "signatures": [ + "sync", + "async", + "cluster" + ] + }, + { + "redis_py": "7.4.1", + "signatures": [ + "sync", + "async", + "cluster" + ] + }, + { + "redis_py": "8.0.1", + "signatures": [ + "sync", + "async", + "cluster" + ] + } + ], + "rust": { + "supported": true, + "handling": "Read", + "field": "Options.tls.ca_certs" + } + }, + "ssl_ca_data": { + "versions": [ + { + "redis_py": "5.3.1", + "signatures": [ + "sync", + "async", + "cluster" + ] + }, + { + "redis_py": "6.4.0", + "signatures": [ + "sync", + "async", + "cluster" + ] + }, + { + "redis_py": "7.4.1", + "signatures": [ + "sync", + "async", + "cluster" + ] + }, + { + "redis_py": "8.0.1", + "signatures": [ + "sync", + "async", + "cluster" + ] + } + ], + "rust": { + "supported": true, + "handling": "Read", + "field": "Options.tls.ca_data" + } + }, + "ssl_ca_path": { + "versions": [ + { + "redis_py": "5.3.1", + "signatures": [ + "sync" + ] + }, + { + "redis_py": "6.4.0", + "signatures": [ + "sync" + ] + }, + { + "redis_py": "7.4.1", + "signatures": [ + "sync", + "async" + ] + }, + { + "redis_py": "8.0.1", + "signatures": [ + "sync", + "async" + ] + } + ], + "rust": { + "supported": true, + "handling": "Read", + "field": "Options.tls.ca_path" + }, + "note": "Python's async client raises TypeError on it before 7.4.1, so Rust reading it is a superset with the pinned 5.3.1" + }, + "ssl_cert_reqs": { + "versions": [ + { + "redis_py": "5.3.1", + "signatures": [ + "sync", + "async", + "cluster" + ] + }, + { + "redis_py": "6.4.0", + "signatures": [ + "sync", + "async", + "cluster" + ] + }, + { + "redis_py": "7.4.1", + "signatures": [ + "sync", + "async", + "cluster" + ] + }, + { + "redis_py": "8.0.1", + "signatures": [ + "sync", + "async", + "cluster" + ] + } + ], + "rust": { + "supported": true, + "handling": "Read", + "field": "Options.tls.cert_reqs" + } + }, + "ssl_certfile": { + "versions": [ + { + "redis_py": "5.3.1", + "signatures": [ + "sync", + "async", + "cluster" + ] + }, + { + "redis_py": "6.4.0", + "signatures": [ + "sync", + "async", + "cluster" + ] + }, + { + "redis_py": "7.4.1", + "signatures": [ + "sync", + "async", + "cluster" + ] + }, + { + "redis_py": "8.0.1", + "signatures": [ + "sync", + "async", + "cluster" + ] + } + ], + "rust": { + "supported": true, + "handling": "Read", + "field": "Options.tls.certfile" + } + }, + "ssl_check_hostname": { + "versions": [ + { + "redis_py": "5.3.1", + "signatures": [ + "sync", + "async", + "cluster" + ] + }, + { + "redis_py": "6.4.0", + "signatures": [ + "sync", + "async", + "cluster" + ] + }, + { + "redis_py": "7.4.1", + "signatures": [ + "sync", + "async", + "cluster" + ] + }, + { + "redis_py": "8.0.1", + "signatures": [ + "sync", + "async", + "cluster" + ] + } + ], + "rust": { + "supported": true, + "handling": "Read", + "field": "Options.tls.check_hostname" + } + }, + "ssl_ciphers": { + "versions": [ + { + "redis_py": "5.3.1", + "signatures": [ + "sync", + "async", + "cluster" + ] + }, + { + "redis_py": "6.4.0", + "signatures": [ + "sync", + "async", + "cluster" + ] + }, + { + "redis_py": "7.4.1", + "signatures": [ + "sync", + "async", + "cluster" + ] + }, + { + "redis_py": "8.0.1", + "signatures": [ + "sync", + "async", + "cluster" + ] + } + ], + "rust": { + "supported": false, + "handling": "Warn", + "field": null + } + }, + "ssl_exclude_verify_flags": { + "versions": [ + { + "redis_py": "7.4.1", + "signatures": [ + "sync", + "async", + "cluster" + ] + }, + { + "redis_py": "8.0.1", + "signatures": [ + "sync", + "async", + "cluster" + ] + } + ], + "rust": { + "supported": false, + "handling": "unlisted", + "field": null + }, + "note": "No SETTINGS row, so a Rust store drops it without a warning" + }, + "ssl_include_verify_flags": { + "versions": [ + { + "redis_py": "7.4.1", + "signatures": [ + "sync", + "async", + "cluster" + ] + }, + { + "redis_py": "8.0.1", + "signatures": [ + "sync", + "async", + "cluster" + ] + } + ], + "rust": { + "supported": false, + "handling": "unlisted", + "field": null + }, + "note": "No SETTINGS row, so a Rust store drops it without a warning" + }, + "ssl_keyfile": { + "versions": [ + { + "redis_py": "5.3.1", + "signatures": [ + "sync", + "async", + "cluster" + ] + }, + { + "redis_py": "6.4.0", + "signatures": [ + "sync", + "async", + "cluster" + ] + }, + { + "redis_py": "7.4.1", + "signatures": [ + "sync", + "async", + "cluster" + ] + }, + { + "redis_py": "8.0.1", + "signatures": [ + "sync", + "async", + "cluster" + ] + } + ], + "rust": { + "supported": true, + "handling": "Read", + "field": "Options.tls.keyfile" + } + }, + "ssl_min_version": { + "versions": [ + { + "redis_py": "5.3.1", + "signatures": [ + "sync", + "async", + "cluster" + ] + }, + { + "redis_py": "6.4.0", + "signatures": [ + "sync", + "async", + "cluster" + ] + }, + { + "redis_py": "7.4.1", + "signatures": [ + "sync", + "async", + "cluster" + ] + }, + { + "redis_py": "8.0.1", + "signatures": [ + "sync", + "async", + "cluster" + ] + } + ], + "rust": { + "supported": false, + "handling": "Warn", + "field": null + } + }, + "ssl_ocsp_context": { + "versions": [ + { + "redis_py": "5.3.1", + "signatures": [ + "sync" + ] + }, + { + "redis_py": "6.4.0", + "signatures": [ + "sync" + ] + }, + { + "redis_py": "7.4.1", + "signatures": [ + "sync" + ] + }, + { + "redis_py": "8.0.1", + "signatures": [ + "sync" + ] + } + ], + "rust": { + "supported": false, + "handling": "Warn", + "field": null + }, + "note": "Sync-only on every tested version, so the proxy's async path raises TypeError on it in Python too" + }, + "ssl_ocsp_expected_cert": { + "versions": [ + { + "redis_py": "5.3.1", + "signatures": [ + "sync" + ] + }, + { + "redis_py": "6.4.0", + "signatures": [ + "sync" + ] + }, + { + "redis_py": "7.4.1", + "signatures": [ + "sync" + ] + }, + { + "redis_py": "8.0.1", + "signatures": [ + "sync" + ] + } + ], + "rust": { + "supported": false, + "handling": "Warn", + "field": null + }, + "note": "Sync-only on every tested version, so the proxy's async path raises TypeError on it in Python too" + }, + "ssl_password": { + "versions": [ + { + "redis_py": "5.3.1", + "signatures": [ + "sync" + ] + }, + { + "redis_py": "6.4.0", + "signatures": [ + "sync" + ] + }, + { + "redis_py": "7.4.1", + "signatures": [ + "sync", + "async" + ] + }, + { + "redis_py": "8.0.1", + "signatures": [ + "sync", + "async" + ] + } + ], + "rust": { + "supported": true, + "handling": "Read", + "field": "Options.tls.key_password" + }, + "note": "Python's async client raises TypeError on it before 7.4.1, so Rust reading it is a superset with the pinned 5.3.1" + }, + "ssl_validate_ocsp": { + "versions": [ + { + "redis_py": "5.3.1", + "signatures": [ + "sync" + ] + }, + { + "redis_py": "6.4.0", + "signatures": [ + "sync" + ] + }, + { + "redis_py": "7.4.1", + "signatures": [ + "sync" + ] + }, + { + "redis_py": "8.0.1", + "signatures": [ + "sync" + ] + } + ], + "rust": { + "supported": false, + "handling": "Reject", + "field": null + }, + "note": "Sync-only on every tested version, so the proxy's async path raises TypeError on it in Python too" + }, + "ssl_validate_ocsp_stapled": { + "versions": [ + { + "redis_py": "5.3.1", + "signatures": [ + "sync" + ] + }, + { + "redis_py": "6.4.0", + "signatures": [ + "sync" + ] + }, + { + "redis_py": "7.4.1", + "signatures": [ + "sync" + ] + }, + { + "redis_py": "8.0.1", + "signatures": [ + "sync" + ] + } + ], + "rust": { + "supported": false, + "handling": "Reject", + "field": null + }, + "note": "Sync-only on every tested version, so the proxy's async path raises TypeError on it in Python too" + }, + "startup_nodes": { + "versions": [ + { + "redis_py": "5.3.1", + "signatures": [ + "cluster" + ] + }, + { + "redis_py": "6.4.0", + "signatures": [ + "cluster" + ] + }, + { + "redis_py": "7.4.1", + "signatures": [ + "cluster" + ] + }, + { + "redis_py": "8.0.1", + "signatures": [ + "cluster" + ] + } + ], + "rust": { + "supported": true, + "handling": "Read", + "field": "Options.startup_nodes" + } + }, + "unix_socket_path": { + "versions": [ + { + "redis_py": "5.3.1", + "signatures": [ + "sync", + "async" + ] + }, + { + "redis_py": "6.4.0", + "signatures": [ + "sync", + "async" + ] + }, + { + "redis_py": "7.4.1", + "signatures": [ + "sync", + "async" + ] + }, + { + "redis_py": "8.0.1", + "signatures": [ + "sync", + "async" + ] + } + ], + "rust": { + "supported": true, + "handling": "Read", + "field": "Options.unix_socket_path" + } + }, + "url": { + "versions": [], + "rust": { + "supported": true, + "handling": "Read", + "field": "Options.url" + } + }, + "username": { + "versions": [ + { + "redis_py": "5.3.1", + "signatures": [ + "sync", + "async", + "connection", + "cluster" + ] + }, + { + "redis_py": "6.4.0", + "signatures": [ + "sync", + "async", + "connection", + "cluster" + ] + }, + { + "redis_py": "7.4.1", + "signatures": [ + "sync", + "async", + "connection", + "cluster" + ] + }, + { + "redis_py": "8.0.1", + "signatures": [ + "sync", + "async", + "connection", + "cluster" + ] + } + ], + "rust": { + "supported": true, + "handling": "Read", + "field": "Options.username" + } + } + } +}