Skip to content

Commit a59e076

Browse files
committed
Merge remote-tracking branch 'upstream/master' into debug/resourcewarning
2 parents 9d23ff4 + c3a8fcd commit a59e076

File tree

16 files changed

+131
-111
lines changed

16 files changed

+131
-111
lines changed

.github/workflows/posix.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ jobs:
3131
[actions-38-slow.yaml, "slow", "", "", "", "", ""],
3232
[actions-38-locale.yaml, "not slow and not network", "language-pack-zh-hans xsel", "zh_CN.utf8", "zh_CN.utf8", "", ""],
3333
[actions-39-slow.yaml, "slow", "", "", "", "", ""],
34+
[actions-pypy-38.yaml, "not slow and not clipboard", "", "", "", "", ""],
3435
[actions-39-numpydev.yaml, "not slow and not network", "xsel", "", "", "deprecate", "-W error"],
3536
[actions-39.yaml, "not slow and not clipboard", "", "", "", "", ""]
3637
]

ci/deps/actions-pypy-38.yaml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
name: pandas-dev
2+
channels:
3+
- conda-forge
4+
dependencies:
5+
# TODO: Add the rest of the dependencies in here
6+
# once the other plentiful failures/segfaults
7+
# with base pandas has been dealt with
8+
- python=3.8
9+
10+
# tools
11+
- cython>=0.29.24
12+
- pytest>=6.0
13+
- pytest-cov
14+
- pytest-xdist>=1.31
15+
- hypothesis>=5.5.3
16+
17+
# required
18+
- numpy
19+
- python-dateutil
20+
- pytz

doc/source/whatsnew/v1.3.5.rst

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ Fixed regressions
2222
- Fixed regression in :meth:`Series.duplicated` and :meth:`Series.drop_duplicates` when Series has :class:`Categorical` dtype with boolean categories (:issue:`44351`)
2323
- Fixed regression in :meth:`.GroupBy.sum` with ``timedelta64[ns]`` dtype containing ``NaT`` failing to treat that value as NA (:issue:`42659`)
2424
- Fixed regression in :meth:`.RollingGroupby.cov` and :meth:`.RollingGroupby.corr` when ``other`` had the same shape as each group would incorrectly return superfluous groups in the result (:issue:`42915`)
25-
- Fixed regression where a single column ``np.matrix`` was no longer coerced to a 1d ``np.ndarray`` when added to a :class:`DataFrame` (:issue:`42376`)
2625

2726

2827
.. ---------------------------------------------------------------------------

doc/source/whatsnew/v1.4.0.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -702,6 +702,7 @@ Indexing
702702
- Bug in :meth:`DataFrame.loc.__setitem__` changing dtype when indexer was completely ``False`` (:issue:`37550`)
703703
- Bug in :meth:`IntervalIndex.get_indexer_non_unique` returning boolean mask instead of array of integers for a non unique and non monotonic index (:issue:`44084`)
704704
- Bug in :meth:`IntervalIndex.get_indexer_non_unique` not handling targets of ``dtype`` 'object' with NaNs correctly (:issue:`44482`)
705+
- Fixed regression where a single column ``np.matrix`` was no longer coerced to a 1d ``np.ndarray`` when added to a :class:`DataFrame` (:issue:`42376`)
705706
-
706707

707708
Missing
@@ -710,6 +711,7 @@ Missing
710711
- Bug in :meth:`DataFrame.fillna` not replacing missing values when using a dict-like ``value`` and duplicate column names (:issue:`43476`)
711712
- Bug in constructing a :class:`DataFrame` with a dictionary ``np.datetime64`` as a value and ``dtype='timedelta64[ns]'``, or vice-versa, incorrectly casting instead of raising (:issue:`??`)
712713
- Bug in :meth:`Series.interpolate` and :meth:`DataFrame.interpolate` with ``inplace=True`` not writing to the underlying array(s) in-place (:issue:`44749`)
714+
- Bug in :meth:`Index.fillna` incorrectly returning an un-filled :class:`Index` when NA values are present and ``downcast`` argument is specified. This now raises ``NotImplementedError`` instead; do not pass ``downcast`` argument (:issue:`44873`)
713715
-
714716

