Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DEPS: Make pytz an optional dependency #59089

Merged
merged 28 commits into from
Aug 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
51dfbe7
Make pytz an optional dependency
mroeschke Jun 24, 2024
ff76e49
Start to address tests
mroeschke Jun 24, 2024
10df94e
Fix tests
mroeschke Jun 25, 2024
b76fca7
Fix tests
mroeschke Jun 25, 2024
19d424b
Merge remote-tracking branch 'upstream/main' into deps/pytz/optional
mroeschke Jun 25, 2024
7d1b37b
Fix test, import optional pytz in conftest
mroeschke Jun 25, 2024
a6d703e
Fix formatting
mroeschke Jun 25, 2024
2153987
Change minimum
mroeschke Jun 25, 2024
ee34f5a
remove type ignore
mroeschke Jun 25, 2024
74263d3
another pa under 17
mroeschke Jun 25, 2024
3be94bf
Merge remote-tracking branch 'upstream/main' into deps/pytz/optional
mroeschke Jun 26, 2024
6690eaa
Address comments
mroeschke Jun 26, 2024
3b7a526
Merge remote-tracking branch 'upstream/main' into deps/pytz/optional
mroeschke Jul 1, 2024
db94b7e
Undo file
mroeschke Jul 1, 2024
f9f92af
Merge remote-tracking branch 'upstream/main' into deps/pytz/optional
mroeschke Jul 3, 2024
dce0c35
Merge remote-tracking branch 'upstream/main' into deps/pytz/optional
mroeschke Jul 5, 2024
b252886
Merge branch 'main' into deps/pytz/optional
mroeschke Jul 15, 2024
f55e413
Merge remote-tracking branch 'upstream/main' into deps/pytz/optional
mroeschke Jul 22, 2024
d15f8e1
Merge branch 'deps/pytz/optional' of https://github.com/mroeschke/pan…
mroeschke Jul 22, 2024
e8b2c8c
Merge branch 'main' into deps/pytz/optional
mroeschke Jul 25, 2024
445842e
Merge remote-tracking branch 'upstream/main' into deps/pytz/optional
mroeschke Jul 26, 2024
c59f52e
Fix pyarrow 17 test
mroeschke Jul 26, 2024
62cc55e
Merge branch 'main' into deps/pytz/optional
mroeschke Aug 2, 2024
95415ff
Merge branch 'main' into deps/pytz/optional
mroeschke Aug 7, 2024
be76d11
Merge branch 'main' into deps/pytz/optional
mroeschke Aug 7, 2024
9a0b4c1
Test xpasses on pyarrow 18
mroeschke Aug 7, 2024
589ca49
Merge branch 'main' into deps/pytz/optional
mroeschke Aug 12, 2024
02b9527
Merge branch 'main' into deps/pytz/optional
mroeschke Aug 12, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ jobs:
/opt/python/cp311-cp311/bin/python -m venv ~/virtualenvs/pandas-dev
. ~/virtualenvs/pandas-dev/bin/activate
python -m pip install --no-cache-dir -U pip wheel setuptools meson-python==0.13.1 meson[ninja]==1.2.1
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
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
python -m pip install --no-cache-dir --no-build-isolation -e . --config-settings=setup-args="--werror"
python -m pip list --no-cache-dir
export PANDAS_CI=1
Expand Down
8 changes: 4 additions & 4 deletions .github/workflows/unit-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ jobs:
. ~/virtualenvs/pandas-dev/bin/activate
python -m pip install --no-cache-dir -U pip wheel setuptools meson[ninja]==1.2.1 meson-python==0.13.1
python -m pip install numpy --config-settings=setup-args="-Dallow-noblas=true"
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
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
python -m pip install --no-cache-dir --no-build-isolation -e . --config-settings=setup-args="--werror"
python -m pip list --no-cache-dir
export PANDAS_CI=1
Expand Down Expand Up @@ -274,7 +274,7 @@ jobs:
/opt/python/cp311-cp311/bin/python -m venv ~/virtualenvs/pandas-dev
. ~/virtualenvs/pandas-dev/bin/activate
python -m pip install --no-cache-dir -U pip wheel setuptools meson-python==0.13.1 meson[ninja]==1.2.1
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
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
python -m pip install --no-cache-dir --no-build-isolation -e . --config-settings=setup-args="--werror"
python -m pip list --no-cache-dir

