Coverage for databases/tests/types/test_decimal.py: 100%

82 statements  

« prev     ^ index     » next       coverage.py v7.2.7, created at 2024-08-27 18:25 +0000

1from decimal import Decimal, getcontext 

2 

3import pytest 

4from dirty_equals import IsPartialDict 

5 

6from prisma import Prisma 

7from prisma.models import Types 

8from prisma._compat import PYDANTIC_V2, model_json_schema 

9 

10DEFAULT_PRECISION = getcontext().prec 

11 

12 

13@pytest.fixture(autouse=True) 

14def setup_decimal_module() -> None: 

15 # ensure that any modifications to the decimal precision 

16 # are not leaked between tests 

17 getcontext().prec = DEFAULT_PRECISION 

18 

19 

20@pytest.mark.asyncio 

21async def test_serialising(client: Prisma) -> None: 

22 """Decimal values of any precision are correctly serialised / deserialised""" 

23 model = await client.types.create( 

24 data={ 

25 'decimal_': Decimal(1), 

26 }, 

27 ) 

28 assert model.decimal_ == Decimal(1) 

29 

30 getcontext().prec = 16 

31 

32 value = Decimal(1) / Decimal(7) 

33 model = await client.types.create( 

34 data={ 

35 'decimal_': value, 

36 }, 

37 ) 

38 assert value == model.decimal_ 

39 assert str(model.decimal_) == '0.1428571428571429' 

40 

41 

42# TODO: split up this test into multiple tests 

43 

44 

45@pytest.mark.asyncio 

46async def test_filtering(client: Prisma) -> None: 

47 """Finding records by a Decimal value""" 

48 async with client.batch_() as batcher: 

49 batcher.types.create({'decimal_': Decimal(1)}) 

50 batcher.types.create({'decimal_': Decimal('2.1234')}) 

51 batcher.types.create({'decimal_': Decimal(3)}) 

52 

53 total = await client.types.count( 

54 where={ 

55 'decimal_': Decimal(1), 

56 }, 

57 ) 

58 assert total == 1 

59 

60 found = await client.types.find_first( 

61 where={ 

62 'decimal_': { 

63 'equals': Decimal('2.1234'), 

64 }, 

65 }, 

66 ) 

67 assert found is not None 

68 assert str(found.decimal_) == '2.1234' 

69 

70 results = await client.types.find_many( 

71 where={ 

72 'decimal_': { 

73 'not_in': [Decimal(1), Decimal(3)], 

74 }, 

75 }, 

76 ) 

77 assert len(results) == 1 

78 assert results[0].decimal_ == Decimal('2.1234') 

79 

80 results = await client.types.find_many( 

81 where={ 

82 'decimal_': { 

83 'lt': Decimal(2), 

84 }, 

85 }, 

86 ) 

87 assert len(results) == 1 

88 assert results[0].decimal_ == Decimal(1) 

89 

90 found = await client.types.find_first( 

91 where={ 

92 'decimal_': { 

93 'lt': Decimal(1), 

94 }, 

95 }, 

96 ) 

97 assert found is None 

98 

99 results = await client.types.find_many( 

100 where={ 

101 'decimal_': { 

102 'lte': Decimal(3), 

103 }, 

104 }, 

105 ) 

106 assert len(results) == 3 

107 

108 found = await client.types.find_first( 

109 where={ 

110 'decimal_': { 

111 'lte': Decimal(1), 

112 }, 

113 }, 

114 ) 

115 assert found is not None 

116 assert found.decimal_ == Decimal(1) 

117 

118 found = await client.types.find_first( 

119 where={ 

120 'decimal_': { 

121 'lte': Decimal('0.99999'), 

122 }, 

123 }, 

124 ) 

125 assert found is None 

126 

127 found = await client.types.find_first( 

128 where={ 

129 'decimal_': { 

130 'gt': Decimal('0.99999'), 

131 }, 

132 }, 

133 ) 

134 assert found is not None 

135 assert found.decimal_ == Decimal(1) 

136 

137 found = await client.types.find_first( 

138 where={ 

139 'decimal_': { 

140 'gt': Decimal('4'), 

141 }, 

142 }, 

143 ) 

