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

chore(python): Clean up some remnants of Python 3.8 support #20293

Merged
merged 3 commits into from
Dec 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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 .github/workflows/test-bytecode-parser.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ jobs:
fail-fast: false
matrix:
# Only the versions that are not already run as part of the regular test suite
python-version: ['3.9', '3.10']
python-version: ['3.10', '3.11']

steps:
- uses: actions/checkout@v4
Expand Down
2 changes: 1 addition & 1 deletion docs/source/user-guide/installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ pip install 'polars[numpy,fsspec]'
| style | Style dataframes through the `style` namespace. |
| timezone | Timezone support[^note]. |

[^note]: Only needed if you are on Python < 3.9 or you are on Windows.
[^note]: Only needed if you are on Windows.

### Rust

Expand Down
26 changes: 5 additions & 21 deletions py-polars/polars/_utils/convert.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@
Any,
Callable,
NoReturn,
no_type_check,
overload,
)
from zoneinfo import ZoneInfo, ZoneInfoNotFoundError

from polars._utils.constants import (
EPOCH,
Expand All @@ -22,7 +22,6 @@
SECONDS_PER_HOUR,
US_PER_SECOND,
)
from polars.dependencies import _ZONEINFO_AVAILABLE, zoneinfo

if TYPE_CHECKING:
from collections.abc import Sequence
Expand Down Expand Up @@ -161,38 +160,23 @@ def to_py_datetime(

if time_zone is None:
return EPOCH + td
elif _ZONEINFO_AVAILABLE:
else:
dt = EPOCH_UTC + td
return _localize_datetime(dt, time_zone)
else:
msg = "install polars[timezone] to handle datetimes with time zone information"
raise ImportError(msg)


def _localize_datetime(dt: datetime, time_zone: str) -> datetime:
# zone info installation should already be checked
tz: ZoneInfo | tzinfo
try:
tz = string_to_zoneinfo(time_zone)
except zoneinfo.ZoneInfoNotFoundError:
tz = ZoneInfo(time_zone)
except ZoneInfoNotFoundError:
# try fixed offset, which is not supported by ZoneInfo
tz = _parse_fixed_tz_offset(time_zone)

return dt.astimezone(tz)


@no_type_check
@lru_cache(None)
def string_to_zoneinfo(key: str) -> Any:
"""
Convert a time zone string to a Python ZoneInfo object.

This is a simple wrapper for the zoneinfo.ZoneInfo constructor.
The wrapper is useful because zoneinfo is not available on Python 3.8
and the backports module may not be installed.
"""
return zoneinfo.ZoneInfo(key)


# cache here as we have a single tz per column
# and this function will be called on every conversion
@lru_cache(16)
Expand Down
9 changes: 0 additions & 9 deletions py-polars/polars/dependencies.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
_PYARROW_AVAILABLE = True
_PYDANTIC_AVAILABLE = True
_PYICEBERG_AVAILABLE = True
_ZONEINFO_AVAILABLE = True


class _LazyModule(ModuleType):
Expand Down Expand Up @@ -150,7 +149,6 @@ def _lazy_import(module_name: str) -> tuple[ModuleType, bool]:
import json
import pickle
import subprocess
import zoneinfo

import altair
import deltalake
Expand Down Expand Up @@ -182,11 +180,6 @@ def _lazy_import(module_name: str) -> tuple[ModuleType, bool]:
pyarrow, _PYARROW_AVAILABLE = _lazy_import("pyarrow")
pydantic, _PYDANTIC_AVAILABLE = _lazy_import("pydantic")
pyiceberg, _PYICEBERG_AVAILABLE = _lazy_import("pyiceberg")
zoneinfo, _ZONEINFO_AVAILABLE = (
_lazy_import("zoneinfo")
if sys.version_info >= (3, 9)
else _lazy_import("backports.zoneinfo")
)
gevent, _GEVENT_AVAILABLE = _lazy_import("gevent")


Expand Down Expand Up @@ -308,7 +301,6 @@ def import_optional(
"pydantic",
"pyiceberg",
"pyarrow",
"zoneinfo",
# lazy utilities
"_check_for_numpy",
"_check_for_pandas",
Expand All @@ -324,5 +316,4 @@ def import_optional(
"_NUMPY_AVAILABLE",
"_PANDAS_AVAILABLE",
"_PYARROW_AVAILABLE",
"_ZONEINFO_AVAILABLE",
]
4 changes: 2 additions & 2 deletions py-polars/polars/testing/parametric/strategies/data.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from collections.abc import Mapping
from datetime import datetime, timedelta, timezone
from typing import TYPE_CHECKING, Any, Literal
from zoneinfo import ZoneInfo

import hypothesis.strategies as st
from hypothesis.errors import InvalidArgument
Expand All @@ -25,7 +26,6 @@
U32_MAX,
U64_MAX,
)
from polars._utils.convert import string_to_zoneinfo
from polars.datatypes import (
Array,
Binary,
Expand Down Expand Up @@ -167,7 +167,7 @@ def datetimes(
if time_zone is None:
return st.datetimes(min_value, max_value)

time_zone_info = string_to_zoneinfo(time_zone)
time_zone_info = ZoneInfo(time_zone)

# Make sure time zone offsets do not cause out-of-bound datetimes
if time_unit == "ns":
Expand Down
2 changes: 1 addition & 1 deletion py-polars/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ cloudpickle = ["cloudpickle"]
graph = ["matplotlib"]
plot = ["altair >= 5.4.0"]
style = ["great-tables >= 0.8.0"]
timezone = ["backports.zoneinfo; python_version < '3.9'", "tzdata; platform_system == 'Windows'"]
timezone = ["tzdata; platform_system == 'Windows'"]

# GPU Engine
gpu = ["cudf-polars-cu12"]
Expand Down
7 changes: 3 additions & 4 deletions py-polars/requirements-dev.txt
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,11 @@ pyarrow
pydantic>=2.0.0
numba
# Datetime / time zones
backports.zoneinfo; python_version < '3.9'
tzdata; platform_system == 'Windows'
# Database
sqlalchemy
adbc-driver-manager; python_version >= '3.9' and platform_system != 'Windows'
adbc-driver-sqlite; python_version >= '3.9' and platform_system != 'Windows'
adbc-driver-manager; platform_system != 'Windows'
adbc-driver-sqlite; platform_system != 'Windows'
aiosqlite
connectorx
kuzu
Expand All @@ -49,7 +48,7 @@ zstandard
# Plotting
altair>=5.4.0
# Styling
great-tables>=0.8.0; python_version >= '3.9'
great-tables>=0.8.0
# Async
gevent
# Graph
Expand Down
4 changes: 1 addition & 3 deletions py-polars/tests/unit/constructors/test_constructors.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from decimal import Decimal
from random import shuffle
from typing import TYPE_CHECKING, Any, Literal, NamedTuple
from zoneinfo import ZoneInfo

import numpy as np
import pandas as pd
Expand All @@ -23,16 +24,13 @@
if TYPE_CHECKING:
import sys
from collections.abc import Callable
from zoneinfo import ZoneInfo

from polars._typing import PolarsDataType

if sys.version_info >= (3, 11):
from typing import Self
else:
from typing_extensions import Self
else:
from polars._utils.convert import string_to_zoneinfo as ZoneInfo


# -----------------------------------------------------------------------------------
Expand Down
4 changes: 1 addition & 3 deletions py-polars/tests/unit/dataframe/test_df.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from io import BytesIO
from operator import floordiv, truediv
from typing import TYPE_CHECKING, Any, Callable, cast
from zoneinfo import ZoneInfo

import numpy as np
import pyarrow as pa
Expand All @@ -34,12 +35,9 @@

if TYPE_CHECKING:
from collections.abc import Iterator, Sequence
from zoneinfo import ZoneInfo

from polars import Expr
from polars._typing import JoinStrategy, UniqueKeepStrategy
else:
from polars._utils.convert import string_to_zoneinfo as ZoneInfo


def test_version() -> None:
Expand Down
4 changes: 1 addition & 3 deletions py-polars/tests/unit/dataframe/test_upsample.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

from datetime import datetime
from typing import TYPE_CHECKING
from zoneinfo import ZoneInfo

import pytest

Expand All @@ -11,11 +12,8 @@

if TYPE_CHECKING:
from datetime import timezone
from zoneinfo import ZoneInfo

from polars._typing import FillNullStrategy, PolarsIntegerType
else:
from polars._utils.convert import string_to_zoneinfo as ZoneInfo


@pytest.mark.parametrize(
Expand Down
5 changes: 1 addition & 4 deletions py-polars/tests/unit/datatypes/test_temporal.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import io
from datetime import date, datetime, time, timedelta, timezone
from typing import TYPE_CHECKING, Any, cast
from zoneinfo import ZoneInfo

import hypothesis.strategies as st
import numpy as np
Expand All @@ -27,15 +28,11 @@
from tests.unit.conftest import DATETIME_DTYPES, TEMPORAL_DTYPES

if TYPE_CHECKING:
from zoneinfo import ZoneInfo

from polars._typing import (
Ambiguous,
PolarsTemporalType,
TimeUnit,
)
else:
from polars._utils.convert import string_to_zoneinfo as ZoneInfo


def test_fill_null() -> None:
Expand Down
5 changes: 1 addition & 4 deletions py-polars/tests/unit/expr/test_exprs.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from datetime import date, datetime, timedelta, timezone
from itertools import permutations
from typing import TYPE_CHECKING, Any, cast
from zoneinfo import ZoneInfo

import pytest

Expand All @@ -18,11 +19,7 @@
)

if TYPE_CHECKING:
from zoneinfo import ZoneInfo

from polars._typing import PolarsDataType
else:
from polars._utils.convert import string_to_zoneinfo as ZoneInfo


def test_arg_true() -> None:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

from datetime import datetime
from typing import TYPE_CHECKING
from zoneinfo import ZoneInfo

import pytest

Expand All @@ -10,11 +11,7 @@
from polars.testing import assert_series_equal

if TYPE_CHECKING:
from zoneinfo import ZoneInfo

from polars._typing import TimeUnit
else:
from polars._utils.convert import string_to_zoneinfo as ZoneInfo


def test_date_datetime() -> None:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

from datetime import date, datetime, timedelta
from typing import TYPE_CHECKING
from zoneinfo import ZoneInfo

import hypothesis.strategies as st
import pytest
Expand All @@ -13,11 +14,7 @@
from polars.testing import assert_frame_equal, assert_series_equal

if TYPE_CHECKING:
from zoneinfo import ZoneInfo

from polars._typing import ClosedInterval, PolarsDataType, TimeUnit
else:
from polars._utils.convert import string_to_zoneinfo as ZoneInfo


def test_datetime_range() -> None:
Expand Down
Loading
Loading