Skip to content

Commit eb6b283

Browse files
committed
2 parents 3954c84 + 1d71fe6 commit eb6b283

36 files changed

+1313
-74
lines changed

.github/actions/run-tests/action.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ runs:
1414
if: failure()
1515

1616
- name: Upload coverage to Codecov
17-
uses: codecov/codecov-action@v4
17+
uses: codecov/codecov-action@v5
1818
with:
1919
flags: unittests
2020
name: codecov-pandas

.github/actions/setup-conda/action.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ runs:
77
using: composite
88
steps:
99
- name: Install ${{ inputs.environment-file }}
10-
uses: mamba-org/setup-micromamba@v1
10+
uses: mamba-org/setup-micromamba@v2
1111
with:
1212
environment-file: ${{ inputs.environment-file }}
1313
environment-name: test

.github/workflows/docbuild-and-upload.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,10 @@ jobs:
5959
- name: Build documentation
6060
run: doc/make.py --warnings-are-errors
6161

62+
- name: Build the interactive terminal
63+
working-directory: web/interactive_terminal
64+
run: jupyter lite build
65+
6266
- name: Build documentation zip
6367
run: doc/make.py zip_html
6468

.github/workflows/wheels.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ jobs:
153153
run: echo "sdist_name=$(cd ./dist && ls -d */)" >> "$GITHUB_ENV"
154154

155155
- name: Build wheels
156-
uses: pypa/cibuildwheel@v2.22.0
156+
uses: pypa/cibuildwheel@v2.23.0
157157
with:
158158
package-dir: ./dist/${{ startsWith(matrix.buildplat[1], 'macosx') && env.sdist_name || needs.build_sdist.outputs.sdist_file }}
159159
env:

.pre-commit-config.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ ci:
1919
skip: [pyright, mypy]
2020
repos:
2121
- repo: https://github.com/astral-sh/ruff-pre-commit
22-
rev: v0.9.4
22+
rev: v0.9.9
2323
hooks:
2424
- id: ruff
2525
args: [--exit-non-zero-on-fix]
@@ -70,7 +70,7 @@ repos:
7070
- id: trailing-whitespace
7171
args: [--markdown-linebreak-ext=md]
7272
- repo: https://github.com/PyCQA/isort
73-
rev: 6.0.0
73+
rev: 6.0.1
7474
hooks:
7575
- id: isort
7676
- repo: https://github.com/asottile/pyupgrade

doc/source/user_guide/text.rst

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ Behavior differences
9090
These are places where the behavior of ``StringDtype`` objects differ from
9191
``object`` dtype:
9292

93-
l. For ``StringDtype``, :ref:`string accessor methods<api.series.str>`
93+
1. For ``StringDtype``, :ref:`string accessor methods<api.series.str>`
9494
that return **numeric** output will always return a nullable integer dtype,
9595
rather than either int or float dtype, depending on the presence of NA values.
9696
Methods returning **boolean** output will return a nullable boolean dtype.
@@ -332,8 +332,8 @@ regular expression object will raise a ``ValueError``.
332332
---------------------------------------------------------------------------
333333
ValueError: case and flags cannot be set when pat is a compiled regex
334334

335-
``removeprefix`` and ``removesuffix`` have the same effect as ``str.removeprefix`` and ``str.removesuffix`` added in Python 3.9
336-
<https://docs.python.org/3/library/stdtypes.html#str.removeprefix>`__:
335+
``removeprefix`` and ``removesuffix`` have the same effect as ``str.removeprefix`` and ``str.removesuffix`` added in
336+
`Python 3.9 <https://docs.python.org/3/library/stdtypes.html#str.removeprefix>`__:
337337

338338
.. versionadded:: 1.4.0
339339

