@@ -162,9 +162,160 @@ def _assert_match(result_fill_value, expected_fill_value):
162
162
assert match_value or match_missing
163
163
164
164
165
- def test_maybe_promote_int_with_int ():
166
- # placeholder due to too many xfails; see GH 23982 / 25425
167
- pass
165
+ @pytest .mark .parametrize (
166
+ "dtype, fill_value, expected_dtype" ,
167
+ [
168
+ # size 8
169
+ ("int8" , 1 , "int8" ),
170
+ ("int8" , np .iinfo ("int8" ).max + 1 , "int16" ),
171
+ ("int8" , np .iinfo ("int16" ).max + 1 , "int32" ),
172
+ ("int8" , np .iinfo ("int32" ).max + 1 , "int64" ),
173
+ ("int8" , np .iinfo ("int64" ).max + 1 , "object" ),
174
+ ("int8" , - 1 , "int8" ),
175
+ ("int8" , np .iinfo ("int8" ).min - 1 , "int16" ),
176
+ ("int8" , np .iinfo ("int16" ).min - 1 , "int32" ),
177
+ ("int8" , np .iinfo ("int32" ).min - 1 , "int64" ),
178
+ ("int8" , np .iinfo ("int64" ).min - 1 , "object" ),
179
+ # keep signed-ness as long as possible
180
+ ("uint8" , 1 , "uint8" ),
181
+ ("uint8" , np .iinfo ("int8" ).max + 1 , "uint8" ),
182
+ ("uint8" , np .iinfo ("uint8" ).max + 1 , "uint16" ),
183
+ ("uint8" , np .iinfo ("int16" ).max + 1 , "uint16" ),
184
+ ("uint8" , np .iinfo ("uint16" ).max + 1 , "uint32" ),
185
+ ("uint8" , np .iinfo ("int32" ).max + 1 , "uint32" ),
186
+ ("uint8" , np .iinfo ("uint32" ).max + 1 , "uint64" ),
187
+ ("uint8" , np .iinfo ("int64" ).max + 1 , "uint64" ),
188
+ ("uint8" , np .iinfo ("uint64" ).max + 1 , "object" ),
189
+ # max of uint8 cannot be contained in int8
190
+ ("uint8" , - 1 , "int16" ),
191
+ ("uint8" , np .iinfo ("int8" ).min - 1 , "int16" ),
192
+ ("uint8" , np .iinfo ("int16" ).min - 1 , "int32" ),
193
+ ("uint8" , np .iinfo ("int32" ).min - 1 , "int64" ),
194
+ ("uint8" , np .iinfo ("int64" ).min - 1 , "object" ),
195
+ # size 16
196
+ ("int16" , 1 , "int16" ),
197
+ ("int16" , np .iinfo ("int8" ).max + 1 , "int16" ),
198
+ ("int16" , np .iinfo ("int16" ).max + 1 , "int32" ),
199
+ ("int16" , np .iinfo ("int32" ).max + 1 , "int64" ),
200
+ ("int16" , np .iinfo ("int64" ).max + 1 , "object" ),
201
+ ("int16" , - 1 , "int16" ),
202
+ ("int16" , np .iinfo ("int8" ).min - 1 , "int16" ),
203
+ ("int16" , np .iinfo ("int16" ).min - 1 , "int32" ),
204
+ ("int16" , np .iinfo ("int32" ).min - 1 , "int64" ),
205
+ ("int16" , np .iinfo ("int64" ).min - 1 , "object" ),
206
+ ("uint16" , 1 , "uint16" ),
207
+ ("uint16" , np .iinfo ("int8" ).max + 1 , "uint16" ),
208
+ ("uint16" , np .iinfo ("uint8" ).max + 1 , "uint16" ),
209
+ ("uint16" , np .iinfo ("int16" ).max + 1 , "uint16" ),
210
+ ("uint16" , np .iinfo ("uint16" ).max + 1 , "uint32" ),
211
+ ("uint16" , np .iinfo ("int32" ).max + 1 , "uint32" ),
212
+ ("uint16" , np .iinfo ("uint32" ).max + 1 , "uint64" ),
213
+ ("uint16" , np .iinfo ("int64" ).max + 1 , "uint64" ),
214
+ ("uint16" , np .iinfo ("uint64" ).max + 1 , "object" ),
215
+ ("uint16" , - 1 , "int32" ),
216
+ ("uint16" , np .iinfo ("int8" ).min - 1 , "int32" ),
217
+ ("uint16" , np .iinfo ("int16" ).min - 1 , "int32" ),
218
+ ("uint16" , np .iinfo ("int32" ).min - 1 , "int64" ),
219
+ ("uint16" , np .iinfo ("int64" ).min - 1 , "object" ),
220
+ # size 32
221
+ ("int32" , 1 , "int32" ),
222
+ ("int32" , np .iinfo ("int8" ).max + 1 , "int32" ),
223
+ ("int32" , np .iinfo ("int16" ).max + 1 , "int32" ),
224
+ ("int32" , np .iinfo ("int32" ).max + 1 , "int64" ),
225
+ ("int32" , np .iinfo ("int64" ).max + 1 , "object" ),
226
+ ("int32" , - 1 , "int32" ),
227
+ ("int32" , np .iinfo ("int8" ).min - 1 , "int32" ),
228
+ ("int32" , np .iinfo ("int16" ).min - 1 , "int32" ),
229
+ ("int32" , np .iinfo ("int32" ).min - 1 , "int64" ),
230
+ ("int32" , np .iinfo ("int64" ).min - 1 , "object" ),
231
+ ("uint32" , 1 , "uint32" ),
232
+ ("uint32" , np .iinfo ("int8" ).max + 1 , "uint32" ),
233
+ ("uint32" , np .iinfo ("uint8" ).max + 1 , "uint32" ),
234
+ ("uint32" , np .iinfo ("int16" ).max + 1 , "uint32" ),
235
+ ("uint32" , np .iinfo ("uint16" ).max + 1 , "uint32" ),
236
+ ("uint32" , np .iinfo ("int32" ).max + 1 , "uint32" ),
237
+ ("uint32" , np .iinfo ("uint32" ).max + 1 , "uint64" ),
238
+ ("uint32" , np .iinfo ("int64" ).max + 1 , "uint64" ),
239
+ ("uint32" , np .iinfo ("uint64" ).max + 1 , "object" ),
240
+ ("uint32" , - 1 , "int64" ),
241
+ ("uint32" , np .iinfo ("int8" ).min - 1 , "int64" ),
242
+ ("uint32" , np .iinfo ("int16" ).min - 1 , "int64" ),
243
+ ("uint32" , np .iinfo ("int32" ).min - 1 , "int64" ),
244
+ ("uint32" , np .iinfo ("int64" ).min - 1 , "object" ),
245
+ # size 64
246
+ ("int64" , 1 , "int64" ),
247
+ ("int64" , np .iinfo ("int8" ).max + 1 , "int64" ),
248
+ ("int64" , np .iinfo ("int16" ).max + 1 , "int64" ),
249
+ ("int64" , np .iinfo ("int32" ).max + 1 , "int64" ),
250
+ ("int64" , np .iinfo ("int64" ).max + 1 , "object" ),
251
+ ("int64" , - 1 , "int64" ),
252
+ ("int64" , np .iinfo ("int8" ).min - 1 , "int64" ),
253
+ ("int64" , np .iinfo ("int16" ).min - 1 , "int64" ),
254
+ ("int64" , np .iinfo ("int32" ).min - 1 , "int64" ),
255
+ ("int64" , np .iinfo ("int64" ).min - 1 , "object" ),
256
+ ("uint64" , 1 , "uint64" ),
257
+ ("uint64" , np .iinfo ("int8" ).max + 1 , "uint64" ),
258
+ ("uint64" , np .iinfo ("uint8" ).max + 1 , "uint64" ),
259
+ ("uint64" , np .iinfo ("int16" ).max + 1 , "uint64" ),
260
+ ("uint64" , np .iinfo ("uint16" ).max + 1 , "uint64" ),
261
+ ("uint64" , np .iinfo ("int32" ).max + 1 , "uint64" ),
262
+ ("uint64" , np .iinfo ("uint32" ).max + 1 , "uint64" ),
263
+ ("uint64" , np .iinfo ("int64" ).max + 1 , "uint64" ),
264
+ ("uint64" , np .iinfo ("uint64" ).max + 1 , "object" ),
265
+ ("uint64" , - 1 , "object" ),
266
+ ("uint64" , np .iinfo ("int8" ).min - 1 , "object" ),
267
+ ("uint64" , np .iinfo ("int16" ).min - 1 , "object" ),
268
+ ("uint64" , np .iinfo ("int32" ).min - 1 , "object" ),
269
+ ("uint64" , np .iinfo ("int64" ).min - 1 , "object" ),
270
+ ],
271
+ )
272
+ def test_maybe_promote_int_with_int (dtype , fill_value , expected_dtype , box ):
273
+ dtype = np .dtype (dtype )
274
+ expected_dtype = np .dtype (expected_dtype )
275
+ boxed , box_dtype = box # read from parametrized fixture
276
+
277
+ if not boxed :
278
+ if expected_dtype == object :
279
+ pytest .xfail ("overflow error" )
280
+ if expected_dtype == "int32" :
281
+ pytest .xfail ("always upcasts to platform int" )
282
+ if dtype == "int8" and expected_dtype == "int16" :
283
+ pytest .xfail ("casts to int32 instead of int16" )
284
+ if (
285
+ issubclass (dtype .type , np .unsignedinteger )
286
+ and np .iinfo (dtype ).max < fill_value <= np .iinfo ("int64" ).max
287
+ ):
288
+ pytest .xfail ("falsely casts to signed" )
289
+ if (dtype , expected_dtype ) in [
290
+ ("uint8" , "int16" ),
291
+ ("uint32" , "int64" ),
292
+ ] and fill_value != np .iinfo ("int32" ).min - 1 :
293
+ pytest .xfail ("casts to int32 instead of int8/int16" )
294
+ # this following xfail is "only" a consequence of the - now strictly
295
+ # enforced - principle that maybe_promote_with_scalar always casts
296
+ pytest .xfail ("wrong return type of fill_value" )
297
+ if boxed :
298
+ if expected_dtype != object :
299
+ pytest .xfail ("falsely casts to object" )
300
+ if box_dtype is None and (
301
+ fill_value > np .iinfo ("int64" ).max or np .iinfo ("int64" ).min < fill_value < 0
302
+ ):
303
+ pytest .xfail ("falsely casts to float instead of object" )
304
+
305
+ # output is not a generic int, but corresponds to expected_dtype
306
+ exp_val_for_scalar = np .array ([fill_value ], dtype = expected_dtype )[0 ]
307
+ # no missing value marker for integers
308
+ exp_val_for_array = None if expected_dtype != "object" else np .nan
309
+
310
+ _check_promote (
311
+ dtype ,
312
+ fill_value ,
313
+ boxed ,
314
+ box_dtype ,
315
+ expected_dtype ,
316
+ exp_val_for_scalar ,
317
+ exp_val_for_array ,
318
+ )
168
319
169
320
170
321
# override parametrization due to to many xfails; see GH 23982 / 25425
0 commit comments