Coverage for polar/custom_field/schemas.py: 100%

79 statements  

« prev     ^ index     » next       coverage.py v7.10.6, created at 2025-12-05 17:15 +0000

1from typing import Annotated, Literal 1a

2 

3from pydantic import UUID4, Discriminator, Field, StringConstraints, TypeAdapter 1a

4 

5from polar.kit.metadata import ( 1a

6 MetadataInputMixin, 

7 MetadataOutputMixin, 

8) 

9from polar.kit.schemas import ( 1a

10 ClassName, 

11 IDSchema, 

12 MergeJSONSchema, 

13 Schema, 

14 SetSchemaReference, 

15 TimestampedSchema, 

16) 

17from polar.models.custom_field import ( 1a

18 CustomFieldCheckboxProperties, 

19 CustomFieldDateProperties, 

20 CustomFieldNumberProperties, 

21 CustomFieldSelectProperties, 

22 CustomFieldTextProperties, 

23 CustomFieldType, 

24) 

25from polar.organization.schemas import OrganizationID 1a

26 

27Slug = Annotated[ 1a

28 str, 

29 StringConstraints(to_lower=True, min_length=1, pattern=r"^[a-z0-9-_]+$"), 

30 Field( 

31 description=( 

32 "Identifier of the custom field. " 

33 "It'll be used as key when storing the value. " 

34 "Must be unique across the organization." 

35 "It can only contain ASCII letters, numbers and hyphens." 

36 ), 

37 min_length=1, 

38 ), 

39] 

40Name = Annotated[str, Field(description="Name of the custom field.", min_length=1)] 1a

41 

42 

43class CustomFieldCreateBase(MetadataInputMixin, Schema): 1a

44 """Schema to create a new custom field.""" 

45 

46 type: CustomFieldType = Field(description="Data type of the custom field.") 1a

47 slug: Slug 1a

48 name: Name 1a

49 organization_id: OrganizationID | None = Field( 1a

50 default=None, 

51 description=( 

52 "The ID of the organization owning the custom field. " 

53 "**Required unless you use an organization token.**" 

54 ), 

55 ) 

56 

57 

58class CustomFieldCreateText(CustomFieldCreateBase): 1a

59 """Schema to create a custom field of type text.""" 

60 

61 type: Literal[CustomFieldType.text] 1a

62 properties: CustomFieldTextProperties 1a

63 

64 

65class CustomFieldCreateNumber(CustomFieldCreateBase): 1a

66 """Schema to create a custom field of type number.""" 

67 

68 type: Literal[CustomFieldType.number] 1a

69 properties: CustomFieldNumberProperties 1a

70 

71 

72class CustomFieldCreateDate(CustomFieldCreateBase): 1a

73 """Schema to create a custom field of type date.""" 

74 

75 type: Literal[CustomFieldType.date] 1a

76 properties: CustomFieldDateProperties 1a

77 

78 

79class CustomFieldCreateCheckbox(CustomFieldCreateBase): 1a

80 """Schema to create a custom field of type checkbox.""" 

81 

82 type: Literal[CustomFieldType.checkbox] 1a

83 properties: CustomFieldCheckboxProperties 1a

84 

85 

86class CustomFieldCreateSelect(CustomFieldCreateBase): 1a

87 """Schema to create a custom field of type select.""" 

88 

89 type: Literal[CustomFieldType.select] 1a

90 properties: CustomFieldSelectProperties 1a

91 

92 

93CustomFieldCreate = Annotated[ 1a

94 CustomFieldCreateText 

95 | CustomFieldCreateNumber 

96 | CustomFieldCreateDate 

97 | CustomFieldCreateCheckbox 

98 | CustomFieldCreateSelect, 

99 Discriminator("type"), 

100 SetSchemaReference("CustomFieldCreate"), 

101] 

102 

103 

104class CustomFieldUpdateBase(MetadataInputMixin, Schema): 1a

105 """Schema to update an existing custom field.""" 

106 

107 name: Name | None = None 1a

108 slug: Slug | None = None 1a

109 

110 

111class CustomFieldUpdateText(CustomFieldUpdateBase): 1a

112 """Schema to update a custom field of type text.""" 

113 

114 type: Literal[CustomFieldType.text] 1a

115 properties: CustomFieldTextProperties | None = None 1a

116 

117 

118class CustomFieldUpdateNumber(CustomFieldUpdateBase): 1a

119 """Schema to update a custom field of type number.""" 

120 

121 type: Literal[CustomFieldType.number] 1a

