Skip to content

Commit ba4f001

Browse files
committed
Merge remote-tracking branch 'upstream/master' into Rt05
* upstream/master: fix ci failures (pandas-dev#25225) STY: use pytest.raises context manager (indexes/period) (pandas-dev#25199) DOC: exclude autogenerated c/cpp/html files from 'trailing whitespace' checks (pandas-dev#24549) DOC: Fixes to docstrings and add PR10 (space before colon) to validation (pandas-dev#25109) REF: Remove many Panel tests (pandas-dev#25191) BUG: Fix Series.is_unique with single occurrence of NaN (pandas-dev#25182)
2 parents b55b270 + 1d1b14c commit ba4f001

31 files changed

+212
-940
lines changed

ci/code_checks.sh

+12-3
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ if [[ -z "$CHECK" || "$CHECK" == "lint" ]]; then
9393
# this particular codebase (e.g. src/headers, src/klib, src/msgpack). However,
9494
# we can lint all header files since they aren't "generated" like C files are.
9595
MSG='Linting .c and .h' ; echo $MSG
96-
cpplint --quiet --extensions=c,h --headers=h --recursive --filter=-readability/casting,-runtime/int,-build/include_subdir pandas/_libs/src/*.h pandas/_libs/src/parser pandas/_libs/ujson pandas/_libs/tslibs/src/datetime
96+
cpplint --quiet --extensions=c,h --headers=h --recursive --filter=-readability/casting,-runtime/int,-build/include_subdir pandas/_libs/src/*.h pandas/_libs/src/parser pandas/_libs/ujson pandas/_libs/tslibs/src/datetime pandas/io/msgpack pandas/_libs/*.cpp pandas/util
9797
RET=$(($RET + $?)) ; echo $MSG "DONE"
9898

9999
echo "isort --version-number"
@@ -174,9 +174,10 @@ if [[ -z "$CHECK" || "$CHECK" == "patterns" ]]; then
174174
MSG='Check that no file in the repo contains tailing whitespaces' ; echo $MSG
175175
set -o pipefail
176176
if [[ "$AZURE" == "true" ]]; then
177-
! grep -n --exclude="*.svg" -RI "\s$" * | awk -F ":" '{print "##vso[task.logissue type=error;sourcepath=" $1 ";linenumber=" $2 ";] Tailing whitespaces found: " $3}'
177+
# we exclude all c/cpp files as the c/cpp files of pandas code base are tested when Linting .c and .h files
178+
! grep -n '--exclude=*.'{svg,c,cpp,html} -RI "\s$" * | awk -F ":" '{print "##vso[task.logissue type=error;sourcepath=" $1 ";linenumber=" $2 ";] Tailing whitespaces found: " $3}'
178179
else
179-
! grep -n --exclude="*.svg" -RI "\s$" * | awk -F ":" '{print $1 ":" $2 ":Tailing whitespaces found: " $3}'
180+
! grep -n '--exclude=*.'{svg,c,cpp,html} -RI "\s$" * | awk -F ":" '{print $1 ":" $2 ":Tailing whitespaces found: " $3}'
180181
fi
181182
RET=$(($RET + $?)) ; echo $MSG "DONE"
182183
fi
@@ -240,8 +241,16 @@ fi
240241
### DOCSTRINGS ###
241242
if [[ -z "$CHECK" || "$CHECK" == "docstrings" ]]; then
242243

244+
<<<<<<< HEAD
243245
MSG='Validate docstrings (GL06, GL07, GL09, SS04, SS05, PR03, PR05, EX04, RT04, RT05, SA05)' ; echo $MSG
244246
$BASE_DIR/scripts/validate_docstrings.py --format=azure --errors=GL06,GL07,GL09,SS04,SS05,PR03,PR05,EX04,RT04,RT05,SA05
247+
||||||| merged common ancestors
248+
MSG='Validate docstrings (GL06, GL07, GL09, SS04, PR03, PR05, EX04, RT04, SS05, SA05)' ; echo $MSG
249+
$BASE_DIR/scripts/validate_docstrings.py --format=azure --errors=GL06,GL07,GL09,SS04,PR03,PR05,EX04,RT04,SS05,SA05
250+
=======
251+
MSG='Validate docstrings (GL06, GL07, GL09, SS04, PR03, PR05, PR10, EX04, RT04, SS05, SA05)' ; echo $MSG
252+
$BASE_DIR/scripts/validate_docstrings.py --format=azure --errors=GL06,GL07,GL09,SS04,PR03,PR05,EX04,RT04,SS05,SA05
253+
>>>>>>> upstream/master
245254
RET=$(($RET + $?)) ; echo $MSG "DONE"
246255

247256
fi

doc/source/whatsnew/v0.24.2.rst

+1-1
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ Bug Fixes
8787

8888
**Other**
8989

90-
-
90+
- Bug in :meth:`Series.is_unique` where single occurrences of ``NaN`` were not considered unique (:issue:`25180`)
9191
-
9292
-
9393

pandas/core/base.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1365,7 +1365,7 @@ def is_unique(self):
13651365
-------
13661366
is_unique : boolean
13671367
"""
1368-
return self.nunique() == len(self)
1368+
return self.nunique(dropna=False) == len(self)
13691369

13701370
@property
13711371
def is_monotonic(self):

pandas/core/config.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -282,8 +282,8 @@ def __doc__(self):
282282
Note: partial matches are supported for convenience, but unless you use the
283283
full option name (e.g. x.y.z.option_name), your code may break in future
284284
versions if new options with similar names are introduced.
285-
value :
286-
new value of option.
285+
value : object
286+
New value of option.
287287
288288
Returns
289289
-------

pandas/core/internals/blocks.py

-14
Original file line numberDiff line numberDiff line change
@@ -268,20 +268,6 @@ def _slice(self, slicer):
268268
""" return a slice of my values """
269269
return self.values[slicer]
270270

271-
def reshape_nd(self, labels, shape, ref_items):
272-
"""
273-
Parameters
274-
----------
275-
labels : list of new axis labels
276-
shape : new shape
277-
ref_items : new ref_items
278-
279-
return a new block that is transformed to a nd block
280-
"""
281-
return _block2d_to_blocknd(values=self.get_values().T,
282-
placement=self.mgr_locs, shape=shape,
283-
labels=labels, ref_items=ref_items)
284-
285271
def getitem_block(self, slicer, new_mgr_locs=None):
286272
"""
287273
Perform __getitem__-like, return result as block.

pandas/core/internals/managers.py

-4
Original file line numberDiff line numberDiff line change
@@ -584,10 +584,6 @@ def comp(s, regex=False):
584584
bm._consolidate_inplace()
585585
return bm
586586

587-
def reshape_nd(self, axes, **kwargs):
588-
""" a 2d-nd reshape operation on a BlockManager """
589-
return self.apply('reshape_nd', axes=axes, **kwargs)
590-
591587
def is_consolidated(self):
592588
"""
593589
Return True if more than one block with the same dtype

pandas/io/excel.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1003,7 +1003,7 @@ class ExcelWriter(object):
10031003
mode : {'w' or 'a'}, default 'w'
10041004
File mode to use (write or append).
10051005
1006-
.. versionadded:: 0.24.0
1006+
.. versionadded:: 0.24.0
10071007
10081008
Attributes
10091009
----------

pandas/io/pytables.py

-19
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,6 @@ class DuplicateWarning(Warning):
197197
u'appendable_multiseries': 'AppendableMultiSeriesTable',
198198
u'appendable_frame': 'AppendableFrameTable',
199199
u'appendable_multiframe': 'AppendableMultiFrameTable',
200-
u'appendable_panel': 'AppendablePanelTable',
201200
u'worm': 'WORMTable',
202201
u'legacy_frame': 'LegacyFrameTable',
203202
u'legacy_panel': 'LegacyPanelTable',
@@ -4420,24 +4419,6 @@ def read(self, **kwargs):
44204419
return df
44214420

44224421

4423-
class AppendablePanelTable(AppendableTable):
4424-
4425-
""" suppor the new appendable table formats """
4426-
table_type = u'appendable_panel'
4427-
ndim = 3
4428-
obj_type = Panel
4429-
4430-
def get_object(self, obj):
4431-
""" these are written transposed """
4432-
if self.is_transposed:
4433-
obj = obj.transpose(*self.data_orientation)
4434-
return obj
4435-
4436-
@property
4437-
def is_transposed(self):
4438-
return self.data_orientation != tuple(range(self.ndim))
4439-
4440-
44414422
def _reindex_axis(obj, axis, labels, other=None):
44424423
ax = obj._get_axis(axis)
44434424
labels = ensure_index(labels)

pandas/plotting/_core.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -2549,7 +2549,7 @@ def boxplot_frame_groupby(grouped, subplots=True, column=None, fontsize=None,
25492549
Parameters
25502550
----------
25512551
grouped : Grouped DataFrame
2552-
subplots :
2552+
subplots : bool
25532553
* ``False`` - no subplots will be used
25542554
* ``True`` - create a subplot for each group
25552555
column : column name or list of names, or vector

pandas/tests/dtypes/test_missing.py

+1-10
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
from datetime import datetime
44
from decimal import Decimal
5-
from warnings import catch_warnings, filterwarnings, simplefilter
5+
from warnings import catch_warnings, filterwarnings
66

77
import numpy as np
88
import pytest
@@ -94,15 +94,6 @@ def test_isna_isnull(self, isna_f):
9494
expected = df.apply(isna_f)
9595
tm.assert_frame_equal(result, expected)
9696

97-
# panel
98-
with catch_warnings(record=True):
99-
simplefilter("ignore", FutureWarning)
100-
for p in [tm.makePanel(), tm.makePeriodPanel(),
101-
tm.add_nans(tm.makePanel())]:
102-
result = isna_f(p)
103-
expected = p.apply(isna_f)
104-
tm.assert_panel_equal(result, expected)
105-
10697
def test_isna_lists(self):
10798
result = isna([[False]])
10899
exp = np.array([[False]])

pandas/tests/frame/test_query_eval.py

-8
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
from pandas import DataFrame, Index, MultiIndex, Series, date_range
1515
from pandas.core.computation.check import _NUMEXPR_INSTALLED
1616
from pandas.tests.frame.common import TestData
17-
import pandas.util.testing as tm
1817
from pandas.util.testing import (
1918
assert_frame_equal, assert_series_equal, makeCustomDataframe as mkdf)
2019

@@ -355,13 +354,6 @@ def to_series(mi, level):
355354
else:
356355
raise AssertionError("object must be a Series or Index")
357356

358-
@pytest.mark.filterwarnings("ignore::FutureWarning")
359-
def test_raise_on_panel_with_multiindex(self, parser, engine):
360-
p = tm.makePanel(7)
361-
p.items = tm.makeCustomIndex(len(p.items), nlevels=2)
362-
with pytest.raises(NotImplementedError):
363-
pd.eval('p + 1', parser=parser, engine=engine)
364-
365357

366358
@td.skip_if_no_ne
367359
class TestDataFrameQueryNumExprPandas(object):

pandas/tests/groupby/test_groupby.py

-20
Original file line numberDiff line numberDiff line change
@@ -1218,26 +1218,6 @@ def test_groupby_nat_exclude():
12181218
grouped.get_group(pd.NaT)
12191219

12201220

1221-
@pytest.mark.filterwarnings("ignore:\\nPanel:FutureWarning")
1222-
def test_sparse_friendly(df):
1223-
sdf = df[['C', 'D']].to_sparse()
1224-
panel = tm.makePanel()
1225-
tm.add_nans(panel)
1226-
1227-
def _check_work(gp):
1228-
gp.mean()
1229-
gp.agg(np.mean)
1230-
dict(iter(gp))
1231-
1232-
# it works!
1233-
_check_work(sdf.groupby(lambda x: x // 2))
1234-
_check_work(sdf['C'].groupby(lambda x: x // 2))
1235-
_check_work(sdf.groupby(df['A']))
1236-
1237-
# do this someday
1238-
# _check_work(panel.groupby(lambda x: x.month, axis=1))
1239-
1240-
12411221
def test_groupby_2d_malformed():
12421222
d = DataFrame(index=lrange(2))
12431223
d['group'] = ['g1', 'g2']

pandas/tests/indexes/common.py

+21
Original file line numberDiff line numberDiff line change
@@ -913,3 +913,24 @@ def test_astype_category(self, copy, name, ordered):
913913
result = index.astype('category', copy=copy)
914914
expected = CategoricalIndex(index.values, name=name)
915915
tm.assert_index_equal(result, expected)
916+
917+
def test_is_unique(self):
918+
# initialize a unique index
919+
index = self.create_index().drop_duplicates()
920+
assert index.is_unique is True
921+
922+
# empty index should be unique
923+
index_empty = index[:0]
924+
assert index_empty.is_unique is True
925+
926+
# test basic dupes
927+
index_dup = index.insert(0, index[0])
928+
assert index_dup.is_unique is False
929+
930+
# single NA should be unique
931+
index_na = index.insert(0, np.nan)
932+
assert index_na.is_unique is True
933+
934+
# multiple NA should not be unique
935+
index_na_dup = index_na.insert(0, np.nan)
936+
assert index_na_dup.is_unique is False

pandas/tests/indexes/interval/test_interval.py

+4-15
Original file line numberDiff line numberDiff line change
@@ -242,12 +242,10 @@ def test_take(self, closed):
242242
[0, 0, 1], [1, 1, 2], closed=closed)
243243
tm.assert_index_equal(result, expected)
244244

245-
def test_unique(self, closed):
246-
# unique non-overlapping
247-
idx = IntervalIndex.from_tuples(
248-
[(0, 1), (2, 3), (4, 5)], closed=closed)
249-
assert idx.is_unique is True
250-
245+
def test_is_unique_interval(self, closed):
246+
"""
247+
Interval specific tests for is_unique in addition to base class tests
248+
"""
251249
# unique overlapping - distinct endpoints
252250
idx = IntervalIndex.from_tuples([(0, 1), (0.5, 1.5)], closed=closed)
253251
assert idx.is_unique is True
@@ -261,15 +259,6 @@ def test_unique(self, closed):
261259
idx = IntervalIndex.from_tuples([(-1, 1), (-2, 2)], closed=closed)
262260
assert idx.is_unique is True
263261

264-
# duplicate
265-
idx = IntervalIndex.from_tuples(
266-
[(0, 1), (0, 1), (2, 3)], closed=closed)
267-
assert idx.is_unique is False
268-
269-
# empty
270-
idx = IntervalIndex([], closed=closed)
271-
assert idx.is_unique is True
272-
273262
def test_monotonic(self, closed):
274263
# increasing non-overlapping
275264
idx = IntervalIndex.from_tuples(

pandas/tests/indexes/multi/test_duplicates.py

+12
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,18 @@ def test_has_duplicates(idx, idx_dup):
143143
assert mi.is_unique is False
144144
assert mi.has_duplicates is True
145145

146+
# single instance of NaN
147+
mi_nan = MultiIndex(levels=[['a', 'b'], [0, 1]],
148+
codes=[[-1, 0, 0, 1, 1], [-1, 0, 1, 0, 1]])
149+
assert mi_nan.is_unique is True
150+
assert mi_nan.has_duplicates is False
151+
152+
# multiple instances of NaN
153+
mi_nan_dup = MultiIndex(levels=[['a', 'b'], [0, 1]],
154+
codes=[[-1, -1, 0, 0, 1, 1], [-1, -1, 0, 1, 0, 1]])
155+
assert mi_nan_dup.is_unique is False
156+
assert mi_nan_dup.has_duplicates is True
157+
146158

147159
def test_has_duplicates_from_tuples():
148160
# GH 9075

pandas/tests/indexes/period/test_asfreq.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,9 @@ def test_asfreq(self):
6767
assert pi7.asfreq('H', 'S') == pi5
6868
assert pi7.asfreq('Min', 'S') == pi6
6969

70-
pytest.raises(ValueError, pi7.asfreq, 'T', 'foo')
70+
msg = "How must be one of S or E"
71+
with pytest.raises(ValueError, match=msg):
72+
pi7.asfreq('T', 'foo')
7173
result1 = pi1.asfreq('3M')
7274
result2 = pi1.asfreq('M')
7375
expected = period_range(freq='M', start='2001-12', end='2001-12')

0 commit comments

Comments
 (0)