Skip to content

Commit f836e39

Browse files
committed
Merge remote-tracking branch 'upstream/main' into to_feather
2 parents 5e71dcd + 743111e commit f836e39

File tree

12 files changed

+257
-82
lines changed

12 files changed

+257
-82
lines changed

ci/code_checks.sh

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,6 @@ if [[ -z "$CHECK" || "$CHECK" == "docstrings" ]]; then
9898
pandas.api.extensions.ExtensionDtype \
9999
pandas.api.extensions.ExtensionArray \
100100
pandas.arrays.NumpyExtensionArray \
101-
pandas.api.extensions.ExtensionArray._accumulate \
102101
pandas.api.extensions.ExtensionArray._concat_same_type \
103102
pandas.api.extensions.ExtensionArray._formatter \
104103
pandas.api.extensions.ExtensionArray._from_factorized \
@@ -109,9 +108,6 @@ if [[ -z "$CHECK" || "$CHECK" == "docstrings" ]]; then
109108
pandas.api.extensions.ExtensionArray._values_for_factorize \
110109
pandas.api.extensions.ExtensionArray.interpolate \
111110
pandas.api.extensions.ExtensionArray.ravel \
112-
pandas.api.extensions.ExtensionArray.ndim \
113-
pandas.api.extensions.ExtensionArray.shape \
114-
pandas.api.extensions.ExtensionArray.tolist \
115111
pandas.DataFrame.__dataframe__
116112
RET=$(($RET + $?)) ; echo $MSG "DONE"
117113

doc/source/whatsnew/v2.1.0.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,7 @@ Deprecations
370370
- Deprecated the ``method`` and ``limit`` keywords in :meth:`DataFrame.replace` and :meth:`Series.replace` (:issue:`33302`)
371371
- Deprecated the use of non-supported datetime64 and timedelta64 resolutions with :func:`pandas.array`. Supported resolutions are: "s", "ms", "us", "ns" resolutions (:issue:`53058`)
372372
- Deprecated values "pad", "ffill", "bfill", "backfill" for :meth:`Series.interpolate` and :meth:`DataFrame.interpolate`, use ``obj.ffill()`` or ``obj.bfill()`` instead (:issue:`53581`)
373+
- Deprecated the behavior of :meth:`Index.argmax`, :meth:`Index.argmin`, :meth:`Series.argmax`, :meth:`Series.argmin` with either all-NAs and skipna=True or any-NAs and skipna=False returning -1; in a future version this will raise ``ValueError`` (:issue:`33941`, :issue:`33942`)
373374
-
374375

375376
.. ---------------------------------------------------------------------------
@@ -527,6 +528,7 @@ I/O
527528
- Bug in :func:`read_hdf` not properly closing store after a ``IndexError`` is raised (:issue:`52781`)
528529
- Bug in :func:`read_html`, style elements were read into DataFrames (:issue:`52197`)
529530
- Bug in :func:`read_html`, tail texts were removed together with elements containing ``display:none`` style (:issue:`51629`)
531+
- Bug in :func:`read_sql_table` raising an exception when reading a view (:issue:`52969`)
530532
- Bug in :func:`read_sql` when reading multiple timezone aware columns with the same column name (:issue:`44421`)
531533
- Bug in :func:`read_xml` stripping whitespace in string data (:issue:`53811`)
532534
- Bug in :meth:`DataFrame.to_html` where ``colspace`` was incorrectly applied in case of multi index columns (:issue:`53885`)

pandas/core/arrays/base.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -520,6 +520,12 @@ def dtype(self) -> ExtensionDtype:
520520
def shape(self) -> Shape:
521521
"""
522522
Return a tuple of the array dimensions.
523+
524+
Examples
525+
--------
526+
>>> arr = pd.array([1, 2, 3])
527+
>>> arr.shape
528+
(3,)
523529
"""
524530
return (len(self),)
525531

@@ -536,6 +542,12 @@ def size(self) -> int:
536542
def ndim(self) -> int:
537543
"""
538544
Extension Arrays are only allowed to be 1-dimensional.
545+
546+
Examples
547+
--------
548+
>>> arr = pd.array([1, 2, 3])
549+
>>> arr.ndim
550+
1
539551
"""
540552
return 1
541553

