Skip to content

Commit aaaa2da

Browse files
committed
Merge remote-tracking branch 'upstream/master' into read_excel-docstring
* upstream/master: REF/TST: replace capture_stdout with pytest capsys fixture (pandas-dev#24501) BUG: fix .iat assignment creates a new column (pandas-dev#24495) DOC: add checks on the returns section in the docstrings (pandas-dev#23138) (pandas-dev#23432) ENH: Add strings_as_fixed_length parameter for df.to_records() (pandas-dev#18146) (pandas-dev#22229) TST: Skip db tests unless explicitly specified in -m pattern (pandas-dev#24492) Mix EA into DTA/TDA; part of 24024 (pandas-dev#24502) DOC: Fix building of a single API document (pandas-dev#24506)
2 parents f11bce8 + 100ffff commit aaaa2da

28 files changed

+470
-129
lines changed

.travis.yml

+4-4
Original file line numberDiff line numberDiff line change
@@ -34,23 +34,23 @@ matrix:
3434
include:
3535
- dist: trusty
3636
env:
37-
- JOB="3.7" ENV_FILE="ci/deps/travis-37.yaml" PATTERN="not slow and not network and not db"
37+
- JOB="3.7" ENV_FILE="ci/deps/travis-37.yaml" PATTERN="not slow and not network"
3838

3939
- dist: trusty
4040
env:
41-
- JOB="2.7" ENV_FILE="ci/deps/travis-27.yaml" PATTERN="not slow"
41+
- JOB="2.7" ENV_FILE="ci/deps/travis-27.yaml" PATTERN="not slow and db"
4242
addons:
4343
apt:
4444
packages:
4545
- python-gtk2
4646

4747
- dist: trusty
4848
env:
49-
- JOB="3.6, locale" ENV_FILE="ci/deps/travis-36-locale.yaml" PATTERN="not slow and not network" LOCALE_OVERRIDE="zh_CN.UTF-8"
49+
- JOB="3.6, locale" ENV_FILE="ci/deps/travis-36-locale.yaml" PATTERN="not slow and not network and db" LOCALE_OVERRIDE="zh_CN.UTF-8"
5050

5151
- dist: trusty
5252
env:
53-
- JOB="3.6, coverage" ENV_FILE="ci/deps/travis-36.yaml" PATTERN="not slow and not network" PANDAS_TESTING_MODE="deprecate" COVERAGE=true
53+
- JOB="3.6, coverage" ENV_FILE="ci/deps/travis-36.yaml" PATTERN="not slow and not network and db" PANDAS_TESTING_MODE="deprecate" COVERAGE=true
5454

5555
# In allow_failures
5656
- dist: trusty

ci/azure/posix.yml

+6-6
Original file line numberDiff line numberDiff line change
@@ -12,37 +12,37 @@ jobs:
1212
py35_np_120:
1313
ENV_FILE: ci/deps/azure-macos-35.yaml
1414
CONDA_PY: "35"
15-
PATTERN: "not slow and not network and not db"
15+
PATTERN: "not slow and not network"
1616

1717
${{ if eq(parameters.name, 'Linux') }}:
1818
py27_np_120:
1919
ENV_FILE: ci/deps/azure-27-compat.yaml
2020
CONDA_PY: "27"
21-
PATTERN: "not slow and not network and not db"
21+
PATTERN: "not slow and not network"
2222

2323
py27_locale_slow_old_np:
2424
ENV_FILE: ci/deps/azure-27-locale.yaml
2525
CONDA_PY: "27"
26-
PATTERN: "slow and not db"
26+
PATTERN: "slow"
2727
LOCALE_OVERRIDE: "zh_CN.UTF-8"
2828
EXTRA_APT: "language-pack-zh-hans"
2929

3030
py36_locale_slow:
3131
ENV_FILE: ci/deps/azure-36-locale_slow.yaml
3232
CONDA_PY: "36"
33-
PATTERN: "not slow and not network and not db"
33+
PATTERN: "not slow and not network"
3434
LOCALE_OVERRIDE: "it_IT.UTF-8"
3535

3636
py37_locale:
3737
ENV_FILE: ci/deps/azure-37-locale.yaml
3838
CONDA_PY: "37"
39-
PATTERN: "not slow and not network and not db"
39+
PATTERN: "not slow and not network"
4040
LOCALE_OVERRIDE: "zh_CN.UTF-8"
4141

4242
py37_np_dev:
4343
ENV_FILE: ci/deps/azure-37-numpydev.yaml
4444
CONDA_PY: "37"
45-
PATTERN: "not slow and not network and not db"
45+
PATTERN: "not slow and not network"
4646
TEST_ARGS: "-W error"
4747
PANDAS_TESTING_MODE: "deprecate"
4848
EXTRA_APT: "xsel"

ci/azure/windows.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ jobs:
3838
displayName: 'Build'
3939
- script: |
4040
call activate pandas-dev
41-
pytest -m "not slow and not network and not db" --junitxml=test-data.xml pandas -n 2 -r sxX --strict --durations=10 %*
41+
pytest -m "not slow and not network" --junitxml=test-data.xml pandas -n 2 -r sxX --strict --durations=10 %*
4242
displayName: 'Test'
4343
- task: PublishTestResults@2
4444
inputs:

doc/make.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ def __init__(self, num_jobs=0, include_api=True, single_doc=None,
5050
if single_doc and single_doc.endswith('.rst'):
5151
self.single_doc_html = os.path.splitext(single_doc)[0] + '.html'
5252
elif single_doc:
53-
self.single_doc_html = 'generated/pandas.{}.html'.format(
53+
self.single_doc_html = 'api/generated/pandas.{}.html'.format(
5454
single_doc)
5555

5656
def _process_single_doc(self, single_doc):

doc/source/conf.py

+1-2
Original file line numberDiff line numberDiff line change
@@ -98,8 +98,7 @@
9898
if (fname == 'index.rst'
9999
and os.path.abspath(dirname) == source_path):
100100
continue
101-
elif (pattern == '-api'
102-
and (fname == 'api.rst' or dirname == 'generated')):
101+
elif pattern == '-api' and dirname == 'api':
103102
exclude_patterns.append(fname)
104103
elif fname != pattern:
105104
exclude_patterns.append(fname)

doc/source/index.rst.template

+1-1
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ See the package overview for more detail about what's in the library.
113113
{{ single_doc[:-4] }}
114114
{% elif single_doc %}
115115
.. autosummary::
116-
:toctree: generated/
116+
:toctree: api/generated/
117117

118118
{{ single_doc }}
119119
{% else -%}

doc/source/whatsnew/v0.24.0.rst

+2
Original file line numberDiff line numberDiff line change
@@ -411,6 +411,7 @@ Other Enhancements
411411
- :meth:`DataFrame.to_stata` and :class:`pandas.io.stata.StataWriter117` can write mixed sting columns to Stata strl format (:issue:`23633`)
412412
- :meth:`DataFrame.between_time` and :meth:`DataFrame.at_time` have gained the ``axis`` parameter (:issue:`8839`)
413413
- The ``scatter_matrix``, ``andrews_curves``, ``parallel_coordinates``, ``lag_plot``, ``autocorrelation_plot``, ``bootstrap_plot``, and ``radviz`` plots from the ``pandas.plotting`` module are now accessible from calling :meth:`DataFrame.plot` (:issue:`11978`)
414+
- :meth:`DataFrame.to_records` now accepts ``index_dtypes`` and ``column_dtypes`` parameters to allow different data types in stored column and index records (:issue:`18146`)
414415
- :class:`IntervalIndex` has gained the :attr:`~IntervalIndex.is_overlapping` attribute to indicate if the ``IntervalIndex`` contains any overlapping intervals (:issue:`23309`)
415416
- :func:`pandas.DataFrame.to_sql` has gained the ``method`` argument to control SQL insertion clause. See the :ref:`insertion method <io.sql.method>` section in the documentation. (:issue:`8953`)
416417

@@ -1494,6 +1495,7 @@ Indexing
14941495
- Bug in :class:`Index` slicing with boolean :class:`Index` may raise ``TypeError`` (:issue:`22533`)
14951496
- Bug in ``PeriodArray.__setitem__`` when accepting slice and list-like value (:issue:`23978`)
14961497
- Bug in :class:`DatetimeIndex`, :class:`TimedeltaIndex` where indexing with ``Ellipsis`` would lose their ``freq`` attribute (:issue:`21282`)
1498+
- Bug in ``iat`` where using it to assign an incompatible value would create a new column (:issue:`23236`)
14971499

14981500
Missing
14991501
^^^^^^^

pandas/conftest.py

+12-3
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import collections
12
from datetime import date, time, timedelta
23
from decimal import Decimal
34
import importlib
@@ -54,14 +55,22 @@ def pytest_runtest_setup(item):
5455
if 'network' in item.keywords and item.config.getoption("--skip-network"):
5556
pytest.skip("skipping due to --skip-network")
5657

57-
if 'db' in item.keywords and item.config.getoption("--skip-db"):
58-
pytest.skip("skipping due to --skip-db")
59-
6058
if 'high_memory' in item.keywords and not item.config.getoption(
6159
"--run-high-memory"):
6260
pytest.skip(
6361
"skipping high memory test since --run-high-memory was not set")
6462

63+
# if "db" not explicitly set in the -m pattern, we skip the db tests
64+
if 'db' in item.keywords:
65+
pattern = item.config.getoption('-m')
66+
markers = collections.defaultdict(bool)
67+
for marker in item.iter_markers():
68+
markers[marker.name] = True
69+
markers['db'] = False
70+
db_in_pattern = not eval(pattern, {}, markers)
71+
if not db_in_pattern:
72+
pytest.skip('skipping db unless -m "db" is specified')
73+
6574

6675
# Configurations for all tests and all test modules
6776

pandas/core/arrays/datetimelike.py

+46-7
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,14 @@
2828
from pandas.core.dtypes.missing import isna
2929

3030
from pandas.core import nanops
31-
from pandas.core.algorithms import checked_add_with_arr, take, unique1d
31+
from pandas.core.algorithms import (
32+
checked_add_with_arr, take, unique1d, value_counts)
3233
import pandas.core.common as com
3334

3435
from pandas.tseries import frequencies
3536
from pandas.tseries.offsets import DateOffset, Tick
3637

37-
from .base import ExtensionOpsMixin
38+
from .base import ExtensionArray, ExtensionOpsMixin
3839

3940

4041
def _make_comparison_op(cls, op):
@@ -343,7 +344,9 @@ def ceil(self, freq, ambiguous='raise', nonexistent='raise'):
343344
return self._round(freq, RoundTo.PLUS_INFTY, ambiguous, nonexistent)
344345

345346

346-
class DatetimeLikeArrayMixin(ExtensionOpsMixin, AttributesMixin):
347+
class DatetimeLikeArrayMixin(ExtensionOpsMixin,
348+
AttributesMixin,
349+
ExtensionArray):
347350
"""
348351
Shared Base/Mixin class for DatetimeArray, TimedeltaArray, PeriodArray
349352
@@ -701,6 +704,43 @@ def repeat(self, repeats, *args, **kwargs):
701704
values = self._data.repeat(repeats)
702705
return type(self)(values.view('i8'), dtype=self.dtype)
703706

707+
def value_counts(self, dropna=False):
708+
"""
709+
Return a Series containing counts of unique values.
710+
711+
Parameters
712+
----------
713+
dropna : boolean, default True
714+
Don't include counts of NaT values.
715+
716+
Returns
717+
-------
718+
Series
719+
"""
720+
from pandas import Series, Index
721+
722+
if dropna:
723+
values = self[~self.isna()]._data
724+
else:
725+
values = self._data
726+
727+
cls = type(self)
728+
729+
result = value_counts(values, sort=False, dropna=dropna)
730+
index = Index(cls(result.index.view('i8'), dtype=self.dtype),
731+
name=result.index.name)
732+
return Series(result.values, index=index, name=result.name)
733+
734+
def map(self, mapper):
735+
# TODO(GH-23179): Add ExtensionArray.map
736+
# Need to figure out if we want ExtensionArray.map first.
737+
# If so, then we can refactor IndexOpsMixin._map_values to
738+
# a standalone function and call from here..
739+
# Else, just rewrite _map_infer_values to do the right thing.
740+
from pandas import Index
741+
742+
return Index(self).map(mapper).array
743+
704744
# ------------------------------------------------------------------
705745
# Null Handling
706746

@@ -1357,10 +1397,9 @@ def _reduce(self, name, axis=0, skipna=True, **kwargs):
13571397
if op:
13581398
return op(axis=axis, skipna=skipna, **kwargs)
13591399
else:
1360-
raise TypeError("cannot perform {name} with type {dtype}"
1361-
.format(name=name, dtype=self.dtype))
1362-
# TODO: use super(DatetimeLikeArrayMixin, self)._reduce
1363-
# after we subclass ExtensionArray
1400+
return super(DatetimeLikeArrayMixin, self)._reduce(
1401+
name, skipna, **kwargs
1402+
)
13641403

13651404
def min(self, axis=None, skipna=True, *args, **kwargs):
13661405
"""

pandas/core/arrays/period.py

+2-19
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
from pandas.core.dtypes.missing import isna, notna
2323

2424
import pandas.core.algorithms as algos
25-
from pandas.core.arrays import ExtensionArray, datetimelike as dtl
25+
from pandas.core.arrays import datetimelike as dtl
2626
import pandas.core.common as com
2727
from pandas.core.missing import backfill_1d, pad_1d
2828

@@ -92,9 +92,7 @@ def wrapper(self, other):
9292
return compat.set_function_name(wrapper, opname, cls)
9393

9494

95-
class PeriodArray(dtl.DatetimeLikeArrayMixin,
96-
dtl.DatelikeOps,
97-
ExtensionArray):
95+
class PeriodArray(dtl.DatetimeLikeArrayMixin, dtl.DatelikeOps):
9896
"""
9997
Pandas ExtensionArray for storing Period data.
10098
@@ -418,21 +416,6 @@ def fillna(self, value=None, method=None, limit=None):
418416
new_values = self.copy()
419417
return new_values
420418

421-
def value_counts(self, dropna=False):
422-
from pandas import Series, PeriodIndex
423-
424-
if dropna:
425-
values = self[~self.isna()]._data
426-
else:
427-
values = self._data
428-
429-
cls = type(self)
430-
431-
result = algos.value_counts(values, sort=False)
432-
index = PeriodIndex(cls(result.index, freq=self.freq),
433-
name=result.index.name)
434-
return Series(result.values, index=index, name=result.name)
435-
436419
# --------------------------------------------------------------------
437420

438421
def _time_shift(self, n, freq=None):

pandas/core/arrays/timedeltas.py

+11-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717
from pandas.core.dtypes.common import (
1818
_NS_DTYPE, _TD_DTYPE, ensure_int64, is_datetime64_dtype, is_float_dtype,
19-
is_integer_dtype, is_list_like, is_object_dtype, is_scalar,
19+
is_int64_dtype, is_integer_dtype, is_list_like, is_object_dtype, is_scalar,
2020
is_string_dtype, is_timedelta64_dtype, is_timedelta64_ns_dtype,
2121
pandas_dtype)
2222
from pandas.core.dtypes.dtypes import DatetimeTZDtype
@@ -244,6 +244,16 @@ def _maybe_clear_freq(self):
244244
# ----------------------------------------------------------------
245245
# Array-Like / EA-Interface Methods
246246

247+
def __array__(self, dtype=None):
248+
# TODO(https://github.com/pandas-dev/pandas/pull/23593)
249+
# Maybe push to parent once datetimetz __array__ is figured out.
250+
if is_object_dtype(dtype):
251+
return np.array(list(self), dtype=object)
252+
elif is_int64_dtype(dtype):
253+
return self.asi8
254+
255+
return self._data
256+
247257
@Appender(dtl.DatetimeLikeArrayMixin._validate_fill_value.__doc__)
248258
def _validate_fill_value(self, fill_value):
249259
if isna(fill_value):

pandas/core/dtypes/inference.py

+4-1
Original file line numberDiff line numberDiff line change
@@ -398,8 +398,11 @@ def is_dict_like(obj):
398398
>>> is_dict_like([1, 2, 3])
399399
False
400400
"""
401+
for attr in ("__getitem__", "keys", "__contains__"):
402+
if not hasattr(obj, attr):
403+
return False
401404

402-
return hasattr(obj, '__getitem__') and hasattr(obj, 'keys')
405+
return True
403406

404407

405408
def is_named_tuple(obj):

0 commit comments

Comments
 (0)