Skip to content

Commit 70e71f7

Browse files
Merge branch 'main' into groupby-then-resample-if-index-out-of-order
2 parents d2842b5 + 0fadaa9 commit 70e71f7

File tree

83 files changed

+549
-360
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

83 files changed

+549
-360
lines changed

.circleci/config.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ jobs:
5656
/opt/python/cp311-cp311/bin/python -m venv ~/virtualenvs/pandas-dev
5757
. ~/virtualenvs/pandas-dev/bin/activate
5858
python -m pip install --no-cache-dir -U pip wheel setuptools meson-python==0.13.1 meson[ninja]==1.2.1
59-
python -m pip install --no-cache-dir versioneer[toml] cython numpy python-dateutil pytz pytest>=7.3.2 pytest-xdist>=3.4.0 hypothesis>=6.84.0
59+
python -m pip install --no-cache-dir versioneer[toml] cython numpy python-dateutil pytest>=7.3.2 pytest-xdist>=3.4.0 hypothesis>=6.84.0
6060
python -m pip install --no-cache-dir --no-build-isolation -e . --config-settings=setup-args="--werror"
6161
python -m pip list --no-cache-dir
6262
export PANDAS_CI=1

.github/workflows/unit-tests.yml

+4-4
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,7 @@ jobs:
236236
. ~/virtualenvs/pandas-dev/bin/activate
237237
python -m pip install --no-cache-dir -U pip wheel setuptools meson[ninja]==1.2.1 meson-python==0.13.1
238238
python -m pip install numpy --config-settings=setup-args="-Dallow-noblas=true"
239-
python -m pip install --no-cache-dir versioneer[toml] cython python-dateutil pytz pytest>=7.3.2 pytest-xdist>=3.4.0 hypothesis>=6.84.0
239+
python -m pip install --no-cache-dir versioneer[toml] cython python-dateutil pytest>=7.3.2 pytest-xdist>=3.4.0 hypothesis>=6.84.0
240240
python -m pip install --no-cache-dir --no-build-isolation -e . --config-settings=setup-args="--werror"
241241
python -m pip list --no-cache-dir
242242
export PANDAS_CI=1
@@ -274,7 +274,7 @@ jobs:
274274
/opt/python/cp311-cp311/bin/python -m venv ~/virtualenvs/pandas-dev
275275
. ~/virtualenvs/pandas-dev/bin/activate
276276
python -m pip install --no-cache-dir -U pip wheel setuptools meson-python==0.13.1 meson[ninja]==1.2.1
277-
python -m pip install --no-cache-dir versioneer[toml] cython numpy python-dateutil pytz pytest>=7.3.2 pytest-xdist>=3.4.0 hypothesis>=6.84.0
277+
python -m pip install --no-cache-dir versioneer[toml] cython numpy python-dateutil pytest>=7.3.2 pytest-xdist>=3.4.0 hypothesis>=6.84.0
278278
python -m pip install --no-cache-dir --no-build-isolation -e . --config-settings=setup-args="--werror"
279279
python -m pip list --no-cache-dir
280280
@@ -295,7 +295,7 @@ jobs:
295295
# In general, this will remain frozen(present, but not running) until:
296296
# - The next unreleased Python version has released beta 1
297297
# - This version should be available on GitHub Actions.
298-
# - Our required build/runtime dependencies(numpy, pytz, Cython, python-dateutil)
298+
# - Our required build/runtime dependencies(numpy, Cython, python-dateutil)
299299
# support that unreleased Python version.
300300
# To unfreeze, comment out the ``if: false`` condition, and make sure you update
301301
# the name of the workflow and Python version in actions/setup-python ``python-version:``
@@ -348,7 +348,7 @@ jobs:
348348
python -m pip install --upgrade pip setuptools wheel meson[ninja]==1.2.1 meson-python==0.13.1
349349
python -m pip install --pre --extra-index-url https://pypi.anaconda.org/scientific-python-nightly-wheels/simple numpy
350350
python -m pip install versioneer[toml]
351-
python -m pip install python-dateutil pytz tzdata cython hypothesis>=6.84.0 pytest>=7.3.2 pytest-xdist>=3.4.0 pytest-cov
351+
python -m pip install python-dateutil tzdata cython hypothesis>=6.84.0 pytest>=7.3.2 pytest-xdist>=3.4.0 pytest-cov
352352
python -m pip install -ve . --no-build-isolation --no-index --no-deps --config-settings=setup-args="--werror"
353353
python -m pip list
354354

