From 8067096a8e739344115f47bddaf6e2db4eaafb44 Mon Sep 17 00:00:00 2001 From: Stephen Eisenhauer Date: Tue, 24 Mar 2026 11:43:07 -0700 Subject: [PATCH 1/2] fix: Improve type annotations in `SignatureVerifier` Receive headers as abstract/immutable `collections.abc.Mapping` instead of `Dict` to more accurately declare compatibility with dict-like objects (common for holding headers in HTTP frameworks), and mark timestamp/signature args as `Optional` in `is_valid` to reflect reality and fix the typechecker errors in `is_valid_request`. --- slack_sdk/signature/__init__.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/slack_sdk/signature/__init__.py b/slack_sdk/signature/__init__.py index aa46e5348..24082e307 100644 --- a/slack_sdk/signature/__init__.py +++ b/slack_sdk/signature/__init__.py @@ -2,8 +2,9 @@ import hashlib import hmac +from collections.abc import Mapping from time import time -from typing import Dict, Optional, Union +from typing import Optional, Union class Clock: @@ -26,7 +27,7 @@ def __init__(self, signing_secret: str, clock: Clock = Clock()): def is_valid_request( self, body: Union[str, bytes], - headers: Dict[str, str], + headers: Mapping[str, str], ) -> bool: """Verifies if the given signature is valid""" if headers is None: @@ -34,15 +35,15 @@ def is_valid_request( normalized_headers = {k.lower(): v for k, v in headers.items()} return self.is_valid( body=body, - timestamp=normalized_headers.get("x-slack-request-timestamp", None), # type: ignore[arg-type] - signature=normalized_headers.get("x-slack-signature", None), # type: ignore[arg-type] + timestamp=normalized_headers.get("x-slack-request-timestamp", None), + signature=normalized_headers.get("x-slack-signature", None), ) def is_valid( self, body: Union[str, bytes], - timestamp: str, - signature: str, + timestamp: Optional[str], + signature: Optional[str], ) -> bool: """Verifies if the given signature is valid""" if timestamp is None or signature is None: From bdb6cac607180fcc35ad1c67c05d3ae58ae3f1bb Mon Sep 17 00:00:00 2001 From: Stephen Eisenhauer Date: Tue, 24 Mar 2026 14:19:57 -0700 Subject: [PATCH 2/2] Keep runtime fallback for 3.7/3.8 compat Because `Mapping` is not subscriptable until Python 3.9, the previous change introduced runtime errors for 3.7/3.8. Applies suggested workaround from @WilliamBergamin to continue using Dict at runtime until <3.9 is eventually dropped. --- slack_sdk/signature/__init__.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/slack_sdk/signature/__init__.py b/slack_sdk/signature/__init__.py index 24082e307..ecdc67539 100644 --- a/slack_sdk/signature/__init__.py +++ b/slack_sdk/signature/__init__.py @@ -2,9 +2,14 @@ import hashlib import hmac -from collections.abc import Mapping from time import time -from typing import Optional, Union +from typing import Dict, Optional, Union, TYPE_CHECKING + +# Fallback to Dict for Python 3.7/3.8 compatibility (safe to remove once these versions are no longer supported) +if TYPE_CHECKING: + from collections.abc import Mapping +else: + Mapping = Dict class Clock: