@@ -34,12 +34,29 @@ class DynamoDBBaseUserTable(Model, Generic[ID]):
3434 __tablename__ : str = config .get ("DATABASE_USERTABLE_NAME" )
3535
3636 class Meta :
37+ """The required `Meta` definitions for PynamoDB.
38+
39+ Args:
40+ table_name (str): The name of the table.
41+ region (str): The AWS region string where the table should be created.
42+ billing_mode (str): The billing mode to use when creating the table. \
43+ Currently only supports `PAY_PER_REQUEST`.
44+ """
45+
3746 table_name : str = config .get ("DATABASE_USERTABLE_NAME" )
3847 region : str = config .get ("DATABASE_REGION" )
3948 billing_mode : str = config .get ("DATABASE_BILLING_MODE" ).value
4049
4150 class EmailIndex (GlobalSecondaryIndex ):
51+ """Enable the `email` attribute to be a Global Secondary Index.
52+
53+ Args:
54+ GlobalSecondaryIndex (_type_): The Global Secondary Index base class.
55+ """
56+
4257 class Meta :
58+ """The metadata for the Global Secondary Index."""
59+
4360 index_name : str = "email-index"
4461 projection = AllProjection ()
4562
@@ -64,6 +81,12 @@ class Meta:
6481
6582
6683class DynamoDBBaseUserTableUUID (DynamoDBBaseUserTable [UUID_ID ]):
84+ """A base class representing `User` objects with unique IDs.
85+
86+ Args:
87+ DynamoDBBaseUserTable (_type_): The underlying table object.
88+ """
89+
6790 if TYPE_CHECKING : # pragma: no cover
6891 id : UUID_ID
6992 else :
@@ -76,26 +99,59 @@ class DynamoDBBaseOAuthAccountTable(Model, Generic[ID]):
7699 __tablename__ : str = config .get ("DATABASE_OAUTHTABLE_NAME" )
77100
78101 class Meta :
102+ """The required `Meta` definitions for PynamoDB.
103+
104+ Args:
105+ table_name (str): The name of the table.
106+ region (str): The AWS region string where the table should be created.
107+ billing_mode (str): The billing mode to use when creating the table. \
108+ Currently only supports `PAY_PER_REQUEST`.
109+ """
110+
79111 table_name : str = config .get ("DATABASE_OAUTHTABLE_NAME" )
80112 region : str = config .get ("DATABASE_REGION" )
81113 billing_mode : str = config .get ("DATABASE_BILLING_MODE" ).value
82114
83115 class AccountIdIndex (GlobalSecondaryIndex ):
116+ """Enable the `account_id` attribute to be a Global Secondary Index.
117+
118+ Args:
119+ GlobalSecondaryIndex (_type_): The Global Secondary Index base class.
120+ """
121+
84122 class Meta :
123+ """The metadata for the Global Secondary Index."""
124+
85125 index_name : str = "account_id-index"
86126 projection = AllProjection ()
87127
88128 account_id = UnicodeAttribute (hash_key = True )
89129
90130 class OAuthNameIndex (GlobalSecondaryIndex ):
131+ """Enable the `oauth_name` attribute to be a Global Secondary Index.
132+
133+ Args:
134+ GlobalSecondaryIndex (_type_): The Global Secondary Index base class.
135+ """
136+
91137 class Meta :
138+ """The metadata for the Global Secondary Index."""
139+
92140 index_name : str = "oauth_name-index"
93141 projection = AllProjection ()
94142
95143 oauth_name = UnicodeAttribute (hash_key = True )
96144
97145 class UserIdIndex (GlobalSecondaryIndex ):
146+ """Enable the `user_id` attribute to be a Global Secondary Index.
147+
148+ Args:
149+ GlobalSecondaryIndex (_type_): The Global Secondary Index base class.
150+ """
151+
98152 class Meta :
153+ """The metadata for the Global Secondary Index."""
154+
99155 index_name = "user_id-index"
100156 projection = AllProjection ()
101157
@@ -124,6 +180,12 @@ class Meta:
124180
125181
126182class DynamoDBBaseOAuthAccountTableUUID (DynamoDBBaseOAuthAccountTable [UUID_ID ]):
183+ """A base class representing `OAuthAccount` objects with unique IDs.
184+
185+ Args:
186+ DynamoDBBaseOAuthAccountTable (_type_): The underlying table object.
187+ """
188+
127189 if TYPE_CHECKING : # pragma: no cover
128190 id : UUID_ID
129191 user_id : UUID_ID
@@ -134,7 +196,9 @@ class DynamoDBBaseOAuthAccountTableUUID(DynamoDBBaseOAuthAccountTable[UUID_ID]):
134196
135197class DynamoDBUserDatabase (Generic [UP , ID ], BaseUserDatabase [UP , ID ]):
136198 """
137- Database adapter for AWS DynamoDB using aiopynamodb.
199+ Database adapter for AWS DynamoDB using `aiopynamodb`. \
200+
201+ Stores `User` and `OAuth` accounts.
138202 """
139203
140204 user_table : type [UP ]
@@ -145,6 +209,12 @@ def __init__(
145209 user_table : type [UP ],
146210 oauth_account_table : type [DynamoDBBaseOAuthAccountTable ] | None = None ,
147211 ):
212+ """Initialize the database adapter.
213+
214+ Args:
215+ user_table (type[UP]): The underlying table for storing `User` accounts.
216+ oauth_account_table (type[DynamoDBBaseOAuthAccountTable] | None, optional): The underlying table for storing `OAuth` accounts. Defaults to None.
217+ """
148218 self .user_table = user_table
149219 self .oauth_account_table = oauth_account_table
150220
@@ -153,9 +223,16 @@ async def _hydrate_oauth_accounts(
153223 user : UP ,
154224 instant_update : bool = False ,
155225 ) -> UP :
156- """
157- Populate the `oauth_accounts` list of a user by querying the OAuth table.
158- This mimics SQLAlchemy's lazy relationship loading.
226+ """Populate the `oauth_accounts` list of a user by querying the `OAuth` table. \
227+
228+ This mimics *SQLAlchemy*'s lazy relationship loading.
229+
230+ Args:
231+ user (UP): The `User` object that should be refreshed.
232+ instant_update (bool, optional): Whether to use consistent reads. Defaults to False.
233+
234+ Returns:
235+ UP: The refreshed user.
159236 """
160237 if self .oauth_account_table is None :
161238 return user
@@ -172,7 +249,15 @@ async def _hydrate_oauth_accounts(
172249 return user
173250
174251 async def get (self , id : ID , instant_update : bool = False ) -> UP | None :
175- """Get a user by id and hydrate oauth_accounts if available."""
252+ """Get a user by id and hydrate `oauth_accounts` if available.
253+
254+ Args:
255+ id (ID): The id of the user account.
256+ instant_update (bool, optional): Whether to use consistent reads. Defaults to False.
257+
258+ Returns:
259+ UP | None: The `User` object, if found.
260+ """
176261 await ensure_tables_exist (self .user_table ) # type: ignore
177262
178263 try :
@@ -183,7 +268,15 @@ async def get(self, id: ID, instant_update: bool = False) -> UP | None:
183268 return None
184269
185270 async def get_by_email (self , email : str , instant_update : bool = False ) -> UP | None :
186- """Get a user by email using the email GSI (case-insensitive)."""
271+ """Get a user by email using the email **Global Secondary Index** (case-insensitive).
272+
273+ Args:
274+ email (str): The email of the user account.
275+ instant_update (bool, optional): Whether to use consistent reads. Defaults to False.
276+
277+ Returns:
278+ UP | None: The `User` object, if found.
279+ """
187280 await ensure_tables_exist (self .user_table ) # type: ignore
188281
189282 email_lower = email .lower ()
@@ -202,7 +295,19 @@ async def get_by_oauth_account(
202295 account_id : str ,
203296 instant_update : bool = False ,
204297 ) -> UP | None :
205- """Find a user by oauth provider and account_id."""
298+ """Find a user by oauth provider and `account_id`.
299+
300+ Args:
301+ oauth (str): The name of the `OAuth` provider.
302+ account_id (str): The id of the `OAuth` account.
303+ instant_update (bool, optional): Whether to use consistent reads. Defaults to False.
304+
305+ Raises:
306+ NotImplementedError: If the `OAuth` table was not specified upon initialization.
307+
308+ Returns:
309+ UP | None: The `User` object, if found.
310+ """
206311 if self .oauth_account_table is None :
207312 raise NotImplementedError ()
208313 await ensure_tables_exist (self .user_table , self .oauth_account_table ) # type: ignore
@@ -225,7 +330,18 @@ async def get_by_oauth_account(
225330 return None
226331
227332 async def create (self , create_dict : dict [str , Any ] | UP ) -> UP :
228- """Create a new user and return an instance of UP."""
333+ """Create a new user and return an instance of UP.
334+
335+ Args:
336+ create_dict (dict[str, Any] | UP): A dictionary holding the data of the user account.
337+
338+ Raises:
339+ ValueError: If the user account could not be created for whatever reason.
340+ ValueError: If the user account could not be created because the table did not exist.
341+
342+ Returns:
343+ UP: The newly created `User` object.
344+ """
229345 await ensure_tables_exist (self .user_table ) # type: ignore
230346
231347 if isinstance (create_dict , dict ):
@@ -248,7 +364,19 @@ async def create(self, create_dict: dict[str, Any] | UP) -> UP:
248364 return user
249365
250366 async def update (self , user : UP , update_dict : dict [str , Any ]) -> UP :
251- """Update a user with update_dict and return the updated UP instance."""
367+ """Update a user with `update_dict` and return the updated UP instance.
368+
369+ Args:
370+ user (UP): The `User` instance to be updated.
371+ update_dict (dict[str, Any]): A dictionary with the changes that should be applied.
372+
373+ Raises:
374+ ValueError: If the user account could not be updated for whatever reason.
375+ ValueError: If the user account could not be updated because the table did not exist.
376+
377+ Returns:
378+ UP: The refreshed `User` object.
379+ """
252380 await ensure_tables_exist (self .user_table ) # type: ignore
253381
254382 try :
@@ -266,7 +394,15 @@ async def update(self, user: UP, update_dict: dict[str, Any]) -> UP:
266394 ) from e
267395
268396 async def delete (self , user : UP ) -> None :
269- """Delete a user."""
397+ """Delete a user.
398+
399+ Args:
400+ user (UP): The `User` object to be deleted.
401+
402+ Raises:
403+ ValueError: If the user account could not be deleted for whatever reason.
404+ ValueError: If the user account could not be deleted because the table did not exist.
405+ """
270406 await ensure_tables_exist (self .user_table ) # type: ignore
271407
272408 try :
@@ -280,7 +416,20 @@ async def delete(self, user: UP) -> None:
280416 ) from e
281417
282418 async def add_oauth_account (self , user : UP , create_dict : dict [str , Any ]) -> UP :
283- """Add an OAuth account and return the refreshed user (UP)."""
419+ """Add an `OAuth` account and return the refreshed user (UP).
420+
421+ Args:
422+ user (UP): The `User` object, which the newly created `OAuth` account should be linked to.
423+ create_dict (dict[str, Any]): A dictionary holding the data of the `OAuth` account.
424+
425+ Raises:
426+ NotImplementedError: If the `OAuth` table was not specified upon initialization.
427+ ValueError: If the `OAuth` account could not be created for whatever reason.
428+ ValueError: If the `OAuth` account could not be created because the table did not exist.
429+
430+ Returns:
431+ UP: The refreshed `User` object.
432+ """
284433 if self .oauth_account_table is None :
285434 raise NotImplementedError ()
286435 await ensure_tables_exist (self .user_table , self .oauth_account_table ) # type: ignore
@@ -310,7 +459,21 @@ async def update_oauth_account(
310459 oauth_account : OAP , # type: ignore
311460 update_dict : dict [str , Any ],
312461 ) -> UP :
313- """Update an OAuth account and return the refreshed user (UP)."""
462+ """Update an OAuth account and return the refreshed user (UP).
463+
464+ Args:
465+ user (UP): The `User` object, which the updated `OAuth` account should be linked to.
466+ oauth_account (OAP): The existing `OAuth` account to be updated.
467+ update_dict (dict[str, Any]): A dictionary with the changes that should be applied.
468+
469+ Raises:
470+ NotImplementedError: If the `OAuth` table was not specified upon initialization.
471+ ValueError: If the `OAuth` account could not be updated for whatever reason.
472+ ValueError: If the `OAuth` account could not be updated because the table did not exist.
473+
474+ Returns:
475+ UP: The refreshed `User` object.
476+ """
314477 if self .oauth_account_table is None :
315478 raise NotImplementedError ()
316479 await ensure_tables_exist (self .user_table , self .oauth_account_table ) # type: ignore
0 commit comments