715717
MultiIndex

pandas/_typing.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,9 @@ def closed(self) -> bool:
242242

243243
# compression keywords and compression
244244
CompressionDict = Dict[str, Any]
245-
CompressionOptions = Optional[Union[str, CompressionDict]]
245+
CompressionOptions = Optional[
246+
Union[Literal["infer", "gzip", "bz2", "zip", "xz"], CompressionDict]
247+
]
246248

247249

248250
# types in DataFrameFormatter

pandas/core/arrays/numpy_.py

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
from pandas.core.dtypes.missing import isna
1919

2020
from pandas.core import (
21+
arraylike,
2122
nanops,
2223
ops,
2324
)
@@ -144,6 +145,14 @@ def __array_ufunc__(self, ufunc: np.ufunc, method: str, *inputs, **kwargs):
144145
if result is not NotImplemented:
145146
return result
146147

148+
if method == "reduce":
149+
result = arraylike.dispatch_reduction_ufunc(
150+
self, ufunc, method, *inputs, **kwargs
151+
)
152+
if result is not NotImplemented:
153+
# e.g. tests.series.test_ufunc.TestNumpyReductions
154+
return result
155+
147156
# Defer to the implementation of the ufunc on unwrapped values.
148157
inputs = tuple(x._ndarray if isinstance(x, PandasArray) else x for x in inputs)
149158
if out:
@@ -153,13 +162,8 @@ def __array_ufunc__(self, ufunc: np.ufunc, method: str, *inputs, **kwargs):
153162
result = getattr(ufunc, method)(*inputs, **kwargs)
154163

155164
if ufunc.nout > 1:
156-
# multiple return values
157-
if not lib.is_scalar(result[0]):
158-
# re-box array-like results
159-
return tuple(type(self)(x) for x in result)
160-
else:
161-
# but not scalar reductions
162-
return result
165+
# multiple return values; re-box array-like results
166+
return tuple(type(self)(x) for x in result)
163167
elif method == "at":
164168
# no return value
165169
return None
@@ -171,11 +175,8 @@ def __array_ufunc__(self, ufunc: np.ufunc, method: str, *inputs, **kwargs):
171175
# e.g. test_np_max_nested_tuples
172176
return result
173177
else:
174-
# one return value
175-
if not lib.is_scalar(result):
176-
# re-box array-like results, but not scalar reductions
177-
result = type(self)(result)
178-
return result
178+
# one return value; re-box array-like results
179+
return type(self)(result)
179180

180181
# ------------------------------------------------------------------------
181182
# Pandas ExtensionArray Interface

