Skip to content

Commit d7c20f2

Browse files
committed
COMPAT: avoid invalid buffer comparisions
closes #18064
1 parent 9e3ad63 commit d7c20f2

File tree

2 files changed

+117
-55
lines changed

2 files changed

+117
-55
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

+108-46
Original file line numberDiff line numberDiff line change
@@ -60,25 +60,33 @@ 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)
67-
68-
for p in passes:
69-
assert inference.is_list_like(p)
70-
71-
for f in fails:
72-
assert not inference.is_list_like(f)
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+
ids=str)
70+
def test_is_list_like_passes(ll):
71+
assert inference.is_list_like(ll)
72+
73+
74+
@pytest.mark.parametrize(
75+
"ll",
76+
[
77+
1, '2', object(), str],
78+
ids=str)
79+
def test_is_list_like_fails(ll):
80+
assert not inference.is_list_like(ll)
7381

7482

7583
@pytest.mark.parametrize('inner', [
7684
[], [1], (1, ), (1, 2), {'a': 1}, set([1, 'a']), Series([1]),
7785
Series([]), Series(['a']).str, (x for x in range(5))
78-
])
86+
], ids=str)
7987
@pytest.mark.parametrize('outer', [
8088
list, Series, np.array, tuple
81-
])
89+
], ids=str)
8290
def test_is_nested_list_like_passes(inner, outer):
8391
result = outer([inner for _ in range(5)])
8492
assert inference.is_list_like(result)
@@ -88,20 +96,21 @@ def test_is_nested_list_like_passes(inner, outer):
8896
'abc', [], [1], (1,), ['a'], 'a', {'a'},
8997
[1, 2, 3], Series([1]), DataFrame({"A": [1]}),
9098
([1, 2] for _ in range(5)),
91-
])
99+
], ids=str)
92100
def test_is_nested_list_like_fails(obj):
93101
assert not inference.is_nested_list_like(obj)
94102

95103

96-
def test_is_dict_like():
97-
passes = [{}, {'A': 1}, Series([1])]
98-
fails = ['1', 1, [1, 2], (1, 2), range(2), Index([1])]
104+
@pytest.mark.parametrize(
105+
"ll", [{}, {'A': 1}, Series([1])], ids=str)
106+
def test_is_dict_like_passes(ll):
107+
assert inference.is_dict_like(ll)
99108

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

103-
for f in fails:
104-
assert not inference.is_dict_like(f)
110+
@pytest.mark.parametrize(
111+
"ll", ['1', 1, [1, 2], (1, 2), range(2), Index([1])], ids=str)
112+
def test_is_dict_like_fails(ll):
113+
assert not inference.is_dict_like(ll)
105114

106115

107116
def test_is_file_like():
@@ -148,15 +157,16 @@ class MockFile(object):
148157
assert not is_file(mock.Mock())
149158

150159

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}))
160+
@pytest.mark.parametrize(
161+
"ll", [collections.namedtuple('Test', list('abc'))(1, 2, 3)], ids=str)
162+
def test_is_names_tuple_passes(ll):
163+
assert inference.is_named_tuple(ll)
154164

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

158-
for f in fails:
159-
assert not inference.is_named_tuple(f)
166+
@pytest.mark.parametrize(
167+
"ll", [(1, 2, 3), 'a', Series({'pi': 3.14})], ids=str)
168+
def test_is_names_tuple_fails(ll):
169+
assert not inference.is_named_tuple(ll)
160170

161171

162172
def test_is_hashable():
@@ -208,27 +218,32 @@ class OldStyleClass():
208218
hash(c) # this will not raise
209219

210220

211-
def test_is_re():
212-
passes = re.compile('ad'),
213-
fails = 'x', 2, 3, object()
221+
@pytest.mark.parametrize(
222+
"ll", [re.compile('ad')], ids=str)
223+
def test_is_re_passes(ll):
224+
assert inference.is_re(ll)
214225

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

218-
for f in fails:
219-
assert not inference.is_re(f)
227+
@pytest.mark.parametrize(
228+
"ll", ['x', 2, 3, object()], ids=str)
229+
def test_is_re_fails(ll):
230+
assert not inference.is_re(ll)
220231

221232

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()
233+
@pytest.mark.parametrize(
234+
"ll", [r'a', u('x'),
235+
r'asdf',
236+
re.compile('adsf'),
237+
u(r'\u2233\s*'),
238+
re.compile(r'')])
239+
def test_is_recompilable_passes(ll):
240+
assert inference.is_re_compilable(ll)
226241

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

230-
for f in fails:
231-
assert not inference.is_re_compilable(f)
243+
@pytest.mark.parametrize(
244+
"ll", [1, [], object()])
245+
def test_is_recompilable_fails(ll):
246+
assert not inference.is_re_compilable(ll)
232247

233248

234249
class TestInference(object):
@@ -300,15 +315,14 @@ def test_maybe_convert_numeric_infinities(self):
300315
np.array(['foo_' + infinity], dtype=object),
301316
na_values, maybe_int)
302317

303-
def test_maybe_convert_numeric_post_floatify_nan(self):
318+
def test_maybe_convert_numeric_post_floatify_nan(self, coerce):
304319
# see gh-13314
305320
data = np.array(['1.200', '-999.000', '4.500'], dtype=object)
306321
expected = np.array([1.2, np.nan, 4.5], dtype=np.float64)
307322
nan_values = set([-999, -999.0])
308323

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)
324+
out = lib.maybe_convert_numeric(data, nan_values, coerce)
325+
tm.assert_numpy_array_equal(out, expected)
312326

313327
def test_convert_infs(self):
314328
arr = np.array(['inf', 'inf', 'inf'], dtype='O')
@@ -739,6 +753,36 @@ def test_is_datetimelike_array_all_nan_nat_like(self):
739753
assert not lib.is_timedelta64_array(arr)
740754
assert not lib.is_timedelta_or_timedelta64_array(arr)
741755

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

744788
dates = [date(2012, 1, day) for day in range(1, 20)]
@@ -752,6 +796,24 @@ def test_date(self):
752796
result = lib.infer_dtype(dates, skipna=True)
753797
assert result == 'date'
754798

799+
def test_is_numeric_array(self):
800+
801+
assert lib.is_float_array(np.array([1, 2.0]))
802+
assert lib.is_float_array(np.array([1, 2.0, np.nan]))
803+
assert not lib.is_float_array(np.array([1, 2]))
804+
805+
assert lib.is_integer_array(np.array([1, 2]))
806+
assert not lib.is_integer_array(np.array([1, 2.0]))
807+
808+
def test_is_string_array(self):
809+
810+
assert lib.is_string_array(np.array(['foo', 'bar']))
811+
assert not lib.is_string_array(
812+
np.array(['foo', 'bar', np.nan], dtype=object), skipna=False)
813+
assert lib.is_string_array(
814+
np.array(['foo', 'bar', np.nan], dtype=object), skipna=True)
815+
assert not lib.is_string_array(np.array([1, 2]))
816+
755817
def test_to_object_array_tuples(self):
756818
r = (5, 6)
757819
values = [r]

0 commit comments

Comments
 (0)