Expand All @@ -295,7 +295,7 @@ jobs:
# In general, this will remain frozen(present, but not running) until:
# - The next unreleased Python version has released beta 1
# - This version should be available on GitHub Actions.
# - Our required build/runtime dependencies(numpy, pytz, Cython, python-dateutil)
# - Our required build/runtime dependencies(numpy, Cython, python-dateutil)
# support that unreleased Python version.
# To unfreeze, comment out the ``if: false`` condition, and make sure you update
# the name of the workflow and Python version in actions/setup-python ``python-version:``
Expand Down Expand Up @@ -348,7 +348,7 @@ jobs:
python -m pip install --upgrade pip setuptools wheel meson[ninja]==1.2.1 meson-python==0.13.1
python -m pip install --pre --extra-index-url https://pypi.anaconda.org/scientific-python-nightly-wheels/simple numpy
python -m pip install versioneer[toml]
python -m pip install python-dateutil pytz tzdata cython hypothesis>=6.84.0 pytest>=7.3.2 pytest-xdist>=3.4.0 pytest-cov
python -m pip install python-dateutil tzdata cython hypothesis>=6.84.0 pytest>=7.3.2 pytest-xdist>=3.4.0 pytest-cov
python -m pip install -ve . --no-build-isolation --no-index --no-deps --config-settings=setup-args="--werror"
python -m pip list

Expand Down
2 changes: 1 addition & 1 deletion ci/deps/actions-310-minimum_versions.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ dependencies:
# required dependencies
- python-dateutil=2.8.2
- numpy=1.23.5
- pytz=2020.1

# optional dependencies
- beautifulsoup4=4.11.2
Expand All @@ -49,6 +48,7 @@ dependencies:
- pyreadstat=1.2.0
- pytables=3.8.0
- python-calamine=0.1.7
- pytz=2023.4
- pyxlsb=1.0.10
- s3fs=2022.11.0
- scipy=1.10.0
Expand Down
2 changes: 1 addition & 1 deletion ci/deps/actions-310.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ dependencies:
# required dependencies
- python-dateutil
- numpy
- pytz

# optional dependencies
- beautifulsoup4>=4.11.2
Expand All @@ -47,6 +46,7 @@ dependencies:
- pyreadstat>=1.2.0
- pytables>=3.8.0
- python-calamine>=0.1.7
- pytz>=2023.4
- pyxlsb>=1.0.10
- s3fs>=2022.11.0
- scipy>=1.10.0
Expand Down
2 changes: 1 addition & 1 deletion ci/deps/actions-311-downstream_compat.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ dependencies:
# required dependencies
- python-dateutil
- numpy
- pytz

# optional dependencies
- beautifulsoup4>=4.11.2
Expand All @@ -48,6 +47,7 @@ dependencies:
- pyreadstat>=1.2.0
- pytables>=3.8.0
- python-calamine>=0.1.7
- pytz>=2023.4
- pyxlsb>=1.0.10
- s3fs>=2022.11.0
- scipy>=1.10.0
Expand Down
1 change: 0 additions & 1 deletion ci/deps/actions-311-numpydev.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ dependencies:

# pandas dependencies
- python-dateutil
- pytz
- pip

- pip:
Expand Down
1 change: 0 additions & 1 deletion ci/deps/actions-311-pyarrownightly.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ dependencies:
# required dependencies
- python-dateutil
- numpy<2
- pytz
- pip

- pip:
Expand Down
2 changes: 1 addition & 1 deletion ci/deps/actions-311.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ dependencies:
# required dependencies
- python-dateutil
- numpy
- pytz

# optional dependencies
- beautifulsoup4>=4.11.2
Expand All @@ -47,6 +46,7 @@ dependencies:
- pyreadstat>=1.2.0
- pytables>=3.8.0
- python-calamine>=0.1.7
- pytz>=2023.4
- pyxlsb>=1.0.10
- s3fs>=2022.11.0
- scipy>=1.10.0
Expand Down
2 changes: 1 addition & 1 deletion ci/deps/actions-312.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ dependencies:
# required dependencies
- python-dateutil
- numpy
- pytz

# optional dependencies
- beautifulsoup4>=4.11.2
Expand All @@ -47,6 +46,7 @@ dependencies:
- pyreadstat>=1.2.0
- pytables>=3.8.0
- python-calamine>=0.1.7
- pytz>=2023.4
- pyxlsb>=1.0.10
- s3fs>=2022.11.0
- scipy>=1.10.0
Expand Down
1 change: 0 additions & 1 deletion ci/deps/actions-pypy-39.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,5 @@ dependencies:
# required
- numpy
- python-dateutil
- pytz
- pip:
- tzdata>=2022.7
2 changes: 1 addition & 1 deletion ci/deps/circle-311-arm64.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ dependencies:
# required dependencies
- python-dateutil
- numpy
- pytz

