Skip to content

Commit 92c2077

Browse files
committed
Merge remote-tracking branch 'upstream/main' into deps/optional/bump
2 parents e5ccdc1 + a4c63d6 commit 92c2077

File tree

16 files changed

+209
-60
lines changed

16 files changed

+209
-60
lines changed

.pre-commit-config.yaml

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ ci:
1919
skip: [pyright, mypy]
2020
repos:
2121
- repo: https://github.com/astral-sh/ruff-pre-commit
22-
rev: v0.12.7
22+
rev: v0.12.11
2323
hooks:
2424
- id: ruff
2525
args: [--exit-non-zero-on-fix]
@@ -51,7 +51,7 @@ repos:
5151
- id: cython-lint
5252
- id: double-quote-cython-strings
5353
- repo: https://github.com/pre-commit/pre-commit-hooks
54-
rev: v5.0.0
54+
rev: v6.0.0
5555
hooks:
5656
- id: check-case-conflict
5757
- id: check-toml
@@ -64,8 +64,6 @@ repos:
6464
args: [--fix=auto]
6565
exclude: ^pandas/tests/io/parser/data/utf16_ex.txt$
6666
- id: fix-byte-order-marker
67-
- id: fix-encoding-pragma
68-
args: [--remove]
6967
- id: trailing-whitespace
7068
args: [--markdown-linebreak-ext=md]
7169
- repo: https://github.com/PyCQA/isort
@@ -94,19 +92,19 @@ repos:
9492
- id: sphinx-lint
9593
args: ["--enable", "all", "--disable", "line-too-long"]
9694
- repo: https://github.com/pre-commit/mirrors-clang-format
97-
rev: v20.1.8
95+
rev: v21.1.0
9896
hooks:
9997
- id: clang-format
10098
files: ^pandas/_libs/src|^pandas/_libs/include
10199
args: [-i]
102100
types_or: [c, c++]
103101
- repo: https://github.com/trim21/pre-commit-mirror-meson
104-
rev: v1.8.3
102+
rev: v1.9.0
105103
hooks:
106104
- id: meson-fmt
107105
args: ['--inplace']
108106
- repo: https://github.com/shellcheck-py/shellcheck-py
109-
rev: v0.10.0.1
107+
rev: v0.11.0.1
110108
hooks:
111109
- id: shellcheck
112110
args: ["--severity=warning"]
@@ -266,6 +264,11 @@ repos:
266264
language: python
267265
entry: python scripts/validate_unwanted_patterns.py --validation-type="nodefault_used_not_only_for_typing"
268266
types: [python]
267+
- id: unwanted-patterns-doesnt-use-pandas-warnings
268+
name: Check that warning classes for deprecations use pandas' warning classes
269+
language: python
270+
entry: python scripts/validate_unwanted_patterns.py --validation-type="doesnt_use_pandas_warnings"
271+
types: [ python ]
269272
- id: no-return-exception
270273
name: Use raise instead of return for exceptions
271274
language: pygrep

pandas/_config/config.py

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@
7373