ci/code_checks.sh

-14
Original file line numberDiff line numberDiff line change
@@ -158,26 +158,15 @@ if [[ -z "$CHECK" || "$CHECK" == "docstrings" ]]; then
158158
-i "pandas.Series.sparse.sp_values SA01" \
159159
-i "pandas.Series.sparse.to_coo PR07,RT03,SA01" \
160160
-i "pandas.Series.std PR01,RT03,SA01" \
161-
-i "pandas.Series.str.capitalize RT03" \
162-
-i "pandas.Series.str.casefold RT03" \
163-
-i "pandas.Series.str.center RT03,SA01" \
164-
-i "pandas.Series.str.decode PR07,RT03,SA01" \
165-
-i "pandas.Series.str.encode PR07,RT03,SA01" \
166-
-i "pandas.Series.str.ljust RT03,SA01" \
167-
-i "pandas.Series.str.lower RT03" \
168161
-i "pandas.Series.str.lstrip RT03" \
169162
-i "pandas.Series.str.match RT03" \
170163
-i "pandas.Series.str.normalize RT03,SA01" \
171164
-i "pandas.Series.str.partition RT03" \
172165
-i "pandas.Series.str.repeat SA01" \
173166
-i "pandas.Series.str.replace SA01" \
174-
-i "pandas.Series.str.rjust RT03,SA01" \
175167
-i "pandas.Series.str.rpartition RT03" \
176168
-i "pandas.Series.str.rstrip RT03" \
177169
-i "pandas.Series.str.strip RT03" \
178-
-i "pandas.Series.str.swapcase RT03" \
179-
-i "pandas.Series.str.title RT03" \
180-
-i "pandas.Series.str.upper RT03" \
181170
-i "pandas.Series.str.wrap RT03,SA01" \
182171
-i "pandas.Series.str.zfill RT03" \
183172
-i "pandas.Series.struct.dtypes SA01" \
@@ -231,11 +220,8 @@ if [[ -z "$CHECK" || "$CHECK" == "docstrings" ]]; then
231220
-i "pandas.Timestamp.to_period PR01,SA01" \
232221
-i "pandas.Timestamp.today SA01" \
233222
-i "pandas.Timestamp.toordinal SA01" \
234-
-i "pandas.Timestamp.tz_localize SA01" \
235223
-i "pandas.Timestamp.tzinfo GL08" \
236-
-i "pandas.Timestamp.tzname SA01" \
237224
-i "pandas.Timestamp.unit SA01" \
238-
-i "pandas.Timestamp.utcfromtimestamp PR01,SA01" \
239225
-i "pandas.Timestamp.utcoffset SA01" \
240226
-i "pandas.Timestamp.utctimetuple SA01" \
241227
-i "pandas.Timestamp.value GL08" \

ci/deps/actions-310-minimum_versions.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ dependencies:
2323
# required dependencies
2424
- python-dateutil=2.8.2
2525
- numpy=1.23.5
26-
- pytz=2020.1
2726

2827
# optional dependencies
2928
- beautifulsoup4=4.11.2
@@ -49,6 +48,7 @@ dependencies:
4948
- pyreadstat=1.2.0
5049
- pytables=3.8.0
5150
- python-calamine=0.1.7
51+
- pytz=2023.4
5252
- pyxlsb=1.0.10
5353
- s3fs=2022.11.0
5454
- scipy=1.10.0

ci/deps/actions-310.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ dependencies:
2121
# required dependencies
2222
- python-dateutil
2323
- numpy
24-
- pytz
2524

2625
# optional dependencies
2726
- beautifulsoup4>=4.11.2
@@ -47,6 +46,7 @@ dependencies:
4746
- pyreadstat>=1.2.0
4847
- pytables>=3.8.0
4948
- python-calamine>=0.1.7
49+
- pytz>=2023.4
5050
- pyxlsb>=1.0.10
5151
- s3fs>=2022.11.0
5252
- scipy>=1.10.0

ci/deps/actions-311-downstream_compat.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ dependencies:
2222
# required dependencies
2323
- python-dateutil
2424
- numpy
25-
- pytz
2625

