Skip to content

Commit c9e5b7a

Browse files
committed
fix: lockdown type-hinting syntax to python3.9
1 parent c616233 commit c9e5b7a

24 files changed

+134
-167
lines changed

src/fastapi_csrf_protect/__init__.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,10 @@
1212
FastAPI extension that provides Csrf Protection Token support
1313
"""
1414

15-
### Standard packages ###
16-
from typing import Tuple
17-
1815
### Local modules ###
1916
from fastapi_csrf_protect.core import CsrfProtect
2017

21-
__all__: Tuple[str, ...] = ("CsrfProtect",)
18+
__all__: tuple[str, ...] = ("CsrfProtect",)
2219
__name__ = "fastapi-csrf-protect"
2320
__package__ = "fastapi-csrf-protect"
2421
__version__ = "1.0.4"

src/fastapi_csrf_protect/core.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
from hashlib import sha1
1414
from re import match
1515
from os import urandom
16-
from typing import Dict, Optional, Tuple, Union
16+
from typing import Optional, Union
1717

1818
### Third-party packages ###
1919
from itsdangerous import BadData, SignatureExpired, URLSafeTimedSerializer
@@ -32,7 +32,7 @@
3232

3333

3434
class CsrfProtect(CsrfConfig):
35-
def generate_csrf_tokens(self, secret_key: Optional[str] = None) -> Tuple[str, str]:
35+
def generate_csrf_tokens(self, secret_key: Optional[str] = None) -> tuple[str, str]:
3636
"""
3737
Generate a CSRF token and a signed CSRF token using server's secret key to be stored in cookie.
3838
@@ -56,7 +56,7 @@ def get_csrf_from_body(self, data: bytes) -> str:
5656
:param data: attached request body containing cookie data with configured `token_key`
5757
:type data: bytes
5858
"""
59-
fields: Dict[str, Tuple[type, str]] = {self._token_key: (str, "csrf-token")}
59+
fields: dict[str, tuple[type, str]] = {self._token_key: (str, "csrf-token")}
6060
Body = create_model("Body", **fields)
6161
content: str = '{"' + data.decode("utf-8").replace("&", '","').replace("=", '":"') + '"}'
6262
body = Body.model_validate_json(content)
@@ -192,4 +192,4 @@ async def validate_csrf(
192192
raise TokenValidationError("The CSRF token is invalid.")
193193

194194

195-
__all__: Tuple[str, ...] = ("CsrfProtect",)
195+
__all__: tuple[str, ...] = ("CsrfProtect",)

src/fastapi_csrf_protect/csrf_config.py

Lines changed: 20 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,9 @@
1010
# *************************************************************
1111

1212
### Standard packages ###
13-
from typing import Any, ClassVar, Callable, Literal, Optional, Sequence, Set, Tuple, Union, cast
13+
from typing import Any, ClassVar, Callable, Literal, Optional, Sequence, Set, Union
1414

1515
### Third-party packages ###
16-
from pydantic import ValidationError
1716
from pydantic_settings import BaseSettings
1817

1918
### Local modules ###
@@ -42,29 +41,25 @@ class CsrfConfig(object):
4241

4342
@classmethod
4443
def load_config(
45-
cls, settings: Callable[..., Union[Sequence[Tuple[str, Any]], BaseSettings]]
44+
cls, settings: Callable[..., Union[Sequence[tuple[str, Any]], BaseSettings]]
4645
) -> None:
47-
try:
48-
config = LoadConfig(**{key.lower(): value for key, value in settings()})
49-
cls._cookie_key = config.cookie_key or cls._cookie_key
50-
cls._cookie_path = config.cookie_path or cls._cookie_path
51-
cls._cookie_domain = config.cookie_domain
52-
if config.cookie_samesite in {"lax", "none", "strict"}:
53-
cls._cookie_samesite = cast(Literal["lax", "none", "strict"], config.cookie_samesite)
54-
cls._cookie_secure = False if config.cookie_secure is None else config.cookie_secure
55-
cls._header_name = config.header_name or cls._header_name
56-
cls._header_type = config.header_type
57-
cls._httponly = True if config.httponly is None else config.httponly
58-
cls._max_age = config.max_age or cls._max_age
59-
cls._methods = config.methods or cls._methods
60-
cls._secret_key = config.secret_key
61-
cls._token_location = config.token_location or cls._token_location
62-
cls._token_key = config.token_key or cls._token_key
63-
except ValidationError:
64-
raise
65-
except Exception as err:
66-
print(err)
67-
raise TypeError('CsrfConfig must be pydantic "BaseSettings" or list of tuple')
46+
"""
47+
:raises pydantic_core.ValidationError: in case of settings' attribute type mismatched
48+
"""
49+
config = LoadConfig(**{key.lower(): value for key, value in settings()})
50+
cls._cookie_key = config.cookie_key or cls._cookie_key
51+
cls._cookie_path = config.cookie_path or cls._cookie_path
52+
cls._cookie_domain = config.cookie_domain
53+
cls._cookie_samesite = config.cookie_samesite
54+
cls._cookie_secure = False if config.cookie_secure is None else config.cookie_secure
55+
cls._header_name = config.header_name or cls._header_name
56+
cls._header_type = config.header_type
57+
cls._httponly = True if config.httponly is None else config.httponly
58+
cls._max_age = config.max_age or cls._max_age
59+
cls._methods = config.methods or cls._methods
60+
cls._secret_key = config.secret_key
61+
cls._token_location = config.token_location or cls._token_location
62+
cls._token_key = config.token_key or cls._token_key
6863

6964

70-
__all__: Tuple[str, ...] = ("CsrfConfig",)
65+
__all__: tuple[str, ...] = ("CsrfConfig",)

src/fastapi_csrf_protect/exceptions.py

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,6 @@
99
# HISTORY:
1010
# *************************************************************
1111

12-
### Standard packages ###
13-
from typing import Tuple
14-
15-
1612
class CsrfProtectError(Exception):
1713
def __init__(self, status_code: int, message: str):
1814
self.status_code = status_code
@@ -34,7 +30,7 @@ def __init__(self, message: str):
3430
super().__init__(401, message)
3531

3632

37-
__all__: Tuple[str, ...] = (
33+
__all__: tuple[str, ...] = (
3834
"CsrfProtectError",
3935
"InvalidHeaderError",
4036
"MissingTokenError",

src/fastapi_csrf_protect/flexible/__init__.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,7 @@
99
# HISTORY:
1010
# *************************************************************
1111

12-
### Standard packages ###
13-
from typing import Tuple
14-
1512
### Local modules ###
1613
from fastapi_csrf_protect.flexible.core import CsrfProtect
1714

18-
__all__: Tuple[str, ...] = ("CsrfProtect",)
15+
__all__: tuple[str, ...] = ("CsrfProtect",)

src/fastapi_csrf_protect/flexible/core.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
from hashlib import sha1
1414
from os import urandom
1515
from re import match
16-
from typing import Dict, Tuple, Optional, Union
16+
from typing import Optional, Union
1717

1818
### Third-party packages ###
1919
from itsdangerous import BadData, SignatureExpired, URLSafeTimedSerializer
@@ -38,7 +38,7 @@ class CsrfProtect(CsrfConfig):
3838
2. Body
3939
"""
4040

