Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

✨ Pydantic v2 migration #470

Closed
wants to merge 7 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ jobs:
- uses: pre-commit/action@v3.0.0
with:
extra_args: --all-files --verbose
- name: Mypy check
run: bash scripts/mypy.sh
test:
name: test on python ${{ matrix.python-version }}
runs-on: ubuntu-latest
Expand Down
41 changes: 41 additions & 0 deletions authx/_internal/_session.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
from datetime import timedelta
from typing import Callable, Optional
from uuid import uuid4

from pydantic_settings import BaseSettings


def genSessionId() -> str:
return uuid4().hex


settings = {"sessionIdGenerator": genSessionId}


class Config(BaseSettings):
redisURL: str = "redis://localhost:6379/0"
settings: dict = settings
sessionIdName: str = "ssid"
expireTime: timedelta = timedelta(hours=6)

def genSessionId(self) -> str:
return self.settings["sessionIdGenerator"]()


config = Config()


def basicConfig(
redisURL: Optional[str] = "",
sessionIdName: Optional[str] = "",
sessionIdGenerator: Optional[Callable[[], str]] = None,
expireTime: Optional[timedelta] = None,
):
if redisURL:
config.redisURL = redisURL
if sessionIdName:
config.sessionIdName = sessionIdName
if sessionIdGenerator:
config.settings["sessionIdGenerator"] = sessionIdGenerator
if expireTime:
config.expireTime = expireTime
3 changes: 2 additions & 1 deletion authx/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
from typing import List, Optional, Sequence

from jwt.algorithms import get_default_algorithms, requires_cryptography
from pydantic import BaseSettings, Field
from pydantic import Field
from pydantic_settings import BaseSettings

from authx.exceptions import BadConfigurationError
from authx.types import AlgorithmType, HTTPMethods, SameSitePolicy, StringOrSequence, TokenLocations
Expand Down
13 changes: 6 additions & 7 deletions authx/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from hmac import compare_digest
from typing import Any, Dict, List, Optional, Sequence

from pydantic import BaseModel, Extra, Field, ValidationError, validator
from pydantic import BaseModel, ConfigDict, Field, ValidationError, validator