2726
# optional dependencies
2827
- beautifulsoup4>=4.11.2
@@ -48,6 +47,7 @@ dependencies:
4847
- pyreadstat>=1.2.0
4948
- pytables>=3.8.0
5049
- python-calamine>=0.1.7
50+
- pytz>=2023.4
5151
- pyxlsb>=1.0.10
5252
- s3fs>=2022.11.0
5353
- scipy>=1.10.0

ci/deps/actions-311-numpydev.yaml

-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ dependencies:
1818

1919
# pandas dependencies
2020
- python-dateutil
21-
- pytz
2221
- pip
2322

2423
- pip:

ci/deps/actions-311-pyarrownightly.yaml

-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ dependencies:
1919
# required dependencies
2020
- python-dateutil
2121
- numpy<2
22-
- pytz
2322
- pip
2423

2524
- pip:

ci/deps/actions-311.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ dependencies:
2121
# required dependencies
2222
- python-dateutil
2323
- numpy
24-
- pytz
2524

2625
# optional dependencies
2726
- beautifulsoup4>=4.11.2
@@ -47,6 +46,7 @@ dependencies:
4746
- pyreadstat>=1.2.0
4847
- pytables>=3.8.0
4948
- python-calamine>=0.1.7
49+
- pytz>=2023.4
5050
- pyxlsb>=1.0.10
5151
- s3fs>=2022.11.0
5252
- scipy>=1.10.0

ci/deps/actions-312.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ dependencies:
2121
# required dependencies
2222
- python-dateutil
2323
- numpy
24-
- pytz
2524

2625
# optional dependencies
2726
- beautifulsoup4>=4.11.2
@@ -47,6 +46,7 @@ dependencies:
4746
- pyreadstat>=1.2.0
4847
- pytables>=3.8.0
4948
- python-calamine>=0.1.7
49+
- pytz>=2023.4
5050
- pyxlsb>=1.0.10
5151
- s3fs>=2022.11.0
5252
- scipy>=1.10.0

ci/deps/actions-pypy-39.yaml

-1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,5 @@ dependencies:
2222
# required
2323
- numpy
2424
- python-dateutil
25-
- pytz
2625
- pip:
2726
- tzdata>=2022.7

ci/deps/circle-311-arm64.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ dependencies:
2121
# required dependencies
2222
- python-dateutil
2323
- numpy
24-
- pytz
2524

2625
# optional dependencies
2726
- beautifulsoup4>=4.11.2
@@ -47,6 +46,7 @@ dependencies:
4746
- pyreadstat>=1.2.0
4847
- pytables>=3.8.0
4948
- python-calamine>=0.1.7
49+
- pytz>=2023.4
5050
- pyxlsb>=1.0.10
5151
- s3fs>=2022.11.0
5252
- scipy>=1.10.0

ci/meta.yaml

-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@ requirements:
3737
- numpy >=1.21.6 # [py<311]
3838
- numpy >=1.23.2 # [py>=311]
3939
- python-dateutil >=2.8.2
40-
- pytz >=2020.1
4140
- python-tzdata >=2022.7
4241

4342
test:

doc/source/development/contributing_docstring.rst

+1-1
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ backticks. The following are considered inline code:
142142
143143
With several mistakes in the docstring.
144144
145-
It has a blank like after the signature ``def func():``.
145+
It has a blank line after the signature ``def func():``.
146146
147147
The text 'Some function' should go in the line after the
148148
opening quotes of the docstring, not in the same line.

doc/source/getting_started/install.rst

+11-1
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,6 @@ Package Minimum support
205205
================================================================ ==========================
206206
`NumPy <https://numpy.org>`__ 1.23.5
207207
`python-dateutil <https://dateutil.readthedocs.io/en/stable/>`__ 2.8.2
208-
`pytz <https://pypi.org/project/pytz/>`__ 2020.1
209208
`tzdata <https://pypi.org/project/tzdata/>`__ 2022.7
210209
================================================================ ==========================
211210