41-
def generate_csrf_tokens(self, secret_key: Optional[str] = None) -> Tuple[str, str]:
41+
def generate_csrf_tokens(self, secret_key: Optional[str] = None) -> tuple[str, str]:
4242
"""
4343
Generate a CSRF token and a signed CSRF token using server's secret key to be stored in cookie.
4444
@@ -62,7 +62,7 @@ def get_csrf_from_body(self, data: bytes) -> str:
6262
:param data: attached request body containing cookie data with configured `token_key`
6363
:type data: bytes
6464
"""
65-
fields: Dict[str, Tuple[type, str]] = {self._token_key: (str, "csrf-token")}
65+
fields: dict[str, tuple[type, str]] = {self._token_key: (str, "csrf-token")}
6666
Body = create_model("Body", **fields)
6767
content: str = '{"' + data.decode("utf-8").replace("&", '","').replace("=", '":"') + '"}'
6868
body = Body.model_validate_json(content)
@@ -171,7 +171,7 @@ async def validate_csrf(
171171
if signed_token is None:
172172
raise MissingTokenError(f"Missing Cookie: `{cookie_key}`.")
173173
time_limit = time_limit or self._max_age
174-
token: None | str = self.get_csrf_from_headers(request.headers)
174+
token: Optional[str] = self.get_csrf_from_headers(request.headers)
175175
if not token:
176176
token = self.get_csrf_from_body(await request.body())
177177
serializer = URLSafeTimedSerializer(secret_key, salt="fastapi-csrf-token")
@@ -185,4 +185,4 @@ async def validate_csrf(
185185
raise TokenValidationError("The CSRF token is invalid.")
186186

187187

188-
__all__: Tuple[str, ...] = ("CsrfProtect",)
188+
__all__: tuple[str, ...] = ("CsrfProtect",)

src/fastapi_csrf_protect/flexible/csrf_config.py

Lines changed: 21 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,9 @@
1010
# *************************************************************
1111

1212
### Standard packages ###
13-
from typing import Any, ClassVar, Callable, Literal, Optional, Sequence, Set, Tuple, Union, cast
13+
from typing import Any, ClassVar, Callable, Literal, Optional, Sequence, Set, Union
1414

1515
### Third-party packages ###
16-
from pydantic import ValidationError
1716
from pydantic_settings import BaseSettings
1817

1918
### Local modules ###
@@ -41,28 +40,24 @@ class CsrfConfig(object):
4140

4241
@classmethod
4342
def load_config(
44-
cls, settings: Callable[..., Union[Sequence[Tuple[str, Any]], BaseSettings]]
43+
cls, settings: Callable[..., Union[Sequence[tuple[str, Any]], BaseSettings]]
4544
) -> None:
46-
try:
47-
config = LoadConfig(**{key.lower(): value for key, value in settings()})
48-
cls._cookie_key = config.cookie_key or cls._cookie_key
49-
cls._cookie_path = config.cookie_path or cls._cookie_path
50-
cls._cookie_domain = config.cookie_domain
51-
if config.cookie_samesite in {"lax", "none", "strict"}:
52-
cls._cookie_samesite = cast(Literal["lax", "none", "strict"], config.cookie_samesite)
53-
cls._cookie_secure = False if config.cookie_secure is None else config.cookie_secure
54-
cls._header_name = config.header_name or cls._header_name
55-
cls._header_type = config.header_type
56-
cls._httponly = True if config.httponly is None else config.httponly
57-
cls._max_age = config.max_age or cls._max_age
58-
cls._methods = config.methods or cls._methods
59-
cls._secret_key = config.secret_key
60-
cls._token_key = config.token_key or cls._token_key
61-
except ValidationError:
62-
raise
63-
except Exception as err:
64-
print(err)
65-
raise TypeError('CsrfConfig must be pydantic "BaseSettings" or list of tuple')
66-
67-
68-
__all__: Tuple[str, ...] = ("CsrfConfig",)
45+
"""
46+
:raises pydantic_core.ValidationError: in case of settings' attribute type mismatched
47+
"""
48+
config = LoadConfig(**{key.lower(): value for key, value in settings()})
49+
cls._cookie_key = config.cookie_key or cls._cookie_key
50+
cls._cookie_path = config.cookie_path or cls._cookie_path
51+
cls._cookie_domain = config.cookie_domain
52+
cls._cookie_samesite = config.cookie_samesite
53+
cls._cookie_secure = False if config.cookie_secure is None else config.cookie_secure
54+
cls._header_name = config.header_name or cls._header_name
55+
cls._header_type = config.header_type
56+
cls._httponly = True if config.httponly is None else config.httponly
57+
cls._max_age = config.max_age or cls._max_age
58+
cls._methods = config.methods or cls._methods
59+
cls._secret_key = config.secret_key
60+
cls._token_key = config.token_key or cls._token_key
61+
62+
63+
__all__: tuple[str, ...] = ("CsrfConfig",)

src/fastapi_csrf_protect/flexible/load_config.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
### Standard packages ###
1313
from __future__ import annotations
14-
from typing import Literal, Optional, Set, Tuple
14+
from typing import Literal, Optional, Set
1515

1616
### Third-party packages ###
1717
from pydantic import (
@@ -45,4 +45,4 @@ def validate_cookie_samesite_none_secure(self) -> LoadConfig:
4545
return self
4646

4747

48-
__all__: Tuple[str, ...] = ("LoadConfig",)
48+
__all__: tuple[str, ...] = ("LoadConfig",)

src/fastapi_csrf_protect/load_config.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
### Standard packages ###
1313
from __future__ import annotations
14-
from typing import Literal, Optional, Set, Tuple
14+
from typing import Literal, Optional, Set
1515

1616
### Third-party packages ###
1717
from pydantic import (
@@ -53,4 +53,4 @@ def validate_token_key(self) -> LoadConfig:
5353
return self
5454

5555

56-
__all__: Tuple[str, ...] = ("LoadConfig",)
56+
__all__: tuple[str, ...] = ("LoadConfig",)

tests/__init__.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111

1212
### Standard packages ###
1313
from collections.abc import Generator
14-
from typing import Tuple
1514

1615
### Third-party packages ###
1716
from fastapi import Depends, FastAPI, Request
@@ -62,4 +61,4 @@ def csrf_protect_error_handler(request: Request, exc: CsrfProtectError) -> JSONR
6261
yield client
6362

6463

65-
__all__: Tuple[str, ...] = ("test_client",)
64+
__all__: tuple[str, ...] = ("test_client",)

0 commit comments

Comments
 (0)