122 properties: CustomFieldNumberProperties | None = None 1a

123 

124 

125class CustomFieldUpdateDate(CustomFieldUpdateBase): 1a

126 """Schema to update a custom field of type date.""" 

127 

128 type: Literal[CustomFieldType.date] 1a

129 properties: CustomFieldDateProperties | None = None 1a

130 

131 

132class CustomFieldUpdateCheckbox(CustomFieldUpdateBase): 1a

133 """Schema to update a custom field of type checkbox.""" 

134 

135 type: Literal[CustomFieldType.checkbox] 1a

136 properties: CustomFieldCheckboxProperties | None = None 1a

137 

138 

139class CustomFieldUpdateSelect(CustomFieldUpdateBase): 1a

140 """Schema to update a custom field of type select.""" 

141 

142 type: Literal[CustomFieldType.select] 1a

143 properties: CustomFieldSelectProperties | None = None 1a

144 

145 

146CustomFieldUpdate = Annotated[ 1a

147 CustomFieldUpdateText 

148 | CustomFieldUpdateNumber 

149 | CustomFieldUpdateDate 

150 | CustomFieldUpdateCheckbox 

151 | CustomFieldUpdateSelect, 

152 Discriminator("type"), 

153 SetSchemaReference("CustomFieldUpdate"), 

154] 

155 

156 

157class CustomFieldBase(MetadataOutputMixin, IDSchema, TimestampedSchema): 1a

158 """Schema for a custom field.""" 

159 

160 type: CustomFieldType = Field(description="Data type of the custom field.") 1a

161 slug: str = Field( 1a

162 description="Identifier of the custom field. " 

163 "It'll be used as key when storing the value." 

164 ) 

165 name: str = Field(description="Name of the custom field.") 1a

166 organization_id: OrganizationID = Field( 1a

167 description="The ID of the organization owning the custom field." 

168 ) 

169 

170 

171class CustomFieldText(CustomFieldBase): 1a

172 """Schema for a custom field of type text.""" 

173 

174 type: Literal[CustomFieldType.text] 1a

175 properties: CustomFieldTextProperties 1a

176 

177 

178class CustomFieldNumber(CustomFieldBase): 1a

179 """Schema for a custom field of type number.""" 

180 

181 type: Literal[CustomFieldType.number] 1a

182 properties: CustomFieldNumberProperties 1a

183 

184 

185class CustomFieldDate(CustomFieldBase): 1a

186 """Schema for a custom field of type date.""" 

187 

188 type: Literal[CustomFieldType.date] 1a

189 properties: CustomFieldDateProperties 1a

190 

191 

192class CustomFieldCheckbox(CustomFieldBase): 1a

193 """Schema for a custom field of type checkbox.""" 

194 

195 type: Literal[CustomFieldType.checkbox] 1a

196 properties: CustomFieldCheckboxProperties 1a

197 

198 

199class CustomFieldSelect(CustomFieldBase): 1a

200 """Schema for a custom field of type select.""" 

201 

202 type: Literal[CustomFieldType.select] 1a

203 properties: CustomFieldSelectProperties 1a

204 

205 

206CustomField = Annotated[ 1a

207 CustomFieldText 

208 | CustomFieldNumber 

209 | CustomFieldDate 

210 | CustomFieldCheckbox 

211 | CustomFieldSelect, 

212 Discriminator("type"), 

213 SetSchemaReference("CustomField"), 

214 MergeJSONSchema({"title": "CustomField"}), 

215 ClassName("CustomField"), 

216] 

217 

218CustomFieldAdapter: TypeAdapter[CustomField] = TypeAdapter(CustomField) 1a

219 

220 

221class AttachedCustomField(Schema): 1a

222 """Schema of a custom field attached to a resource.""" 

223 

224 custom_field_id: UUID4 = Field(description="ID of the custom field.") 1a

225 custom_field: CustomField 1a

226 order: int = Field(description="Order of the custom field in the resource.") 1a

227 required: bool = Field( 1a

228 description="Whether the value is required for this custom field." 

229 ) 

230 

231 

232class AttachedCustomFieldCreate(Schema): 1a

233 """Schema to attach a custom field to a resource.""" 

234 

235 custom_field_id: UUID4 = Field(description="ID of the custom field to attach.") 1a

236 required: bool = Field( 1a

237 description="Whether the value is required for this custom field." 

238 ) 

239 

240 

241AttachedCustomFieldListCreate = Annotated[ 1a

242 list[AttachedCustomFieldCreate], 

243 Field(description="List of custom fields to attach."), 

244]