Skip to content

Commit 94c5332

Browse files
committed
Fix config mechanism
1 parent be3e1bf commit 94c5332

File tree

6 files changed

+152
-34
lines changed

6 files changed

+152
-34
lines changed

fastapi_users_db_dynamodb/__init__.py

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
from fastapi_users.models import ID, OAP, UP
2323

2424
from . import config
25-
from ._generics import UUID_ID
25+
from ._generics import UUID_ID, classproperty
2626
from .attributes import GUID, TransformingUnicodeAttribute
2727
from .config import __version__ # noqa: F401
2828
from .tables import ensure_tables_exist
@@ -31,7 +31,9 @@
3131
class DynamoDBBaseUserTable(Model, Generic[ID]):
3232
"""Base user table schema for DynamoDB."""
3333

34-
__tablename__: str = config.get("DATABASE_USERTABLE_NAME")
34+
@classproperty
35+
def __tablename__(self) -> str:
36+
return config.get("DATABASE_USERTABLE_NAME")
3537

3638
class Meta:
3739
"""The required `Meta` definitions for PynamoDB.
@@ -43,9 +45,17 @@ class Meta:
4345
Currently only supports `PAY_PER_REQUEST`.
4446
"""
4547

46-
table_name: str = config.get("DATABASE_USERTABLE_NAME")
47-
region: str = config.get("DATABASE_REGION")
48-
billing_mode: str = config.get("DATABASE_BILLING_MODE").value
48+
@classproperty
49+
def table_name(self) -> str:
50+
return config.get("DATABASE_USERTABLE_NAME")
51+
52+
@classproperty
53+
def region(self) -> str:
54+
return config.get("DATABASE_REGION")
55+
56+
@classproperty
57+
def billing_mode(self) -> str:
58+
return config.get("DATABASE_BILLING_MODE").value
4959

5060
class EmailIndex(GlobalSecondaryIndex):
5161
"""Enable the `email` attribute to be a Global Secondary Index.
@@ -96,7 +106,9 @@ class DynamoDBBaseUserTableUUID(DynamoDBBaseUserTable[UUID_ID]):
96106
class DynamoDBBaseOAuthAccountTable(Model, Generic[ID]):
97107
"""Base OAuth account table schema for DynamoDB."""
98108

99-
__tablename__: str = config.get("DATABASE_OAUTHTABLE_NAME")
109+
@classproperty
110+
def __tablename__(self) -> str:
111+
return config.get("DATABASE_OAUTHTABLE_NAME")
100112

101113
class Meta:
102114
"""The required `Meta` definitions for PynamoDB.
@@ -108,9 +120,17 @@ class Meta:
108120
Currently only supports `PAY_PER_REQUEST`.
109121
"""
110122

111-
table_name: str = config.get("DATABASE_OAUTHTABLE_NAME")
112-
region: str = config.get("DATABASE_REGION")
113-
billing_mode: str = config.get("DATABASE_BILLING_MODE").value
123+
@classproperty
124+
def table_name(self) -> str:
125+
return config.get("DATABASE_OAUTHTABLE_NAME")
126+
127+
@classproperty
128+
def region(self) -> str:
129+
return config.get("DATABASE_REGION")
130+
131+
@classproperty
132+
def billing_mode(self) -> str:
133+
return config.get("DATABASE_BILLING_MODE").value
114134

115135
class AccountIdIndex(GlobalSecondaryIndex):
116136
"""Enable the `account_id` attribute to be a Global Secondary Index.

fastapi_users_db_dynamodb/_generics.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,44 @@
66
UUID_ID = uuid.UUID
77

88

