Skip to content

Commit 50e3ad6

Browse files
author
Matt Roeschke
committed
Merge remote-tracking branch 'upstream/master' into close_other_tz_issues
2 parents 209188e + af7f2ef commit 50e3ad6

28 files changed

+62
-215
lines changed

ci/deps/azure-35-compat.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ dependencies:
1111
- openpyxl=2.4.8
1212
- pytables=3.4.2
1313
- python-dateutil=2.6.1
14-
- python=3.5.*
14+
- python=3.5.3
1515
- pytz=2017.2
1616
- scipy=0.19.0
1717
- xlrd=1.1.0

doc/source/user_guide/advanced.rst

+3-1
Original file line numberDiff line numberDiff line change
@@ -1108,6 +1108,8 @@ the :meth:`~Index.is_unique` attribute.
11081108
weakly_monotonic.is_monotonic_increasing
11091109
weakly_monotonic.is_monotonic_increasing & weakly_monotonic.is_unique
11101110
1111+
.. _advanced.endpoints_are_inclusive:
1112+
11111113
Endpoints are inclusive
11121114
~~~~~~~~~~~~~~~~~~~~~~~
11131115

@@ -1137,7 +1139,7 @@ index can be somewhat complicated. For example, the following does not work:
11371139
s.loc['c':'e' + 1]
11381140

11391141
A very common use case is to limit a time series to start and end at two
1140-
specific dates. To enable this, we made the design to make label-based
1142+
specific dates. To enable this, we made the design choice to make label-based
11411143
slicing include both endpoints:
11421144

11431145
.. ipython:: python

doc/source/user_guide/indexing.rst

+6-4
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,8 @@ of multi-axis indexing.
6161
* A list or array of labels ``['a', 'b', 'c']``.
6262
* A slice object with labels ``'a':'f'`` (Note that contrary to usual python
6363
slices, **both** the start and the stop are included, when present in the
64-
index! See :ref:`Slicing with labels
65-
<indexing.slicing_with_labels>`.).
64+
index! See :ref:`Slicing with labels <indexing.slicing_with_labels>`
65+
and :ref:`Endpoints are inclusive <advanced.endpoints_are_inclusive>`.)
6666
* A boolean array
6767
* A ``callable`` function with one argument (the calling Series or DataFrame) and
6868
that returns valid output for indexing (one of the above).
@@ -335,8 +335,7 @@ The ``.loc`` attribute is the primary access method. The following are valid inp
335335
* A list or array of labels ``['a', 'b', 'c']``.
336336
* A slice object with labels ``'a':'f'`` (Note that contrary to usual python
337337
slices, **both** the start and the stop are included, when present in the
338-
index! See :ref:`Slicing with labels
339-
<indexing.slicing_with_labels>`.).
338+
index! See :ref:`Slicing with labels <indexing.slicing_with_labels>`.
340339
* A boolean array.
341340
* A ``callable``, see :ref:`Selection By Callable <indexing.callable>`.
342341

@@ -418,6 +417,9 @@ error will be raised (since doing otherwise would be computationally expensive,
418417
as well as potentially ambiguous for mixed type indexes). For instance, in the
419418
above example, ``s.loc[1:6]`` would raise ``KeyError``.
420419

420+
For the rationale behind this behavior, see
421+
:ref:`Endpoints are inclusive <advanced.endpoints_are_inclusive>`.
422+
421423
.. _indexing.integer:
422424

423425
Selection by position

doc/source/user_guide/timeseries.rst

-10
Original file line numberDiff line numberDiff line change
@@ -474,16 +474,6 @@ resulting ``DatetimeIndex``:
474474
Custom frequency ranges
475475
~~~~~~~~~~~~~~~~~~~~~~~
476476