@@ -1599,6 +1611,14 @@ def _accumulate(
15991611
Raises
16001612
------
16011613
NotImplementedError : subclass does not define accumulations
1614+
1615+
Examples
1616+
--------
1617+
>>> arr = pd.array([1, 2, 3])
1618+
>>> arr._accumulate(name='cumsum')
1619+
<IntegerArray>
1620+
[1, 3, 6]
1621+
Length: 3, dtype: Int64
16021622
"""
16031623
raise NotImplementedError(f"cannot perform {name} with type {self.dtype}")
16041624

@@ -1694,6 +1714,12 @@ def tolist(self) -> list:
16941714
Returns
16951715
-------
16961716
list
1717+
1718+
Examples
1719+
--------
1720+
>>> arr = pd.array([1, 2, 3])
1721+
>>> arr.tolist()
1722+
[1, 2, 3]
16971723
"""
16981724
if self.ndim > 1:
16991725
return [x.tolist() for x in self]

pandas/core/base.py

Lines changed: 36 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
final,
1515
overload,
1616
)
17+
import warnings
1718

1819
import numpy as np
1920

@@ -36,6 +37,7 @@
3637
cache_readonly,
3738
doc,
3839
)
40+
from pandas.util._exceptions import find_stack_level
3941

4042
from pandas.core.dtypes.cast import can_hold_element
4143
from pandas.core.dtypes.common import (
@@ -735,15 +737,29 @@ def argmax(
735737

736738
if isinstance(delegate, ExtensionArray):
737739
if not skipna and delegate.isna().any():
740+
warnings.warn(
741+
f"The behavior of {type(self).__name__}.argmax/argmin "
742+
"with skipna=False and NAs, or with all-NAs is deprecated. "
743+
"In a future version this will raise ValueError.",
744+
FutureWarning,
745+
stacklevel=find_stack_level(),
746+
)
738747
return -1
739748
else:
740749
return delegate.argmax()
741750
else:
751+
result = nanops.nanargmax(delegate, skipna=skipna)
752+
if result == -1:
753+
warnings.warn(
754+
f"The behavior of {type(self).__name__}.argmax/argmin "
755+
"with skipna=False and NAs, or with all-NAs is deprecated. "
756+
"In a future version this will raise ValueError.",
757+
FutureWarning,
758+
stacklevel=find_stack_level(),
759+
)
742760
# error: Incompatible return value type (got "Union[int, ndarray]", expected
743761
# "int")
744-
return nanops.nanargmax( # type: ignore[return-value]
745-
delegate, skipna=skipna
746-
)
762+
return result # type: ignore[return-value]
747763

748764
@doc(argmax, op="min", oppose="max", value="smallest")
749765
def argmin(
@@ -755,15 +771,29 @@ def argmin(
755771

756772
if isinstance(delegate, ExtensionArray):
757773
if not skipna and delegate.isna().any():
774+
warnings.warn(
775+
f"The behavior of {type(self).__name__}.argmax/argmin "
776+
"with skipna=False and NAs, or with all-NAs is deprecated. "
777+
"In a future version this will raise ValueError.",
778+
FutureWarning,
779+
stacklevel=find_stack_level(),
780+
)
758781
return -1
759782
else:
760783
return delegate.argmin()
761784
else:
785+
result = nanops.nanargmin(delegate, skipna=skipna)
786+
if result == -1:
787+
warnings.warn(
788+
f"The behavior of {type(self).__name__}.argmax/argmin "
789+
"with skipna=False and NAs, or with all-NAs is deprecated. "
790+
"In a future version this will raise ValueError.",
791+
FutureWarning,
792+
stacklevel=find_stack_level(),
793+
)
762794
# error: Incompatible return value type (got "Union[int, ndarray]", expected
763795
# "int")
764-
return nanops.nanargmin( # type: ignore[return-value]
765-
delegate, skipna=skipna
766-
)
796+
return result # type: ignore[return-value]
767797

768798
def tolist(self):
769799
"""

pandas/core/indexes/base.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7271,6 +7271,13 @@ def argmin(self, axis=None, skipna: bool = True, *args, **kwargs) -> int:
72717271
# Take advantage of cache
72727272
mask = self._isnan
72737273
if not skipna or mask.all():
7274+
warnings.warn(
7275+
f"The behavior of {type(self).__name__}.argmax/argmin "
7276+
"with skipna=False and NAs, or with all-NAs is deprecated. "
7277+
"In a future version this will raise ValueError.",
7278+
FutureWarning,
7279+
stacklevel=find_stack_level(),
7280+
)
72747281
return -1
72757282
return super().argmin(skipna=skipna)
72767283

@@ -7283,6 +7290,13 @@ def argmax(self, axis=None, skipna: bool = True, *args, **kwargs) -> int:
72837290
# Take advantage of cache
72847291
mask = self._isnan
72857292
if not skipna or mask.all():
7293+
warnings.warn(
7294+
f"The behavior of {type(self).__name__}.argmax/argmin "
7295+
"with skipna=False and NAs, or with all-NAs is deprecated. "
7296+
"In a future version this will raise ValueError.",
7297+
FutureWarning,
7298+
stacklevel=find_stack_level(),
7299+
)
72867300
return -1
72877301
return super().argmax(skipna=skipna)
72887302

pandas/core/series.py

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2530,7 +2530,12 @@ def idxmin(self, axis: Axis = 0, skipna: bool = True, *args, **kwargs) -> Hashab
25302530
nan
25312531
"""
25322532
axis = self._get_axis_number(axis)
2533-
i = self.argmin(axis, skipna, *args, **kwargs)
2533+
with warnings.catch_warnings():
2534+
# TODO(3.0): this catching/filtering can be removed
2535+
# ignore warning produced by argmin since we will issue a different
2536+
# warning for idxmin
2537+
warnings.simplefilter("ignore")
2538+
i = self.argmin(axis, skipna, *args, **kwargs)
25342539
if i == -1:
25352540
# GH#43587 give correct NA value for Index.
25362541
return self.index._na_value
@@ -2601,7 +2606,12 @@ def idxmax(self, axis: Axis = 0, skipna: bool = True, *args, **kwargs) -> Hashab
26012606
nan
26022607
"""
26032608
axis = self._get_axis_number(axis)
2604-
i = self.argmax(axis, skipna, *args, **kwargs)
2609+
with warnings.catch_warnings():
2610+
# TODO(3.0): this catching/filtering can be removed
2611+
# ignore warning produced by argmax since we will issue a different
2612+
# warning for argmax
2613+
warnings.simplefilter("ignore")
2614+
i = self.argmax(axis, skipna, *args, **kwargs)
26052615
if i == -1:
26062616
# GH#43587 give correct NA value for Index.
26072617
return self.index._na_value

pandas/io/formats/xml.py

Lines changed: 15 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -251,18 +251,11 @@ def other_namespaces(self) -> dict:
251251
"""
252252

253253
nmsp_dict: dict[str, str] = {}
254-
if self.namespaces and self.prefix is None:
255-
nmsp_dict = {
256-
"xmlns": n # noqa: RUF011
257-
for p, n in self.namespaces.items()
258-
if p != ""
259-
}
260-
261-
if self.namespaces and self.prefix:
254+
if self.namespaces:
262255
nmsp_dict = {
263-
"xmlns": n # noqa: RUF011
256+
f"xmlns{p if p=='' else f':{p}'}": n
264257
for p, n in self.namespaces.items()
265-
if p == ""
258+
if n != self.prefix_uri[1:-1]
266259
}
267260

268261
return nmsp_dict
@@ -365,16 +358,16 @@ def build_tree(self) -> bytes:
365358
elem_row = self.build_attribs(d, elem_row)
366359
self.build_elems(d, elem_row)
367360

368-
self.out_xml = tostring(self.root, method="xml", encoding=self.encoding)
361+
self.out_xml = tostring(
362+
self.root,
363+
method="xml",
364+
encoding=self.encoding,
365+
xml_declaration=self.xml_declaration,
366+
)
369367

370368
if self.pretty_print:
371369
self.out_xml = self.prettify_tree()
372370

373-
if self.xml_declaration:
374-
self.out_xml = self.add_declaration()
375-
else:
376-
self.out_xml = self.remove_declaration()
377-
378371
if self.stylesheet is not None:
379372
raise ValueError(
380373
"To use stylesheet, you need lxml installed and selected as parser."
@@ -395,8 +388,10 @@ def get_prefix_uri(self) -> str:
395388
uri = f"{{{self.namespaces[self.prefix]}}}"
396389
except KeyError:
397390
raise KeyError(f"{self.prefix} is not included in namespaces")
398-
else:
391+
elif "" in self.namespaces:
399392
uri = f'{{{self.namespaces[""]}}}'
393+
else:
394+
uri = ""
400395

401396
return uri
402397

@@ -418,31 +413,6 @@ def prettify_tree(self) -> bytes:
418413

419414
return dom.toprettyxml(indent=" ", encoding=self.encoding)
420415

421-
def add_declaration(self) -> bytes:
422-
"""
423-
Add xml declaration.
424-
425-
This method will add xml declaration of working tree. Currently,
426-
xml_declaration is supported in etree starting in Python 3.8.
427-
"""
428-
decl = f'<?xml version="1.0" encoding="{self.encoding}"?>\n'
429-
430-
return (
431-
self.out_xml
432-
if self.out_xml.startswith(b"<?xml")
433-
else decl.encode(self.encoding) + self.out_xml
434-
)
435-
436-
def remove_declaration(self) -> bytes:
437-
"""
438-
Remove xml declaration.
439-
440-
This method will remove xml declaration of working tree. Currently,
441-
pretty_print is not supported in etree.
442-
"""
443-
444-
return self.out_xml.split(b"?>")[-1].strip()
445-
446416

447417
class LxmlXMLFormatter(BaseXMLFormatter):
448418
"""
@@ -513,8 +483,10 @@ def get_prefix_uri(self) -> str:
513483
uri = f"{{{self.namespaces[self.prefix]}}}"
514484
except KeyError:
515485
raise KeyError(f"{self.prefix} is not included in namespaces")
516-
else:
486+
elif "" in self.namespaces:
517487
uri = f'{{{self.namespaces[""]}}}'
488+
else:
489+
uri = ""
518490

519491
return uri
520492

pandas/io/sql.py

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1655,7 +1655,7 @@ def read_table(
16551655
SQLDatabase.read_query
16561656
16571657
"""
1658-
self.meta.reflect(bind=self.con, only=[table_name])
1658+
self.meta.reflect(bind=self.con, only=[table_name], views=True)
16591659
table = SQLTable(table_name, self, index=index_col, schema=schema)
16601660
if chunksize is not None:
16611661
self.returns_generator = True
@@ -1989,7 +1989,9 @@ def get_table(self, table_name: str, schema: str | None = None) -> Table:
19891989
def drop_table(self, table_name: str, schema: str | None = None) -> None:
19901990
schema = schema or self.meta.schema
19911991
if self.has_table(table_name, schema):
1992-
self.meta.reflect(bind=self.con, only=[table_name], schema=schema)
1992+
self.meta.reflect(
1993+
bind=self.con, only=[table_name], schema=schema, views=True
1994+
)
19931995
with self.run_transaction():
19941996
self.get_table(table_name, schema).drop(bind=self.con)
19951997
self.meta.clear()
@@ -2411,7 +2413,15 @@ def to_sql(
24112413

24122414
def has_table(self, name: str, schema: str | None = None) -> bool:
24132415
wld = "?"
2414-
query = f"SELECT name FROM sqlite_master WHERE type='table' AND name={wld};"
2416+
query = f"""
2417+
SELECT
2418+
name
2419+
FROM
2420+
sqlite_master
2421+
WHERE
2422+
type IN ('table', 'view')
2423+
AND name={wld};
2424+
"""
24152425

24162426
return len(self.execute(query, [name]).fetchall()) > 0
24172427

pandas/tests/extension/base/methods.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,8 +160,13 @@ def test_argreduce_series(
160160
self, data_missing_for_sorting, op_name, skipna, expected
161161
):
162162
# data_missing_for_sorting -> [B, NA, A] with A < B and NA missing.
163+
warn = None
164+
if op_name.startswith("arg") and expected == -1:
165+
warn = FutureWarning
166+
msg = "The behavior of Series.argmax/argmin"
163167
ser = pd.Series(data_missing_for_sorting)
164-
result = getattr(ser, op_name)(skipna=skipna)
168+
with tm.assert_produces_warning(warn, match=msg):
169+
result = getattr(ser, op_name)(skipna=skipna)
165170
tm.assert_almost_equal(result, expected)
166171

167172
def test_argmax_argmin_no_skipna_notimplemented(self, data_missing_for_sorting):

0 commit comments

Comments
 (0)