Skip to content

Commit 8ed7a69

Browse files
committed
remove pandas backports to fix test coverage errors
1 parent 0b3753d commit 8ed7a69

File tree

6 files changed

+37
-186
lines changed

6 files changed

+37
-186
lines changed

.github/workflows/docs.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ jobs:
1212
- name: Setup Python
1313
uses: actions/setup-python@v5
1414
with:
15-
python-version: "3.9"
15+
python-version: "3.10"
1616
- name: Install nox
1717
run: |
1818
python -m pip install --upgrade setuptools pip wheel

db_dtypes/__init__.py

+11-29
Original file line numberDiff line numberDiff line change
@@ -21,17 +21,17 @@
2121
import warnings
2222

2323
import numpy
24-
import packaging.version
2524
import pandas
2625
import pandas.api.extensions
2726
from pandas.errors import OutOfBoundsDatetime
2827
import pyarrow
2928
import pyarrow.compute
3029

3130
from db_dtypes import core
31+
from db_dtypes.json import JSONArray, JSONDtype
3232
from db_dtypes.version import __version__
33-
from . import _versions_helpers
3433

34+
from . import _versions_helpers
3535

3636
date_dtype_name = "dbdate"
3737
time_dtype_name = "dbtime"
@@ -47,15 +47,6 @@
4747
_NP_BOX_DTYPE = "datetime64[us]"
4848

4949

50-
# To use JSONArray and JSONDtype, you'll need Pandas 1.5.0 or later. With the removal
51-
# of Python 3.7 compatibility, the minimum Pandas version will be updated to 1.5.0.
52-
if packaging.version.Version(pandas.__version__) >= packaging.version.Version("1.5.0"):
53-
from db_dtypes.json import JSONArray, JSONDtype
54-
else:
55-
JSONArray = None
56-
JSONDtype = None
57-
58-
5950
@pandas.api.extensions.register_extension_dtype
6051
class TimeDtype(core.BaseDatetimeDtype):
6152
"""
@@ -359,21 +350,12 @@ def __sub__(self, other):
359350
)
360351

361352

362-
if not JSONArray or not JSONDtype:
363-
__all__ = [
364-
"__version__",
365-
"DateArray",
366-
"DateDtype",
367-
"TimeArray",
368-
"TimeDtype",
369-
]
370-
else:
371-
__all__ = [
372-
"__version__",
373-
"DateArray",
374-
"DateDtype",
375-
"JSONDtype",
376-
"JSONArray",
377-
"TimeArray",
378-
"TimeDtype",
379-
]
353+
__all__ = [
354+
"__version__",
355+
"DateArray",
356+
"DateDtype",
357+
"JSONDtype",
358+
"JSONArray",
359+
"TimeArray",
360+
"TimeDtype",
361+
]

db_dtypes/pandas_backports.py

+8-114
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,9 @@
1919
the versions in the later versions of pandas.
2020
"""
2121

22-
import operator
23-
from typing import Any
2422

25-
import numpy
2623
import packaging.version
2724
import pandas
28-
from pandas.api.types import is_integer
2925
import pandas.compat.numpy.function
3026
import pandas.core.nanops
3127

@@ -36,17 +32,15 @@
3632
nanany = pandas.core.nanops.nanany
3733
nanmax = pandas.core.nanops.nanmax
3834
nanmin = pandas.core.nanops.nanmin
35+
nanmedian = pandas.core.nanops.nanmedian
3936
numpy_validate_all = pandas.compat.numpy.function.validate_all
4037
numpy_validate_any = pandas.compat.numpy.function.validate_any
4138
numpy_validate_max = pandas.compat.numpy.function.validate_max
4239
numpy_validate_min = pandas.compat.numpy.function.validate_min
40+
numpy_validate_median = pandas.compat.numpy.function.validate_median
4341

44-
if pandas_release >= (1, 3):
45-
nanmedian = pandas.core.nanops.nanmedian
46-
numpy_validate_median = pandas.compat.numpy.function.validate_median
4742

48-
49-
def import_default(module_name, force=False, default=None):
43+
def import_default(module_name, default=None):
5044
"""
5145
Provide an implementation for a class or function when it can't be imported
5246
@@ -57,16 +51,10 @@ def import_default(module_name, force=False, default=None):
5751
"""
5852

5953
if default is None:
60-
return lambda func_or_class: import_default(module_name, force, func_or_class)
61-
62-
if force:
63-
return default
54+
return lambda func_or_class: import_default(module_name, func_or_class)
6455