7474
class DeprecatedOption(NamedTuple):
7575
key: str
76+
category: type[Warning]
7677
msg: str | None
7778
rkey: str | None
7879
removal_ver: str | None
@@ -589,6 +590,7 @@ def register_option(
589590

590591
def deprecate_option(
591592
key: str,
593+
category: type[Warning],
592594
msg: str | None = None,
593595
rkey: str | None = None,
594596
removal_ver: str | None = None,
@@ -608,6 +610,8 @@ def deprecate_option(
608610
key : str
609611
Name of the option to be deprecated.
610612
must be a fully-qualified option name (e.g "x.y.z.rkey").
613+
category : Warning
614+
Warning class for the deprecation.
611615
msg : str, optional
612616
Warning message to output when the key is referenced.
613617
if no message is given a default message will be emitted.
@@ -631,7 +635,7 @@ def deprecate_option(
631635
if key in _deprecated_options:
632636
raise OptionError(f"Option '{key}' has already been defined as deprecated.")
633637

634-
_deprecated_options[key] = DeprecatedOption(key, msg, rkey, removal_ver)
638+
_deprecated_options[key] = DeprecatedOption(key, category, msg, rkey, removal_ver)
635639

636640

637641
#
@@ -716,7 +720,7 @@ def _warn_if_deprecated(key: str) -> bool:
716720
if d.msg:
717721
warnings.warn(
718722
d.msg,
719-
FutureWarning,
723+
d.category,
720724
stacklevel=find_stack_level(),
721725
)
722726
else:
@@ -728,7 +732,11 @@ def _warn_if_deprecated(key: str) -> bool:
728732
else:
729733
msg += ", please refrain from using it."
730734

731-
warnings.warn(msg, FutureWarning, stacklevel=find_stack_level())
735+
warnings.warn(
736+
msg,
737+
d.category,
738+
stacklevel=find_stack_level(),
739+
)
732740
return True
733741
return False
734742

pandas/_libs/src/vendored/ujson/python/objToJSON.c

Lines changed: 38 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ Numeric decoder derived from TCL library
5151
#include <numpy/ndarraytypes.h>
5252
#include <numpy/npy_math.h>
5353

54+
static const int CSTR_SIZE = 20;
55+
5456
npy_int64 get_nat(void) { return NPY_MIN_INT64; }
5557

5658
typedef const char *(*PFN_PyTypeToUTF8)(JSOBJ obj, JSONTypeContext *ti,
@@ -106,7 +108,7 @@ typedef struct __TypeContext {
106108
double doubleValue;
107109
JSINT64 longValue;
108110

109-
const char *cStr;
111+
char *cStr;
110112
NpyArrContext *npyarr;
111113
PdBlockContext *pdblock;
112114
int transpose;
@@ -347,7 +349,8 @@ static const char *PyDateTimeToIsoCallback(JSOBJ obj, JSONTypeContext *tc,
347349
}
348350

349351
NPY_DATETIMEUNIT base = ((PyObjectEncoder *)tc->encoder)->datetimeUnit;
350-
return PyDateTimeToIso(obj, base, len);
352+
GET_TC(tc)->cStr = PyDateTimeToIso(obj, base, len);
353+
return GET_TC(tc)->cStr;
351354
}
352355

353356
static const char *PyTimeToJSON(JSOBJ _obj, JSONTypeContext *tc,
@@ -1007,16 +1010,24 @@ static const char *List_iterGetName(JSOBJ Py_UNUSED(obj),
10071010
//=============================================================================
10081011
static void Index_iterBegin(JSOBJ Py_UNUSED(obj), JSONTypeContext *tc) {
10091012
GET_TC(tc)->index = 0;
1013+
GET_TC(tc)->cStr = PyObject_Malloc(CSTR_SIZE);
1014+
if (!GET_TC(tc)->cStr) {
1015+
PyErr_NoMemory();
1016+
}
10101017
}
10111018

10121019
static int Index_iterNext(JSOBJ obj, JSONTypeContext *tc) {
10131020
const Py_ssize_t index = GET_TC(tc)->index;
10141021
Py_XDECREF(GET_TC(tc)->itemValue);
1022+
if (!GET_TC(tc)->cStr) {
1023+
return 0;
1024+
}
1025+
10151026
if (index == 0) {
1016-
GET_TC(tc)->cStr = "name";
1027+
strcpy(GET_TC(tc)->cStr, "name");
10171028
GET_TC(tc)->itemValue = PyObject_GetAttrString(obj, "name");
10181029
} else if (index == 1) {
1019-
GET_TC(tc)->cStr = "data";
1030+
strcpy(GET_TC(tc)->cStr, "data");
10201031
GET_TC(tc)->itemValue = get_values(obj);
10211032
if (!GET_TC(tc)->itemValue) {
10221033
return 0;
@@ -1049,19 +1060,27 @@ static void Series_iterBegin(JSOBJ Py_UNUSED(obj), JSONTypeContext *tc) {
10491060
PyObjectEncoder *enc = (PyObjectEncoder *)tc->encoder;
10501061
GET_TC(tc)->index = 0;
10511062
enc->outputFormat = VALUES; // for contained series
1063+
GET_TC(tc)->cStr = PyObject_Malloc(CSTR_SIZE);
1064+
if (!GET_TC(tc)->cStr) {
1065+
PyErr_NoMemory();
1066+
}
10521067
}
10531068

10541069
static int Series_iterNext(JSOBJ obj, JSONTypeContext *tc) {
10551070
const Py_ssize_t index = GET_TC(tc)->index;
10561071
Py_XDECREF(GET_TC(tc)->itemValue);
1072+
if (!GET_TC(tc)->cStr) {
1073+
return 0;
1074+
}
1075+
10571076
if (index == 0) {
1058-
GET_TC(tc)->cStr = "name";
1077+
strcpy(GET_TC(tc)->cStr, "name");
10591078
GET_TC(tc)->itemValue = PyObject_GetAttrString(obj, "name");
10601079
} else if (index == 1) {
1061-
GET_TC(tc)->cStr = "index";
1080+
strcpy(GET_TC(tc)->cStr, "index");
10621081
GET_TC(tc)->itemValue = PyObject_GetAttrString(obj, "index");
10631082
} else if (index == 2) {
1064-
GET_TC(tc)->cStr = "data";
1083+
strcpy(GET_TC(tc)->cStr, "data");
10651084
GET_TC(tc)->itemValue = get_values(obj);
10661085
if (!GET_TC(tc)->itemValue) {
10671086
return 0;
@@ -1096,19 +1115,27 @@ static void DataFrame_iterBegin(JSOBJ Py_UNUSED(obj), JSONTypeContext *tc) {
10961115
PyObjectEncoder *enc = (PyObjectEncoder *)tc->encoder;
10971116
GET_TC(tc)->index = 0;
10981117
enc->outputFormat = VALUES; // for contained series & index
1118+
GET_TC(tc)->cStr = PyObject_Malloc(CSTR_SIZE);
1119+
if (!GET_TC(tc)->cStr) {
1120+
PyErr_NoMemory();
1121+
}
10991122
}
11001123

11011124
static int DataFrame_iterNext(JSOBJ obj, JSONTypeContext *tc) {
11021125
const Py_ssize_t index = GET_TC(tc)->index;
11031126
Py_XDECREF(GET_TC(tc)->itemValue);
1127+
if (!GET_TC(tc)->cStr) {
1128+
return 0;
1129+
}
1130+
11041131
if (index == 0) {
1105-
GET_TC(tc)->cStr = "columns";
1132+
strcpy(GET_TC(tc)->cStr, "columns");
11061133
GET_TC(tc)->itemValue = PyObject_GetAttrString(obj, "columns");
11071134
} else if (index == 1) {
1108-
GET_TC(tc)->cStr = "index";
1135+
strcpy(GET_TC(tc)->cStr, "index");
11091136
GET_TC(tc)->itemValue = PyObject_GetAttrString(obj, "index");
11101137
} else if (index == 2) {
1111-
GET_TC(tc)->cStr = "data";
1138+
strcpy(GET_TC(tc)->cStr, "data");
11121139
Py_INCREF(obj);
11131140
GET_TC(tc)->itemValue = obj;
11141141
} else {
@@ -1880,6 +1907,7 @@ static void Object_endTypeContext(JSOBJ Py_UNUSED(obj), JSONTypeContext *tc) {
18801907
GET_TC(tc)->rowLabels = NULL;
18811908
NpyArr_freeLabels(GET_TC(tc)->columnLabels, GET_TC(tc)->columnLabelsLen);
18821909
GET_TC(tc)->columnLabels = NULL;
1910+
PyObject_Free(GET_TC(tc)->cStr);
18831911
GET_TC(tc)->cStr = NULL;
18841912
PyObject_Free(tc->prv);
18851913
tc->prv = NULL;

pandas/core/arrays/string_.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ def __init__(
177177
"'pd.options.future.infer_string = True' option globally and use "
178178
'the "str" alias as a shorthand notation to specify a dtype '
179179
'(instead of "string[pyarrow_numpy]").',
180-
FutureWarning,
180+
FutureWarning, # pdlint: ignore[warning_class]
181181
stacklevel=find_stack_level(),
182182
)
183183
storage = "pyarrow"

pandas/core/arrays/string_arrow.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,7 @@ def _convert_bool_result(self, values, na=lib.no_default, method_name=None):
247247
warnings.warn(
248248
f"Allowing a non-bool 'na' in obj.str.{method_name} is deprecated "
249249
"and will raise in a future version.",
250-
FutureWarning,
250+
FutureWarning, # pdlint: ignore[warning_class]
251251
stacklevel=find_stack_level(),
252252
)
253253
na = bool(na)

pandas/core/dtypes/dtypes.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1053,7 +1053,7 @@ def __new__(cls, freq) -> PeriodDtype: # noqa: PYI034
10531053
warnings.warn(
10541054
"PeriodDtype[B] is deprecated and will be removed in a future "
10551055
"version. Use a DatetimeIndex with freq='B' instead",
1056-
FutureWarning,
1056+
FutureWarning, # pdlint: ignore[warning_class]
10571057
stacklevel=find_stack_level(),
10581058
)
10591059

pandas/core/generic.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9139,7 +9139,7 @@ def resample(
91399139
"deprecated and will be removed in a future version. "
91409140
"Explicitly cast PeriodIndex to DatetimeIndex before resampling "
91419141
"instead.",
9142-
FutureWarning,
9142+
FutureWarning, # pdlint: ignore[warning_class]
91439143
stacklevel=find_stack_level(),
91449144
)
91459145
else:

pandas/core/groupby/groupby.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ class providing the base-class of operations.
6161
from pandas.errors import (
6262
AbstractMethodError,
6363
DataError,
64+
Pandas4Warning,
6465
)
6566
from pandas.util._decorators import (
6667
Appender,
@@ -557,7 +558,7 @@ def groups(self) -> dict[Hashable, Index]:
557558
"and will be removed. In a future version `groups` by one element "
558559
"list will return tuple. Use ``df.groupby(by='a').groups`` "
559560
"instead of ``df.groupby(by=['a']).groups`` to avoid this warning",
560-
FutureWarning,
561+
Pandas4Warning,
561562
stacklevel=find_stack_level(),
562563
)
563564
return self._grouper.groups

pandas/core/resample.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1949,7 +1949,7 @@ def _resampler_for_grouping(self):
19491949
warnings.warn(
19501950
"Resampling a groupby with a PeriodIndex is deprecated. "
19511951
"Cast to DatetimeIndex before resampling instead.",
1952-
FutureWarning,
1952+
FutureWarning, # pdlint: ignore[warning_class]
19531953
stacklevel=find_stack_level(),
19541954
)
19551955
return PeriodIndexResamplerGroupby
@@ -2293,11 +2293,12 @@ def _get_resampler(self, obj: NDFrame) -> Resampler:
22932293
)
22942294
elif isinstance(ax, PeriodIndex):
22952295
if isinstance(ax, PeriodIndex):
2296+
# TODO: Enforce in 3.0 (#53481)
22962297
# GH#53481
22972298
warnings.warn(
22982299
"Resampling with a PeriodIndex is deprecated. "
22992300
"Cast index to DatetimeIndex before resampling instead.",
2300-
FutureWarning,
2301+
FutureWarning, # pdlint: ignore[warning_class]
23012302
stacklevel=find_stack_level(),
23022303
)
23032304
return PeriodIndexResampler(

pandas/core/strings/object_array.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -159,35 +159,38 @@ def _str_contains(
159159
upper_pat = pat.upper()
160160
f = lambda x: upper_pat in x.upper()
161161
if na is not lib.no_default and not isna(na) and not isinstance(na, bool):
162+
# TODO: Enforce in 3.0 (#59615)
162163
# GH#59561
163164
warnings.warn(
164165
"Allowing a non-bool 'na' in obj.str.contains is deprecated "
165166
"and will raise in a future version.",
166-
FutureWarning,
167+
FutureWarning, # pdlint: ignore[warning_class]
167168
stacklevel=find_stack_level(),
168169
)
169170
return self._str_map(f, na, dtype=np.dtype("bool"))
170171

171172
def _str_startswith(self, pat, na=lib.no_default):
172173
f = lambda x: x.startswith(pat)
173174
if na is not lib.no_default and not isna(na) and not isinstance(na, bool):
175+
# TODO: Enforce in 3.0 (#59615)
174176
# GH#59561
175177
warnings.warn(
176178
"Allowing a non-bool 'na' in obj.str.startswith is deprecated "
177179
"and will raise in a future version.",
178-
FutureWarning,
180+
FutureWarning, # pdlint: ignore[warning_class]
179181
stacklevel=find_stack_level(),
180182
)
181183
return self._str_map(f, na_value=na, dtype=np.dtype(bool))
182184

183185
def _str_endswith(self, pat, na=lib.no_default):
184186
f = lambda x: x.endswith(pat)
185187
if na is not lib.no_default and not isna(na) and not isinstance(na, bool):
188+
# TODO: Enforce in 3.0 (#59615)
186189
# GH#59561
187190
warnings.warn(
188191
"Allowing a non-bool 'na' in obj.str.endswith is deprecated "
189192
"and will raise in a future version.",
190-
FutureWarning,
193+
FutureWarning, # pdlint: ignore[warning_class]
191194
stacklevel=find_stack_level(),
192195
)
193196
return self._str_map(f, na_value=na, dtype=np.dtype(bool))

0 commit comments

Comments
 (0)