477-
.. warning::
478-
479-
This functionality was originally exclusive to ``cdate_range``, which is
480-
deprecated as of version 0.21.0 in favor of ``bdate_range``. Note that
481-
``cdate_range`` only utilizes the ``weekmask`` and ``holidays`` parameters
482-
when custom business day, 'C', is passed as the frequency string. Support has
483-
been expanded with ``bdate_range`` to work with any custom frequency string.
484-
485-
.. versionadded:: 0.21.0
486-
487477
``bdate_range`` can also generate a range of custom frequency dates by using
488478
the ``weekmask`` and ``holidays`` parameters. These parameters will only be
489479
used if a custom frequency string is passed.

doc/source/whatsnew/v0.25.0.rst

+8-1
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,13 @@ What's new in 0.25.0 (April XX, 2019)
55

66
.. warning::
77

8-
Starting with the 0.25.x series of releases, pandas only supports Python 3.5 and higher.
8+
Starting with the 0.25.x series of releases, pandas only supports Python 3.5.3 and higher.
99
See :ref:`install.dropping-27` for more details.
1010

11+
.. warning::
12+
13+
The minimum supported Python version will be bumped to 3.6 in a future release.
14+
1115
.. warning::
1216

1317
`Panel` has been fully removed. For N-D labeled data structures, please
@@ -634,6 +638,9 @@ Removal of prior version deprecations/changes
634638
- Removed the previously deprecated behavior of altering column or index labels with :meth:`Series.rename_axis` or :meth:`DataFrame.rename_axis` (:issue:`17842`)
635639
- Removed the previously deprecated ``tupleize_cols`` keyword argument in :meth:`read_html`, :meth:`read_csv`, and :meth:`DataFrame.to_csv` (:issue:`17877`, :issue:`17820`)
636640
- Removed the previously deprecated ``DataFrame.from.csv`` and ``Series.from_csv`` (:issue:`17812`)
641+
- Removed the previously deprecated ``raise_on_error`` keyword argument in :meth:`DataFrame.where` and :meth:`DataFrame.mask` (:issue:`17744`)
642+
- Removed the previously deprecated ``ordered`` and ``categories`` keyword arguments in ``astype`` (:issue:`17742`)
643+
- Removed the previously deprecated ``cdate_range`` (:issue:`17691`)
637644

638645
.. _whatsnew_0250.performance:
639646

pandas/core/generic.py

+2-31
Original file line numberDiff line numberDiff line change
@@ -8644,13 +8644,6 @@ def _where(self, cond, other=np.nan, inplace=False, axis=None, level=None,
86448644
86458645
try_cast : bool, default False
86468646
Try to cast the result back to the input type (if possible).
8647-
raise_on_error : bool, default True
8648-
Whether to raise on invalid data types (e.g. trying to where on
8649-
strings).
8650-
8651-
.. deprecated:: 0.21.0
8652-
8653-
Use `errors`.
86548647
86558648
Returns
86568649
-------
@@ -8738,18 +8731,7 @@ def _where(self, cond, other=np.nan, inplace=False, axis=None, level=None,
87388731
cond_rev="False", name='where',
87398732
name_other='mask'))
87408733
def where(self, cond, other=np.nan, inplace=False, axis=None, level=None,
8741-
errors='raise', try_cast=False, raise_on_error=None):
8742-
8743-
if raise_on_error is not None:
8744-
warnings.warn(
8745-
"raise_on_error is deprecated in "
8746-
"favor of errors='raise|ignore'",
8747-
FutureWarning, stacklevel=2)
8748-
8749-
if raise_on_error:
8750-
errors = 'raise'
8751-
else:
8752-
errors = 'ignore'
8734+
errors='raise', try_cast=False):
87538735