@@ -419,3 +418,14 @@ Dependency Minimum Version pip extra Notes
419418
========================= ================== =============== =============================================================
420419
Zstandard 0.19.0 compression Zstandard compression
421420
========================= ================== =============== =============================================================
421+
422+
Timezone
423+
^^^^^^^^
424+
425+
Installable with ``pip install "pandas[timezone]"``
426+
427+
========================= ================== =================== =============================================================
428+
Dependency Minimum Version pip extra Notes
429+
========================= ================== =================== =============================================================
430+
pytz 2023.4 timezone Alternative timezone library to ``zoneinfo``.
431+
========================= ================== =================== =============================================================

doc/source/user_guide/timeseries.rst

+2-2
Original file line numberDiff line numberDiff line change
@@ -2569,7 +2569,7 @@ Ambiguous times when localizing
25692569
because daylight savings time (DST) in a local time zone causes some times to occur
25702570
twice within one day ("clocks fall back"). The following options are available:
25712571

2572-
* ``'raise'``: Raises a ``pytz.AmbiguousTimeError`` (the default behavior)
2572+
* ``'raise'``: Raises a ``ValueError`` (the default behavior)
25732573
* ``'infer'``: Attempt to determine the correct offset base on the monotonicity of the timestamps
25742574
* ``'NaT'``: Replaces ambiguous times with ``NaT``
25752575
* ``bool``: ``True`` represents a DST time, ``False`` represents non-DST time. An array-like of ``bool`` values is supported for a sequence of times.
@@ -2604,7 +2604,7 @@ A DST transition may also shift the local time ahead by 1 hour creating nonexist
26042604
local times ("clocks spring forward"). The behavior of localizing a timeseries with nonexistent times
26052605
can be controlled by the ``nonexistent`` argument. The following options are available:
26062606

2607-
* ``'raise'``: Raises a ``pytz.NonExistentTimeError`` (the default behavior)
2607+
* ``'raise'``: Raises a ``ValueError`` (the default behavior)
26082608
* ``'NaT'``: Replaces nonexistent times with ``NaT``
26092609
* ``'shift_forward'``: Shifts nonexistent times forward to the closest real time
26102610
* ``'shift_backward'``: Shifts nonexistent times backward to the closest real time

doc/source/whatsnew/v3.0.0.rst

+35
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ Other enhancements
5050
- :meth:`DataFrame.pivot_table` and :func:`pivot_table` now allow the passing of keyword arguments to ``aggfunc`` through ``**kwargs`` (:issue:`57884`)
5151
- :meth:`Series.cummin` and :meth:`Series.cummax` now supports :class:`CategoricalDtype` (:issue:`52335`)
5252
- :meth:`Series.plot` now correctly handle the ``ylabel`` parameter for pie charts, allowing for explicit control over the y-axis label (:issue:`58239`)
53+
- :meth:`pandas.concat` will raise a ``ValueError`` when ``ignore_index=True`` and ``keys`` is not ``None`` (:issue:`59274`)
5354
- Multiplying two :class:`DateOffset` objects will now raise a ``TypeError`` instead of a ``RecursionError`` (:issue:`59442`)
5455
- Restore support for reading Stata 104-format and enable reading 103-format dta files (:issue:`58554`)
5556
- Support reading Stata 102-format (Stata 1) dta files (:issue:`58978`)
@@ -221,6 +222,8 @@ Optional libraries below the lowest tested version may still work, but are not c
221222
+------------------------+---------------------+
222223
| Package | New Minimum Version |
223224
+========================+=====================+
225+
| pytz | 2023.4 |
226+
+------------------------+---------------------+
224227
| fastparquet | 2023.10.0 |
225228
+------------------------+---------------------+
226229
| adbc-driver-postgresql | 0.10.0 |
@@ -230,6 +233,37 @@ Optional libraries below the lowest tested version may still work, but are not c
230233

231234
See :ref:`install.dependencies` and :ref:`install.optional_dependencies` for more.
232235

