Skip to content

Commit a3f2657

Browse files
committed
Fix typing
1 parent 1484279 commit a3f2657

File tree

5 files changed

+72
-38
lines changed

5 files changed

+72
-38
lines changed

fastapi_users_db_sqlalchemy/__init__.py

Lines changed: 47 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
"""FastAPI Users database adapter for SQLAlchemy."""
22
import uuid
3-
from typing import Any, Dict, Generic, Optional, Type
3+
from typing import TYPE_CHECKING, Any, Dict, Generic, Optional, Type
44

55
from fastapi_users.db.base import BaseUserDatabase
66
from fastapi_users.models import ID, OAP, UP
77
from sqlalchemy import Boolean, Column, ForeignKey, Integer, String, func, select
88
from sqlalchemy.ext.asyncio import AsyncSession
9-
from sqlalchemy.ext.declarative import declared_attr
9+
from sqlalchemy.orm import declarative_mixin, declared_attr
1010
from sqlalchemy.sql import Select
1111

1212
from fastapi_users_db_sqlalchemy.generics import GUID
@@ -16,42 +16,67 @@
1616
UUID_ID = uuid.UUID
1717

1818

19+
@declarative_mixin
1920
class SQLAlchemyBaseUserTable(Generic[ID]):
2021
"""Base SQLAlchemy users table definition."""
2122

2223
__tablename__ = "user"
2324

24-
id: ID
25-
email: str = Column(String(length=320), unique=True, index=True, nullable=False)
26-
hashed_password: str = Column(String(length=1024), nullable=False)
27-
is_active: bool = Column(Boolean, default=True, nullable=False)
28-
is_superuser: bool = Column(Boolean, default=False, nullable=False)
29-
is_verified: bool = Column(Boolean, default=False, nullable=False)
30-
31-
25+
if TYPE_CHECKING: # pragma: no cover
26+
id: ID
27+
email: str
28+
hashed_password: str
29+
is_active: bool
30+
is_superuser: bool
31+
is_verified: bool
32+
else:
33+
email: str = Column(String(length=320), unique=True, index=True, nullable=False)
34+
hashed_password: str = Column(String(length=1024), nullable=False)
35+
is_active: bool = Column(Boolean, default=True, nullable=False)
36+
is_superuser: bool = Column(Boolean, default=False, nullable=False)
37+
is_verified: bool = Column(Boolean, default=False, nullable=False)
38+
39+
40+
@declarative_mixin
3241
class SQLAlchemyBaseUserTableUUID(SQLAlchemyBaseUserTable[UUID_ID]):
33-
id: UUID_ID = Column(GUID, primary_key=True, default=uuid.uuid4)
42+
if TYPE_CHECKING: # pragma: no cover
43+
id: UUID_ID
44+
else:
45+
id: UUID_ID = Column(GUID, primary_key=True, default=uuid.uuid4)
3446

3547

48+
@declarative_mixin
3649
class SQLAlchemyBaseOAuthAccountTable(Generic[ID]):
3750
"""Base SQLAlchemy OAuth account table definition."""
3851

3952
__tablename__ = "oauth_account"
4053

41-
id: ID
42-
oauth_name: str = Column(String(length=100), index=True, nullable=False)
43-
access_token: str = Column(String(length=1024), nullable=False)
44-
expires_at: Optional[int] = Column(Integer, nullable=True)
45-
refresh_token: Optional[str] = Column(String(length=1024), nullable=True)
46-
account_id: str = Column(String(length=320), index=True, nullable=False)
47-
account_email: str = Column(String(length=320), nullable=False)
48-
49-
54+
if TYPE_CHECKING: # pragma: no cover
55+
id: ID
56+
oauth_name: str
57+
access_token: str
58+
expires_at: Optional[int]
59+
refresh_token: Optional[str]
60+
account_id: str
61+
account_email: str
62+
else:
63+
oauth_name: str = Column(String(length=100), index=True, nullable=False)
64+
access_token: str = Column(String(length=1024), nullable=False)
65+
expires_at: Optional[int] = Column(Integer, nullable=True)
66+
refresh_token: Optional[str] = Column(String(length=1024), nullable=True)
67+
account_id: str = Column(String(length=320), index=True, nullable=False)
68+
account_email: str = Column(String(length=320), nullable=False)
69+
70+
71+
@declarative_mixin
5072
class SQLAlchemyBaseOAuthAccountTableUUID(SQLAlchemyBaseOAuthAccountTable[UUID_ID]):
51-
id: UUID_ID = Column(GUID, primary_key=True, default=uuid.uuid4)
73+
if TYPE_CHECKING: # pragma: no cover
74+
id: UUID_ID
75+
else:
76+
id: UUID_ID = Column(GUID, primary_key=True, default=uuid.uuid4)
5277

