Skip to content

Commit cff2842

Browse files
authored
COMPAT: avoid invalid buffer comparisions (#18252)
closes #18064
1 parent feaa0d0 commit cff2842

File tree

2 files changed

+109
-51
lines changed

2 files changed

+109
-51
lines changed

pandas/_libs/src/inference.pyx

+9-9
Original file line numberDiff line numberDiff line change
@@ -613,7 +613,7 @@ cdef class Validator:
613613
self.dtype = dtype
614614
self.skipna = skipna
615615

616-
cdef bint validate(self, object[:] values) except -1:
616+
cdef bint validate(self, ndarray values) except -1:
617617
if not self.n:
618618
return False
619619

@@ -629,7 +629,7 @@ cdef class Validator:
629629

630630
@cython.wraparound(False)
631631
@cython.boundscheck(False)
632-
cdef bint _validate(self, object[:] values) except -1:
632+
cdef bint _validate(self, ndarray values) except -1:
633633
cdef:
634634
Py_ssize_t i
635635
Py_ssize_t n = self.n
@@ -642,7 +642,7 @@ cdef class Validator:
642642

643643
@cython.wraparound(False)
644644
@cython.boundscheck(False)
645-
cdef bint _validate_skipna(self, object[:] values) except -1:
645+
cdef bint _validate_skipna(self, ndarray values) except -1:
646646
cdef:
647647
Py_ssize_t i
648648
Py_ssize_t n = self.n
@@ -852,7 +852,7 @@ cdef class DatetimeValidator(TemporalValidator):
852852
return is_null_datetime64(value)
853853

854854

855-
cpdef bint is_datetime_array(ndarray[object] values):
855+
cpdef bint is_datetime_array(ndarray values):
856856
cdef:
857857
DatetimeValidator validator = DatetimeValidator(
858858
len(values),
@@ -876,7 +876,7 @@ cpdef bint is_datetime64_array(ndarray values):
876876
return validator.validate(values)
877877

878878

879-
cpdef bint is_datetime_with_singletz_array(ndarray[object] values):
879+
cpdef bint is_datetime_with_singletz_array(ndarray values):
880880
"""
881881
Check values have the same tzinfo attribute.
882882
Doesn't check values are datetime-like types.
@@ -959,7 +959,7 @@ cdef class DateValidator(Validator):
959959
return is_date(value)
960960

961961

962-
cpdef bint is_date_array(ndarray[object] values, bint skipna=False):
962+
cpdef bint is_date_array(ndarray values, bint skipna=False):
963963
cdef DateValidator validator = DateValidator(len(values), skipna=skipna)
964964
return validator.validate(values)
965965

@@ -970,7 +970,7 @@ cdef class TimeValidator(Validator):
970970
return is_time(value)
971971

972972

973-
cpdef bint is_time_array(ndarray[object] values, bint skipna=False):
973+
cpdef bint is_time_array(ndarray values, bint skipna=False):
974974
cdef TimeValidator validator = TimeValidator(len(values), skipna=skipna)
975975
return validator.validate(values)
976976

@@ -984,7 +984,7 @@ cdef class PeriodValidator(TemporalValidator):
984984
return is_null_period(value)
985985

986986

987-
cpdef bint is_period_array(ndarray[object] values):
987+
cpdef bint is_period_array(ndarray values):
988988
cdef PeriodValidator validator = PeriodValidator(len(values), skipna=True)
989989
return validator.validate(values)
990990

@@ -995,7 +995,7 @@ cdef class IntervalValidator(Validator):
995995
return is_interval(value)
996996

997997

998-
cpdef bint is_interval_array(ndarray[object] values):
998+
cpdef bint is_interval_array(ndarray values):
999999
cdef:
10001000
IntervalValidator validator = IntervalValidator(
10011001
len(values),

pandas/tests/dtypes/test_inference.py

+100-42
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
from pandas.util import testing as tm
4040

4141

42-
@pytest.fixture(params=[True, False], ids=lambda val: str(val))
42+
@pytest.fixture(params=[True, False], ids=str)
4343
def coerce(request):
4444
return request.param
4545

@@ -60,16 +60,20 @@ def __getitem__(self):
6060
assert (not is_seq(A()))
6161

6262

63-
def test_is_list_like():
64-
passes = ([], [1], (1, ), (1, 2), {'a': 1}, set([1, 'a']), Series([1]),
65-
Series([]), Series(['a']).str)
66-
fails = (1, '2', object(), str)
63+
@pytest.mark.parametrize(
64+
"ll",
65+
[
66+
[], [1], (1, ), (1, 2), {'a': 1},
67+
set([1, 'a']), Series([1]),
68+
Series([]), Series(['a']).str])
69+
def test_is_list_like_passes(ll):
70+
assert inference.is_list_like(ll)
6771

68-
for p in passes:
69-
assert inference.is_list_like(p)
7072

71-
for f in fails:
72-
assert not inference.is_list_like(f)
73+
@pytest.mark.parametrize(
74+
"ll", [1, '2', object(), str])
75+
def test_is_list_like_fails(ll):
76+
assert not inference.is_list_like(ll)
7377

7478

7579
@pytest.mark.parametrize('inner', [
@@ -93,15 +97,16 @@ def test_is_nested_list_like_fails(obj):
9397
assert not inference.is_nested_list_like(obj)
9498

9599

96-
def test_is_dict_like():
97-
passes = [{}, {'A': 1}, Series([1])]
98-
fails = ['1', 1, [1, 2], (1, 2), range(2), Index([1])]
100+
@pytest.mark.parametrize(
101+
"ll", [{}, {'A': 1}, Series([1])])
102+
def test_is_dict_like_passes(ll):
103+
assert inference.is_dict_like(ll)
99104

100-
for p in passes:
101-
assert inference.is_dict_like(p)
102105

103-
for f in fails:
104-
assert not inference.is_dict_like(f)
106+
@pytest.mark.parametrize(
107+
"ll", ['1', 1, [1, 2], (1, 2), range(2), Index([1])])
108+
def test_is_dict_like_fails(ll):
109+
assert not inference.is_dict_like(ll)
105110

106111

107112
def test_is_file_like():
@@ -148,15 +153,16 @@ class MockFile(object):
148153
assert not is_file(mock.Mock())
149154

150155

151-
def test_is_named_tuple():
152-
passes = (collections.namedtuple('Test', list('abc'))(1, 2, 3), )
153-
fails = ((1, 2, 3), 'a', Series({'pi': 3.14}))
156+
@pytest.mark.parametrize(
157+
"ll", [collections.namedtuple('Test', list('abc'))(1, 2, 3)])
158+
def test_is_names_tuple_passes(ll):
159+
assert inference.is_named_tuple(ll)
154160

155-
for p in passes:
156-
assert inference.is_named_tuple(p)
157161

158-
for f in fails:
159-
assert not inference.is_named_tuple(f)
162+
@pytest.mark.parametrize(
163+
"ll", [(1, 2, 3), 'a', Series({'pi': 3.14})])
164+
def test_is_names_tuple_fails(ll):
165+
assert not inference.is_named_tuple(ll)
160166

161167

162168
def test_is_hashable():
@@ -208,27 +214,32 @@ class OldStyleClass():
208214
hash(c) # this will not raise
209215

210216

211-
def test_is_re():
212-
passes = re.compile('ad'),
213-
fails = 'x', 2, 3, object()
217+
@pytest.mark.parametrize(
218+
"ll", [re.compile('ad')])
219+
def test_is_re_passes(ll):
220+
assert inference.is_re(ll)
214221

215-
for p in passes:
216-
assert inference.is_re(p)
217222

218-
for f in fails:
219-
assert not inference.is_re(f)
223+
@pytest.mark.parametrize(
224+
"ll", ['x', 2, 3, object()])
225+
def test_is_re_fails(ll):
226+
assert not inference.is_re(ll)
220227

221228

222-
def test_is_recompilable():
223-
passes = (r'a', u('x'), r'asdf', re.compile('adsf'), u(r'\u2233\s*'),
224-
re.compile(r''))
225-
fails = 1, [], object()
229+
@pytest.mark.parametrize(
230+
"ll", [r'a', u('x'),
231+
r'asdf',
232+
re.compile('adsf'),
233+
u(r'\u2233\s*'),
234+
re.compile(r'')])
235+
def test_is_recompilable_passes(ll):
236+
assert inference.is_re_compilable(ll)
226237

227-
for p in passes:
228-
assert inference.is_re_compilable(p)
229238

230-
for f in fails:
231-
assert not inference.is_re_compilable(f)
239+
@pytest.mark.parametrize(
240+
"ll", [1, [], object()])
241+
def test_is_recompilable_fails(ll):
242+
assert not inference.is_re_compilable(ll)
232243

233244

234245
class TestInference(object):
@@ -300,15 +311,14 @@ def test_maybe_convert_numeric_infinities(self):
300311
np.array(['foo_' + infinity], dtype=object),
301312
na_values, maybe_int)
302313

303-
def test_maybe_convert_numeric_post_floatify_nan(self):
314+
def test_maybe_convert_numeric_post_floatify_nan(self, coerce):
304315
# see gh-13314
305316
data = np.array(['1.200', '-999.000', '4.500'], dtype=object)
306317
expected = np.array([1.2, np.nan, 4.5], dtype=np.float64)
307318
nan_values = set([-999, -999.0])
308319

309-
for coerce_type in (True, False):
310-
out = lib.maybe_convert_numeric(data, nan_values, coerce_type)
311-
tm.assert_numpy_array_equal(out, expected)
320+
out = lib.maybe_convert_numeric(data, nan_values, coerce)
321+
tm.assert_numpy_array_equal(out, expected)
312322

313323
def test_convert_infs(self):
314324
arr = np.array(['inf', 'inf', 'inf'], dtype='O')
@@ -739,6 +749,36 @@ def test_is_datetimelike_array_all_nan_nat_like(self):
739749
assert not lib.is_timedelta64_array(arr)
740750
assert not lib.is_timedelta_or_timedelta64_array(arr)
741751

752+
assert lib.is_datetime_with_singletz_array(
753+
np.array([pd.Timestamp('20130101', tz='US/Eastern'),
754+
pd.Timestamp('20130102', tz='US/Eastern')],
755+
dtype=object))
756+
assert not lib.is_datetime_with_singletz_array(
757+
np.array([pd.Timestamp('20130101', tz='US/Eastern'),
758+
pd.Timestamp('20130102', tz='CET')],
759+
dtype=object))
760+
761+
@pytest.mark.parametrize(
762+
"func",
763+
[
764+
'is_datetime_array',
765+
'is_datetime64_array',
766+
'is_bool_array',
767+
'is_timedelta_array',
768+
'is_timedelta64_array',
769+
'is_timedelta_or_timedelta64_array',
770+
'is_date_array',
771+
'is_time_array',
772+
'is_interval_array',
773+
'is_period_array'])
774+
def test_other_dtypes_for_array(self, func):
775+
func = getattr(lib, func)
776+
arr = np.array(['foo', 'bar'])
777+
assert not func(arr)
778+
779+
arr = np.array([1, 2])
780+
assert not func(arr)
781+
742782
def test_date(self):
743783

744784
dates = [date(2012, 1, day) for day in range(1, 20)]
@@ -752,6 +792,24 @@ def test_date(self):
752792
result = lib.infer_dtype(dates, skipna=True)
753793
assert result == 'date'
754794

795+
def test_is_numeric_array(self):
796+
797+
assert lib.is_float_array(np.array([1, 2.0]))
798+
assert lib.is_float_array(np.array([1, 2.0, np.nan]))
799+
assert not lib.is_float_array(np.array([1, 2]))
800+
801+
assert lib.is_integer_array(np.array([1, 2]))
802+
assert not lib.is_integer_array(np.array([1, 2.0]))
803+
804+
def test_is_string_array(self):
805+
806+
assert lib.is_string_array(np.array(['foo', 'bar']))
807+
assert not lib.is_string_array(
808+
np.array(['foo', 'bar', np.nan], dtype=object), skipna=False)
809+
assert lib.is_string_array(
810+
np.array(['foo', 'bar', np.nan], dtype=object), skipna=True)
811+
assert not lib.is_string_array(np.array([1, 2]))
812+
755813
def test_to_object_array_tuples(self):
756814
r = (5, 6)
757815
values = [r]

0 commit comments

Comments
 (0)