144 assert found is None 

145 

146 found = await client.types.find_first( 

147 where={ 

148 'decimal_': { 

149 'gte': Decimal('1'), 

150 }, 

151 }, 

152 ) 

153 assert found is not None 

154 assert found.decimal_ == Decimal('1') 

155 

156 found = await client.types.find_first( 

157 where={ 

158 'decimal_': { 

159 'gte': Decimal('4'), 

160 }, 

161 }, 

162 ) 

163 assert found is None 

164 

165 results = await client.types.find_many( 

166 where={ 

167 'decimal_': { 

168 'in': [Decimal(3), Decimal(1), Decimal(2)], 

169 }, 

170 }, 

171 order={ 

172 'decimal_': 'asc', 

173 }, 

174 ) 

175 assert len(results) == 2 

176 assert results[0].decimal_ == Decimal(1) 

177 assert results[1].decimal_ == Decimal(3) 

178 

179 found = await client.types.find_first( 

180 where={ 

181 'decimal_': { 

182 'not': Decimal('1'), 

183 }, 

184 }, 

185 order={ 

186 'decimal_': 'asc', 

187 }, 

188 ) 

189 assert found is not None 

190 assert found.decimal_ == Decimal('2.1234') 

191 

192 found = await client.types.find_first( 

193 where={ 

194 'decimal_': { 

195 'not': {'equals': Decimal('1')}, 

196 }, 

197 }, 

198 order={ 

199 'decimal_': 'asc', 

200 }, 

201 ) 

202 assert found is not None 

203 assert found.decimal_ == Decimal('2.1234') 

204 

205 

206@pytest.mark.asyncio 

207async def test_filtering_nulls(client: Prisma) -> None: 

208 """None is a valid filter for nullable Decimal fields""" 

209 await client.types.create( 

210 { 

211 'string': 'a', 

212 'optional_decimal': None, 

213 }, 

214 ) 

215 await client.types.create( 

216 { 

217 'string': 'b', 

218 'optional_decimal': Decimal('3'), 

219 }, 

220 ) 

221 await client.types.create( 

222 { 

223 'string': 'c', 

224 'optional_decimal': Decimal('4'), 

225 }, 

226 ) 

227 

228 found = await client.types.find_first( 

229 where={ 

230 'NOT': [ 

231 { 

232 'optional_decimal': None, 

233 }, 

234 ], 

235 }, 

236 order={ 

237 'string': 'asc', 

238 }, 

239 ) 

240 assert found is not None 

241 assert found.string == 'b' 

242 assert found.optional_decimal == Decimal('3') 

243 

244 count = await client.types.count( 

245 where={ 

246 'optional_decimal': None, 

247 }, 

248 ) 

249 assert count == 1 

250 

251 count = await client.types.count( 

252 where={ 

253 'NOT': [ 

254 { 

255 'optional_decimal': None, 

256 }, 

257 ], 

258 }, 

259 ) 

260 assert count == 2 

261 

262 

263def test_json_schema() -> None: 

264 """Ensure a JSON Schema definition can be created""" 

265 if PYDANTIC_V2: 

266 assert model_json_schema(Types) == IsPartialDict( 

267 properties=IsPartialDict( 

268 { 

269 'decimal_': { 

270 'title': 'Decimal ', 

271 'anyOf': [{'type': 'number'}, {'type': 'string'}], 

272 }, 

273 'optional_decimal': { 

274 'title': 'Optional Decimal', 

275 'anyOf': [ 

276 {'type': 'number'}, 

277 {'type': 'string'}, 

278 {'type': 'null'}, 

279 ], 

280 'default': None, 

281 }, 

282 } 

283 ) 

284 ) 

285 else: 

286 assert model_json_schema(Types) == IsPartialDict( 

287 properties=IsPartialDict( 

288 { 

289 'decimal_': { 

290 'title': 'Decimal ', 

291 'type': 'number', 

292 }, 

293 'optional_decimal': { 

294 'title': 'Optional Decimal', 

295 'type': 'number', 

296 }, 

297 } 

298 ) 

299 )