6556
name = default.__name__
66-
try:
67-
module = __import__(module_name, {}, {}, [name])
68-
except ModuleNotFoundError:
69-
return default
57+
module = __import__(module_name, {}, {}, [name])
7058

7159
return getattr(module, name, default)
7260

@@ -77,105 +65,11 @@ def import_default(module_name, force=False, default=None):
7765
# 'datetime.date'
7866
@import_default("pandas.core.arraylike")
7967
class OpsMixin:
80-
def _cmp_method(self, other, op): # pragma: NO COVER
81-
return NotImplemented
82-
83-
def __eq__(self, other):
84-
return self._cmp_method(other, operator.eq)
85-
86-
def __ne__(self, other):
87-
return self._cmp_method(other, operator.ne)
88-
89-
def __lt__(self, other):
90-
return self._cmp_method(other, operator.lt)
91-
92-
def __le__(self, other):
93-
return self._cmp_method(other, operator.le)
94-
95-
def __gt__(self, other):
96-
return self._cmp_method(other, operator.gt)
97-
98-
def __ge__(self, other):
99-
return self._cmp_method(other, operator.ge)
100-
101-
__add__ = __radd__ = __sub__ = lambda self, other: NotImplemented
68+
pass
10269

10370

10471
# TODO: use public API once pandas 1.5 / 2.x is released.
10572
# See: https://github.com/pandas-dev/pandas/pull/45544
106-
@import_default("pandas.core.arrays._mixins", pandas_release < (1, 3))
73+
@import_default("pandas.core.arrays._mixins")
10774
class NDArrayBackedExtensionArray(pandas.core.arrays.base.ExtensionArray):
108-
def __init__(self, values, dtype):
109-
assert isinstance(values, numpy.ndarray)
110-
self._ndarray = values
111-
self._dtype = dtype
112-
113-
@classmethod
114-
def _from_backing_data(cls, data):
115-
return cls(data, data.dtype)
116-
117-
def __getitem__(self, index):
118-
value = self._ndarray[index]
119-
if is_integer(index):
120-
return self._box_func(value)
121-
return self.__class__(value, self._dtype)
122-
123-
def __setitem__(self, index, value):
124-
self._ndarray[index] = self._validate_setitem_value(value)
125-
126-
def __len__(self):
127-
return len(self._ndarray)
128-
129-
@property
130-
def shape(self):
131-
return self._ndarray.shape
132-
133-
@property
134-
def ndim(self) -> int:
135-
return self._ndarray.ndim
136-
137-
@property
138-
def size(self) -> int:
139-
return self._ndarray.size
140-
141-
@property
142-
def nbytes(self) -> int:
143-
return self._ndarray.nbytes
144-
145-
def copy(self):
146-
return self[:]
147-
148-
def repeat(self, n):
149-
return self.__class__(self._ndarray.repeat(n), self._dtype)
150-
151-
def take(
152-
self,
153-
indices,
154-
*,
155-
allow_fill: bool = False,
156-
fill_value: Any = None,
157-
axis: int = 0,
158-
):
159-
from pandas.core.algorithms import take
160-
161-
if allow_fill:
162-
fill_value = self._validate_scalar(fill_value)
163-
164-
new_data = take(
165-
self._ndarray,
166-
indices,
167-
allow_fill=allow_fill,
168-
fill_value=fill_value,
169-
axis=axis,
170-
)
171-
return self._from_backing_data(new_data)
172-
173-
@classmethod
174-
def _concat_same_type(cls, to_concat, axis=0):
175-
dtypes = {str(x.dtype) for x in to_concat}
176-
if len(dtypes) != 1:
177-
raise ValueError("to_concat must have the same dtype (tz)", dtypes)
178-
179-
new_values = [x._ndarray for x in to_concat]
180-
new_values = numpy.concatenate(new_values, axis=axis)
181-
return to_concat[0]._from_backing_data(new_values) # type: ignore[arg-type]
75+
pass

tests/unit/test_date.py

-12
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323
import pytest
2424

2525
import db_dtypes
26-
from db_dtypes import pandas_backports
2726

2827
VALUE_PARSING_TEST_CASES = [
2928
# Min/Max values for pandas.Timestamp.
@@ -48,9 +47,6 @@
4847
float("nan"),
4948
]
5049

51-
if hasattr(pandas, "NA"):
52-
NULL_VALUE_TEST_CASES.append(pandas.NA)
53-
5450

5551
def test_box_func():
5652
input_array = db_dtypes.DateArray([])
@@ -261,10 +257,6 @@ def test_date_min_2d():
261257
)
262258

263259

