diff --git a/.flake8 b/.flake8 index abbd0dc..10c3960 100644 --- a/.flake8 +++ b/.flake8 @@ -1,3 +1,3 @@ [flake8] max-line-length = 88 -ignore = E203, W503 +extend-ignore = E203,W503,E701 diff --git a/fido2/client.py b/fido2/client.py index 3185871..860f908 100644 --- a/fido2/client.py +++ b/fido2/client.py @@ -68,6 +68,7 @@ Mapping, Sequence, Tuple, + overload, ) import abc @@ -463,6 +464,14 @@ def _get_extension_results(self, assertion): return ClientExtensionOutputs(extension_outputs) +@overload +def _cbor_list(values: Sequence) -> list: ... + + +@overload +def _cbor_list(values: None) -> None: ... + + def _cbor_list(values): if not values: return None diff --git a/fido2/ctap2/base.py b/fido2/ctap2/base.py index 4fd1390..29a041c 100644 --- a/fido2/ctap2/base.py +++ b/fido2/ctap2/base.py @@ -135,7 +135,7 @@ class AssertionResponse(_CborDataObject): (only set for the first response, if > 1). """ - credential: Dict[str, Any] + credential: Mapping[str, Any] auth_data: AuthenticatorData signature: bytes user: Optional[Dict[str, Any]] = None @@ -154,7 +154,7 @@ def verify(self, client_param: bytes, public_key: CoseKey): @classmethod def from_ctap1( - cls, app_param: bytes, credential: Dict[str, Any], authentication + cls, app_param: bytes, credential: Mapping[str, Any], authentication ) -> "AssertionResponse": """Create an AssertionResponse from a CTAP1 SignatureData instance. diff --git a/fido2/utils.py b/fido2/utils.py index 34be309..df80e20 100644 --- a/fido2/utils.py +++ b/fido2/utils.py @@ -48,6 +48,8 @@ TypeVar, Hashable, get_type_hints, + overload, + Type, ) import struct import warnings @@ -168,6 +170,7 @@ def read(self, size: Optional[int] = -1) -> bytes: _T = TypeVar("_T", bound=Hashable) +_S = TypeVar("_S", bound="_DataClassMapping") class _DataClassMapping(Mapping[_T, Any]): @@ -252,8 +255,16 @@ def _parse_value(cls, t, value): # Convert to enum values, other wrappers return t(value) + @overload @classmethod - def from_dict(cls, data: Optional[Mapping[_T, Any]]): + def from_dict(cls: Type[_S], data: None) -> None: ... + + @overload + @classmethod + def from_dict(cls: Type[_S], data: Mapping[_T, Any]) -> _S: ... + + @classmethod + def from_dict(cls, data): if data is None: return None if isinstance(data, cls): diff --git a/fido2/webauthn.py b/fido2/webauthn.py index ba7a6fc..33e7a72 100644 --- a/fido2/webauthn.py +++ b/fido2/webauthn.py @@ -464,7 +464,7 @@ def _parse_value(cls, t, value): return super(_JsonDataObject, cls)._parse_value(t, value) @classmethod - def from_dict(cls, data: Optional[Mapping[str, Any]]): + def from_dict(cls, data): webauthn_json_mapping.warn() return super().from_dict(data) @@ -566,7 +566,7 @@ def __getitem__(self, key): return super().__getitem__(key) @classmethod - def from_dict(cls, data: Optional[Mapping[str, Any]]): + def from_dict(cls, data): if data is not None and not webauthn_json_mapping.enabled: value = dict(data) value["clientDataJSON"] = value.pop("clientData", None) @@ -596,7 +596,7 @@ def __getitem__(self, key): return super().__getitem__(key) @classmethod - def from_dict(cls, data: Optional[Mapping[str, Any]]): + def from_dict(cls, data): if data is not None and not webauthn_json_mapping.enabled: value = dict(data) value["clientDataJSON"] = value.pop("clientData", None)