9+
class classproperty:
10+
def __init__(self, fget=None, fset=None, fdel=None):
11+
self.fget = fget
12+
self.fset = fset
13+
self.fdel = fdel
14+
self.__doc__ = getattr(fget, "__doc__", None)
15+
16+
def __get__(self, instance, owner):
17+
if self.fget is None:
18+
raise AttributeError("unreadable attribute")
19+
return self.fget(owner)
20+
21+
def __set__(self, instance, value):
22+
if self.fset is None:
23+
raise AttributeError("can't set attribute")
24+
cls = type(instance) if instance is not None else instance
25+
if cls is None: # when instance is None, need to use owner
26+
raise AttributeError("class not found for setting")
27+
return self.fset(cls, value)
28+
29+
def __delete__(self, instance):
30+
if self.fdel is None:
31+
raise AttributeError("can't delete attribute")
32+
cls = type(instance) if instance is not None else instance
33+
if cls is None:
34+
raise AttributeError("class not found for deletion")
35+
return self.fdel(cls)
36+
37+
def getter(self, fget):
38+
return type(self)(fget, self.fset, self.fdel)
39+
40+
def setter(self, fset):
41+
return type(self)(self.fget, fset, self.fdel)
42+
43+
def deleter(self, fdel):
44+
return type(self)(self.fget, self.fset, fdel)
45+
46+
947
def now_utc() -> datetime:
1048
"""
1149
Returns the current time in UTC with timezone awareness.

fastapi_users_db_dynamodb/access_token.py

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,17 @@
1111
from fastapi_users.models import ID
1212

1313
from . import config
14-
from ._generics import UUID_ID, now_utc
14+
from ._generics import UUID_ID, classproperty, now_utc
1515
from .attributes import GUID
1616
from .tables import ensure_tables_exist
1717

1818

1919
class DynamoDBBaseAccessTokenTable(Model, Generic[ID]):
2020
"""Base access token table schema for DynamoDB."""
2121

22-
__tablename__: str = config.get("DATABASE_TOKENTABLE_NAME")
22+
@classproperty
23+
def __tablename__(self) -> str:
24+
return config.get("DATABASE_TOKENTABLE_NAME")
2325

2426
class Meta:
2527
"""The required `Meta` definitions for PynamoDB.
@@ -31,9 +33,17 @@ class Meta:
3133
Currently only supports `PAY_PER_REQUEST`.
3234
"""
3335

34-
table_name: str = config.get("DATABASE_TOKENTABLE_NAME")
35-
region: str = config.get("DATABASE_REGION")
36-
billing_mode: str = config.get("DATABASE_BILLING_MODE").value
36+
@classproperty
37+
def table_name(self) -> str:
38+
return config.get("DATABASE_TOKENTABLE_NAME")
39+
40+
@classproperty
41+
def region(self) -> str:
42+
return config.get("DATABASE_REGION")
43+
44+
@classproperty
45+
def billing_mode(self) -> str:
46+
return config.get("DATABASE_BILLING_MODE").value
3747

3848
class CreatedAtIndex(GlobalSecondaryIndex):
3949
"""Enable the `created_at` attribute to be a Global Secondary Index.

