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

91 statements  

« prev     ^ index     » next       coverage.py v7.2.7, created at 2023-06-05 16:09 +0200

1""" 

2This file contains available Field types. 

3""" 

4 

5import datetime as dt 

6import decimal 

7import types 

8import typing 

9 

10from pydal.objects import Table 

11 

12from .core import TypeDAL, TypedFieldType, TypedTable 

13 

14T = typing.TypeVar("T", bound=typing.Type[typing.Any]) 

15 

16 

17## general 

18 

19 

20def TypedField( 

21 _type: T | types.UnionType, 

22 **kwargs: typing.Any, 

23) -> T: 

24 """ 

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

26 

27 and the return type (T) is the input type in _type 

28 

29 Example: 

30 age: TypedField(int, default=18) 

31 """ 

32 return TypedFieldType(_type, **kwargs) 

33 

34 

35TYPE_STR = typing.Type[str] 

36TYPE_INT = typing.Type[int] 

37TYPE_LIST_OF_INT = typing.Type[list[int]] 

38 

39 

40## specific 

41def StringField(**kw: typing.Any) -> TYPE_STR: 

42 """ 

43 Pydal type is string, Python type is str. 

44 """ 

45 kw["type"] = "string" 

46 return TypedField(str, **kw) 

47 

48 

49String = StringField 

50 

51 

52def TextField(**kw: typing.Any) -> TYPE_STR: 

53 """ 

54 Pydal type is text, Python type is str. 

55 """ 

56 kw["type"] = "text" 

57 return TypedField(str, **kw) 

58 

59 

60Text = TextField 

61 

62 

63def BlobField(**kw: typing.Any) -> typing.Type[bytes]: 

64 """ 

65 Pydal type is blob, Python type is bytes. 

66 """ 

67 kw["type"] = "blob" 

68 return TypedField(bytes, **kw) 

69 

70 

71Blob = BlobField 

72 

73 

74def BooleanField(**kw: typing.Any) -> typing.Type[bool]: 

75 """ 

76 Pydal type is boolean, Python type is bool. 

77 """ 

78 kw["type"] = "boolean" 

79 return TypedField(bool, **kw) 

80 

81 

82Boolean = BooleanField 

83 

84 

85def IntegerField(**kw: typing.Any) -> typing.Type[int]: 

86 """ 

87 Pydal type is integer, Python type is int. 

88 """ 

89 kw["type"] = "integer" 

90 return TypedField(int, **kw) 

91 

92 

93Integer = IntegerField 

94 

95 

96def DoubleField(**kw: typing.Any) -> typing.Type[float]: 

97 """ 

98 Pydal type is double, Python type is float. 

99 """ 

100 kw["type"] = "double" 

101 return TypedField(float, **kw) 

102 

103 

104Double = DoubleField 

105 

106 

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

108 """ 

109 Pydal type is decimal, Python type is Decimal. 

110 """ 

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

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

113 

114 

115Decimal = DecimalField 

116 

117 

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

119 """ 

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

121 """ 

122 kw["type"] = "date" 

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

124 

125 

126Date = DateField 

127 

128 

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

130 """ 

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

132 """ 

133 kw["type"] = "time" 

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

135 

136 

137Time = TimeField 

138 

139 

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

141 """ 

142 Pydal type is datetime, Python type is datetime.datetime. 

143 """ 

144 kw["type"] = "datetime" 

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

146 

147 

148Datetime = DatetimeField 

149 

150 

151def PasswordField(**kw: typing.Any) -> TYPE_STR: 

152 """ 

153 Pydal type is password, Python type is str. 

154 """ 

155 kw["type"] = "password" 

156 return TypedField(str, **kw) 

157 

158 

159Password = PasswordField 

160 

161 

162def UploadField(**kw: typing.Any) -> TYPE_STR: 

163 """ 

164 Pydal type is upload, Python type is str. 

165 """ 

166 kw["type"] = "upload" 

167 return TypedField(str, **kw) 

168 

169 

170Upload = UploadField 

171 

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

173 

174 

175def ReferenceField(other_table: str | TypedTable | Table | T_subclass, **kw: typing.Any) -> TYPE_INT: 

176 """ 

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

178 """ 

179 if isinstance(other_table, str): 

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

181 elif isinstance(other_table, Table): 

182 # db.table 

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

184 elif issubclass(type(other_table), type) and issubclass(other_table, TypedTable): 

185 # SomeTable 

186 snakename = TypeDAL._to_snake(other_table.__name__) 

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

188 else: 

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

190 

191 return TypedField(int, **kw) 

192 

193 

194Reference = ReferenceField 

195 

196 

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

198 """ 

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

200 """ 

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

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

203 

204 

205ListString = ListStringField 

206 

207 

208def ListIntegerField(**kw: typing.Any) -> TYPE_LIST_OF_INT: 

209 """ 

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

211 """ 

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

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

214 

215 

216ListInteger = ListIntegerField 

217 

218 

219def ListReferenceField(other_table: str, **kw: typing.Any) -> TYPE_LIST_OF_INT: 

220 """ 

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

222 """ 

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

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

225 

226 

227ListReference = ListReferenceField 

228 

229 

230def JSONField(**kw: typing.Any) -> typing.Type[object]: 

231 """ 

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

233 """ 

234 kw["type"] = "json" 

235 return TypedField(object, **kw) 

236 

237 

238def BigintField(**kw: typing.Any) -> TYPE_INT: 

239 """ 

240 Pydal type is bigint, Python type is int. 

241 """ 

242 kw["type"] = "bigint" 

243 return TypedField(int, **kw) 

244 

245 

246Bigint = BigintField