# optional dependencies
- beautifulsoup4>=4.11.2
Expand All @@ -47,6 +46,7 @@ dependencies:
- pyreadstat>=1.2.0
- pytables>=3.8.0
- python-calamine>=0.1.7
- pytz>=2023.4
- pyxlsb>=1.0.10
- s3fs>=2022.11.0
- scipy>=1.10.0
Expand Down
1 change: 0 additions & 1 deletion ci/meta.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ requirements:
- numpy >=1.21.6 # [py<311]
- numpy >=1.23.2 # [py>=311]
- python-dateutil >=2.8.2
- pytz >=2020.1
- python-tzdata >=2022.7

test:
Expand Down
12 changes: 11 additions & 1 deletion doc/source/getting_started/install.rst
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,6 @@ Package Minimum support
================================================================ ==========================
`NumPy <https://numpy.org>`__ 1.23.5
`python-dateutil <https://dateutil.readthedocs.io/en/stable/>`__ 2.8.2
`pytz <https://pypi.org/project/pytz/>`__ 2020.1
`tzdata <https://pypi.org/project/tzdata/>`__ 2022.7
================================================================ ==========================

Expand Down Expand Up @@ -419,3 +418,14 @@ Dependency Minimum Version pip extra Notes
========================= ================== =============== =============================================================
Zstandard 0.19.0 compression Zstandard compression
========================= ================== =============== =============================================================

Timezone
^^^^^^^^

Installable with ``pip install "pandas[timezone]"``

========================= ================== =================== =============================================================
Dependency Minimum Version pip extra Notes
========================= ================== =================== =============================================================
pytz 2023.4 timezone Alternative timezone library to ``zoneinfo``.
========================= ================== =================== =============================================================
4 changes: 2 additions & 2 deletions doc/source/user_guide/timeseries.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2569,7 +2569,7 @@ Ambiguous times when localizing
because daylight savings time (DST) in a local time zone causes some times to occur
twice within one day ("clocks fall back"). The following options are available:

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

* ``'raise'``: Raises a ``pytz.NonExistentTimeError`` (the default behavior)
* ``'raise'``: Raises a ``ValueError`` (the default behavior)
* ``'NaT'``: Replaces nonexistent times with ``NaT``
* ``'shift_forward'``: Shifts nonexistent times forward to the closest real time
* ``'shift_backward'``: Shifts nonexistent times backward to the closest real time
Expand Down
33 changes: 33 additions & 0 deletions doc/source/whatsnew/v3.0.0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,8 @@ Optional libraries below the lowest tested version may still work, but are not c
+------------------------+---------------------+
| Package | New Minimum Version |
+========================+=====================+
| pytz | 2023.4 |
+------------------------+---------------------+
| fastparquet | 2023.10.0 |
+------------------------+---------------------+
| adbc-driver-postgresql | 0.10.0 |
Expand All @@ -230,6 +232,37 @@ Optional libraries below the lowest tested version may still work, but are not c

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

.. _whatsnew_300.api_breaking.pytz:

``pytz`` now an optional dependency
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

pandas now uses :py:mod:`zoneinfo` from the standard library as the default timezone implementation when passing a timezone
string to various methods. (:issue:`34916`)

*Old behavior:*

.. code-block:: ipython

In [1]: ts = pd.Timestamp(2024, 1, 1).tz_localize("US/Pacific")
In [2]: ts.tz
<DstTzInfo 'US/Pacific' LMT-1 day, 16:07:00 STD>

*New behavior:*

.. ipython:: python

ts = pd.Timestamp(2024, 1, 1).tz_localize("US/Pacific")
ts.tz

``pytz`` timezone objects are still supported when passed directly, but they will no longer be returned by default
from string inputs. Moreover, ``pytz`` is no longer a required dependency of pandas, but can be installed
with the pip extra ``pip install pandas[timezone]``.


Additionally, pandas no longer throws ``pytz`` exceptions for timezone operations leading to ambiguous or nonexistent
times. These cases will now raise a ``ValueError``.

.. _whatsnew_300.api_breaking.other:

Other API changes
Expand Down
2 changes: 1 addition & 1 deletion environment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ dependencies:
# required dependencies
- python-dateutil
- numpy<2
- pytz

# optional dependencies
- beautifulsoup4>=4.11.2
Expand All @@ -50,6 +49,7 @@ dependencies:
- pyreadstat>=1.2.0
- pytables>=3.8.0
- python-calamine>=0.1.7
- pytz>=2023.4
- pyxlsb>=1.0.10
- s3fs>=2022.11.0
- scipy>=1.10.0
Expand Down
2 changes: 1 addition & 1 deletion pandas/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
__docformat__ = "restructuredtext"

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