tests/test_access_token.py

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
DynamoDBUserDatabase,
1212
config,
1313
)
14-
from fastapi_users_db_dynamodb._generics import now_utc
14+
from fastapi_users_db_dynamodb._generics import classproperty, now_utc
1515
from fastapi_users_db_dynamodb.access_token import (
1616
DynamoDBAccessTokenDatabase,
1717
DynamoDBBaseAccessTokenTableUUID,
@@ -36,7 +36,9 @@ class AccessToken(DynamoDBBaseAccessTokenTableUUID, Base):
3636
Base (_type_): The PynamoDB base class definition.
3737
"""
3838

39-
__tablename__: str = config.get("DATABASE_TOKENTABLE_NAME") + "_test"
39+
@classproperty
40+
def __tablename__(self) -> str:
41+
return config.get("DATABASE_TOKENTABLE_NAME") + "_test"
4042

4143
class Meta:
4244
"""The required `Meta` definitions for PynamoDB.
@@ -48,9 +50,17 @@ class Meta:
4850
Currently only supports `PAY_PER_REQUEST`.
4951
"""
5052

51-
table_name: str = config.get("DATABASE_TOKENTABLE_NAME") + "_test"
52-
region: str = config.get("DATABASE_REGION")
53-
billing_mode: str = config.get("DATABASE_BILLING_MODE").value
53+
@classproperty
54+
def table_name(self) -> str:
55+
return config.get("DATABASE_TOKENTABLE_NAME") + "_test"
56+
57+
@classproperty
58+
def region(self) -> str:
59+
return config.get("DATABASE_REGION")
60+
61+
@classproperty
62+
def billing_mode(self) -> str:
63+
return config.get("DATABASE_BILLING_MODE").value
5464

5565

5666
class User(DynamoDBBaseUserTableUUID, Base):
@@ -61,7 +71,9 @@ class User(DynamoDBBaseUserTableUUID, Base):
6171
Base (_type_): The PynamoDB base class definition.
6272
"""
6373

64-
__tablename__: str = config.get("DATABASE_USERTABLE_NAME") + "_test"
74+
@classproperty
75+
def __tablename__(self) -> str:
76+
return config.get("DATABASE_USERTABLE_NAME") + "_test"
6577

6678
class Meta:
6779
"""The required `Meta` definitions for PynamoDB.
@@ -73,9 +85,17 @@ class Meta:
7385
Currently only supports `PAY_PER_REQUEST`.
7486
"""
7587

76-
table_name: str = config.get("DATABASE_USERTABLE_NAME") + "_test"
77-
region: str = config.get("DATABASE_REGION")
78-
billing_mode: str = config.get("DATABASE_BILLING_MODE").value
88+
@classproperty
89+
def table_name(self) -> str:
90+
return config.get("DATABASE_USERTABLE_NAME") + "_test"
91+
92+
@classproperty
93+
def region(self) -> str:
94+
return config.get("DATABASE_REGION")
95+
96+
@classproperty
97+
def billing_mode(self) -> str:
98+
return config.get("DATABASE_BILLING_MODE").value
7999

80100

81101
@pytest_asyncio.fixture

tests/test_misc.py

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
from aiopynamodb.models import Model
33

44
from fastapi_users_db_dynamodb import config
5+
from fastapi_users_db_dynamodb._generics import classproperty
56
from fastapi_users_db_dynamodb.attributes import GUID
67
from fastapi_users_db_dynamodb.tables import delete_tables, ensure_tables_exist
78

@@ -31,9 +32,17 @@ class Meta:
3132
Currently only supports `PAY_PER_REQUEST`.
3233
"""
3334

34-
table_name: str = "valid_model_test"
35-
region: str = config.get("DATABASE_REGION")
36-
billing_mode: str = config.get("DATABASE_BILLING_MODE").value
35+
@classproperty
36+
def table_name(self) -> str:
37+
return "valid_model_test"
38+
39+
@classproperty
40+
def region(self) -> str:
41+
return config.get("DATABASE_REGION")
42+
43+
@classproperty
44+
def billing_mode(self) -> str:
45+
return config.get("DATABASE_BILLING_MODE").value
3746

3847

3948
@pytest.mark.asyncio

tests/test_users.py

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
DynamoDBBaseOAuthAccountTableUUID,
1313
DynamoDBBaseUserTableUUID,
1414
DynamoDBUserDatabase,
15+
classproperty,
1516
config,
1617
)
1718

@@ -34,7 +35,9 @@ class User(DynamoDBBaseUserTableUUID, Base):
3435
Base (_type_): The PynamoDB base class definition.
3536
"""
3637

37-
__tablename__: str = config.get("DATABASE_USERTABLE_NAME") + "_test"
38+
@classproperty
39+
def __tablename__(self) -> str:
40+
return config.get("DATABASE_USERTABLE_NAME") + "_test"
3841

3942
class Meta:
4043
"""The required `Meta` definitions for PynamoDB.
@@ -46,9 +49,17 @@ class Meta:
4649
Currently only supports `PAY_PER_REQUEST`.
4750
"""
4851

49-
table_name: str = config.get("DATABASE_USERTABLE_NAME") + "_test"
50-
region: str = config.get("DATABASE_REGION")
51-
billing_mode: str = config.get("DATABASE_BILLING_MODE").value
52+
@classproperty
53+
def table_name(self) -> str:
54+
return config.get("DATABASE_USERTABLE_NAME") + "_test"
55+
56+
@classproperty
57+
def region(self) -> str:
58+
return config.get("DATABASE_REGION")
59+
60+
@classproperty
61+
def billing_mode(self) -> str:
62+
return config.get("DATABASE_BILLING_MODE").value
5263

5364
if TYPE_CHECKING:
5465
first_name: str | None = None
@@ -85,7 +96,9 @@ class UserOAuth(DynamoDBBaseUserTableUUID, OAuthBase):
8596
OAuthBase (_type_): The base class representing `OAuth` related models.
8697
"""
8798

88-
__tablename__: str = config.get("DATABASE_OAUTHTABLE_NAME") + "_test"
99+
@classproperty
100+
def __tablename__(self) -> str:
101+
return config.get("DATABASE_OAUTHTABLE_NAME") + "_test"
89102

90103
class Meta:
91104
"""The required `Meta` definitions for PynamoDB.
@@ -97,9 +110,17 @@ class Meta:
97110
Currently only supports `PAY_PER_REQUEST`.
98111
"""
99112

100-
table_name: str = config.get("DATABASE_OAUTHTABLE_NAME") + "_test"
101-
region: str = config.get("DATABASE_REGION")
102-
billing_mode: str = config.get("DATABASE_BILLING_MODE").value
113+
@classproperty
114+
def table_name(self) -> str:
115+
return config.get("DATABASE_OAUTHTABLE_NAME") + "_test"
116+
117+
@classproperty
118+
def region(self) -> str:
119+
return config.get("DATABASE_REGION")
120+
121+
@classproperty
122+
def billing_mode(self) -> str:
123+
return config.get("DATABASE_BILLING_MODE").value
103124

104125
if TYPE_CHECKING:
105126
first_name: str | None = None

0 commit comments

Comments
 (0)