diff --git a/py-polars/polars/__init__.py b/py-polars/polars/__init__.py index cbf3f88087f0..e869efec4370 100644 --- a/py-polars/polars/__init__.py +++ b/py-polars/polars/__init__.py @@ -91,7 +91,6 @@ SQLInterfaceError, SQLSyntaxError, StructFieldNotFoundError, - TimeZoneAwareConstructorWarning, UnstableWarning, ) from polars.expr import Expr @@ -247,7 +246,6 @@ "ChronoFormatWarning", "MapWithoutReturnDtypeWarning", "PolarsWarning", - "TimeZoneAwareConstructorWarning", "UnstableWarning", # core classes "DataFrame", diff --git a/py-polars/polars/_utils/construction/series.py b/py-polars/polars/_utils/construction/series.py index 87d888dc410a..e68e4d4f275b 100644 --- a/py-polars/polars/_utils/construction/series.py +++ b/py-polars/polars/_utils/construction/series.py @@ -1,7 +1,6 @@ from __future__ import annotations import contextlib -import warnings from datetime import date, datetime, time, timedelta from decimal import Decimal as PyDecimal from itertools import islice @@ -24,7 +23,6 @@ is_simple_numpy_backed_pandas_series, ) from polars._utils.various import ( - find_stacklevel, range_to_series, ) from polars._utils.wrap import wrap_s @@ -64,7 +62,6 @@ from polars.dependencies import numpy as np from polars.dependencies import pandas as pd from polars.dependencies import pyarrow as pa -from polars.exceptions import TimeZoneAwareConstructorWarning with contextlib.suppress(ImportError): # Module not available when building docs from polars.polars import PySeries @@ -74,30 +71,6 @@ from polars.dependencies import pandas as pd from polars.type_aliases import PolarsDataType -TZ_NAIVE_VALUES_WITH_TZ_AWARE_DTYPE_MSG = ( - "Constructing a Series with time-zone-naive " - "datetimes and a time-zone-aware dtype results in a Series where " - "the datetimes are converted to the given time zone as if starting " - "from UTC.\n\n" - "Note: this is a breaking change since pre-1.0.0 behaviour.\n\n" - "Hint: to silence this warning, you can filter out " - "warnings of class pl.TimeZoneAwareConstructorWarning.\n" - "Alternatively, you can replace " - "`pl.Series(values, dtype=pl.Datetime({}, {}))` with one of:\n" - "- `pl.Series(values, dtype=pl.Datetime(time_unit)).dt.replace_time_zone(time_zone)`\n" - "- `pl.Series(values, dtype=pl.Datetime(time_unit)).dt.convert_time_zone(time_zone)`\n" - "depending on whether you want to replace or convert the time zone." -) -TZ_AWARE_VALUES_WITH_TZ_NAIVE_DTYPE_MSG = ( - "Constructing a Series with time-zone-aware " - "datetimes and a time-zone-naive dtype results in a Series where " - "the datetimes are converted to UTC.\n\n" - "Hint: to silence this warning, you can filter out " - "warnings of class pl.TimeZoneAwareConstructorWarning.\n" - "Alternatively, you can set the time zone in the `dtype`, e.g.:\n" - " pl.Series(values, dtype=pl.Datetime({}, 'UTC'))`" -) - def sequence_to_pyseries( name: str, @@ -229,34 +202,11 @@ def sequence_to_pyseries( if (values_dtype == Date) & (dtype == Datetime): result = s.cast(Datetime(time_unit or "us")) if time_zone is not None: - if time_zone != "UTC": - warnings.warn( - TZ_NAIVE_VALUES_WITH_TZ_AWARE_DTYPE_MSG.format( - time_unit or "us", time_zone - ), - TimeZoneAwareConstructorWarning, - stacklevel=find_stacklevel(), - ) result = result.dt.convert_time_zone(time_zone) return result._s if (dtype == Datetime) and (value.tzinfo is not None or time_zone is not None): - values_tz = str(value.tzinfo) if value.tzinfo is not None else None dtype_tz = time_zone - if values_tz is not None and dtype_tz is None and values_tz != "UTC": - warnings.warn( - TZ_AWARE_VALUES_WITH_TZ_NAIVE_DTYPE_MSG.format(time_unit or "us"), - TimeZoneAwareConstructorWarning, - stacklevel=find_stacklevel(), - ) - if values_tz is None and dtype_tz is not None and dtype_tz != "UTC": - warnings.warn( - TZ_NAIVE_VALUES_WITH_TZ_AWARE_DTYPE_MSG.format( - time_unit or "us", time_zone - ), - TimeZoneAwareConstructorWarning, - stacklevel=find_stacklevel(), - ) return s.dt.convert_time_zone(dtype_tz or "UTC")._s return s._s diff --git a/py-polars/polars/exceptions.py b/py-polars/polars/exceptions.py index 5adbf11e95c8..f839c828cdd0 100644 --- a/py-polars/polars/exceptions.py +++ b/py-polars/polars/exceptions.py @@ -145,10 +145,6 @@ class PolarsInefficientMapWarning(PolarsWarning): # type: ignore[misc] """Warning issued when a potentially slow `map_*` operation is performed.""" -class TimeZoneAwareConstructorWarning(PolarsWarning): # type: ignore[misc] - """Warning issued when constructing Series from non-UTC time-zone-aware inputs.""" - - class UnstableWarning(PolarsWarning): # type: ignore[misc] """Warning issued when unstable functionality is used.""" diff --git a/py-polars/polars/testing/parametric/strategies/core.py b/py-polars/polars/testing/parametric/strategies/core.py index d5996d5f9b9d..df4d27e500b0 100644 --- a/py-polars/polars/testing/parametric/strategies/core.py +++ b/py-polars/polars/testing/parametric/strategies/core.py @@ -1,6 +1,5 @@ from __future__ import annotations -import warnings from dataclasses import dataclass from typing import TYPE_CHECKING, Any, Collection, Mapping, Sequence, overload @@ -10,7 +9,6 @@ from polars._utils.deprecation import issue_deprecation_warning from polars.dataframe import DataFrame from polars.datatypes import DataType, DataTypeClass, Null -from polars.exceptions import TimeZoneAwareConstructorWarning from polars.series import Series from polars.string_cache import StringCache from polars.testing.parametric.strategies._utils import flexhash @@ -205,13 +203,7 @@ def series( # noqa: D417 ) ) - with warnings.catch_warnings(): - warnings.filterwarnings( - "ignore", - "Constructing a Series with time-zone-naive", - category=TimeZoneAwareConstructorWarning, - ) - s = Series(name=name, values=values, dtype=dtype) + s = Series(name=name, values=values, dtype=dtype) # Apply chunking if allow_chunks and size > 1 and draw(st.booleans()): diff --git a/py-polars/tests/unit/constructors/test_constructors.py b/py-polars/tests/unit/constructors/test_constructors.py index 0910b2204f29..47398b04e1eb 100644 --- a/py-polars/tests/unit/constructors/test_constructors.py +++ b/py-polars/tests/unit/constructors/test_constructors.py @@ -16,7 +16,6 @@ from polars._utils.construction.utils import try_get_type_hints from polars.datatypes import PolarsDataType, numpy_char_code_to_dtype from polars.dependencies import dataclasses, pydantic -from polars.exceptions import TimeZoneAwareConstructorWarning from polars.testing import assert_frame_equal, assert_series_equal if TYPE_CHECKING: @@ -897,17 +896,15 @@ def test_init_1d_sequence() -> None: [datetime(2020, 1, 1, tzinfo=timezone.utc)], schema={"ts": pl.Datetime("ms")} ) assert df.schema == {"ts": pl.Datetime("ms", "UTC")} - with pytest.warns(TimeZoneAwareConstructorWarning, match="converted to UTC"): - df = pl.DataFrame( - [datetime(2020, 1, 1, tzinfo=timezone(timedelta(hours=1)))], - schema={"ts": pl.Datetime("ms")}, - ) + df = pl.DataFrame( + [datetime(2020, 1, 1, tzinfo=timezone(timedelta(hours=1)))], + schema={"ts": pl.Datetime("ms")}, + ) assert df.schema == {"ts": pl.Datetime("ms", "UTC")} - with pytest.warns(TimeZoneAwareConstructorWarning, match="converted to UTC"): - df = pl.DataFrame( - [datetime(2020, 1, 1, tzinfo=ZoneInfo("Asia/Kathmandu"))], - schema={"ts": pl.Datetime("ms")}, - ) + df = pl.DataFrame( + [datetime(2020, 1, 1, tzinfo=ZoneInfo("Asia/Kathmandu"))], + schema={"ts": pl.Datetime("ms")}, + ) assert df.schema == {"ts": pl.Datetime("ms", "UTC")} diff --git a/py-polars/tests/unit/constructors/test_series.py b/py-polars/tests/unit/constructors/test_series.py index 73a27afe5853..c2055090c16e 100644 --- a/py-polars/tests/unit/constructors/test_series.py +++ b/py-polars/tests/unit/constructors/test_series.py @@ -105,15 +105,13 @@ def test_series_init_ambiguous_datetime() -> None: value = datetime(2001, 10, 28, 2) dtype = pl.Datetime(time_zone="Europe/Belgrade") - with pytest.warns(pl.TimeZoneAwareConstructorWarning, match="converted to"): - result = pl.Series([value], dtype=dtype, strict=True) + result = pl.Series([value], dtype=dtype, strict=True) expected = pl.Series([datetime(2001, 10, 28, 3)]).dt.replace_time_zone( "Europe/Belgrade" ) assert_series_equal(result, expected) - with pytest.warns(pl.TimeZoneAwareConstructorWarning, match="converted to"): - result = pl.Series([value], dtype=dtype, strict=False) + result = pl.Series([value], dtype=dtype, strict=False) assert_series_equal(result, expected) @@ -121,20 +119,15 @@ def test_series_init_nonexistent_datetime() -> None: value = datetime(2024, 3, 31, 2, 30) dtype = pl.Datetime(time_zone="Europe/Amsterdam") - with pytest.warns( - pl.TimeZoneAwareConstructorWarning, match="converted to the given time zone" - ): - pl.Series([value], dtype=dtype, strict=True) - - with pytest.warns( - pl.TimeZoneAwareConstructorWarning, match="converted to the given time zone" - ): - result = pl.Series([value], dtype=dtype, strict=False) + result = pl.Series([value], dtype=dtype, strict=True) expected = pl.Series([datetime(2024, 3, 31, 4, 30)]).dt.replace_time_zone( "Europe/Amsterdam" ) assert_series_equal(result, expected) + result = pl.Series([value], dtype=dtype, strict=False) + assert_series_equal(result, expected) + # https://github.com/pola-rs/polars/issues/15518 def test_series_init_np_temporal_with_nat_15518() -> None: diff --git a/py-polars/tests/unit/dataframe/test_df.py b/py-polars/tests/unit/dataframe/test_df.py index ae8220733419..5cd805e3ca85 100644 --- a/py-polars/tests/unit/dataframe/test_df.py +++ b/py-polars/tests/unit/dataframe/test_df.py @@ -1,6 +1,5 @@ from __future__ import annotations -import contextlib import sys import typing from collections import OrderedDict @@ -18,7 +17,7 @@ import polars.selectors as cs from polars._utils.construction import iterable_to_pydf from polars.datatypes import DTYPE_TEMPORAL_UNITS, INTEGER_DTYPES -from polars.exceptions import ComputeError, TimeZoneAwareConstructorWarning +from polars.exceptions import ComputeError from polars.testing import ( assert_frame_equal, assert_frame_not_equal, @@ -2449,17 +2448,15 @@ def test_init_datetimes_with_timezone() -> None: "dtype_time_zone", "expected_time_zone", "expected_item", - "warn", ), [ - (None, "", None, None, datetime(2020, 1, 1), False), + (None, "", None, None, datetime(2020, 1, 1)), ( timezone(timedelta(hours=-8)), "-08:00", "UTC", "UTC", datetime(2020, 1, 1, 8, tzinfo=timezone.utc), - False, ), ( timezone(timedelta(hours=-8)), @@ -2467,7 +2464,6 @@ def test_init_datetimes_with_timezone() -> None: None, "UTC", datetime(2020, 1, 1, 8, tzinfo=timezone.utc), - True, ), ], ) @@ -2477,19 +2473,11 @@ def test_init_vs_strptime_consistency( dtype_time_zone: str | None, expected_time_zone: str, expected_item: datetime, - warn: bool, ) -> None: - msg = r"converted to UTC" - context_manager: contextlib.AbstractContextManager[pytest.WarningsRecorder | None] - if warn: - context_manager = pytest.warns(TimeZoneAwareConstructorWarning, match=msg) - else: - context_manager = contextlib.nullcontext() - with context_manager: - result_init = pl.Series( - [datetime(2020, 1, 1, tzinfo=tzinfo)], - dtype=pl.Datetime("us", dtype_time_zone), - ) + result_init = pl.Series( + [datetime(2020, 1, 1, tzinfo=tzinfo)], + dtype=pl.Datetime("us", dtype_time_zone), + ) result_strptime = pl.Series([f"2020-01-01 00:00{offset}"]).str.strptime( pl.Datetime("us", dtype_time_zone) ) diff --git a/py-polars/tests/unit/datatypes/test_temporal.py b/py-polars/tests/unit/datatypes/test_temporal.py index 03ce62c4e8a6..7f6c9c404690 100644 --- a/py-polars/tests/unit/datatypes/test_temporal.py +++ b/py-polars/tests/unit/datatypes/test_temporal.py @@ -1,6 +1,5 @@ from __future__ import annotations -import contextlib import io from datetime import date, datetime, time, timedelta, timezone from typing import TYPE_CHECKING, Any, cast @@ -16,7 +15,6 @@ ComputeError, InvalidOperationError, PolarsInefficientMapWarning, - TimeZoneAwareConstructorWarning, ) from polars.testing import ( assert_frame_equal, @@ -340,10 +338,9 @@ def test_datetime_consistency() -> None: datetime(3099, 12, 31, 23, 59, 59, 123456, tzinfo=ZoneInfo("Asia/Kathmandu")), datetime(9999, 12, 31, 23, 59, 59, 999999, tzinfo=ZoneInfo("Asia/Kathmandu")), ] - with pytest.warns(TimeZoneAwareConstructorWarning, match="converted to UTC"): - ddf = pl.DataFrame({"dtm": test_data}).with_columns( - pl.col("dtm").dt.nanosecond().alias("ns") - ) + ddf = pl.DataFrame({"dtm": test_data}).with_columns( + pl.col("dtm").dt.nanosecond().alias("ns") + ) assert ddf.rows() == [ (test_data[0], 555555000), (test_data[1], 986754000), @@ -357,10 +354,9 @@ def test_datetime_consistency() -> None: datetime(2021, 11, 7, 1, 0, fold=1, tzinfo=ZoneInfo("US/Central")), datetime(2021, 11, 7, 2, 0, tzinfo=ZoneInfo("US/Central")), ] - with pytest.warns(TimeZoneAwareConstructorWarning, match="converted to UTC"): - ddf = pl.DataFrame({"dtm": test_data}).select( - pl.col("dtm").dt.convert_time_zone("US/Central") - ) + ddf = pl.DataFrame({"dtm": test_data}).select( + pl.col("dtm").dt.convert_time_zone("US/Central") + ) assert ddf.rows() == [ (test_data[0],), (test_data[1],), @@ -1277,8 +1273,7 @@ def test_tz_datetime_duration_arithm_5221() -> None: def test_auto_infer_time_zone() -> None: dt = datetime(2022, 10, 17, 10, tzinfo=ZoneInfo("Asia/Shanghai")) - with pytest.warns(TimeZoneAwareConstructorWarning, match="converted to UTC"): - s = pl.Series([dt]) + s = pl.Series([dt]) assert s.dtype == pl.Datetime("us", "UTC") assert s[0] == dt @@ -2324,47 +2319,37 @@ def test_series_is_temporal() -> None: @pytest.mark.parametrize( - ("time_zone", "warn"), + "time_zone", [ - (None, False), - (timezone.utc, False), - ("America/Caracas", True), - ("Asia/Kathmandu", True), - ("Asia/Taipei", True), - ("Europe/Amsterdam", True), - ("Europe/Lisbon", True), - ("Indian/Maldives", True), - ("Pacific/Norfolk", True), - ("Pacific/Samoa", True), - ("Turkey", True), - ("US/Eastern", True), - ("UTC", False), - ("Zulu", True), + None, + timezone.utc, + "America/Caracas", + "Asia/Kathmandu", + "Asia/Taipei", + "Europe/Amsterdam", + "Europe/Lisbon", + "Indian/Maldives", + "Pacific/Norfolk", + "Pacific/Samoa", + "Turkey", + "US/Eastern", + "UTC", + "Zulu", ], ) -def test_misc_precision_any_value_conversion(time_zone: Any, warn: bool) -> None: - context_manager: contextlib.AbstractContextManager[pytest.WarningsRecorder | None] - msg = r"converted to UTC" - if warn: - context_manager = pytest.warns(TimeZoneAwareConstructorWarning, match=msg) - else: - context_manager = contextlib.nullcontext() - +def test_misc_precision_any_value_conversion(time_zone: Any) -> None: tz = ZoneInfo(time_zone) if isinstance(time_zone, str) else time_zone # default precision (μs) dt = datetime(2514, 5, 30, 1, 53, 4, 986754, tzinfo=tz) - with context_manager: - assert pl.Series([dt]).to_list() == [dt] + assert pl.Series([dt]).to_list() == [dt] # ms precision dt = datetime(2243, 1, 1, 0, 0, 0, 1000, tzinfo=tz) - with context_manager: - assert pl.Series([dt]).cast(pl.Datetime("ms", time_zone)).to_list() == [dt] + assert pl.Series([dt]).cast(pl.Datetime("ms", time_zone)).to_list() == [dt] # ns precision dt = datetime(2256, 1, 1, 0, 0, 0, 1, tzinfo=tz) - with context_manager: - assert pl.Series([dt]).cast(pl.Datetime("ns", time_zone)).to_list() == [dt] + assert pl.Series([dt]).cast(pl.Datetime("ns", time_zone)).to_list() == [dt] @pytest.mark.parametrize( diff --git a/py-polars/tests/unit/functions/range/test_datetime_range.py b/py-polars/tests/unit/functions/range/test_datetime_range.py index 2b2252e18ee7..fc6c2d6938ef 100644 --- a/py-polars/tests/unit/functions/range/test_datetime_range.py +++ b/py-polars/tests/unit/functions/range/test_datetime_range.py @@ -7,7 +7,6 @@ import polars as pl from polars.datatypes import DTYPE_TEMPORAL_UNITS -from polars.exceptions import TimeZoneAwareConstructorWarning from polars.testing import assert_frame_equal, assert_series_equal if TYPE_CHECKING: @@ -107,20 +106,19 @@ def test_datetime_range_invalid_time_unit() -> None: def test_datetime_range_lazy_time_zones_warning() -> None: start = datetime(2020, 1, 1, tzinfo=ZoneInfo("Asia/Kathmandu")) stop = datetime(2020, 1, 2, tzinfo=ZoneInfo("Asia/Kathmandu")) - with pytest.warns(TimeZoneAwareConstructorWarning, match="converted to UTC"): - ( - pl.DataFrame({"start": [start], "stop": [stop]}) - .with_columns( - pl.datetime_range( - start, - stop, - interval="678d", - eager=False, - time_zone="Pacific/Tarawa", - ) + ( + pl.DataFrame({"start": [start], "stop": [stop]}) + .with_columns( + pl.datetime_range( + start, + stop, + interval="678d", + eager=False, + time_zone="Pacific/Tarawa", ) - .lazy() ) + .lazy() + ) @pytest.mark.parametrize("low", ["start", pl.col("start")]) diff --git a/py-polars/tests/unit/operations/namespaces/test_strptime.py b/py-polars/tests/unit/operations/namespaces/test_strptime.py index 058e343b529e..3189106c2b0d 100644 --- a/py-polars/tests/unit/operations/namespaces/test_strptime.py +++ b/py-polars/tests/unit/operations/namespaces/test_strptime.py @@ -6,14 +6,13 @@ from __future__ import annotations -import contextlib from datetime import date, datetime, time, timedelta, timezone from typing import TYPE_CHECKING import pytest import polars as pl -from polars.exceptions import ComputeError, TimeZoneAwareConstructorWarning +from polars.exceptions import ComputeError from polars.testing import assert_series_equal if TYPE_CHECKING: @@ -176,13 +175,6 @@ def test_non_exact_short_elements_10223(value: str, attr: str) -> None: def test_to_datetime_non_exact_strptime( offset: str, time_zone: str | None, tzinfo: timezone | None, format: str ) -> None: - msg = "converted to UTC" - context_manager: contextlib.AbstractContextManager[pytest.WarningsRecorder | None] - if offset: - context_manager = pytest.warns(TimeZoneAwareConstructorWarning, match=msg) - else: - context_manager = contextlib.nullcontext() - s = pl.Series( "a", [ @@ -194,30 +186,28 @@ def test_to_datetime_non_exact_strptime( ) result = s.str.to_datetime(format, strict=False, exact=True) - with context_manager: - expected = pl.Series( - "a", - [ - datetime(2022, 1, 16, tzinfo=tzinfo), - datetime(2022, 1, 17, tzinfo=tzinfo), - None, - None, - ], - ) + expected = pl.Series( + "a", + [ + datetime(2022, 1, 16, tzinfo=tzinfo), + datetime(2022, 1, 17, tzinfo=tzinfo), + None, + None, + ], + ) assert_series_equal(result, expected) assert result.dtype == pl.Datetime("us", time_zone) result = s.str.to_datetime(format, strict=False, exact=False) - with context_manager: - expected = pl.Series( - "a", - [ - datetime(2022, 1, 16, tzinfo=tzinfo), - datetime(2022, 1, 17, tzinfo=tzinfo), - datetime(2022, 1, 18, tzinfo=tzinfo), - datetime(2022, 1, 19, tzinfo=tzinfo), - ], - ) + expected = pl.Series( + "a", + [ + datetime(2022, 1, 16, tzinfo=tzinfo), + datetime(2022, 1, 17, tzinfo=tzinfo), + datetime(2022, 1, 18, tzinfo=tzinfo), + datetime(2022, 1, 19, tzinfo=tzinfo), + ], + ) assert_series_equal(result, expected) assert result.dtype == pl.Datetime("us", time_zone) diff --git a/py-polars/tests/unit/test_config.py b/py-polars/tests/unit/test_config.py index d193ed6435d9..0b72ab3e8816 100644 --- a/py-polars/tests/unit/test_config.py +++ b/py-polars/tests/unit/test_config.py @@ -826,6 +826,7 @@ def test_warn_unstable(recwarn: pytest.WarningsRecorder) -> None: ("POLARS_TABLE_WIDTH", "set_tbl_width_chars", 80, "80"), ("POLARS_VERBOSE", "set_verbose", True, "1"), ("POLARS_WARN_UNSTABLE", "warn_unstable", True, "1"), + ("POLARS_MIGRATION_MODE", "set_migration_mode", True, "1"), ], ) def test_unset_config_env_vars(