Skip to content

Commit 15fde16

Browse files
committed
Merge remote-tracking branch 'upstream/master' into Rt05
* upstream/master: API: more consistent error message for MultiIndex.from_arrays (pandas-dev#25189) fix typo of see also in DataFrame stat funcs (pandas-dev#25388) edited whatsnew typo (pandas-dev#25381) REGR: fix TimedeltaIndex sum and datetime subtraction with NaT (pandas-dev#25282, pandas-dev#25317) (pandas-dev#25329) ENH: indexing and __getitem__ of dataframe and series accept zerodim integer np.array as int (pandas-dev#24924) [CLN] Excel Module Cleanups (pandas-dev#25275) Interval dtype fix (pandas-dev#25338) BUG/ENH: Timestamp.strptime (pandas-dev#25124) 14873: test for groupby.agg coercing booleans (pandas-dev#25327) [BUG] exception handling of MultiIndex.__contains__ too narrow (pandas-dev#25268) 9236: test for the DataFrame.groupby with MultiIndex having pd.NaT (pandas-dev#25310) pandas-dev#23049: test for Fatal Stack Overflow stemming From Misuse of astype('category') (pandas-dev#25366) Remove spurious MultiIndex creation in `_set_axis_name` (pandas-dev#25371) DOC: modify typos in Contributing section (pandas-dev#25365) DOC/BLD: fix --no-api option (pandas-dev#25209) DOC: Correct doc mistake in combiner func (pandas-dev#25360)
2 parents 953159c + 5449279 commit 15fde16

31 files changed

+259
-59
lines changed

doc/source/conf.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -98,9 +98,9 @@
9898
if (fname == 'index.rst'
9999
and os.path.abspath(dirname) == source_path):
100100
continue
101-
elif pattern == '-api' and dirname == 'api':
101+
elif pattern == '-api' and dirname == 'reference':
102102
exclude_patterns.append(fname)
103-
elif fname != pattern:
103+
elif pattern != '-api' and fname != pattern:
104104
exclude_patterns.append(fname)
105105

106106
with open(os.path.join(source_path, 'index.rst.template')) as f:

doc/source/development/contributing.rst

+4-4
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ Bug reports must:
5454
...
5555
```
5656

57-
#. Include the full version string of *pandas* and its dependencies. You can use the built in function::
57+
#. Include the full version string of *pandas* and its dependencies. You can use the built-in function::
5858

5959
>>> import pandas as pd
6060
>>> pd.show_versions()
@@ -211,7 +211,7 @@ See the full conda docs `here <http://conda.pydata.org/docs>`__.
211211
Creating a Python Environment (pip)
212212
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
213213

214-
If you aren't using conda for you development environment, follow these instructions.
214+
If you aren't using conda for your development environment, follow these instructions.
215215
You'll need to have at least python3.5 installed on your system.
216216

217217
.. code-block:: none
@@ -484,7 +484,7 @@ contributing them to the project::
484484

485485
./ci/code_checks.sh
486486

487-
The script verify the linting of code files, it looks for common mistake patterns
487+
The script verifies the linting of code files, it looks for common mistake patterns
488488
(like missing spaces around sphinx directives that make the documentation not
489489
being rendered properly) and it also validates the doctests. It is possible to
490490
run the checks independently by using the parameters ``lint``, ``patterns`` and
@@ -675,7 +675,7 @@ Otherwise, you need to do it manually:
675675
676676
You'll also need to
677677

678-
1. write a new test that asserts a warning is issued when calling with the deprecated argument
678+
1. Write a new test that asserts a warning is issued when calling with the deprecated argument
679679
2. Update all of pandas existing tests and code to use the new argument
680680

681681
See :ref:`contributing.warnings` for more.

doc/source/getting_started/basics.rst

+1-1
Original file line numberDiff line numberDiff line change
@@ -505,7 +505,7 @@ So, for instance, to reproduce :meth:`~DataFrame.combine_first` as above:
505505
.. ipython:: python
506506
507507
def combiner(x, y):
508-
np.where(pd.isna(x), y, x)
508+
return np.where(pd.isna(x), y, x)
509509
df1.combine(df2, combiner)
510510
511511
.. _basics.stats:

doc/source/whatsnew/v0.24.2.rst

+3
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ Fixed Regressions
2626

2727
- Fixed regression in :meth:`DataFrame.duplicated()`, where empty dataframe was not returning a boolean dtyped Series. (:issue:`25184`)
2828
- Fixed regression in :meth:`Series.min` and :meth:`Series.max` where ``numeric_only=True`` was ignored when the ``Series`` contained ```Categorical`` data (:issue:`25299`)
29+
- Fixed regression in subtraction between :class:`Series` objects with ``datetime64[ns]`` dtype incorrectly raising ``OverflowError`` when the `Series` on the right contains null values (:issue:`25317`)
30+
- Fixed regression in :class:`TimedeltaIndex` where `np.sum(index)` incorrectly returned a zero-dimensional object instead of a scalar (:issue:`25282`)
31+
- Fixed regression in ``IntervalDtype`` construction where passing an incorrect string with 'Interval' as a prefix could result in a ``RecursionError``. (:issue:`25338`)
2932

3033
.. _whatsnew_0242.enhancements:
3134

doc/source/whatsnew/v0.25.0.rst

+4-2
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ including other versions of pandas.
1919
Other Enhancements
2020
^^^^^^^^^^^^^^^^^^
2121

22+
- Indexing of ``DataFrame`` and ``Series`` now accepts zerodim ``np.ndarray`` (:issue:`24919`)
2223
- :meth:`Timestamp.replace` now supports the ``fold`` argument to disambiguate DST transition times (:issue:`25017`)
2324
- :meth:`DataFrame.at_time` and :meth:`Series.at_time` now support :meth:`datetime.time` objects with timezones (:issue:`24043`)
2425
-
@@ -28,6 +29,8 @@ Other Enhancements
2829
Backwards incompatible API changes
2930
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3031

32+
- :meth:`Timestamp.strptime` will now raise a NotImplementedError (:issue:`25016`)
33+
3134
.. _whatsnew_0250.api.other:
3235

3336
Other API Changes
@@ -149,10 +152,9 @@ Missing
149152
MultiIndex
150153
^^^^^^^^^^
151154

155+
- Bug in which incorrect exception raised by :meth:`pd.Timedelta` when testing the membership of :class:`MultiIndex` (:issue:`24570`)
152156
-
153157
-
154-
-
155-
156158

157159
I/O
158160
^^^

pandas/_libs/tslibs/nattype.pyx

+8-1
Original file line numberDiff line numberDiff line change
@@ -374,7 +374,6 @@ class NaTType(_NaT):
374374
utctimetuple = _make_error_func('utctimetuple', datetime)
375375
timetz = _make_error_func('timetz', datetime)
376376
timetuple = _make_error_func('timetuple', datetime)
377-
strptime = _make_error_func('strptime', datetime)
378377
strftime = _make_error_func('strftime', datetime)
379378
isocalendar = _make_error_func('isocalendar', datetime)
380379
dst = _make_error_func('dst', datetime)
@@ -388,6 +387,14 @@ class NaTType(_NaT):
388387
# The remaining methods have docstrings copy/pasted from the analogous
389388
# Timestamp methods.
390389

390+
strptime = _make_error_func('strptime', # noqa:E128
391+
"""
392+
Timestamp.strptime(string, format)
393+
394+
Function is not implemented. Use pd.to_datetime().
395+
"""
396+
)
397+
391398
utcfromtimestamp = _make_error_func('utcfromtimestamp', # noqa:E128
392399
"""
393400
Timestamp.utcfromtimestamp(ts)

pandas/_libs/tslibs/timestamps.pyx

+11
Original file line numberDiff line numberDiff line change
@@ -697,6 +697,17 @@ class Timestamp(_Timestamp):
697697
"""
698698
return cls(datetime.fromtimestamp(ts))
699699

700+
# Issue 25016.
701+
@classmethod
702+
def strptime(cls, date_string, format):
703+
"""
704+
Timestamp.strptime(string, format)
705+
706+
Function is not implemented. Use pd.to_datetime().
707+
"""
708+
raise NotImplementedError("Timestamp.strptime() is not implmented."
709+
"Use to_datetime() to parse date strings.")
710+
700711
@classmethod
701712
def combine(cls, date, time):
702713
"""

pandas/core/arrays/datetimes.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -720,11 +720,11 @@ def _sub_datetime_arraylike(self, other):
720720

721721
self_i8 = self.asi8
722722
other_i8 = other.asi8
723+
arr_mask = self._isnan | other._isnan
723724
new_values = checked_add_with_arr(self_i8, -other_i8,
724-
arr_mask=self._isnan)
725+
arr_mask=arr_mask)
725726
if self._hasnans or other._hasnans:
726-
mask = (self._isnan) | (other._isnan)
727-
new_values[mask] = iNaT
727+
new_values[arr_mask] = iNaT
728728
return new_values.view('timedelta64[ns]')
729729

730730
def _add_offset(self, offset):

pandas/core/arrays/timedeltas.py

+5
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,8 @@ def __init__(self, values, dtype=_TD_DTYPE, freq=None, copy=False):
190190
"ndarray, or Series or Index containing one of those."
191191
)
192192
raise ValueError(msg.format(type(values).__name__))
193+
if values.ndim != 1:
194+
raise ValueError("Only 1-dimensional input arrays are supported.")
193195

194196
if values.dtype == 'i8':
195197
# for compat with datetime/timedelta/period shared methods,
@@ -945,6 +947,9 @@ def sequence_to_td64ns(data, copy=False, unit="ns", errors="raise"):
945947
.format(dtype=data.dtype))
946948

947949
data = np.array(data, copy=copy)
950+
if data.ndim != 1:
951+
raise ValueError("Only 1-dimensional input arrays are supported.")
952+
948953
assert data.dtype == 'm8[ns]', data
949954
return data, inferred_freq
950955

pandas/core/dtypes/dtypes.py

+12-7
Original file line numberDiff line numberDiff line change
@@ -931,13 +931,18 @@ def construct_from_string(cls, string):
931931
attempt to construct this type from a string, raise a TypeError
932932
if its not possible
933933
"""
934-
if (isinstance(string, compat.string_types) and
935-
(string.startswith('interval') or
936-
string.startswith('Interval'))):
937-
return cls(string)
934+
if not isinstance(string, compat.string_types):
935+
msg = "a string needs to be passed, got type {typ}"
936+
raise TypeError(msg.format(typ=type(string)))
937+
938+
if (string.lower() == 'interval' or
939+
cls._match.search(string) is not None):
940+
return cls(string)
938941

939-
msg = "a string needs to be passed, got type {typ}"
940-
raise TypeError(msg.format(typ=type(string)))
942+
msg = ('Incorrectly formatted string passed to constructor. '
943+
'Valid formats include Interval or Interval[dtype] '
944+
'where dtype is numeric, datetime, or timedelta')
945+
raise TypeError(msg)
941946

942947
@property
943948
def type(self):
@@ -978,7 +983,7 @@ def is_dtype(cls, dtype):
978983
return True
979984
else:
980985
return False
981-
except ValueError:
986+
except (ValueError, TypeError):
982987
return False
983988
else:
984989
return False

pandas/core/frame.py

+1
Original file line numberDiff line numberDiff line change
@@ -2838,6 +2838,7 @@ def _ixs(self, i, axis=0):
28382838
return result
28392839

28402840
def __getitem__(self, key):
2841+
key = lib.item_from_zerodim(key)
28412842
key = com.apply_if_callable(key, self)
28422843

28432844
# shortcut if the key is in columns

pandas/core/generic.py

+1-2
Original file line numberDiff line numberDiff line change
@@ -1333,7 +1333,6 @@ def _set_axis_name(self, name, axis=0, inplace=False):
13331333
cat 4
13341334
monkey 2
13351335
"""
1336-
pd.MultiIndex.from_product([["mammal"], ['dog', 'cat', 'monkey']])
13371336
axis = self._get_axis_number(axis)
13381337
idx = self._get_axis(axis).set_names(name)
13391338

@@ -10874,7 +10873,7 @@ def _doc_parms(cls):
1087410873
Series.max : Return the maximum.
1087510874
Series.idxmin : Return the index of the minimum.
1087610875
Series.idxmax : Return the index of the maximum.
10877-
DataFrame.min : Return the sum over the requested axis.
10876+
DataFrame.sum : Return the sum over the requested axis.
1087810877
DataFrame.min : Return the minimum over the requested axis.
1087910878
DataFrame.max : Return the maximum over the requested axis.
1088010879
DataFrame.idxmin : Return the index of the minimum over the requested axis.

pandas/core/indexes/base.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -665,7 +665,8 @@ def __array_wrap__(self, result, context=None):
665665
"""
666666
Gets called after a ufunc.
667667
"""
668-
if is_bool_dtype(result):
668+
result = lib.item_from_zerodim(result)
669+
if is_bool_dtype(result) or lib.is_scalar(result):
669670
return result
670671

671672
attrs = self._get_attributes_dict()

pandas/core/indexes/multi.py

+8-2
Original file line numberDiff line numberDiff line change
@@ -324,11 +324,17 @@ def from_arrays(cls, arrays, sortorder=None, names=None):
324324
codes=[[0, 0, 1, 1], [1, 0, 1, 0]],
325325
names=['number', 'color'])
326326
"""
327+
error_msg = "Input must be a list / sequence of array-likes."
327328
if not is_list_like(arrays):
328-
raise TypeError("Input must be a list / sequence of array-likes.")
329+
raise TypeError(error_msg)
329330
elif is_iterator(arrays):
330331
arrays = list(arrays)
331332

333+
# Check if elements of array are list-like
334+
for array in arrays:
335+
if not is_list_like(array):
336+
raise TypeError(error_msg)
337+
332338
# Check if lengths of all arrays are equal or not,
333339
# raise ValueError, if not
334340
for i in range(1, len(arrays)):
@@ -840,7 +846,7 @@ def __contains__(self, key):
840846
try:
841847
self.get_loc(key)
842848
return True
843-
except (LookupError, TypeError):
849+
except (LookupError, TypeError, ValueError):
844850
return False
845851

846852
contains = __contains__

pandas/core/indexing.py

+3
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import numpy as np
66

77
from pandas._libs.indexing import _NDFrameIndexerBase
8+
from pandas._libs.lib import item_from_zerodim
89
import pandas.compat as compat
910
from pandas.compat import range, zip
1011
from pandas.errors import AbstractMethodError
@@ -1856,6 +1857,7 @@ def _getitem_axis(self, key, axis=None):
18561857
if axis is None:
18571858
axis = self.axis or 0
18581859

1860+
key = item_from_zerodim(key)
18591861
if is_iterator(key):
18601862
key = list(key)
18611863

@@ -2222,6 +2224,7 @@ def _getitem_axis(self, key, axis=None):
22222224

22232225
# a single integer
22242226
else:
2227+
key = item_from_zerodim(key)
22252228
if not is_integer(key):
22262229
raise TypeError("Cannot index by location index with a "
22272230
"non-integer key")

pandas/io/excel/_base.py

+2-3
Original file line numberDiff line numberDiff line change
@@ -590,9 +590,8 @@ def __new__(cls, path, engine=None, **kwargs):
590590
if engine == 'auto':
591591
engine = _get_default_writer(ext)
592592
except KeyError:
593-
error = ValueError("No engine for filetype: '{ext}'"
594-
.format(ext=ext))
595-
raise error
593+
raise ValueError("No engine for filetype: '{ext}'"
594+
.format(ext=ext))
596595
cls = get_writer(engine)
597596

598597
return object.__new__(cls)

pandas/io/excel/_util.py

+22-17
Original file line numberDiff line numberDiff line change
@@ -5,32 +5,39 @@
55

66
from pandas.core.dtypes.common import is_integer, is_list_like
77

8-
from pandas.core import config
9-
10-
_writer_extensions = ["xlsx", "xls", "xlsm"]
11-
12-
138
_writers = {}
149

1510

1611
def register_writer(klass):
17-
"""Adds engine to the excel writer registry. You must use this method to
18-
integrate with ``to_excel``. Also adds config options for any new
19-
``supported_extensions`` defined on the writer."""
12+
"""
13+
Add engine to the excel writer registry.io.excel.
14+
15+
You must use this method to integrate with ``to_excel``.
16+
17+
Parameters
18+
----------
19+
klass : ExcelWriter
20+
"""
2021
if not callable(klass):
2122
raise ValueError("Can only register callables as engines")
2223
engine_name = klass.engine
2324
_writers[engine_name] = klass
24-
for ext in klass.supported_extensions:
25-
if ext.startswith('.'):
26-
ext = ext[1:]
27-
if ext not in _writer_extensions:
28-
config.register_option("io.excel.{ext}.writer".format(ext=ext),
29-
engine_name, validator=str)
30-
_writer_extensions.append(ext)
3125

3226

3327
def _get_default_writer(ext):
28+
"""
29+
Return the default writer for the given extension.
30+
31+
Parameters
32+
----------
33+
ext : str
34+
The excel file extension for which to get the default engine.
35+
36+
Returns
37+
-------
38+
str
39+
The default engine for the extension.
40+
"""
3441
_default_writers = {'xlsx': 'openpyxl', 'xlsm': 'openpyxl', 'xls': 'xlwt'}
3542
try:
3643
import xlsxwriter # noqa
@@ -230,8 +237,6 @@ def _fill_mi_header(row, control_row):
230237

231238
return _maybe_convert_to_string(row), control_row
232239

233-
# fill blank if index_col not None
234-
235240

236241
def _pop_header_name(row, index_col):
237242
"""

pandas/tests/arithmetic/test_datetime64.py

+14
Original file line numberDiff line numberDiff line change
@@ -1440,6 +1440,20 @@ def test_dt64arr_add_sub_offset_ndarray(self, tz_naive_fixture,
14401440
class TestDatetime64OverflowHandling(object):
14411441
# TODO: box + de-duplicate
14421442

1443+
def test_dt64_overflow_masking(self, box_with_array):
1444+
# GH#25317
1445+
left = Series([Timestamp('1969-12-31')])
1446+
right = Series([NaT])
1447+
1448+
left = tm.box_expected(left, box_with_array)
1449+
right = tm.box_expected(right, box_with_array)
1450+
1451+
expected = TimedeltaIndex([NaT])
1452+
expected = tm.box_expected(expected, box_with_array)
1453+
1454+
result = left - right
1455+
tm.assert_equal(result, expected)
1456+
14431457
def test_dt64_series_arith_overflow(self):
14441458
# GH#12534, fixed by GH#19024
14451459
dt = pd.Timestamp('1700-01-31')

0 commit comments

Comments
 (0)