doc/source/whatsnew/v3.0.0.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,10 @@ Other enhancements
7272
- :meth:`pandas.concat` will raise a ``ValueError`` when ``ignore_index=True`` and ``keys`` is not ``None`` (:issue:`59274`)
7373
- :py:class:`frozenset` elements in pandas objects are now natively printed (:issue:`60690`)
7474
- Add ``"delete_rows"`` option to ``if_exists`` argument in :meth:`DataFrame.to_sql` deleting all records of the table before inserting data (:issue:`37210`).
75+
- Added half-year offset classes :class:`HalfYearBegin`, :class:`HalfYearEnd`, :class:`BHalfYearBegin` and :class:`BHalfYearEnd` (:issue:`60928`)
7576
- Errors occurring during SQL I/O will now throw a generic :class:`.DatabaseError` instead of the raw Exception type from the underlying driver manager library (:issue:`60748`)
7677
- Implemented :meth:`Series.str.isascii` and :meth:`Series.str.isascii` (:issue:`59091`)
78+
- Improved deprecation message for offset aliases (:issue:`60820`)
7779
- Multiplying two :class:`DateOffset` objects will now raise a ``TypeError`` instead of a ``RecursionError`` (:issue:`59442`)
7880
- Restore support for reading Stata 104-format and enable reading 103-format dta files (:issue:`58554`)
7981
- Support passing a :class:`Iterable[Hashable]` input to :meth:`DataFrame.drop_duplicates` (:issue:`59237`)
@@ -614,7 +616,9 @@ Performance improvements
614616
- Performance improvement in :meth:`RangeIndex.take` returning a :class:`RangeIndex` instead of a :class:`Index` when possible. (:issue:`57445`, :issue:`57752`)
615617
- Performance improvement in :func:`merge` if hash-join can be used (:issue:`57970`)
616618
- Performance improvement in :meth:`CategoricalDtype.update_dtype` when ``dtype`` is a :class:`CategoricalDtype` with non ``None`` categories and ordered (:issue:`59647`)
619+
- Performance improvement in :meth:`DataFrame.__getitem__` when ``key`` is a :class:`DataFrame` with many columns (:issue:`61010`)
617620
- Performance improvement in :meth:`DataFrame.astype` when converting to extension floating dtypes, e.g. "Float64" (:issue:`60066`)
621+
- Performance improvement in :meth:`DataFrame.where` when ``cond`` is a :class:`DataFrame` with many columns (:issue:`61010`)
618622
- Performance improvement in :meth:`to_hdf` avoid unnecessary reopenings of the HDF5 file to speedup data addition to files with a very large number of groups . (:issue:`58248`)
619623
- Performance improvement in ``DataFrameGroupBy.__len__`` and ``SeriesGroupBy.__len__`` (:issue:`57595`)
620624
- Performance improvement in indexing operations for string dtypes (:issue:`56997`)
@@ -647,6 +651,7 @@ Datetimelike
647651
- Bug in :meth:`DatetimeIndex.union` and :meth:`DatetimeIndex.intersection` when ``unit`` was non-nanosecond (:issue:`59036`)
648652
- Bug in :meth:`Series.dt.microsecond` producing incorrect results for pyarrow backed :class:`Series`. (:issue:`59154`)
649653
- Bug in :meth:`to_datetime` not respecting dayfirst if an uncommon date string was passed. (:issue:`58859`)
654+
- Bug in :meth:`to_datetime` on float array with missing values throwing ``FloatingPointError`` (:issue:`58419`)
650655
- Bug in :meth:`to_datetime` on float32 df with year, month, day etc. columns leads to precision issues and incorrect result. (:issue:`60506`)
651656
- Bug in :meth:`to_datetime` reports incorrect index in case of any failure scenario. (:issue:`58298`)
652657
- Bug in :meth:`to_datetime` wrongly converts when ``arg`` is a ``np.datetime64`` object with unit of ``ps``. (:issue:`60341`)
@@ -690,6 +695,7 @@ Indexing
690695
^^^^^^^^
691696
- Bug in :meth:`DataFrame.__getitem__` returning modified columns when called with ``slice`` in Python 3.12 (:issue:`57500`)
692697
- Bug in :meth:`DataFrame.from_records` throwing a ``ValueError`` when passed an empty list in ``index`` (:issue:`58594`)
698+
- Bug in :meth:`DataFrame.loc` with inconsistent behavior of loc-set with 2 given indexes to Series (:issue:`59933`)
693699
- Bug in :meth:`MultiIndex.insert` when a new value inserted to a datetime-like level gets cast to ``NaT`` and fails indexing (:issue:`60388`)
694700
- Bug in printing :attr:`Index.names` and :attr:`MultiIndex.levels` would not escape single quotes (:issue:`60190`)
695701

@@ -705,6 +711,7 @@ MultiIndex
705711
- :meth:`MultiIndex.insert` would not insert NA value correctly at unified location of index -1 (:issue:`59003`)
706712
- :func:`MultiIndex.get_level_values` accessing a :class:`DatetimeIndex` does not carry the frequency attribute along (:issue:`58327`, :issue:`57949`)
707713
- Bug in :class:`DataFrame` arithmetic operations in case of unaligned MultiIndex columns (:issue:`60498`)
714+
- Bug in :class:`DataFrame` arithmetic operations with :class:`Series` in case of unaligned MultiIndex (:issue:`61009`)
708715
-
709716

710717
I/O

environment.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,13 @@ dependencies:
116116
- requests
117117
- pygments # Code highlighting
118118

119+
# web interactive REPL
120+
# see the following links for more context:
121+
# 1. https://jupyterlite-pyodide-kernel.readthedocs.io/en/stable/#compatibility
122+
# 2. https://pyodide.org/en/stable/usage/packages-in-pyodide.html
123+
- jupyterlite-core
124+
- jupyterlite-pyodide-kernel
125+
119126
- pip:
120127
- adbc-driver-postgresql>=0.10.0
121128
- adbc-driver-sqlite>=0.8.0
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Autogenerated file containing Cython compile-time defines
2+
3+
DEF CYTHON_COMPATIBLE_WITH_FREE_THREADING = @freethreading_compatible@

pandas/_libs/internals.pyx