pandas/core/computation/scope.py

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -133,18 +133,13 @@ def __init__(
133133
# shallow copy here because we don't want to replace what's in
134134
# scope when we align terms (alignment accesses the underlying
135135
# numpy array of pandas objects)
136-
137-
# error: Incompatible types in assignment (expression has type
138-
# "ChainMap[str, Any]", variable has type "DeepChainMap[str, Any]")
139-
self.scope = self.scope.new_child( # type: ignore[assignment]
140-
(global_dict or frame.f_globals).copy()
141-
)
136+
scope_global = self.scope.new_child((global_dict or frame.f_globals).copy())
137+
self.scope = DeepChainMap(scope_global)
142138
if not isinstance(local_dict, Scope):
143-
# error: Incompatible types in assignment (expression has type
144-
# "ChainMap[str, Any]", variable has type "DeepChainMap[str, Any]")
145-
self.scope = self.scope.new_child( # type: ignore[assignment]
139+
scope_local = self.scope.new_child(
146140
(local_dict or frame.f_locals).copy()
147141
)
142+
self.scope = DeepChainMap(scope_local)
148143
finally:
149144
del frame
150145

@@ -257,9 +252,7 @@ def _get_vars(self, stack, scopes: list[str]) -> None:
257252
for scope, (frame, _, _, _, _, _) in variables:
258253
try:
259254
d = getattr(frame, "f_" + scope)
260-
# error: Incompatible types in assignment (expression has type
261-
# "ChainMap[str, Any]", variable has type "DeepChainMap[str, Any]")
262-
self.scope = self.scope.new_child(d) # type: ignore[assignment]
255+
self.scope = DeepChainMap(self.scope.new_child(d))
263256
finally:
264257
# won't remove it, but DECREF it
265258
# in Py3 this probably isn't necessary since frame won't be

pandas/core/indexes/base.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2723,13 +2723,18 @@ def fillna(self, value=None, downcast=None):
27232723
DataFrame.fillna : Fill NaN values of a DataFrame.
27242724
Series.fillna : Fill NaN Values of a Series.
27252725
"""
2726+
27262727
value = self._require_scalar(value)
27272728
if self.hasnans:
27282729
result = self.putmask(self._isnan, value)
27292730
if downcast is None:
27302731
# no need to care metadata other than name
2731-
# because it can't have freq if
2732+
# because it can't have freq if it has NaTs
27322733
return Index._with_infer(result, name=self.name)
2734+
raise NotImplementedError(
2735+
f"{type(self).__name__}.fillna does not support 'downcast' "
2736+
"argument values other than 'None'."
2737+
)
27332738
return self._view()
27342739

27352740
def dropna(self: _IndexT, how: str_t = "any") -> _IndexT:

pandas/core/indexes/category.py

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -377,20 +377,6 @@ def __contains__(self, key: Any) -> bool:
377377

378378
return contains(self, key, container=self._engine)
379379

380-
@doc(Index.fillna)
381-
def fillna(self, value, downcast=None):
382-
value = self._require_scalar(value)
383-
try:
384-
cat = self._data.fillna(value)
385-
except (ValueError, TypeError):
386-
# invalid fill_value
387-
if not self.hasnans:
388-
# nothing to fill, we can get away without casting
389-
return self.copy()
390-
return self.astype(object).fillna(value, downcast=downcast)
391-
392-
return type(self)._simple_new(cat, name=self.name)
393-
394380
# TODO(2.0): remove reindex once non-unique deprecation is enforced
395381
def reindex(
396382
self, target, method=None, level=None, limit=None, tolerance=None

pandas/io/parsers/readers.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
from pandas._libs.parsers import STR_NA_VALUES
2020
from pandas._typing import (
2121
ArrayLike,
22+
CompressionOptions,
2223
DtypeArg,
2324
FilePath,
2425
ReadCsvBuffer,
@@ -618,7 +619,7 @@ def read_csv(
618619
iterator=False,
619620
chunksize=None,
620621
# Quoting, Compression, and File Format
621-
compression="infer",
622+
compression: CompressionOptions = "infer",
622623
thousands=None,
623624
decimal: str = ".",
624625
lineterminator=None,
@@ -716,7 +717,7 @@ def read_table(
716717
iterator=False,
717718
chunksize=None,
718719
# Quoting, Compression, and File Format
719-
compression="infer",
720+
compression: CompressionOptions = "infer",
720721
thousands=None,
721722
decimal: str = ".",
722723
lineterminator=None,

pandas/io/xml.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -105,8 +105,8 @@ def __init__(
105105
names,
106106
encoding,
107107
stylesheet,
108-
compression,
109-
storage_options,
108+
compression: CompressionOptions,
109+
storage_options: StorageOptions,
110110
) -> None:
111111
self.path_or_buffer = path_or_buffer
112112
self.xpath = xpath
@@ -570,8 +570,8 @@ def _transform_doc(self) -> bytes:
570570
def get_data_from_filepath(
571571
filepath_or_buffer: FilePath | bytes | ReadBuffer[bytes] | ReadBuffer[str],
572572
encoding,
573-
compression,
574-
storage_options,
573+
compression: CompressionOptions,
574+
storage_options: StorageOptions,
575575
) -> str | bytes | ReadBuffer[bytes] | ReadBuffer[str]:
576576
"""
577577
Extract raw XML data.
@@ -666,8 +666,8 @@ def _parse(
666666
encoding,
667667
parser,
668668
stylesheet,
669-
compression,
670-
storage_options,
669+
compression: CompressionOptions,
670+
storage_options: StorageOptions,
671671
**kwargs,
672672
) -> DataFrame:
673673
"""

pandas/tests/indexes/categorical/test_fillna.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,17 +25,19 @@ def test_fillna_categorical(self):
2525
tm.assert_index_equal(result, expected)
2626

2727
def test_fillna_copies_with_no_nas(self):
28-
# Nothing to fill, should still get a copy
28+
# Nothing to fill, should still get a copy for the Categorical method,
29+
# but OK to get a view on CategoricalIndex method
2930
ci = CategoricalIndex([0, 1, 1])
30-
cat = ci._data
3131
result = ci.fillna(0)
32-
assert result._values._ndarray is not cat._ndarray
33-
assert result._values._ndarray.base is None
32+
assert result is not ci
33+
assert tm.shares_memory(result, ci)
3434

35-
# Same check directly on the Categorical object
35+
# But at the EA level we always get a copy.
36+
cat = ci._data
3637
result = cat.fillna(0)
3738
assert result._ndarray is not cat._ndarray
3839
assert result._ndarray.base is None
40+
assert not tm.shares_memory(result, cat)
3941

4042
def test_fillna_validates_with_no_nas(self):
4143
# We validate the fill value even if fillna is a no-op

pandas/tests/indexes/common.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -516,6 +516,11 @@ def test_fillna(self, index):
516516

517517
idx = type(index)(values)
518518

519+
msg = "does not support 'downcast'"
520+
with pytest.raises(NotImplementedError, match=msg):
521+
# For now at least, we only raise if there are NAs present
522+
idx.fillna(idx[0], downcast="infer")
523+
519524
expected = np.array([False] * len(idx), dtype=bool)
520525
expected[1] = True
521526
tm.assert_numpy_array_equal(idx._isnan, expected)

pandas/tests/io/xml/test_to_xml.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1311,7 +1311,12 @@ def test_filename_and_suffix_comp(parser, comp, compfile):
13111311
def test_unsuported_compression(datapath, parser):
13121312
with pytest.raises(ValueError, match="Unrecognized compression type"):
13131313
with tm.ensure_clean() as path:
1314-
geom_df.to_xml(path, parser=parser, compression="7z")
1314+
# Argument "compression" to "to_xml" of "DataFrame" has incompatible type
1315+
# "Literal['7z']"; expected "Union[Literal['infer'], Literal['gzip'],
1316+
# Literal['bz2'], Literal['zip'], Literal['xz'], Dict[str, Any], None]"
1317+
geom_df.to_xml(
1318+
path, parser=parser, compression="7z" # type: ignore[arg-type]
1319+
)
13151320

13161321

13171322
# STORAGE OPTIONS

pandas/tests/io/xml/test_xml.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1069,7 +1069,10 @@ def test_wrong_compression_zip(parser, comp):
10691069
def test_unsuported_compression(datapath, parser):
10701070
with pytest.raises(ValueError, match="Unrecognized compression type"):
10711071
with tm.ensure_clean() as path:
1072-
read_xml(path, parser=parser, compression="7z")
1072+
# error: Argument "compression" to "read_xml" has incompatible type
1073+
# "Literal['7z']"; expected "Union[Literal['infer'], Literal['gzip'],
1074+
# Literal['bz2'], Literal['zip'], Literal['xz'], Dict[str, Any], None]"
1075+
read_xml(path, parser=parser, compression="7z") # type: ignore[arg-type]
10731076

10741077

10751078
# STORAGE OPTIONS

0 commit comments

Comments
 (0)