264-
@pytest.mark.skipif(
265-
not hasattr(pandas_backports, "numpy_validate_median"),
266-
reason="median not available with this version of pandas",
267-
)
268260
@pytest.mark.parametrize(
269261
"values, expected",
270262
[
@@ -287,10 +279,6 @@ def test_date_median(values, expected):
287279
assert series.median() == expected
288280

289281

290-
@pytest.mark.skipif(
291-
not hasattr(pandas_backports, "numpy_validate_median"),
292-
reason="median not available with this version of pandas",
293-
)
294282
def test_date_median_2d():
295283
input_array = db_dtypes.DateArray(
296284
numpy.array(

tests/unit/test_dtypes.py

+17-25
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,11 @@
1414

1515
import datetime
1616

17-
import packaging.version
1817
import pytest
1918

2019
pd = pytest.importorskip("pandas")
2120
np = pytest.importorskip("numpy")
2221

23-
pandas_release = packaging.version.parse(pd.__version__).release
24-
2522
SAMPLE_RAW_VALUES = dict(
2623
dbdate=(datetime.date(2021, 2, 2), "2021-2-3", pd.NaT),
2724
dbtime=(datetime.time(1, 2, 2), "1:2:3.5", pd.NaT),
@@ -538,39 +535,35 @@ def test_min_max_median(dtype):
538535
a = cls(data)
539536
assert a.min() == sample_values[0]
540537
assert a.max() == sample_values[-1]
541-
if pandas_release >= (1, 3):
542-
assert (
543-
a.median() == datetime.time(1, 2, 4)
544-
if dtype == "dbtime"
545-
else datetime.date(2021, 2, 3)
546-
)
538+
assert (
539+
a.median() == datetime.time(1, 2, 4)
540+
if dtype == "dbtime"
541+
else datetime.date(2021, 2, 3)
542+
)
547543

548544
empty = cls([])
549545
assert empty.min() is pd.NaT
550546
assert empty.max() is pd.NaT
551-
if pandas_release >= (1, 3):
552-
assert empty.median() is pd.NaT
547+
assert empty.median() is pd.NaT
553548
empty = cls([None])
554549
assert empty.min() is pd.NaT
555550
assert empty.max() is pd.NaT
556551
assert empty.min(skipna=False) is pd.NaT
557552
assert empty.max(skipna=False) is pd.NaT
558-
if pandas_release >= (1, 3):
559-
with pytest.warns(RuntimeWarning, match="empty slice"):
560-
# It's weird that we get the warning here, and not
561-
# below. :/
562-
assert empty.median() is pd.NaT
563-
assert empty.median(skipna=False) is pd.NaT
553+
with pytest.warns(RuntimeWarning, match="empty slice"):
554+
# It's weird that we get the warning here, and not
555+
# below. :/
556+
assert empty.median() is pd.NaT
557+
assert empty.median(skipna=False) is pd.NaT
564558

565559
a = _make_one(dtype)
566560
assert a.min() == sample_values[0]
567561
assert a.max() == sample_values[1]
568-
if pandas_release >= (1, 3):
569-
assert (
570-
a.median() == datetime.time(1, 2, 2, 750000)
571-
if dtype == "dbtime"
572-
else datetime.date(2021, 2, 2)
573-
)
562+
assert (
563+
a.median() == datetime.time(1, 2, 2, 750000)
564+
if dtype == "dbtime"
565+
else datetime.date(2021, 2, 2)
566+
)
574567

575568

576569
def test_date_add():
@@ -584,8 +577,7 @@ def test_date_add():
584577
do = pd.DateOffset(days=1)
585578
expect = dates.astype("object") + do
586579
np.testing.assert_array_equal(dates + do, expect)
587-
if pandas_release >= (1, 1):
588-
np.testing.assert_array_equal(do + dates, expect)
580+
np.testing.assert_array_equal(do + dates, expect)
589581

590582
with pytest.raises(TypeError):
591583
dates + times.astype("timedelta64")

tests/unit/test_time.py

-5
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020

2121
# To register the types.
2222
import db_dtypes # noqa
23-
from db_dtypes import pandas_backports
2423

2524

2625
def test_box_func():
@@ -117,10 +116,6 @@ def test_time_parsing_errors(value, error):
117116
pandas.Series([value], dtype="dbtime")
118117

119118

120-
@pytest.mark.skipif(
121-
not hasattr(pandas_backports, "numpy_validate_median"),
122-
reason="median not available with this version of pandas",
123-
)
124119
@pytest.mark.parametrize(
125120
"values, expected",
126121
[

0 commit comments

Comments
 (0)