87548736
other = com.apply_if_callable(other, self)
87558737
return self._where(cond, other, inplace, axis, level,
@@ -8759,18 +8741,7 @@ def where(self, cond, other=np.nan, inplace=False, axis=None, level=None,
87598741
cond_rev="True", name='mask',
87608742
name_other='where'))
87618743
def mask(self, cond, other=np.nan, inplace=False, axis=None, level=None,
8762-
errors='raise', try_cast=False, raise_on_error=None):
8763-
8764-
if raise_on_error is not None:
8765-
warnings.warn(
8766-
"raise_on_error is deprecated in "
8767-
"favor of errors='raise|ignore'",
8768-
FutureWarning, stacklevel=2)
8769-
8770-
if raise_on_error:
8771-
errors = 'raise'
8772-
else:
8773-
errors = 'ignore'
8744+
errors='raise', try_cast=False):
87748745

87758746
inplace = validate_bool_kwarg(inplace, 'inplace')
87768747
cond = com.apply_if_callable(cond, self)

pandas/core/indexes/datetimes.py

+1-61
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
import pandas.core.tools.datetimes as tools
3030

3131
from pandas.tseries.frequencies import Resolution, to_offset
32-
from pandas.tseries.offsets import CDay, Nano, prefix_mapping
32+
from pandas.tseries.offsets import Nano, prefix_mapping
3333

3434

3535
def _new_DatetimeIndex(cls, d):
@@ -1568,66 +1568,6 @@ def bdate_range(start=None, end=None, periods=None, freq='B', tz=None,
15681568
closed=closed, **kwargs)
15691569

15701570

1571-
def cdate_range(start=None, end=None, periods=None, freq='C', tz=None,
1572-
normalize=True, name=None, closed=None, **kwargs):
1573-
"""
1574-
Return a fixed frequency DatetimeIndex, with CustomBusinessDay as the
1575-
default frequency
1576-
1577-
.. deprecated:: 0.21.0
1578-
1579-
Parameters
1580-
----------
1581-
start : string or datetime-like, default None
1582-
Left bound for generating dates
1583-
end : string or datetime-like, default None
1584-
Right bound for generating dates
1585-
periods : integer, default None
1586-
Number of periods to generate
1587-
freq : string or DateOffset, default 'C' (CustomBusinessDay)
1588-
Frequency strings can have multiples, e.g. '5H'
1589-
tz : string, default None
1590-
Time zone name for returning localized DatetimeIndex, for example
1591-
Asia/Beijing
1592-
normalize : bool, default False
1593-
Normalize start/end dates to midnight before generating date range
1594-
name : string, default None
1595-
Name of the resulting DatetimeIndex
1596-
weekmask : string, Default 'Mon Tue Wed Thu Fri'
1597-
weekmask of valid business days, passed to ``numpy.busdaycalendar``
1598-
holidays : list
1599-
list/array of dates to exclude from the set of valid business days,
1600-
passed to ``numpy.busdaycalendar``
1601-
closed : string, default None
1602-
Make the interval closed with respect to the given frequency to
1603-
the 'left', 'right', or both sides (None)
1604-
1605-
Notes
1606-
-----
1607-
Of the three parameters: ``start``, ``end``, and ``periods``, exactly two
1608-
must be specified.
1609-
1610-
To learn more about the frequency strings, please see `this link
1611-
<http://pandas.pydata.org/pandas-docs/stable/user_guide/timeseries.html#offset-aliases>`__.
1612-
1613-
Returns
1614-
-------
1615-
rng : DatetimeIndex
1616-
"""
1617-
warnings.warn("cdate_range is deprecated and will be removed in a future "
1618-
"version, instead use pd.bdate_range(..., freq='{freq}')"
1619-
.format(freq=freq), FutureWarning, stacklevel=2)
1620-
1621-
if freq == 'C':
1622-
holidays = kwargs.pop('holidays', [])
1623-
weekmask = kwargs.pop('weekmask', 'Mon Tue Wed Thu Fri')
1624-
freq = CDay(holidays=holidays, weekmask=weekmask)
1625-
1626-
return date_range(start=start, end=end, periods=periods, freq=freq,
1627-
tz=tz, normalize=normalize, name=name,
1628-
closed=closed, **kwargs)
1629-
1630-
16311571
def _time_to_micros(time):
16321572
seconds = time.hour * 60 * 60 + 60 * time.minute + time.second
16331573
return 1000000 * seconds + time.microsecond

