Skip to content

DEPR: Remove sql.execute, *args/**kwargs in resample, unrecognized timezones #57241

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

Merged
merged 7 commits into from
Feb 6, 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
3 changes: 3 additions & 0 deletions doc/source/whatsnew/v3.0.0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,11 @@ Removal of prior version deprecations/changes
- Removed ``DataFrameGroupBy.grouper`` and ``SeriesGroupBy.grouper`` (:issue:`56521`)
- Removed ``axis`` argument from :meth:`DataFrame.groupby`, :meth:`Series.groupby`, :meth:`DataFrame.rolling`, :meth:`Series.rolling`, :meth:`DataFrame.resample`, and :meth:`Series.resample` (:issue:`51203`)
- Removed ``axis`` argument from all groupby operations (:issue:`50405`)
- Removed ``pandas.io.sql.execute`` (:issue:`50185`)
- Removed deprecated argument ``obj`` in :meth:`.DataFrameGroupBy.get_group` and :meth:`.SeriesGroupBy.get_group` (:issue:`53545`)
- Removed the ``ArrayManager`` (:issue:`55043`)
- Removed unused arguments ``*args`` and ``**kwargs`` in :class:`Resampler` methods (:issue:`50977`)
- Unrecognized timezones when parsing strings to datetimes now raises a ``ValueError`` (:issue:`51477`)

.. ---------------------------------------------------------------------------
.. _whatsnew_300.performance:
Expand Down
11 changes: 3 additions & 8 deletions pandas/_libs/tslibs/parsing.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -733,15 +733,10 @@ cdef datetime dateutil_parse(
)
elif res.tzname is not None:
# e.g. "1994 Jan 15 05:16 FOO" where FOO is not recognized
# GH#18702
warnings.warn(
# GH#18702, # GH 50235 enforced in 3.0
raise ValueError(
f'Parsed string "{timestr}" included an un-recognized timezone '
f'"{res.tzname}". Dropping unrecognized timezones is deprecated; '
"in a future version this will raise. Instead pass the string "
"without the timezone, then use .tz_localize to convert to a "
"recognized timezone.",
FutureWarning,
stacklevel=find_stack_level()
f'"{res.tzname}".'
)

out_bestunit[0] = attrname_to_npy_unit[reso]
Expand Down
97 changes: 3 additions & 94 deletions pandas/core/resample.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@
)
from pandas._libs.tslibs.dtypes import freq_to_period_freqstr
from pandas._typing import NDFrameT
from pandas.compat.numpy import function as nv
from pandas.errors import AbstractMethodError
from pandas.util._decorators import (
Appender,
Expand Down Expand Up @@ -1156,8 +1155,6 @@ def sum(
self,
numeric_only: bool = False,
min_count: int = 0,
*args,
**kwargs,
):
"""
Compute sum of group values.
Expand Down Expand Up @@ -1195,17 +1192,13 @@ def sum(
2023-02-01 7
Freq: MS, dtype: int64
"""
maybe_warn_args_and_kwargs(type(self), "sum", args, kwargs)
nv.validate_resampler_func("sum", args, kwargs)
return self._downsample("sum", numeric_only=numeric_only, min_count=min_count)

@final
def prod(
self,
numeric_only: bool = False,
min_count: int = 0,
*args,
**kwargs,
):
"""
Compute prod of group values.
Expand Down Expand Up @@ -1243,17 +1236,13 @@ def prod(
2023-02-01 12
Freq: MS, dtype: int64
"""
maybe_warn_args_and_kwargs(type(self), "prod", args, kwargs)
nv.validate_resampler_func("prod", args, kwargs)
return self._downsample("prod", numeric_only=numeric_only, min_count=min_count)

@final
def min(
self,
numeric_only: bool = False,
min_count: int = 0,
*args,
**kwargs,
):
"""
Compute min value of group.
Expand All @@ -1277,18 +1266,13 @@ def min(
2023-02-01 3
Freq: MS, dtype: int64
"""

maybe_warn_args_and_kwargs(type(self), "min", args, kwargs)
nv.validate_resampler_func("min", args, kwargs)
return self._downsample("min", numeric_only=numeric_only, min_count=min_count)

@final
def max(
self,
numeric_only: bool = False,
min_count: int = 0,
*args,
**kwargs,
):
"""
Compute max value of group.
Expand All @@ -1312,8 +1296,6 @@ def max(
2023-02-01 4
Freq: MS, dtype: int64
"""
maybe_warn_args_and_kwargs(type(self), "max", args, kwargs)
nv.validate_resampler_func("max", args, kwargs)
return self._downsample("max", numeric_only=numeric_only, min_count=min_count)

@final
Expand All @@ -1323,11 +1305,7 @@ def first(
numeric_only: bool = False,
min_count: int = 0,
skipna: bool = True,
*args,
**kwargs,
):
maybe_warn_args_and_kwargs(type(self), "first", args, kwargs)
nv.validate_resampler_func("first", args, kwargs)
return self._downsample(
"first", numeric_only=numeric_only, min_count=min_count, skipna=skipna
)
Expand All @@ -1339,28 +1317,20 @@ def last(
numeric_only: bool = False,
min_count: int = 0,
skipna: bool = True,
*args,
**kwargs,
):
maybe_warn_args_and_kwargs(type(self), "last", args, kwargs)
nv.validate_resampler_func("last", args, kwargs)
return self._downsample(
"last", numeric_only=numeric_only, min_count=min_count, skipna=skipna
)

@final
@doc(GroupBy.median)
def median(self, numeric_only: bool = False, *args, **kwargs):
maybe_warn_args_and_kwargs(type(self), "median", args, kwargs)
nv.validate_resampler_func("median", args, kwargs)
def median(self, numeric_only: bool = False):
return self._downsample("median", numeric_only=numeric_only)

@final
def mean(
self,
numeric_only: bool = False,
*args,
**kwargs,
):
"""
Compute mean of groups, excluding missing values.
Expand Down Expand Up @@ -1395,17 +1365,13 @@ def mean(
2023-02-01 3.5
Freq: MS, dtype: float64
"""
maybe_warn_args_and_kwargs(type(self), "mean", args, kwargs)
nv.validate_resampler_func("mean", args, kwargs)
return self._downsample("mean", numeric_only=numeric_only)

@final
def std(
self,
ddof: int = 1,
numeric_only: bool = False,
*args,
**kwargs,
):
"""
Compute standard deviation of groups, excluding missing values.
Expand Down Expand Up @@ -1443,17 +1409,13 @@ def std(
2023-02-01 2.645751
Freq: MS, dtype: float64
"""
maybe_warn_args_and_kwargs(type(self), "std", args, kwargs)
nv.validate_resampler_func("std", args, kwargs)
return self._downsample("std", ddof=ddof, numeric_only=numeric_only)

@final
def var(
self,
ddof: int = 1,
numeric_only: bool = False,
*args,
**kwargs,
):
"""
Compute variance of groups, excluding missing values.
Expand Down Expand Up @@ -1497,8 +1459,6 @@ def var(
2023-02-01 4.666667
Freq: MS, dtype: float64
"""
maybe_warn_args_and_kwargs(type(self), "var", args, kwargs)
nv.validate_resampler_func("var", args, kwargs)
return self._downsample("var", ddof=ddof, numeric_only=numeric_only)

@final
Expand All @@ -1507,23 +1467,12 @@ def sem(
self,
ddof: int = 1,
numeric_only: bool = False,
*args,
**kwargs,
):
maybe_warn_args_and_kwargs(type(self), "sem", args, kwargs)
nv.validate_resampler_func("sem", args, kwargs)
return self._downsample("sem", ddof=ddof, numeric_only=numeric_only)

@final
@doc(GroupBy.ohlc)
def ohlc(
self,
*args,
**kwargs,
):
maybe_warn_args_and_kwargs(type(self), "ohlc", args, kwargs)
nv.validate_resampler_func("ohlc", args, kwargs)

def ohlc(self):
ax = self.ax
obj = self._obj_with_exclusions
if len(ax) == 0:
Expand All @@ -1544,13 +1493,7 @@ def ohlc(

@final
@doc(SeriesGroupBy.nunique)
def nunique(
self,
*args,
**kwargs,
):
maybe_warn_args_and_kwargs(type(self), "nunique", args, kwargs)
nv.validate_resampler_func("nunique", args, kwargs)
def nunique(self):
return self._downsample("nunique")

@final
Expand Down Expand Up @@ -2874,40 +2817,6 @@ def _asfreq_compat(index: DatetimeIndex | PeriodIndex | TimedeltaIndex, freq):
return new_index


def maybe_warn_args_and_kwargs(cls, kernel: str, args, kwargs) -> None:
"""
Warn for deprecation of args and kwargs in resample functions.

Parameters
----------
cls : type
Class to warn about.
kernel : str
Operation name.
args : tuple or None
args passed by user. Will be None if and only if kernel does not have args.
kwargs : dict or None
kwargs passed by user. Will be None if and only if kernel does not have kwargs.
"""
warn_args = args is not None and len(args) > 0
warn_kwargs = kwargs is not None and len(kwargs) > 0
if warn_args and warn_kwargs:
msg = "args and kwargs"
elif warn_args:
msg = "args"
elif warn_kwargs:
msg = "kwargs"
else:
return
warnings.warn(
f"Passing additional {msg} to {cls.__name__}.{kernel} has "
"no impact on the result and is deprecated. This will "
"raise a TypeError in a future version of pandas.",
category=FutureWarning,
stacklevel=find_stack_level(),
)


def _apply(
grouped: GroupBy, how: Callable, *args, include_groups: bool, **kwargs
) -> DataFrame:
Expand Down
31 changes: 0 additions & 31 deletions pandas/io/sql.py
Original file line number Diff line number Diff line change
Expand Up @@ -235,37 +235,6 @@ def _wrap_result_adbc(
return df


def execute(sql, con, params=None):
"""
Execute the given SQL query using the provided connection object.

Parameters
----------
sql : string
SQL query to be executed.
con : SQLAlchemy connection or sqlite3 connection
If a DBAPI2 object, only sqlite3 is supported.
params : list or tuple, optional, default: None
List of parameters to pass to execute method.

Returns
-------
Results Iterable
"""
warnings.warn(
"`pandas.io.sql.execute` is deprecated and "
"will be removed in the future version.",
FutureWarning,
stacklevel=find_stack_level(),
) # GH50185
sqlalchemy = import_optional_dependency("sqlalchemy", errors="ignore")

if sqlalchemy is not None and isinstance(con, (str, sqlalchemy.engine.Engine)):
raise TypeError("pandas.io.sql.execute requires a connection") # GH50185
with pandasSQL_builder(con, need_transaction=True) as pandas_sql:
return pandas_sql.execute(sql, params)


# -----------------------------------------------------------------------------
# -- Read and write to DataFrames

Expand Down
20 changes: 0 additions & 20 deletions pandas/tests/io/test_sql.py
Original file line number Diff line number Diff line change
Expand Up @@ -1487,26 +1487,6 @@ def test_read_view_sqlite(sqlite_buildin):
tm.assert_frame_equal(result, expected)


def test_execute_typeerror(sqlite_engine_iris):
with pytest.raises(TypeError, match="pandas.io.sql.execute requires a connection"):
with tm.assert_produces_warning(
FutureWarning,
match="`pandas.io.sql.execute` is deprecated and "
"will be removed in the future version.",
):
sql.execute("select * from iris", sqlite_engine_iris)


def test_execute_deprecated(sqlite_conn_iris):
# GH50185
with tm.assert_produces_warning(
FutureWarning,
match="`pandas.io.sql.execute` is deprecated and "
"will be removed in the future version.",
):
sql.execute("select * from iris", sqlite_conn_iris)


def flavor(conn_name):
if "postgresql" in conn_name:
return "postgresql"
Expand Down
41 changes: 0 additions & 41 deletions pandas/tests/resample/test_resample_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
import pytest

from pandas._libs import lib
from pandas.errors import UnsupportedFunctionCall

import pandas as pd
from pandas import (
Expand Down Expand Up @@ -987,46 +986,6 @@ def test_series_downsample_method(method, numeric_only, expected_data):
tm.assert_series_equal(result, expected)


@pytest.mark.parametrize(
"method, raises",
[
("sum", True),
("prod", True),
("min", True),
("max", True),
("first", False),
("last", False),
("median", False),
("mean", True),
("std", True),
("var", True),
("sem", False),
("ohlc", False),
("nunique", False),
],
)
def test_args_kwargs_depr(method, raises):
index = date_range("20180101", periods=3, freq="h")
df = Series([2, 4, 6], index=index)
resampled = df.resample("30min")
args = ()

func = getattr(resampled, method)

error_msg = "numpy operations are not valid with resample."
error_msg_type = "too many arguments passed in"
warn_msg = f"Passing additional args to DatetimeIndexResampler.{method}"

if raises:
with tm.assert_produces_warning(FutureWarning, match=warn_msg):
with pytest.raises(UnsupportedFunctionCall, match=error_msg):
func(*args, 1, 2, 3, 4)
else:
with tm.assert_produces_warning(FutureWarning, match=warn_msg):
with pytest.raises(TypeError, match=error_msg_type):
func(*args, 1, 2, 3, 4)


def test_resample_empty():
# GH#52484
df = DataFrame(
Expand Down
Loading