Skip to content

Commit 66f3f0b

Browse files
chalmerlowegoogle-labs-jules[bot]gcf-owl-bot[bot]
authored
deps!: Drop support for Python 3.7 and 3.8 (AI Experiment) (#337)
* feat: Drop support for Python 3.7 and 3.8 Removes support for Python 3.7 and 3.8, establishing Python 3.9 as the new minimum supported version. This change involves: - Updating `python_requires` and classifiers in `setup.py`. - Modifying Python versions in `noxfile.py` (default, unit tests, system tests) and ensuring constraint file logic remains correct. - Updating the GitHub Actions workflow (`unittest.yml`) matrix, runner, and coverage job version. - Deleting constraint files for Python 3.7 and 3.8 (`testing/constraints-3.7.txt`, `testing/constraints-3.8.txt`). - Removing Kokoro sample configuration directories (`.kokoro/samples/python3.7/`, `.kokoro/samples/python3.8/`). - Updating supported version mentions in `README.rst`. - Removing 3.7 and 3.8 from the `ALL_VERSIONS` list in `samples/snippets/noxfile.py`. * Updates python version in lint.yml * Updates owlbot, removing reference to 3.8 * Updates CONTRIBUTING.rst * updates pytest warnings * Removes test_samples-impl ref to older virtualenv package * Removes references to pandas older than 1.5.0 * Removes pandas older than 1.5 and misc changes * updates pandas in setup.py * more updates related to pandas * still broken * Updates FutureWarning tests to account for unittest coverage * Updates json array type tests to account for unittest coverage * updates python version checks to ensure coverage * update json test for unittest coverage * Update pandas_backports unittests to ensure coverage * Updates per review comments * moves class from version specific compliance file to generic file * Removes weird cut and paste error * fix linting errors * updates import statement to ensure import of JSONArrowType * Revise required github status checks * update linting * temporarily marking a class as no cover * more updates * marked several snippets as pragma no cover * updates linting * Updates constraints and setup.py * migrates class from one time compliance file to another * updating pyarrow version * Updates linting * removes determine all and module reload tests * updates re: ndarrybackedextensionarray * testing blacken as part of owlbot processing using 3.8 * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md * updates blacken to 3.10 * update python version in lint.yml * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md * updates owlbot.py * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md * updates owlbot.py * testing lint.yml * testing linting issue * testing linting issue * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md * updates lint_setup session * Update noxfile.py --------- Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com> Co-authored-by: Owl Bot <gcf-owl-bot[bot]@users.noreply.github.com>
1 parent 158243b commit 66f3f0b

23 files changed

+97
-260
lines changed

.github/sync-repo-settings.yaml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ branchProtectionRules:
1111
- 'cla/google'
1212
- 'docs'
1313
- 'lint'
14-
- 'unit (3.8)'
1514
- 'unit (3.9)'
1615
- 'unit (3.10)'
1716
- 'unit (3.11)'

.github/workflows/unittest.yml

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,11 @@ on:
55
name: unittest
66
jobs:
77
unit:
8-
# TODO(https://github.com/googleapis/gapic-generator-python/issues/2303): use `ubuntu-latest` once this bug is fixed.
9-
# Use ubuntu-22.04 until Python 3.7 is removed from the test matrix
10-
# https://docs.github.com/en/actions/using-github-hosted-runners/using-github-hosted-runners/about-github-hosted-runners#standard-github-hosted-runners-for-public-repositories
11-
runs-on: ubuntu-22.04
8+
# Use `ubuntu-latest` runner.
9+
runs-on: ubuntu-latest
1210
strategy:
1311
matrix:
14-
python: ['3.8', '3.9', '3.10', '3.11', '3.12', '3.13']
12+
python: ['3.9', '3.10', '3.11', '3.12', '3.13']
1513
steps:
1614
- name: Checkout
1715
uses: actions/checkout@v4
@@ -103,7 +101,7 @@ jobs:
103101
- name: Setup Python
104102
uses: actions/setup-python@v5
105103
with:
106-
python-version: "3.8"
104+
python-version: "3.9"
107105
- name: Install coverage
108106
run: |
109107
python -m pip install --upgrade setuptools pip wheel

CONTRIBUTING.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -143,12 +143,12 @@ Running System Tests
143143
$ nox -s system
144144

145145
# Run a single system test
146-
$ nox -s system-3.8 -- -k <name of test>
146+
$ nox -s system-3.9 -- -k <name of test>
147147

148148

149149
.. note::
150150

151-
System tests are only configured to run under Python 3.8.
151+
System tests are only configured to run under Python 3.9.
152152
For expediency, we do not run them in older versions of Python 3.
153153

154154
This alone will not run the tests. You'll need to change some local

README.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,11 @@ dependencies.
3434

3535
Supported Python Versions
3636
^^^^^^^^^^^^^^^^^^^^^^^^^
37-
Python >= 3.7
37+
Python >= 3.9
3838

3939
Unsupported Python Versions
4040
^^^^^^^^^^^^^^^^^^^^^^^^^^^
41-
Python <= 3.6.
41+
Python <= 3.8.
4242

4343

4444
Mac/Linux

db_dtypes/__init__.py

Lines changed: 11 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,14 @@
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
32-
from db_dtypes.version import __version__
31+
from db_dtypes.json import JSONArray, JSONDtype, JSONArrowType # noqa: F401
3332

3433
from . import _versions_helpers
3534

@@ -47,15 +46,6 @@
4746
_NP_BOX_DTYPE = "datetime64[us]"
4847

4948

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, JSONArrowType, JSONDtype
54-
else:
55-
JSONArray = None
56-
JSONDtype = None
57-
58-
5949
@pandas.api.extensions.register_extension_dtype
6050
class TimeDtype(core.BaseDatetimeDtype):
6151
"""
@@ -364,23 +354,13 @@ def _check_python_version():
364354

365355
_check_python_version()
366356

367-
368-
if not JSONArray or not JSONDtype:
369-
__all__ = [
370-
"__version__",
371-
"DateArray",
372-
"DateDtype",
373-
"TimeArray",
374-
"TimeDtype",
375-
]
376-
else:
377-
__all__ = [
378-
"__version__",
379-
"DateArray",
380-
"DateDtype",
381-
"JSONDtype",
382-
"JSONArray",
383-
"JSONArrowType",
384-
"TimeArray",
385-
"TimeDtype",
386-
]
357+
__all__ = [
358+
"__version__",
359+
"DateArray",
360+
"DateDtype",
361+
"TimeArray",
362+
"TimeDtype",
363+
"JSONDtype",
364+
"JSONArray",
365+
"JSONArrowType",
366+
]

db_dtypes/core.py

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import pandas
1919
import pandas.api.extensions
2020
from pandas.api.types import is_dtype_equal, is_list_like, is_scalar, pandas_dtype
21+
from pandas.core.arrays import _mixins
2122

2223
from db_dtypes import pandas_backports
2324

@@ -42,9 +43,7 @@ def construct_from_string(cls, name: str):
4243
return cls()
4344

4445

45-
class BaseDatetimeArray(
46-
pandas_backports.OpsMixin, pandas_backports.NDArrayBackedExtensionArray
47-
):
46+
class BaseDatetimeArray(pandas_backports.OpsMixin, _mixins.NDArrayBackedExtensionArray):
4847
# scalar used to denote NA value inside our self._ndarray, e.g. -1 for
4948
# Categorical, iNaT for Period. Outside of object dtype, self.isna() should
5049
# be exactly locations in self._ndarray with _internal_fill_value. See:
@@ -186,9 +185,6 @@ def median(
186185
keepdims: bool = False,
187186
skipna: bool = True,
188187
):
189-
if not hasattr(pandas_backports, "numpy_validate_median"):
190-
raise NotImplementedError("Need pandas 1.3 or later to calculate median.")
191-
192188
pandas_backports.numpy_validate_median(
193189
(),
194190
{"out": out, "overwrite_input": overwrite_input, "keepdims": keepdims},

db_dtypes/pandas_backports.py

Lines changed: 3 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -19,18 +19,13 @@
1919
the versions in the later versions of pandas.
2020
"""
2121

22-
from typing import Any
23-
24-
import numpy
2522
import packaging.version
2623
import pandas
27-
from pandas.api.types import is_integer
2824
import pandas.compat.numpy.function
29-
import pandas.core.nanops
3025

3126
pandas_release = packaging.version.parse(pandas.__version__).release
3227

33-
# Create aliases for private methods in case they move in a future version.
28+
# # Create aliases for private methods in case they move in a future version.
3429
nanall = pandas.core.nanops.nanall
3530
nanany = pandas.core.nanops.nanany
3631
nanmax = pandas.core.nanops.nanmax
@@ -40,9 +35,8 @@
4035
numpy_validate_max = pandas.compat.numpy.function.validate_max
4136
numpy_validate_min = pandas.compat.numpy.function.validate_min
4237

43-
if pandas_release >= (1, 3):
44-
nanmedian = pandas.core.nanops.nanmedian
45-
numpy_validate_median = pandas.compat.numpy.function.validate_median
38+
nanmedian = pandas.core.nanops.nanmedian
39+
numpy_validate_median = pandas.compat.numpy.function.validate_median
4640

4741

4842
def import_default(module_name, force=False, default=None):
@@ -78,83 +72,3 @@ def import_default(module_name, force=False, default=None):
7872
class OpsMixin:
7973
def _cmp_method(self, other, op): # pragma: NO COVER
8074
return NotImplemented
81-
82-
83-
# TODO: use public API once pandas 1.5 / 2.x is released.
84-
# See: https://github.com/pandas-dev/pandas/pull/45544
85-
@import_default("pandas.core.arrays._mixins", pandas_release < (1, 3))
86-
class NDArrayBackedExtensionArray(pandas.core.arrays.base.ExtensionArray):
87-
def __init__(self, values, dtype):
88-
assert isinstance(values, numpy.ndarray)
89-
self._ndarray = values
90-
self._dtype = dtype
91-
92-
@classmethod
93-
def _from_backing_data(cls, data):
94-
return cls(data, data.dtype)
95-
96-
def __getitem__(self, index):
97-
value = self._ndarray[index]
98-
if is_integer(index):
99-
return self._box_func(value)
100-
return self.__class__(value, self._dtype)
101-
102-
def __setitem__(self, index, value):
103-
self._ndarray[index] = self._validate_setitem_value(value)
104-
105-
def __len__(self):
106-
return len(self._ndarray)
107-
108-
@property
109-
def shape(self):
110-
return self._ndarray.shape
111-
112-
@property
113-
def ndim(self) -> int:
114-
return self._ndarray.ndim
115-
116-
@property
117-
def size(self) -> int:
118-
return self._ndarray.size
119-
120-
@property
121-
def nbytes(self) -> int:
122-
return self._ndarray.nbytes
123-
124-
def copy(self):
125-
return self[:]
126-
127-
def repeat(self, n):
128-
return self.__class__(self._ndarray.repeat(n), self._dtype)
129-
130-
def take(
131-
self,
132-
indices,
133-
*,
134-
allow_fill: bool = False,
135-
fill_value: Any = None,
136-
axis: int = 0,
137-
):
138-
from pandas.core.algorithms import take
139-
140-
if allow_fill:
141-
fill_value = self._validate_scalar(fill_value)
142-
143-
new_data = take(
144-
self._ndarray,
145-
indices,
146-
allow_fill=allow_fill,
147-
fill_value=fill_value,
148-
axis=axis,
149-
)
150-
return self._from_backing_data(new_data)
151-
152-
@classmethod
153-
def _concat_same_type(cls, to_concat, axis=0):
154-
dtypes = {str(x.dtype) for x in to_concat}
155-
if len(dtypes) != 1:
156-
raise ValueError("to_concat must have the same dtype (tz)", dtypes)
157-
158-
new_values = [x._ndarray for x in to_concat]
159-
new_values = numpy.concatenate(new_values, axis=axis)
160-
return to_concat[0]._from_backing_data(new_values) # type: ignore[arg-type]

db_dtypes/version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,4 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15-
__version__ = "1.4.2"
15+
__version__ = "1.4.2" # pragma: NO COVER

noxfile.py

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,9 @@
3232
ISORT_VERSION = "isort==5.11.0"
3333
LINT_PATHS = ["docs", "db_dtypes", "tests", "noxfile.py", "setup.py"]
3434

35-
DEFAULT_PYTHON_VERSION = "3.8"
35+
DEFAULT_PYTHON_VERSION = "3.9"
3636

3737
UNIT_TEST_PYTHON_VERSIONS: List[str] = [
38-
"3.7",
39-
"3.8",
4038
"3.9",
4139
"3.10",
4240
"3.11",
@@ -56,7 +54,7 @@
5654
UNIT_TEST_EXTRAS: List[str] = []
5755
UNIT_TEST_EXTRAS_BY_PYTHON: Dict[str, List[str]] = {}
5856

59-
SYSTEM_TEST_PYTHON_VERSIONS: List[str] = ["3.8"]
57+
SYSTEM_TEST_PYTHON_VERSIONS: List[str] = ["3.9"]
6058
SYSTEM_TEST_STANDARD_DEPENDENCIES: List[str] = [
6159
"mock",
6260
"pytest",
@@ -88,7 +86,10 @@
8886
nox.options.error_on_missing_interpreters = True
8987

9088

91-
@nox.session(python=DEFAULT_PYTHON_VERSION)
89+
# TODO: the linting process still uses python 3.8.
90+
# As soon as that gets upgraded, we should be able to revert this session
91+
# to using the DEFAULT_PYTHON_VERSION.
92+
@nox.session(python="3.8")
9293
def lint(session):
9394
"""Run linters.
9495
@@ -105,7 +106,11 @@ def lint(session):
105106
session.run("flake8", "db_dtypes", "tests")
106107

107108

108-
@nox.session(python=DEFAULT_PYTHON_VERSION)
109+
# TODO: the owlbot-python docker image still has python 3.8 installed (
110+
# and only 3.8).
111+
# As soon as that gets upgraded, we should be able to revert this session
112+
# to using the DEFAULT_PYTHON_VERSION.
113+
@nox.session(python="3.8")
109114
def blacken(session):
110115
"""Run black. Format code to uniform standard."""
111116
session.install(BLACK_VERSION)
@@ -137,7 +142,10 @@ def format(session):
137142
)
138143

139144

140-
@nox.session(python=DEFAULT_PYTHON_VERSION)
145+
# TODO: the linting process still uses python 3.8.
146+
# As soon as that gets upgraded, we should be able to revert this session
147+
# to using the DEFAULT_PYTHON_VERSION.
148+
@nox.session(python="3.8")
141149
def lint_setup_py(session):
142150
"""Verify that setup.py is valid (including RST check)."""
143151
session.install("docutils", "pygments")

owlbot.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
# Add templated files
2929
# ----------------------------------------------------------------------------
3030
templated_files = common.py_library(
31-
system_test_python_versions=["3.8"],
31+
system_test_python_versions=["3.9"],
3232
cov_level=100,
3333
intersphinx_dependencies={
3434
"pandas": "https://pandas.pydata.org/pandas-docs/stable/"

pytest.ini

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,6 @@
22
filterwarnings =
33
# treat all warnings as errors
44
error
5-
# Remove once support for python 3.7 and 3.8 is dropped
6-
# Ignore warnings from older versions of pandas which still have python 3.7/3.8 support
7-
ignore:.*distutils Version classes are deprecated:DeprecationWarning
8-
ignore:.*resolve package from __spec__ or __package__, falling back on __name__ and __path__:ImportWarning
9-
# Remove once https://github.com/dateutil/dateutil/issues/1314 is fixed
10-
# dateutil is a dependency of pandas
11-
ignore:datetime.datetime.utcfromtimestamp\(\) is deprecated:DeprecationWarning:dateutil.tz.tz
125
# Remove once https://github.com/googleapis/python-db-dtypes-pandas/issues/227 is fixed
136
ignore:.*any.*with datetime64 dtypes is deprecated and will raise in a future version:FutureWarning
147
ignore:.*all.*with datetime64 dtypes is deprecated and will raise in a future version:FutureWarning
Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1 @@
1-
pytest===7.4.4; python_version == '3.7' # prevents dependabot from upgrading it
2-
pytest==8.3.3; python_version > '3.7'
1+
pytest==8.3.5

setup.py

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,10 @@
3030
release_status = "Development Status :: 5 - Production/Stable"
3131

3232
dependencies = [
33-
"packaging >= 17.0",
34-
"pandas >= 1.2.0",
35-
"pyarrow>=3.0.0",
36-
"numpy >= 1.16.6",
33+
"numpy >= 1.24.0",
34+
"packaging >= 24.2.0",
35+
"pandas >= 1.5.3",
36+
"pyarrow >= 13.0.0",
3737
]
3838

3939
package_root = os.path.abspath(os.path.dirname(__file__))
@@ -63,8 +63,6 @@ def readme():
6363
"License :: OSI Approved :: Apache Software License",
6464
"Programming Language :: Python",
6565
"Programming Language :: Python :: 3",
66-
"Programming Language :: Python :: 3.7",
67-
"Programming Language :: Python :: 3.8",
6866
"Programming Language :: Python :: 3.9",
6967
"Programming Language :: Python :: 3.10",
7068
"Programming Language :: Python :: 3.11",
@@ -75,6 +73,6 @@ def readme():
7573
],
7674
platforms="Posix; MacOS X; Windows",
7775
install_requires=dependencies,
78-
python_requires=">=3.7",
76+
python_requires=">=3.9",
7977
tests_require=["pytest"],
8078
)

0 commit comments

Comments
 (0)