236+
.. _whatsnew_300.api_breaking.pytz:
237+
238+
``pytz`` now an optional dependency
239+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
240+
241+
pandas now uses :py:mod:`zoneinfo` from the standard library as the default timezone implementation when passing a timezone
242+
string to various methods. (:issue:`34916`)
243+
244+
*Old behavior:*
245+
246+
.. code-block:: ipython
247+
248+
In [1]: ts = pd.Timestamp(2024, 1, 1).tz_localize("US/Pacific")
249+
In [2]: ts.tz
250+
<DstTzInfo 'US/Pacific' LMT-1 day, 16:07:00 STD>
251+
252+
*New behavior:*
253+
254+
.. ipython:: python
255+
256+
ts = pd.Timestamp(2024, 1, 1).tz_localize("US/Pacific")
257+
ts.tz
258+
259+
``pytz`` timezone objects are still supported when passed directly, but they will no longer be returned by default
260+
from string inputs. Moreover, ``pytz`` is no longer a required dependency of pandas, but can be installed
261+
with the pip extra ``pip install pandas[timezone]``.
262+
263+
264+
Additionally, pandas no longer throws ``pytz`` exceptions for timezone operations leading to ambiguous or nonexistent
265+
times. These cases will now raise a ``ValueError``.
266+
233267
.. _whatsnew_300.api_breaking.other:
234268

235269
Other API changes
@@ -621,6 +655,7 @@ Reshaping
621655
^^^^^^^^^
622656
- Bug in :func:`qcut` where values at the quantile boundaries could be incorrectly assigned (:issue:`59355`)
623657
- Bug in :meth:`DataFrame.join` inconsistently setting result index name (:issue:`55815`)
658+
- Bug in :meth:`DataFrame.merge` where merging on a column containing only ``NaN`` values resulted in an out-of-bounds array access (:issue:`59421`)
624659
- Bug in :meth:`DataFrame.unstack` producing incorrect results when ``sort=False`` (:issue:`54987`, :issue:`55516`)
625660
- Bug in :meth:`DataFrame.unstack` producing incorrect results when manipulating empty :class:`DataFrame` with an :class:`ExtentionDtype` (:issue:`59123`)
626661

environment.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ dependencies:
2424
# required dependencies
2525
- python-dateutil
2626
- numpy<2
27-
- pytz
2827

2928
# optional dependencies
3029
- beautifulsoup4>=4.11.2
@@ -50,6 +49,7 @@ dependencies:
5049
- pyreadstat>=1.2.0
5150
- pytables>=3.8.0
5251
- python-calamine>=0.1.7
52+
- pytz>=2023.4
5353
- pyxlsb>=1.0.10
5454
- s3fs>=2022.11.0
5555
- scipy>=1.10.0

pandas/__init__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
__docformat__ = "restructuredtext"
44

55
# Let users know if they're missing any of our hard dependencies
6-
_hard_dependencies = ("numpy", "pytz", "dateutil")
6+
_hard_dependencies = ("numpy", "dateutil")
77
_missing_dependencies = []
88

99
for _dependency in _hard_dependencies:

pandas/_config/config.py

+5
Original file line numberDiff line numberDiff line change
@@ -426,6 +426,11 @@ def option_context(*args) -> Generator[None, None, None]:
426426
None
427427
No return value.
428428
429+
Yields
430+
------
431+
None
432+
No yield value.
433+
429434
See Also
430435
--------
431436
get_option : Retrieve the value of the specified option.

pandas/_libs/tslibs/conversion.pyx

+10-3
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ from pandas._libs.tslibs.timestamps cimport _Timestamp
6969
from pandas._libs.tslibs.timezones cimport (
7070
get_utcoffset,
7171
is_utc,
72+
treat_tz_as_pytz,
7273
)
7374
from pandas._libs.tslibs.tzconversion cimport (
7475
Localizer,
@@ -747,11 +748,17 @@ cdef datetime _localize_pydatetime(datetime dt, tzinfo tz):
747748
identically, i.e. discards nanos from Timestamps.
748749
It also assumes that the `tz` input is not None.
749750
"""
750-
try:
751+
if treat_tz_as_pytz(tz):
752+
import pytz
753+
751754
# datetime.replace with pytz may be incorrect result
752755
# TODO: try to respect `fold` attribute
753-
return tz.localize(dt, is_dst=None)
754-
except AttributeError:
756+
try:
757+
return tz.localize(dt, is_dst=None)
758+
except (pytz.AmbiguousTimeError, pytz.NonExistentTimeError) as err:
759+
# As of pandas 3.0, we raise ValueErrors instead of pytz exceptions
760+
raise ValueError(str(err)) from err
761+
else:
755762
return dt.replace(tzinfo=tz)
756763

757764

0 commit comments

Comments
 (0)