Coverage for app/models.py: 100%

59 statements  

« prev     ^ index     » next       coverage.py v7.16.1, created at 2026-10-26 10:48 +0000

1import uuid 

2from datetime import UTC, datetime 

3 

4from pydantic import EmailStr 

5from sqlmodel import Field, Relationship, SQLModel 

6 

7 

8def get_datetime_utc() -> datetime: 

9 return datetime.now(UTC) 1abcdefghijklmnopqrstuvwxyzABCDEFGHI

10 

11 

12# Shared properties 

13class UserBase(SQLModel): 

14 email: EmailStr = Field(unique=True, index=True, max_length=255) 

15 is_active: bool = True 

16 is_superuser: bool = False 

17 full_name: str | None = Field(default=None, max_length=255) 

18 

19 

20# Properties to receive via API on creation 

21class UserCreate(UserBase): 

22 password: str = Field(min_length=8, max_length=128) 

23 

24 

25class UserRegister(SQLModel): 

26 email: EmailStr = Field(max_length=255) 

27 password: str = Field(min_length=8, max_length=128) 

28 full_name: str | None = Field(default=None, max_length=255) 

29 

30 

31# Properties to receive via API on update, all are optional 

32class UserUpdate(SQLModel): 

33 email: EmailStr | None = Field(default=None, max_length=255) 

34 is_active: bool | None = None 

35 is_superuser: bool | None = None 

36 full_name: str | None = Field(default=None, max_length=255) 

37 password: str | None = Field(default=None, min_length=8, max_length=128) 

38 

39 

40class UserUpdateMe(SQLModel): 

41 full_name: str | None = Field(default=None, max_length=255) 

42 email: EmailStr | None = Field(default=None, max_length=255) 

43 

44 

45class UpdatePassword(SQLModel): 

46 current_password: str = Field(min_length=8, max_length=128) 

47 new_password: str = Field(min_length=8, max_length=128) 

48 

49 

50# Database model, database table inferred from class name 

51class User(UserBase, table=True): 

52 id: uuid.UUID = Field(default_factory=uuid.uuid4, primary_key=True) 

53 hashed_password: str 

54 created_at: datetime | None = Field(default_factory=get_datetime_utc) 

55 items: list[Item] = Relationship(back_populates="owner", cascade_delete=True) 

56 

57 

58# Properties to return via API, id is always required 

59class UserPublic(UserBase): 

60 id: uuid.UUID 

61 created_at: datetime | None = None 

62 

63 

64class UsersPublic(SQLModel): 

65 data: list[UserPublic] 

66 count: int 

67 

68 

69# Shared properties 

70class ItemBase(SQLModel): 

71 title: str = Field(min_length=1, max_length=255) 

72 description: str | None = Field(default=None, max_length=255) 

73 

74 

75# Properties to receive on item creation 

76class ItemCreate(ItemBase): 

77 pass 

78 

79 

80# Properties to receive on item update 

81class ItemUpdate(SQLModel): 

82 title: str | None = Field(default=None, min_length=1, max_length=255) 

83 description: str | None = Field(default=None, max_length=255) 

84 

85 

86# Database model, database table inferred from class name 

87class Item(ItemBase, table=True): 

88 id: uuid.UUID = Field(default_factory=uuid.uuid4, primary_key=True) 

89 created_at: datetime | None = Field(default_factory=get_datetime_utc) 

90 owner_id: uuid.UUID = Field( 

91 foreign_key="user.id", nullable=False, ondelete="CASCADE" 

92 ) 

93 owner: User | None = Relationship(back_populates="items") 

94 

95 

96# Properties to return via API, id is always required 

97class ItemPublic(ItemBase): 

98 id: uuid.UUID 

99 owner_id: uuid.UUID 

100 created_at: datetime | None = None 

101 

102 

103class ItemsPublic(SQLModel): 

104 data: list[ItemPublic] 

105 count: int 

106 

107 

108# Generic message 

109class Message(SQLModel): 

110 message: str 

111 

112 

113# JSON payload containing access token 

114class Token(SQLModel): 

115 access_token: str 

116 token_type: str = "bearer" 

117 

118 

119# Contents of JWT token 

120class TokenPayload(SQLModel): 

121 sub: str | None = None 

122 

123 

124class NewPassword(SQLModel): 

125 token: str 

126 new_password: str = Field(min_length=8, max_length=128)