🌐 AI搜索 & 代理 主页
Skip to content

Commit c9a8f95

Browse files
lithomas1mroeschke
andauthored
CI: Test Python 3.12 (#53743)
* CI: Test Python 3.12 * Update unit-tests.yml * Update config.yml * update * fix condition * fix some tests * Remove wheel building for Python 3.12 * fix more * Use timezone.utc * Address typing, utcfromtimestamp * fix some slice changes * fix all indexing bugs? * fix import * go for green * disable macos for now, fix other tests * Update indexing.py * finally fix? * Update expr.py * Update pandas/tests/computation/test_eval.py Co-authored-by: Matthew Roeschke <10647082+mroeschke@users.noreply.github.com> * Update test_eval.py * Update test_eval.py * fixes * formatting --------- Co-authored-by: Matthew Roeschke <10647082+mroeschke@users.noreply.github.com>
1 parent ee5cf2c commit c9a8f95

File tree

22 files changed

+134
-47
lines changed

22 files changed

+134
-47
lines changed

.circleci/config.yml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,8 @@ jobs:
4747
- run:
4848
name: Build aarch64 wheels
4949
command: |
50-
pip3 install cibuildwheel==2.12.1
51-
cibuildwheel --output-dir wheelhouse
50+
pip3 install cibuildwheel==2.14.1
51+
cibuildwheel --prerelease-pythons --output-dir wheelhouse
5252
environment:
5353
CIBW_BUILD: << parameters.cibw-build >>
5454

@@ -91,4 +91,5 @@ workflows:
9191
only: /^v.*/
9292
matrix:
9393
parameters:
94-
cibw-build: ["cp39-manylinux_aarch64", "cp310-manylinux_aarch64", "cp311-manylinux_aarch64"]
94+
# TODO: Enable Python 3.12 wheels when numpy releases a version that supports Python 3.12
95+
cibw-build: ["cp39-manylinux_aarch64", "cp310-manylinux_aarch64", "cp311-manylinux_aarch64"]#, "cp312-manylinux_aarch64"]

.github/workflows/unit-tests.yml

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -311,12 +311,16 @@ jobs:
311311
# To freeze this file, uncomment out the ``if: false`` condition, and migrate the jobs
312312
# to the corresponding posix/windows-macos/sdist etc. workflows.
313313
# Feel free to modify this comment as necessary.
314-
if: false # Uncomment this to freeze the workflow, comment it to unfreeze
314+
#if: false # Uncomment this to freeze the workflow, comment it to unfreeze
315315
runs-on: ${{ matrix.os }}
316316
strategy:
317317
fail-fast: false
318318
matrix:
319-
os: [ubuntu-22.04, macOS-latest, windows-latest]
319+
# TODO: Disable macOS for now, Github Actions bug where python is not
320+
# symlinked correctly to 3.12
321+
# xref https://github.com/actions/setup-python/issues/701
322+
#os: [ubuntu-22.04, macOS-latest, windows-latest]
323+
os: [ubuntu-22.04, windows-latest]
320324

321325
timeout-minutes: 180
322326

@@ -340,21 +344,21 @@ jobs:
340344
- name: Set up Python Dev Version
341345
uses: actions/setup-python@v4
342346
with:
343-
python-version: '3.11-dev'
347+
python-version: '3.12-dev'
344348

345349
- name: Install dependencies
346350
run: |
347351
python --version
348-
python -m pip install --upgrade pip setuptools wheel
352+
python -m pip install --upgrade pip setuptools wheel meson[ninja]==1.0.1 meson-python==0.13.1
349353
python -m pip install --pre --extra-index-url https://pypi.anaconda.org/scientific-python-nightly-wheels/simple numpy
350354
python -m pip install git+https://github.com/nedbat/coveragepy.git
351355
python -m pip install versioneer[toml]
352-
python -m pip install python-dateutil pytz cython hypothesis>=6.46.1 pytest>=7.3.2 pytest-xdist>=2.2.0 pytest-cov pytest-asyncio>=0.17
356+
python -m pip install python-dateutil pytz tzdata cython hypothesis>=6.46.1 pytest>=7.3.2 pytest-xdist>=2.2.0 pytest-cov pytest-asyncio>=0.17
353357
python -m pip list
354358
355359
- name: Build Pandas
356360
run: |
357-
python -m pip install -e . --no-build-isolation --no-index
361+
python -m pip install -ve . --no-build-isolation --no-index
358362
359363
- name: Build Version
360364
run: |

.github/workflows/wheels.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,8 @@ jobs:
9393
- [macos-12, macosx_*]
9494
- [windows-2022, win_amd64]
9595
# TODO: support PyPy?
96-
python: [["cp39", "3.9"], ["cp310", "3.10"], ["cp311", "3.11"]]
96+
# TODO: Enable Python 3.12 wheels when numpy releases a version that supports Python 3.12
97+
python: [["cp39", "3.9"], ["cp310", "3.10"], ["cp311", "3.11"]]#, ["cp312", "3.12"]]
9798
env:
9899
IS_PUSH: ${{ github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') }}
99100
IS_SCHEDULE_DISPATCH: ${{ github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' }}
@@ -117,6 +118,7 @@ jobs:
117118
#with:
118119
# package-dir: ./dist/${{ needs.build_sdist.outputs.sdist_file }}
119120
env:
121+
CIBW_PRERELEASE_PYTHONS: True
120122
CIBW_BUILD: ${{ matrix.python[0] }}-${{ matrix.buildplat[1] }}
121123

122124
- name: Set up Python

meson.build

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,13 @@ versioneer = files('generate_version.py')
2727
add_project_arguments('-DNPY_NO_DEPRECATED_API=0', language : 'c')
2828
add_project_arguments('-DNPY_NO_DEPRECATED_API=0', language : 'cpp')
2929

30+
# Allow supporting older numpys than the version compiled against
31+
# Set the define to the min supported version of numpy for pandas
32+
# e.g. right now this is targeting numpy 1.21+
33+
add_project_arguments('-DNPY_TARGET_VERSION=NPY_1_21_API_VERSION', language : 'c')
34+
add_project_arguments('-DNPY_TARGET_VERSION=NPY_1_21_API_VERSION', language : 'cpp')
35+
36+
3037
if fs.exists('_version_meson.py')
3138
py.install_sources('_version_meson.py', pure: false, subdir: 'pandas')
3239
else

pandas/compat/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
ISMUSL,
2020
PY310,
2121
PY311,
22+
PY312,
2223
PYPY,
2324
)
2425
import pandas.compat.compressors
@@ -189,5 +190,6 @@ def get_bz2_file() -> type[pandas.compat.compressors.BZ2File]:
189190
"ISMUSL",
190191
"PY310",
191192
"PY311",
193+
"PY312",
192194
"PYPY",
193195
]

pandas/compat/_constants.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
PY310 = sys.version_info >= (3, 10)
1717
PY311 = sys.version_info >= (3, 11)
18+
PY312 = sys.version_info >= (3, 12)
1819
PYPY = platform.python_implementation() == "PyPy"
1920
ISMUSL = "musl" in (sysconfig.get_config_var("HOST_GNU_TYPE") or "")
2021
REF_COUNT = 2 if PY311 else 3
@@ -24,5 +25,6 @@
2425
"ISMUSL",
2526
"PY310",
2627
"PY311",
28+
"PY312",
2729
"PYPY",
2830
]

pandas/core/computation/expr.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -543,15 +543,18 @@ def visit_UnaryOp(self, node, **kwargs):
543543
def visit_Name(self, node, **kwargs):
544544
return self.term_type(node.id, self.env, **kwargs)
545545

546+
# TODO(py314): deprecated since Python 3.8. Remove after Python 3.14 is min
546547
def visit_NameConstant(self, node, **kwargs) -> Term:
547548
return self.const_type(node.value, self.env)
548549

550+
# TODO(py314): deprecated since Python 3.8. Remove after Python 3.14 is min
549551
def visit_Num(self, node, **kwargs) -> Term:
550-
return self.const_type(node.n, self.env)
552+
return self.const_type(node.value, self.env)
551553

552554
def visit_Constant(self, node, **kwargs) -> Term:
553-
return self.const_type(node.n, self.env)
555+
return self.const_type(node.value, self.env)
554556

557+
# TODO(py314): deprecated since Python 3.8. Remove after Python 3.14 is min
555558
def visit_Str(self, node, **kwargs):
556559
name = self.env.add_tmp(node.s)
557560
return self.term_type(name, self.env)

pandas/core/indexes/base.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from __future__ import annotations
22

3+
from collections import abc
34
from datetime import datetime
45
import functools
56
from itertools import zip_longest
@@ -3788,6 +3789,11 @@ def get_loc(self, key):
37883789
try:
37893790
return self._engine.get_loc(casted_key)
37903791
except KeyError as err:
3792+
if isinstance(casted_key, slice) or (
3793+
isinstance(casted_key, abc.Iterable)
3794+
and any(isinstance(x, slice) for x in casted_key)
3795+
):
3796+
raise InvalidIndexError(key)
37913797
raise KeyError(key) from err
37923798
except TypeError:
37933799
# If we have a listlike key, _check_indexing_error will raise

pandas/core/indexes/datetimelike.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,10 @@
3232
to_offset,
3333
)
3434
from pandas.compat.numpy import function as nv
35-
from pandas.errors import NullFrequencyError
35+
from pandas.errors import (
36+
InvalidIndexError,
37+
NullFrequencyError,
38+
)
3639
from pandas.util._decorators import (
3740
Appender,
3841
cache_readonly,
@@ -165,7 +168,7 @@ def __contains__(self, key: Any) -> bool:
165168
hash(key)
166169
try:
167170
self.get_loc(key)
168-
except (KeyError, TypeError, ValueError):
171+
except (KeyError, TypeError, ValueError, InvalidIndexError):
169172
return False
170173
return True
171174

pandas/core/indexing.py

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -742,7 +742,12 @@ def _get_setitem_indexer(self, key):
742742

743743
ax = self.obj._get_axis(0)
744744

745-
if isinstance(ax, MultiIndex) and self.name != "iloc" and is_hashable(key):
745+
if (
746+
isinstance(ax, MultiIndex)
747+
and self.name != "iloc"
748+
and is_hashable(key)
749+
and not isinstance(key, slice)
750+
):
746751
with suppress(KeyError, InvalidIndexError):
747752
# TypeError e.g. passed a bool
748753
return ax.get_loc(key)
@@ -1063,6 +1068,14 @@ def _getitem_nested_tuple(self, tup: tuple):
10631068
# we have a nested tuple so have at least 1 multi-index level
10641069
# we should be able to match up the dimensionality here
10651070

1071+
def _contains_slice(x: object) -> bool:
1072+
# Check if object is a slice or a tuple containing a slice
1073+
if isinstance(x, tuple):
1074+
return any(isinstance(v, slice) for v in x)
1075+
elif isinstance(x, slice):
1076+
return True
1077+
return False
1078+
10661079
for key in tup:
10671080
check_dict_or_set_indexers(key)
10681081

@@ -1073,7 +1086,10 @@ def _getitem_nested_tuple(self, tup: tuple):
10731086
if self.name != "loc":
10741087
# This should never be reached, but let's be explicit about it
10751088
raise ValueError("Too many indices") # pragma: no cover
1076-
if all(is_hashable(x) or com.is_null_slice(x) for x in tup):
1089+
if all(
1090+
(is_hashable(x) and not _contains_slice(x)) or com.is_null_slice(x)
1091+
for x in tup
1092+
):
10771093
# GH#10521 Series should reduce MultiIndex dimensions instead of
10781094
# DataFrame, IndexingError is not raised when slice(None,None,None)
10791095
# with one row.
@@ -1422,7 +1438,15 @@ def _convert_to_indexer(self, key, axis: AxisInt):
14221438
):
14231439
raise IndexingError("Too many indexers")
14241440

1425-
if is_scalar(key) or (isinstance(labels, MultiIndex) and is_hashable(key)):
1441+
# Slices are not valid keys passed in by the user,
1442+
# even though they are hashable in Python 3.12
1443+
contains_slice = False
1444+
if isinstance(key, tuple):
1445+
contains_slice = any(isinstance(v, slice) for v in key)
1446+
1447+
if is_scalar(key) or (
1448+
isinstance(labels, MultiIndex) and is_hashable(key) and not contains_slice
1449+
):
14261450
# Otherwise get_loc will raise InvalidIndexError
14271451

14281452
# if we are a label return me

0 commit comments

Comments
 (0)