4
4
5
5
import numpy as np
6
6
import pandas as pd
7
- import pint
8
7
import pytest
9
8
from pandas .core import ops
10
9
from pandas .tests .extension import base
22
21
import pint_pandas as ppi
23
22
from pint_pandas import PintArray
24
23
25
- ureg = pint . UnitRegistry ()
24
+ ureg = ppi . PintType . ureg
26
25
27
26
28
27
@pytest .fixture (params = [True , False ])
@@ -193,19 +192,76 @@ def all_boolean_reductions(request):
193
192
194
193
195
194
class TestCasting (base .BaseCastingTests ):
196
- pass
195
+ @pytest .mark .xfail (run = True , reason = "TODO: fix pd 1.2 tests" )
196
+ def test_astype_str (self , data ):
197
+ result = pd .Series (data [:5 ]).astype (str )
198
+ expected = pd .Series ([str (x ) for x in data [:5 ]], dtype = str )
199
+ self .assert_series_equal (result , expected )
200
+
201
+ @pytest .mark .xfail (run = True , reason = "TODO: fix pd 1.2 tests" )
202
+ def test_astype_string (self , data ):
203
+ # GH-33465
204
+ result = pd .Series (data [:5 ]).astype ("string" )
205
+ expected = pd .Series ([str (x ) for x in data [:5 ]], dtype = "string" )
206
+ self .assert_series_equal (result , expected )
197
207
198
208
199
209
class TestConstructors (base .BaseConstructorsTests ):
200
- pass
210
+ @pytest .mark .xfail (run = True , reason = "TODO: fix pd 1.2 tests" )
211
+ def test_series_constructor_no_data_with_index (self , dtype , na_value ):
212
+ result = pd .Series (index = [1 , 2 , 3 ], dtype = dtype )
213
+ expected = pd .Series ([na_value ] * 3 , index = [1 , 2 , 3 ], dtype = dtype )
214
+ self .assert_series_equal (result , expected )
215
+
216
+ # GH 33559 - empty index
217
+ result = pd .Series (index = [], dtype = dtype )
218
+ expected = pd .Series ([], index = pd .Index ([], dtype = "object" ), dtype = dtype )
219
+ self .assert_series_equal (result , expected )
220
+
221
+ @pytest .mark .xfail (run = True , reason = "TODO: fix pd 1.2 tests" )
222
+ def test_series_constructor_scalar_na_with_index (self , dtype , na_value ):
223
+ result = pd .Series (na_value , index = [1 , 2 , 3 ], dtype = dtype )
224
+ expected = pd .Series ([na_value ] * 3 , index = [1 , 2 , 3 ], dtype = dtype )
225
+ self .assert_series_equal (result , expected )
226
+
227
+ @pytest .mark .xfail (run = True , reason = "TODO: fix pd 1.2 tests" )
228
+ def test_series_constructor_scalar_with_index (self , data , dtype ):
229
+ scalar = data [0 ]
230
+ result = pd .Series (scalar , index = [1 , 2 , 3 ], dtype = dtype )
231
+ expected = pd .Series ([scalar ] * 3 , index = [1 , 2 , 3 ], dtype = dtype )
232
+ self .assert_series_equal (result , expected )
233
+
234
+ result = pd .Series (scalar , index = ["foo" ], dtype = dtype )
235
+ expected = pd .Series ([scalar ], index = ["foo" ], dtype = dtype )
236
+ self .assert_series_equal (result , expected )
201
237
202
238
203
239
class TestDtype (base .BaseDtypeTests ):
204
- pass
240
+ @pytest .mark .xfail (run = True , reason = "TODO: fix pd 1.2 tests" )
241
+ def test_construct_from_string_another_type_raises (self , dtype ):
242
+ msg = f"Cannot construct a '{ type (dtype ).__name__ } ' from 'another_type'"
243
+ with pytest .raises (TypeError , match = msg ):
244
+ type (dtype ).construct_from_string ("another_type" )
245
+
246
+ @pytest .mark .xfail (run = True , reason = "TODO: fix pd 1.2 tests" )
247
+ def test_construct_from_string_wrong_type_raises (self , dtype ):
248
+ with pytest .raises (
249
+ TypeError ,
250
+ match = "'construct_from_string' expects a string, got <class 'int'>" ,
251
+ ):
252
+ type (dtype ).construct_from_string (0 )
205
253
206
254
207
255
class TestGetitem (base .BaseGetitemTests ):
208
- pass
256
+ @pytest .mark .xfail (run = True , reason = "TODO: fix pd 1.2 tests" )
257
+ def test_getitem_mask_raises (self , data ):
258
+ mask = np .array ([True , False ])
259
+ with pytest .raises (IndexError ):
260
+ data [mask ]
261
+
262
+ mask = pd .array (mask , dtype = "boolean" )
263
+ with pytest .raises (IndexError ):
264
+ data [mask ]
209
265
210
266
211
267
class TestGroupby (base .BaseGroupbyTests ):
@@ -247,7 +303,31 @@ def test_groupby_apply_identity(self, data_for_grouping):
247
303
248
304
249
305
class TestInterface (base .BaseInterfaceTests ):
250
- pass
306
+ @pytest .mark .xfail (run = True , reason = "TODO: fix pd 1.2 tests" )
307
+ def test_contains (self , data , data_missing ):
308
+ # GH-37867
309
+ # Tests for membership checks. Membership checks for nan-likes is tricky and
310
+ # the settled on rule is: `nan_like in arr` is True if nan_like is
311
+ # arr.dtype.na_value and arr.isna().any() is True. Else the check returns False.
312
+
313
+ na_value = data .dtype .na_value
314
+ # ensure data without missing values
315
+ data = data [~ data .isna ()]
316
+
317
+ # first elements are non-missing
318
+ assert data [0 ] in data
319
+ assert data_missing [0 ] in data_missing
320
+
321
+ # check the presence of na_value
322
+ assert na_value in data_missing
323
+ assert na_value not in data
324
+
325
+ # the data can never contain other nan-likes than na_value
326
+ # for na_value_obj in tm.NULL_OBJECTS:
327
+ # if na_value_obj is na_value:
328
+ # continue
329
+ # assert na_value_obj not in data
330
+ # assert na_value_obj not in data_missing
251
331
252
332
253
333
class TestMethods (base .BaseMethodsTests ):
@@ -359,6 +439,30 @@ def test_where_series(self, data, na_value, as_frame): # noqa: F811
359
439
expected = expected .to_frame (name = "a" )
360
440
self .assert_equal (result , expected )
361
441
442
+ @pytest .mark .xfail (run = True , reason = "TODO: fix pd 1.2 tests" )
443
+ @pytest .mark .parametrize ("ascending" , [True , False ])
444
+ def test_sort_values (self , data_for_sorting , ascending , sort_by_key ):
445
+ ser = pd .Series (data_for_sorting )
446
+ result = ser .sort_values (ascending = ascending , key = sort_by_key )
447
+ expected = ser .iloc [[2 , 0 , 1 ]]
448
+ if not ascending :
449
+ expected = expected [::- 1 ]
450
+
451
+ self .assert_series_equal (result , expected )
452
+
453
+ @pytest .mark .xfail (run = True , reason = "TODO: fix pd 1.2 tests" )
454
+ @pytest .mark .parametrize ("ascending" , [True , False ])
455
+ def test_sort_values_missing (
456
+ self , data_missing_for_sorting , ascending , sort_by_key
457
+ ):
458
+ ser = pd .Series (data_missing_for_sorting )
459
+ result = ser .sort_values (ascending = ascending , key = sort_by_key )
460
+ if ascending :
461
+ expected = ser .iloc [[2 , 0 , 1 ]]
462
+ else :
463
+ expected = ser .iloc [[0 , 2 , 1 ]]
464
+ self .assert_series_equal (result , expected )
465
+
362
466
363
467
class TestArithmeticOps (base .BaseArithmeticOpsTests ):
364
468
def check_opname (self , s , op_name , other , exc = None ):
@@ -456,6 +560,20 @@ def test_error(self, data, all_arithmetic_operators):
456
560
with pytest .raises (ValueError ):
457
561
opa (np .arange (len (s )).reshape (- 1 , len (s )))
458
562
563
+ @pytest .mark .xfail (run = True , reason = "TODO: fix pd 1.2 tests" )
564
+ @pytest .mark .parametrize ("box" , [pd .Series , pd .DataFrame ])
565
+ def test_direct_arith_with_ndframe_returns_not_implemented (self , data , box ):
566
+ # EAs should return NotImplemented for ops with Series/DataFrame
567
+ # Pandas takes care of unboxing the series and calling the EA's op.
568
+ other = pd .Series (data )
569
+ if box is pd .DataFrame :
570
+ other = other .to_frame ()
571
+ if hasattr (data , "__add__" ):
572
+ result = data .__add__ (other )
573
+ assert result is NotImplemented
574
+ else :
575
+ raise pytest .skip (f"{ type (data ).__name__ } does not implement add" )
576
+
459
577
460
578
class TestComparisonOps (base .BaseComparisonOpsTests ):
461
579
def _compare_other (self , s , data , op_name , other ):
@@ -479,6 +597,27 @@ def test_compare_array(self, data, all_compare_operators):
479
597
other = data
480
598
self ._compare_other (s , data , op_name , other )
481
599
600
+ @pytest .mark .xfail (run = True , reason = "TODO: fix pd 1.2 tests" )
601
+ @pytest .mark .parametrize ("box" , [pd .Series , pd .DataFrame ])
602
+ def test_direct_arith_with_ndframe_returns_not_implemented (self , data , box ):
603
+ # EAs should return NotImplemented for ops with Series/DataFrame
604
+ # Pandas takes care of unboxing the series and calling the EA's op.
605
+ other = pd .Series (data )
606
+ if box is pd .DataFrame :
607
+ other = other .to_frame ()
608
+
609
+ if hasattr (data , "__eq__" ):
610
+ result = data .__eq__ (other )
611
+ assert result is NotImplemented
612
+ else :
613
+ raise pytest .skip (f"{ type (data ).__name__ } does not implement __eq__" )
614
+
615
+ if hasattr (data , "__ne__" ):
616
+ result = data .__ne__ (other )
617
+ assert result is NotImplemented
618
+ else :
619
+ raise pytest .skip (f"{ type (data ).__name__ } does not implement __ne__" )
620
+
482
621
483
622
class TestOpsUtil (base .BaseOpsUtil ):
484
623
pass
@@ -661,11 +800,17 @@ def test_setitem_loc_iloc_slice(self, data):
661
800
662
801
663
802
class TestOffsetUnits (object ):
664
- def test_offset_concat ():
665
- a = pd .Series (PintArray (range (5 ), ureg .Unit ("degC" )))
666
- b = pd .Series (PintArray (range (6 ), ureg .Unit ("degC" )))
803
+ @pytest .mark .xfail (run = True , reason = "TODO untested issue that was fixed" )
804
+ def test_offset_concat (self ):
805
+ q_a = ureg .Quantity (np .arange (5 ), ureg .Unit ("degC" ))
806
+ q_b = ureg .Quantity (np .arange (6 ), ureg .Unit ("degC" ))
667
807
668
- pd .concat ([a , b ], axis = 1 )
808
+ a = pd .Series (PintArray (q_a ))
809
+ b = pd .Series (PintArray (q_b ))
810
+
811
+ result = pd .concat ([a , b ], axis = 1 )
812
+ expected = pd .Series (PintArray (np .concatenate ([q_b , q_b ]), dtype = "pint[degC]" ))
813
+ self .assert_equal (result , expected )
669
814
670
815
671
816
# would be ideal to just test all of this by running the example notebook
0 commit comments