5378
@declared_attr
54-
def user_id(cls):
79+
def user_id(cls) -> Column[GUID]:
5580
return Column(GUID, ForeignKey("user.id", ondelete="cascade"), nullable=False)
5681

5782

fastapi_users_db_sqlalchemy/access_token.py

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,30 +6,39 @@
66
from fastapi_users.models import ID
77
from sqlalchemy import Column, ForeignKey, String, select
88
from sqlalchemy.ext.asyncio import AsyncSession
9-
from sqlalchemy.ext.declarative import declared_attr
9+
from sqlalchemy.orm import declarative_mixin, declared_attr
1010

1111
from fastapi_users_db_sqlalchemy.generics import GUID, TIMESTAMPAware, now_utc
1212

1313

14+
@declarative_mixin
1415
class SQLAlchemyBaseAccessTokenTable(Generic[ID]):
1516
"""Base SQLAlchemy access token table definition."""
1617

1718
__tablename__ = "accesstoken"
1819

19-
token: str = Column(String(length=43), primary_key=True)
20-
created_at: datetime = Column(
21-
TIMESTAMPAware, index=True, nullable=False, default=now_utc
22-
)
23-
user_id: ID
20+
if TYPE_CHECKING: # pragma: no cover
21+
token: str
22+
created_at: datetime
23+
user_id: ID
24+
else:
25+
token: str = Column(String(length=43), primary_key=True)
26+
created_at: datetime = Column(
27+
TIMESTAMPAware, index=True, nullable=False, default=now_utc
28+
)
2429

2530

31+
@declarative_mixin
2632
class SQLAlchemyBaseAccessTokenTableUUID(SQLAlchemyBaseAccessTokenTable[uuid.UUID]):
27-
if TYPE_CHECKING:
28-
user_id: uuid.UUID # pragma: no cover
33+
if TYPE_CHECKING: # pragma: no cover
34+
user_id: uuid.UUID
2935
else:
36+
3037
@declared_attr
31-
def user_id(cls):
32-
return Column(GUID, ForeignKey("user.id", ondelete="cascade"), nullable=False)
38+
def user_id(cls) -> Column[GUID]:
39+
return Column(
40+
GUID, ForeignKey("user.id", ondelete="cascade"), nullable=False
41+
)
3342

3443

3544
class SQLAlchemyAccessTokenDatabase(Generic[AP], AccessTokenDatabase[AP]):

fastapi_users_db_sqlalchemy/generics.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ class GUID(TypeDecorator): # pragma: no cover
1515
"""
1616

1717
class UUIDChar(CHAR):
18-
python_type = UUID4
18+
python_type = UUID4 # type: ignore
1919

2020
impl = UUIDChar
2121
cache_ok = True

tests/test_access_token.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from pydantic import UUID4
77
from sqlalchemy import exc
88
from sqlalchemy.ext.asyncio import AsyncEngine, AsyncSession, create_async_engine
9-
from sqlalchemy.ext.declarative import DeclarativeMeta, declarative_base
9+
from sqlalchemy.ext.declarative import declarative_base
1010
from sqlalchemy.orm import sessionmaker
1111

1212
from fastapi_users_db_sqlalchemy import SQLAlchemyBaseUserTableUUID
@@ -15,7 +15,7 @@
1515
SQLAlchemyBaseAccessTokenTableUUID,
1616
)
1717

18-
Base: DeclarativeMeta = declarative_base()
18+
Base = declarative_base()
1919

2020

2121
class AccessToken(SQLAlchemyBaseAccessTokenTableUUID, Base):

tests/test_users.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import pytest
44
from sqlalchemy import Column, String, exc
55
from sqlalchemy.ext.asyncio import AsyncEngine, AsyncSession, create_async_engine
6-
from sqlalchemy.ext.declarative import DeclarativeMeta, declarative_base
6+
from sqlalchemy.ext.declarative import declarative_base
77
from sqlalchemy.orm import relationship, sessionmaker
88

99
from fastapi_users_db_sqlalchemy import (
@@ -18,14 +18,14 @@ def create_async_session_maker(engine: AsyncEngine):
1818
return sessionmaker(engine, class_=AsyncSession, expire_on_commit=False)
1919

2020

21-
Base: DeclarativeMeta = declarative_base()
21+
Base = declarative_base()
2222

2323

2424
class User(SQLAlchemyBaseUserTableUUID, Base):
2525
first_name = Column(String, nullable=True)
2626

2727

28-
OAuthBase: DeclarativeMeta = declarative_base()
28+
OAuthBase = declarative_base()
2929

3030

3131
class OAuthAccount(SQLAlchemyBaseOAuthAccountTableUUID, OAuthBase):

0 commit comments

Comments
 (0)