Lines changed: 56 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,7 @@ cimport cython
44
from cpython.object cimport PyObject
55
from cpython.pyport cimport PY_SSIZE_T_MAX
66
from cpython.slice cimport PySlice_GetIndicesEx
7-
from cpython.weakref cimport (
8-
PyWeakref_GetObject,
9-
PyWeakref_NewRef,
10-
)
7+
from cpython.weakref cimport PyWeakref_NewRef
118
from cython cimport Py_ssize_t
129

1310
import numpy as np
@@ -29,6 +26,14 @@ from pandas._libs.util cimport (
2926
is_integer_object,
3027
)
3128

29+
include "free_threading_config.pxi"
30+
31+
IF CYTHON_COMPATIBLE_WITH_FREE_THREADING:
32+
from cpython.ref cimport Py_DECREF
33+
from cpython.weakref cimport PyWeakref_GetRef
34+
ELSE:
35+
from cpython.weakref cimport PyWeakref_GetObject
36+
3237

3338
cdef extern from "Python.h":
3439
PyObject* Py_None
@@ -908,17 +913,37 @@ cdef class BlockValuesRefs:
908913
# if force=False. Clearing for every insertion causes slowdowns if
909914
# all these objects stay alive, e.g. df.items() for wide DataFrames
910915
# see GH#55245 and GH#55008
916+
IF CYTHON_COMPATIBLE_WITH_FREE_THREADING:
917+
cdef PyObject* pobj
918+
cdef bint status
919+
911920
if force or len(self.referenced_blocks) > self.clear_counter:
912-
self.referenced_blocks = [
913-
ref for ref in self.referenced_blocks
914-
if PyWeakref_GetObject(ref) != Py_None
915-
]
921+
IF CYTHON_COMPATIBLE_WITH_FREE_THREADING:
922+
new_referenced_blocks = []
923+
for ref in self.referenced_blocks:
924+
status = PyWeakref_GetRef(ref, &pobj)
925+
if status == -1:
926+
return
927+
elif status == 1:
928+
new_referenced_blocks.append(ref)
929+
Py_DECREF(<object>pobj)
930+
self.referenced_blocks = new_referenced_blocks
931+
ELSE:
932+
self.referenced_blocks = [
933+
ref for ref in self.referenced_blocks
934+
if PyWeakref_GetObject(ref) != Py_None
935+
]
936+
916937
nr_of_refs = len(self.referenced_blocks)
917938
if nr_of_refs < self.clear_counter // 2:
918939
self.clear_counter = max(self.clear_counter // 2, 500)
919940
elif nr_of_refs > self.clear_counter:
920941
self.clear_counter = max(self.clear_counter * 2, nr_of_refs)
921942

943+
cpdef _add_reference_maybe_locked(self, Block blk):
944+
self._clear_dead_references()
945+
self.referenced_blocks.append(PyWeakref_NewRef(blk, None))
946+
922947
cpdef add_reference(self, Block blk):
923948
"""Adds a new reference to our reference collection.
924949
@@ -927,8 +952,15 @@ cdef class BlockValuesRefs:
927952
blk : Block
928953
The block that the new references should point to.
929954
"""
955+
IF CYTHON_COMPATIBLE_WITH_FREE_THREADING:
956+
with cython.critical_section(self):
957+
self._add_reference_maybe_locked(blk)
958+
ELSE:
959+
self._add_reference_maybe_locked(blk)
960+
961+
def _add_index_reference_maybe_locked(self, index: object) -> None:
930962
self._clear_dead_references()
931-
self.referenced_blocks.append(PyWeakref_NewRef(blk, None))
963+
self.referenced_blocks.append(PyWeakref_NewRef(index, None))
932964

933965
def add_index_reference(self, index: object) -> None:
934966
"""Adds a new reference to our reference collection when creating an index.
@@ -938,8 +970,16 @@ cdef class BlockValuesRefs:
938970
index : Index
939971
The index that the new reference should point to.
940972
"""
941-
self._clear_dead_references()
942-
self.referenced_blocks.append(PyWeakref_NewRef(index, None))
973+
IF CYTHON_COMPATIBLE_WITH_FREE_THREADING:
974+
with cython.critical_section(self):
975+
self._add_index_reference_maybe_locked(index)
976+
ELSE:
977+
self._add_index_reference_maybe_locked(index)
978+
979+
def _has_reference_maybe_locked(self) -> bool:
980+
self._clear_dead_references(force=True)
981+
# Checking for more references than block pointing to itself
982+
return len(self.referenced_blocks) > 1
943983

944984
def has_reference(self) -> bool:
945985
"""Checks if block has foreign references.
@@ -951,6 +991,8 @@ cdef class BlockValuesRefs:
951991
-------
952992
bool
953993
"""
954-
self._clear_dead_references(force=True)
955-
# Checking for more references than block pointing to itself
956-
return len(self.referenced_blocks) > 1
994+
IF CYTHON_COMPATIBLE_WITH_FREE_THREADING:
995+
with cython.critical_section(self):
996+
return self._has_reference_maybe_locked()
997+
ELSE:
998+
return self._has_reference_maybe_locked()

0 commit comments

Comments
 (0)