for _dependency in _hard_dependencies:
Expand Down
13 changes: 10 additions & 3 deletions pandas/_libs/tslibs/conversion.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ from pandas._libs.tslibs.timestamps cimport _Timestamp
from pandas._libs.tslibs.timezones cimport (
get_utcoffset,
is_utc,
treat_tz_as_pytz,
)
from pandas._libs.tslibs.tzconversion cimport (
Localizer,
Expand Down Expand Up @@ -747,11 +748,17 @@ cdef datetime _localize_pydatetime(datetime dt, tzinfo tz):
identically, i.e. discards nanos from Timestamps.
It also assumes that the `tz` input is not None.
"""
try:
if treat_tz_as_pytz(tz):
import pytz

# datetime.replace with pytz may be incorrect result
# TODO: try to respect `fold` attribute
return tz.localize(dt, is_dst=None)
except AttributeError:
try:
return tz.localize(dt, is_dst=None)
except (pytz.AmbiguousTimeError, pytz.NonExistentTimeError) as err:
# As of pandas 3.0, we raise ValueErrors instead of pytz exceptions
raise ValueError(str(err)) from err
else:
return dt.replace(tzinfo=tz)


Expand Down
16 changes: 8 additions & 8 deletions pandas/_libs/tslibs/nattype.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -1045,7 +1045,7 @@ class NaTType(_NaT):
* bool contains flags to determine if time is dst or not (note
that this flag is only applicable for ambiguous fall dst dates).
* 'NaT' will return NaT for an ambiguous time.
* 'raise' will raise an AmbiguousTimeError for an ambiguous time.
* 'raise' will raise a ValueError for an ambiguous time.

nonexistent : {'raise', 'shift_forward', 'shift_backward', 'NaT', \
timedelta}, default 'raise'
Expand All @@ -1058,7 +1058,7 @@ timedelta}, default 'raise'
closest existing time.
* 'NaT' will return NaT where there are nonexistent times.
* timedelta objects will shift nonexistent times by the timedelta.
* 'raise' will raise an NonExistentTimeError if there are
* 'raise' will raise a ValueError if there are
nonexistent times.

Returns
Expand Down Expand Up @@ -1146,7 +1146,7 @@ timedelta}, default 'raise'
* bool contains flags to determine if time is dst or not (note
that this flag is only applicable for ambiguous fall dst dates).
* 'NaT' will return NaT for an ambiguous time.
* 'raise' will raise an AmbiguousTimeError for an ambiguous time.
* 'raise' will raise a ValueError for an ambiguous time.

nonexistent : {'raise', 'shift_forward', 'shift_backward', 'NaT', \
timedelta}, default 'raise'
Expand All @@ -1159,7 +1159,7 @@ timedelta}, default 'raise'
closest existing time.
* 'NaT' will return NaT where there are nonexistent times.
* timedelta objects will shift nonexistent times by the timedelta.
* 'raise' will raise an NonExistentTimeError if there are
* 'raise' will raise a ValueError if there are
nonexistent times.

Raises
Expand Down Expand Up @@ -1241,7 +1241,7 @@ timedelta}, default 'raise'
* bool contains flags to determine if time is dst or not (note
that this flag is only applicable for ambiguous fall dst dates).
* 'NaT' will return NaT for an ambiguous time.
* 'raise' will raise an AmbiguousTimeError for an ambiguous time.
* 'raise' will raise a ValueError for an ambiguous time.

nonexistent : {'raise', 'shift_forward', 'shift_backward', 'NaT', \
timedelta}, default 'raise'
Expand All @@ -1254,7 +1254,7 @@ timedelta}, default 'raise'
closest existing time.
* 'NaT' will return NaT where there are nonexistent times.
* timedelta objects will shift nonexistent times by the timedelta.
* 'raise' will raise an NonExistentTimeError if there are
* 'raise' will raise a ValueError if there are
nonexistent times.

Raises
Expand Down Expand Up @@ -1405,7 +1405,7 @@ timedelta}, default 'raise'
* bool contains flags to determine if time is dst or not (note
that this flag is only applicable for ambiguous fall dst dates).
* 'NaT' will return NaT for an ambiguous time.
* 'raise' will raise an AmbiguousTimeError for an ambiguous time.
* 'raise' will raise a ValueError for an ambiguous time.

nonexistent : 'shift_forward', 'shift_backward', 'NaT', timedelta, \
default 'raise'
Expand All @@ -1420,7 +1420,7 @@ default 'raise'
closest existing time.
* 'NaT' will return NaT where there are nonexistent times.
* timedelta objects will shift nonexistent times by the timedelta.
* 'raise' will raise an NonExistentTimeError if there are
* 'raise' will raise a ValueError if there are
nonexistent times.

Returns
Expand Down
Loading