pandas/core/internals/blocks.py

+4-11
Original file line numberDiff line numberDiff line change
@@ -542,17 +542,10 @@ def _astype(self, dtype, copy=False, errors='raise', values=None,
542542
if self.is_categorical_astype(dtype):
543543

544544
# deprecated 17636
545-
if ('categories' in kwargs or 'ordered' in kwargs):
546-
if isinstance(dtype, CategoricalDtype):
547-
raise TypeError(
548-
"Cannot specify a CategoricalDtype and also "
549-
"`categories` or `ordered`. Use "
550-
"`dtype=CategoricalDtype(categories, ordered)`"
551-
" instead.")
552-
warnings.warn("specifying 'categories' or 'ordered' in "
553-
".astype() is deprecated; pass a "
554-
"CategoricalDtype instead",
555-
FutureWarning, stacklevel=7)
545+
for deprecated_arg in ('categories', 'ordered'):
546+
if deprecated_arg in kwargs:
547+
raise ValueError('Got an unexpected argument: {}'.format(
548+
deprecated_arg))
556549

557550
categories = kwargs.get('categories', None)
558551
ordered = kwargs.get('ordered', None)

pandas/tests/api/test_api.py

-10
Original file line numberDiff line numberDiff line change
@@ -131,13 +131,3 @@ def test_testing(self):
131131

132132
from pandas import testing
133133
self.check(testing, self.funcs)
134-
135-
136-
class TestCDateRange:
137-
138-
def test_deprecation_cdaterange(self):
139-
# GH17596
140-
from pandas.core.indexes.datetimes import cdate_range
141-
with tm.assert_produces_warning(FutureWarning,
142-
check_stacklevel=False):
143-
cdate_range('2017-01-01', '2017-12-31')

pandas/tests/io/data/test4.xls

0 Bytes
Binary file not shown.

pandas/tests/io/data/test4.xlsm

338 Bytes
Binary file not shown.

pandas/tests/io/data/test4.xlsx

-19.4 KB
Binary file not shown.

pandas/tests/io/data/test5.xls

0 Bytes
Binary file not shown.

pandas/tests/io/data/test5.xlsm

625 Bytes
Binary file not shown.

pandas/tests/io/data/test5.xlsx

624 Bytes
Binary file not shown.
0 Bytes
Binary file not shown.
165 Bytes
Binary file not shown.
165 Bytes
Binary file not shown.

pandas/tests/io/data/test_squeeze.xls

0 Bytes
Binary file not shown.
132 Bytes
Binary file not shown.
134 Bytes
Binary file not shown.

pandas/tests/io/data/test_types.xlsm

309 Bytes
Binary file not shown.

pandas/tests/io/data/test_types.xlsx

-24.2 KB
Binary file not shown.

pandas/tests/io/excel/test_readers.py

+24-29
Original file line numberDiff line numberDiff line change
@@ -31,24 +31,29 @@ def ignore_xlrd_time_clock_warning():
3131
yield
3232

3333

34+
@pytest.fixture(params=[
35+
# Add any engines to test here
36+
pytest.param('xlrd', marks=td.skip_if_no('xlrd')),
37+
pytest.param('openpyxl', marks=td.skip_if_no('openpyxl')),
38+
pytest.param(None, marks=td.skip_if_no('xlrd')),
39+
])
40+
def engine(request):
41+
"""
42+
A fixture for Excel reader engines.
43+
"""
44+
return request.param
45+
46+
3447
class TestReaders:
3548

36-
@pytest.fixture(autouse=True, params=[
37-
# Add any engines to test here
38-
pytest.param('xlrd', marks=pytest.mark.skipif(
39-
not td.safe_import("xlrd"), reason="no xlrd")),
40-
pytest.param('openpyxl', marks=pytest.mark.skipif(
41-
not td.safe_import("openpyxl"), reason="no openpyxl")),
42-
pytest.param(None, marks=pytest.mark.skipif(
43-
not td.safe_import("xlrd"), reason="no xlrd")),
44-
])
45-
def cd_and_set_engine(self, request, datapath, monkeypatch, read_ext):
49+
@pytest.fixture(autouse=True)
50+
def cd_and_set_engine(self, engine, datapath, monkeypatch, read_ext):
4651
"""
4752
Change directory and set engine for read_excel calls.
4853
"""
49-
if request.param == 'openpyxl' and read_ext == '.xls':
54+
if engine == 'openpyxl' and read_ext == '.xls':
5055
pytest.skip()
51-
func = partial(pd.read_excel, engine=request.param)
56+
func = partial(pd.read_excel, engine=engine)
5257
monkeypatch.chdir(datapath("io", "data"))
5358
monkeypatch.setattr(pd, 'read_excel', func)
5459

@@ -726,23 +731,15 @@ def test_read_excel_squeeze(self, read_ext):
726731

727732
class TestExcelFileRead:
728733

729-
@pytest.fixture(autouse=True, params=[
730-
# Add any engines to test here
731-
pytest.param('xlrd', marks=pytest.mark.skipif(
732-
not td.safe_import("xlrd"), reason="no xlrd")),
733-
pytest.param('openpyxl', marks=pytest.mark.skipif(
734-
not td.safe_import("openpyxl"), reason="no openpyxl")),
735-
pytest.param(None, marks=pytest.mark.skipif(
736-
not td.safe_import("xlrd"), reason="no xlrd")),
737-
])
738-
def cd_and_set_engine(self, request, datapath, monkeypatch, read_ext):
734+
@pytest.fixture(autouse=True)
735+
def cd_and_set_engine(self, engine, datapath, monkeypatch, read_ext):
739736
"""
740737
Change directory and set engine for ExcelFile objects.
741738
"""
742-
if request.param == 'openpyxl' and read_ext == '.xls':
739+
if engine == 'openpyxl' and read_ext == '.xls':
743740
pytest.skip()
744741

745-
func = partial(pd.ExcelFile, engine=request.param)
742+
func = partial(pd.ExcelFile, engine=engine)
746743
monkeypatch.chdir(datapath("io", "data"))
747744
monkeypatch.setattr(pd, 'ExcelFile', func)
748745

@@ -830,20 +827,18 @@ def test_sheet_name(self, read_ext, df_ref):
830827
tm.assert_frame_equal(df1_parse, df_ref, check_names=False)
831828
tm.assert_frame_equal(df2_parse, df_ref, check_names=False)
832829

833-
def test_excel_read_buffer(self, read_ext):
830+
def test_excel_read_buffer(self, engine, read_ext):
834831
pth = 'test1' + read_ext
835-
engine = pd.ExcelFile.keywords['engine'] # TODO: fixturize
836832
expected = pd.read_excel(pth, 'Sheet1', index_col=0, engine=engine)
837833

838834
with open(pth, 'rb') as f:
839835
with pd.ExcelFile(f) as xls:
840836
actual = pd.read_excel(xls, 'Sheet1', index_col=0)
841837

842-
tm.assert_frame_equal(expected, actual)
838+
tm.assert_frame_equal(expected, actual)
843839

844-
def test_reader_closes_file(self, read_ext):
840+
def test_reader_closes_file(self, engine, read_ext):
845841
f = open('test1' + read_ext, 'rb')
846-
engine = pd.ExcelFile.keywords['engine'] # TODO: fixturize
847842
with pd.ExcelFile(f) as xlsx:
848843
# parses okay
849844
pd.read_excel(xlsx, 'Sheet1', index_col=0, engine=engine)

0 commit comments

Comments
 (0)