Coverage for src/typedal/fields.py: 100%

85 statements  

« prev     ^ index     » next       coverage.py v7.3.2, created at 2023-10-19 13:50 +0200

1""" 

2This file contains available Field types. 

3""" 

4 

5import datetime as dt 

6import decimal 

7import typing 

8 

9from pydal.objects import Table 

10 

11from .core import TypeDAL, TypedField, TypedTable 

12 

13T = typing.TypeVar("T", bound=typing.Any) 

14 

15 

16## general 

17 

18 

19# def TypedField( 

20# _type: typing.Type[T] | types.UnionType, 

21# **kwargs: typing.Any, 

22# ) -> T: 

23# """ 

24# sneaky: its a function and not a class, because there's a return type. 

25# 

26# and the return type (T) is the input type in _type 

27# 

28# Example: 

29# age: TypedField(int, default=18) 

30# """ 

31# return typing.cast(T, TypedFieldType(_type, **kwargs)) 

32 

33 

34## specific 

35def StringField(**kw: typing.Any) -> TypedField[str]: 

36 """ 

37 Pydal type is string, Python type is str. 

38 """ 

39 kw["type"] = "string" 

40 return TypedField(str, **kw) 

41 

42 

43String = StringField 

44 

45 

46def TextField(**kw: typing.Any) -> TypedField[str]: 

47 """ 

48 Pydal type is text, Python type is str. 

49 """ 

50 kw["type"] = "text" 

51 return TypedField(str, **kw) 

52 

53 

54Text = TextField 

55 

56 

57def BlobField(**kw: typing.Any) -> TypedField[bytes]: 

58 """ 

59 Pydal type is blob, Python type is bytes. 

60 """ 

61 kw["type"] = "blob" 

62 return TypedField(bytes, **kw) 

63 

64 

65Blob = BlobField 

66 

67 

68def BooleanField(**kw: typing.Any) -> TypedField[bool]: 

69 """ 

70 Pydal type is boolean, Python type is bool. 

71 """ 

72 kw["type"] = "boolean" 

73 return TypedField(bool, **kw) 

74 

75 

76Boolean = BooleanField 

77 

78 

79def IntegerField(**kw: typing.Any) -> TypedField[int]: 

80 """ 

81 Pydal type is integer, Python type is int. 

82 """ 

83 kw["type"] = "integer" 

84 return TypedField(int, **kw) 

85 

86 

87Integer = IntegerField 

88 

89 

90def DoubleField(**kw: typing.Any) -> TypedField[float]: 

91 """ 

92 Pydal type is double, Python type is float. 

93 """ 

94 kw["type"] = "double" 

95 return TypedField(float, **kw) 

96 

97 

98Double = DoubleField 

99 

100 

101def DecimalField(n: int, m: int, **kw: typing.Any) -> TypedField[decimal.Decimal]: 

102 """ 

103 Pydal type is decimal, Python type is Decimal. 

104 """ 

105 kw["type"] = f"decimal({n}, {m})" 

106 return TypedField(decimal.Decimal, **kw) 

107 

108 

109Decimal = DecimalField 

110 

111 

112def DateField(**kw: typing.Any) -> TypedField[dt.date]: 

113 """ 

114 Pydal type is date, Python type is datetime.date. 

115 """ 

116 kw["type"] = "date" 

117 return TypedField(dt.date, **kw) 

118 

119 

120Date = DateField 

121 

122 

123def TimeField(**kw: typing.Any) -> TypedField[dt.time]: 

124 """ 

125 Pydal type is time, Python type is datetime.time. 

126 """ 

127 kw["type"] = "time" 

128 return TypedField(dt.time, **kw) 

129 

130 

131Time = TimeField 

132 

133 

134def DatetimeField(**kw: typing.Any) -> TypedField[dt.datetime]: 

135 """ 

136 Pydal type is datetime, Python type is datetime.datetime. 

137 """ 

138 kw["type"] = "datetime" 

139 return TypedField(dt.datetime, **kw) 

140 

141 

142Datetime = DatetimeField 

143 

144 

145def PasswordField(**kw: typing.Any) -> TypedField[str]: 

146 """ 

147 Pydal type is password, Python type is str. 

148 """ 

149 kw["type"] = "password" 

150 return TypedField(str, **kw) 

151 

152 

153Password = PasswordField 

154 

155 

156def UploadField(**kw: typing.Any) -> TypedField[str]: 

157 """ 

158 Pydal type is upload, Python type is str. 

159 """ 

160 kw["type"] = "upload" 

161 return TypedField(str, **kw) 

162 

163 

164Upload = UploadField 

165 

166T_subclass = typing.TypeVar("T_subclass", TypedTable, Table) 

167 

168 

169def ReferenceField( 

170 other_table: str | typing.Type[TypedTable] | TypedTable | Table | T_subclass, **kw: typing.Any 

171) -> TypedField[int]: 

172 """ 

173 Pydal type is reference, Python type is int (id). 

174 """ 

175 if isinstance(other_table, str): 

176 kw["type"] = f"reference {other_table}" 

177 elif isinstance(other_table, Table): 

178 # db.table 

179 kw["type"] = f"reference {other_table._tablename}" 

180 elif isinstance(other_table, type) and issubclass(other_table, TypedTable): 

181 # SomeTable 

182 snakename = TypeDAL.to_snake(other_table.__name__) 

183 kw["type"] = f"reference {snakename}" 

184 else: 

185 raise ValueError(f"Don't know what to do with {type(other_table)}") 

186 

187 return TypedField(int, **kw) 

188 

189 

190Reference = ReferenceField 

191 

192 

193def ListStringField(**kw: typing.Any) -> TypedField[list[str]]: 

194 """ 

195 Pydal type is list:string, Python type is list of str. 

196 """ 

197 kw["type"] = "list:string" 

198 return TypedField(list[str], **kw) 

199 

200 

201ListString = ListStringField 

202 

203 

204def ListIntegerField(**kw: typing.Any) -> TypedField[list[int]]: 

205 """ 

206 Pydal type is list:integer, Python type is list of int. 

207 """ 

208 kw["type"] = "list:integer" 

209 return TypedField(list[int], **kw) 

210 

211 

212ListInteger = ListIntegerField 

213 

214 

215def ListReferenceField(other_table: str, **kw: typing.Any) -> TypedField[list[int]]: 

216 """ 

217 Pydal type is list:reference, Python type is list of int (id). 

218 """ 

219 kw["type"] = f"list:reference {other_table}" 

220 return TypedField(list[int], **kw) 

221 

222 

223ListReference = ListReferenceField 

224 

225 

226def JSONField(**kw: typing.Any) -> TypedField[object]: 

227 """ 

228 Pydal type is json, Python type is object (can be anything JSON-encodable). 

229 """ 

230 kw["type"] = "json" 

231 return TypedField(object, **kw) 

232 

233 

234def BigintField(**kw: typing.Any) -> TypedField[int]: 

235 """ 

236 Pydal type is bigint, Python type is int. 

237 """ 

238 kw["type"] = "bigint" 

239 return TypedField(int, **kw) 

240 

241 

242Bigint = BigintField