from authx._internal._utils import get_now, get_now_ts, get_uuid
from authx.exceptions import (
Expand All @@ -18,6 +18,8 @@


class TokenPayload(BaseModel):
model_config = ConfigDict(extra='allow')

jti: Optional[str] = Field(default_factory=get_uuid)
iss: Optional[str] = None
sub: Optional[str] = None
Expand All @@ -30,16 +32,13 @@ class TokenPayload(BaseModel):
scopes: Optional[List[str]] = None
fresh: bool = False

class Config:
extra = Extra.allow

@property
def _additional_fields(self):
return set(self.__dict__) - set(self.__fields__)

@property
def extra_dict(self):
return self.dict(include=self._additional_fields)
return self.model_dump(include=self._additional_fields)

@property
def issued_at(self) -> datetime.datetime:
Expand Down Expand Up @@ -122,7 +121,7 @@ def decode(
issuer=issuer,
verify=verify,
)
return cls.parse_obj(payload)
return cls.model_validate(payload)


class RequestToken(BaseModel):
Expand Down Expand Up @@ -153,7 +152,7 @@ def verify(
issuer=issuer,
)
# Parse payload
payload = TokenPayload.parse_obj(decoded_token)
payload = TokenPayload.model_validate(decoded_token)
except JWTDecodeError as e:
raise JWTDecodeError(*e.args) from e
except ValidationError as e:
Expand Down
4 changes: 2 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,9 @@ classifiers = [
]

dependencies = [
"fastapi >=0.65.2,<0.99.0",
"fastapi >=0.65.2,<0.200.0",
"pyjwt[crypto] >=2.6.0,<3.0.0",
"pydantic >=1.7.4,!=1.8,!=1.8.1,<2.0.0",
"pydantic >=2.0.3"
]

dynamic = ["version"]
Expand Down
16 changes: 8 additions & 8 deletions requirements/docs.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@
#
# pip-compile --output-file=requirements/docs.txt requirements/docs.in
#
babel==2.13.0
babel==2.13.1
# via mkdocs-material
beautifulsoup4==4.12.2
# via mkdocs-mermaid2-plugin
certifi==2023.7.22
# via requests
charset-normalizer==3.3.0
charset-normalizer==3.3.2
# via requests
click==8.1.7
# via
Expand All @@ -36,9 +36,9 @@ jinja2==3.1.2
# -r requirements/docs.in
# mkdocs
# mkdocs-material
jsbeautifier==1.14.9
jsbeautifier==1.14.11
# via mkdocs-mermaid2-plugin
markdown==3.5
markdown==3.5.1
# via
# markdown-include
# mdx-include
Expand All @@ -63,9 +63,9 @@ mkdocs==1.5.3
# mkdocs-mermaid2-plugin
mkdocs-markdownextradata-plugin==0.2.5
# via -r requirements/docs.in
mkdocs-material==9.4.6
mkdocs-material==9.4.8
# via -r requirements/docs.in
mkdocs-material-extensions==1.2
mkdocs-material-extensions==1.3
# via mkdocs-material
mkdocs-mermaid2-plugin==1.1.1
# via -r requirements/docs.in
Expand All @@ -81,7 +81,7 @@ pygments==2.16.1
# via
# mkdocs-material
# rich
pymdown-extensions==10.3
pymdown-extensions==10.3.1
# via
# -r requirements/docs.in
# mkdocs-material
Expand Down Expand Up @@ -123,7 +123,7 @@ typer[all]==0.7.0
# typer-cli
typer-cli==0.0.13
# via -r requirements/docs.in
urllib3==2.0.6
urllib3==2.0.7
# via requests
watchdog==3.0.0
# via mkdocs
Expand Down
12 changes: 6 additions & 6 deletions requirements/linting.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,19 @@
#
# pip-compile --output-file=requirements/linting.txt requirements/linting.in
#
black==23.9.1
black==23.10.1
# via -r requirements/linting.in
cfgv==3.4.0
# via pre-commit
click==8.1.7
# via black
distlib==0.3.7
# via virtualenv
filelock==3.12.4
filelock==3.13.1
# via virtualenv
identify==2.5.30
identify==2.5.31
# via pre-commit
mypy==1.6.0
mypy==1.6.1
# via -r requirements/linting.in
mypy-extensions==1.0.0
# via
Expand All @@ -38,13 +38,13 @@ pyupgrade==3.15.0
# via -r requirements/linting.in
pyyaml==6.0.1
# via pre-commit
ruff==0.0.292
ruff==0.1.4
# via -r requirements/linting.in
tokenize-rt==5.2.0
# via pyupgrade
typing-extensions==4.8.0
# via mypy
virtualenv==20.24.5
virtualenv==20.24.6
# via pre-commit

# The following packages are considered to be unsafe in a requirements file:
Expand Down
2 changes: 1 addition & 1 deletion requirements/optional.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ async-timeout==4.0.3
# via redis
ecdsa==0.18.0
# via python-jose
prometheus-client==0.17.1
prometheus-client==0.18.0
# via -r requirements/optional.in
pyasn1==0.5.0
# via
Expand Down
25 changes: 18 additions & 7 deletions requirements/pyproject.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,27 +4,38 @@
#
# pip-compile --extra=all --output-file=requirements/pyproject.txt pyproject.toml
#
anyio==4.0.0
# via starlette
annotated-types==0.6.0
# via pydantic
anyio==3.7.1
# via
# fastapi
# starlette
cffi==1.16.0
# via cryptography
cryptography==41.0.4
cryptography==41.0.5
# via pyjwt
fastapi==0.98.0
fastapi==0.104.1
# via authx (pyproject.toml)
idna==3.4
# via anyio
pycparser==2.21
# via cffi
pydantic==1.10.13
pydantic==2.4.2
# via
# authx (pyproject.toml)
# fastapi
pydantic-core==2.10.1
# via pydantic
pyjwt[crypto]==2.8.0
# via authx (pyproject.toml)
# via
# authx (pyproject.toml)
# pyjwt
sniffio==1.3.0
# via anyio
starlette==0.27.0
# via fastapi
typing-extensions==4.8.0
# via pydantic
# via
# fastapi
# pydantic
# pydantic-core
3 changes: 2 additions & 1 deletion requirements/testing.in
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@ pytest
pytest-asyncio
pytest-cov
httpx
anyio<4
requests
SQLAlchemy
itsdangerous
websockets
uvicorn
uvloop
freezegun
freezegun
31 changes: 18 additions & 13 deletions requirements/testing.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,28 +4,34 @@
#
# pip-compile --output-file=requirements/testing.txt requirements/testing.in
#
anyio==4.0.0
# via httpcore
anyio==3.7.1
# via
# -r requirements/testing.in
# httpx
certifi==2023.7.22
# via
# httpcore
# httpx
# requests
charset-normalizer==3.3.0
charset-normalizer==3.3.2
# via requests
click==8.1.7
# via uvicorn
coverage[toml]==7.3.2
# via pytest-cov
# via
# coverage
# pytest-cov
freezegun==1.2.2
# via -r requirements/testing.in
greenlet==3.0.1
# via sqlalchemy
h11==0.14.0
# via
# httpcore
# uvicorn
httpcore==0.18.0
httpcore==1.0.1
# via httpx
httpx==0.25.0
httpx==0.25.1
# via -r requirements/testing.in
idna==3.4
# via
Expand All @@ -40,7 +46,7 @@ packaging==23.2
# via pytest
pluggy==1.3.0
# via pytest
pytest==7.4.2
pytest==7.4.3
# via
# -r requirements/testing.in
# pytest-asyncio
Expand All @@ -58,17 +64,16 @@ six==1.16.0
sniffio==1.3.0
# via
# anyio
# httpcore
# httpx
sqlalchemy==2.0.22
sqlalchemy==2.0.23
# via -r requirements/testing.in
typing-extensions==4.8.0
# via sqlalchemy
urllib3==2.0.6
urllib3==2.0.7
# via requests
uvicorn==0.23.2
uvicorn==0.24.0.post1
# via -r requirements/testing.in
uvloop==0.18.0
uvloop==0.19.0
# via -r requirements/testing.in
websockets==11.0.3
websockets==12.0
# via -r requirements/testing.in
Empty file modified scripts/requirements.sh
100644 → 100755
Empty file.