Skip to content

Commit c44c6e3

Browse files
Merge remote-tracking branch 'upstream/master' into bug26390
2 parents b3da29f + 1263e1a commit c44c6e3

File tree

17 files changed

+72
-60
lines changed

17 files changed

+72
-60
lines changed

.travis.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,14 @@ install:
8686
- ci/submit_cython_cache.sh
8787
- echo "install done"
8888

89+
before_script:
90+
# display server (for clipboard functionality) needs to be started here,
91+
# does not work if done in install:setup_env.sh (GH-26103)
92+
- export DISPLAY=":99.0"
93+
- echo "sh -e /etc/init.d/xvfb start"
94+
- sh -e /etc/init.d/xvfb start
95+
- sleep 3
96+
8997
script:
9098
- echo "script start"
9199
- source activate pandas-dev

ci/azure/windows.yml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,13 @@ jobs:
1919
steps:
2020
- powershell: Write-Host "##vso[task.prependpath]$env:CONDA\Scripts"
2121
displayName: Add conda to PATH
22-
- script: conda env create --file ci\\deps\\azure-windows-$(CONDA_PY).yaml
22+
- script: conda update -q -n base conda
23+
displayName: Update conda
24+
- script: conda env create -q --file ci\\deps\\azure-windows-$(CONDA_PY).yaml
2325
displayName: Create anaconda environment
2426
- script: |
2527
call activate pandas-dev
28+
call conda list
2629
ci\\incremental\\build.cmd
2730
displayName: 'Build'
2831
- script: |

ci/deps/azure-windows-37.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
name: pandas-dev
22
channels:
33
- defaults
4+
- conda-forge
45
dependencies:
56
- beautifulsoup4
67
- bottleneck
8+
- gcsfs
79
- html5lib
810
- jinja2
911
- lxml

ci/setup_env.sh

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -118,16 +118,10 @@ echo "conda list"
118118
conda list
119119

120120
# Install DB for Linux
121-
export DISPLAY=":99."
122121
if [ ${TRAVIS_OS_NAME} == "linux" ]; then
123122
echo "installing dbs"
124123
mysql -e 'create database pandas_nosetest;'
125124
psql -c 'create database pandas_nosetest;' -U postgres
126-
127-
echo
128-
echo "sh -e /etc/init.d/xvfb start"
129-
sh -e /etc/init.d/xvfb start
130-
sleep 3
131125
else
132126
echo "not using dbs on non-linux"
133127
fi

doc/source/whatsnew/v0.11.0.rst

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -238,14 +238,9 @@ Enhancements
238238

239239
- support ``read_hdf/to_hdf`` API similar to ``read_csv/to_csv``
240240

241-
.. ipython:: python
242-
:suppress:
243-
244-
from pandas.compat import lrange
245-
246241
.. ipython:: python
247242
248-
df = pd.DataFrame({'A': lrange(5), 'B': lrange(5)})
243+
df = pd.DataFrame({'A': range(5), 'B': range(5)})
249244
df.to_hdf('store.h5', 'table', append=True)
250245
pd.read_hdf('store.h5', 'table', where=['index > 2'])
251246

doc/source/whatsnew/v0.12.0.rst

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -83,13 +83,8 @@ API changes
8383
``iloc`` API to be *purely* positional based.
8484

8585
.. ipython:: python
86-
:suppress:
8786
88-
from pandas.compat import lrange
89-
90-
.. ipython:: python
91-
92-
df = pd.DataFrame(lrange(5), list('ABCDE'), columns=['a'])
87+
df = pd.DataFrame(range(5), index=list('ABCDE'), columns=['a'])
9388
mask = (df.a % 2 == 0)
9489
mask
9590

doc/source/whatsnew/v0.25.0.rst

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,8 @@ Deprecations
257257

258258
- Deprecated the ``units=M`` (months) and ``units=Y`` (year) parameters for ``units`` of :func:`pandas.to_timedelta`, :func:`pandas.Timedelta` and :func:`pandas.TimedeltaIndex` (:issue:`16344`)
259259
- The functions :func:`pandas.to_datetime` and :func:`pandas.to_timedelta` have deprecated the ``box`` keyword. Instead, use :meth:`to_numpy` or :meth:`Timestamp.to_datetime64` or :meth:`Timedelta.to_timedelta64`. (:issue:`24416`)
260+
- The :meth:`DataFrame.compound` and :meth:`Series.compound` methods are deprecated and will be removed in a future version.
261+
260262

261263
.. _whatsnew_0250.prior_deprecations:
262264

@@ -373,7 +375,7 @@ Indexing
373375
- Improved exception message when calling :meth:`DataFrame.iloc` with a list of non-numeric objects (:issue:`25753`).
374376
- Bug in :meth:`DataFrame.loc` and :meth:`Series.loc` where ``KeyError`` was not raised for a ``MultiIndex`` when the key was less than or equal to the number of levels in the :class:`MultiIndex` (:issue:`14885`).
375377
- Bug in which :meth:`DataFrame.append` produced an erroneous warning indicating that a ``KeyError`` will be thrown in the future when the data to be appended contains new columns (:issue:`22252`).
376-
-
378+
- Bug in which :meth:`DataFrame.to_csv` caused a segfault for a reindexed data frame, when the indices were single-level :class:`MultiIndex` (:issue:`26303`).
377379

378380

379381
Missing

mypy.ini

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,9 @@ ignore_errors=True
2323
[mypy-pandas.core.internals.blocks]
2424
ignore_errors=True
2525

26-
[mypy-pandas.core.ops]
27-
ignore_errors=True
28-
2926
[mypy-pandas.core.panel]
3027
ignore_errors=True
3128

32-
[mypy-pandas.core.resample]
33-
ignore_errors=True
34-
3529
[mypy-pandas.core.reshape.merge]
3630
ignore_errors=True
3731

pandas/_libs/tslibs/period.pyx

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2208,10 +2208,6 @@ cdef class _Period:
22082208
def now(cls, freq=None):
22092209
return Period(datetime.now(), freq=freq)
22102210

2211-
# HACK IT UP AND YOU BETTER FIX IT SOON
2212-
def __str__(self):
2213-
return self.__unicode__()
2214-
22152211
@property
22162212
def freqstr(self):
22172213
return self.freq.freqstr
@@ -2221,9 +2217,9 @@ cdef class _Period:
22212217
formatted = period_format(self.ordinal, base)
22222218
return "Period('%s', '%s')" % (formatted, self.freqstr)
22232219

2224-
def __unicode__(self):
2220+
def __str__(self):
22252221
"""
2226-
Return a unicode string representation for a particular DataFrame
2222+
Return a string representation for a particular DataFrame
22272223
"""
22282224
base, mult = get_freq_code(self.freq)
22292225
formatted = period_format(self.ordinal, base)

pandas/core/dtypes/dtypes.py

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -126,14 +126,11 @@ class PandasExtensionDtype(ExtensionDtype):
126126
isnative = 0
127127
_cache = {} # type: Dict[str_type, 'PandasExtensionDtype']
128128

129-
def __unicode__(self):
130-
return self.name
131-
132129
def __str__(self):
133130
"""
134131
Return a string representation for a particular Object
135132
"""
136-
return self.__unicode__()
133+
return self.name
137134

138135
def __bytes__(self):
139136
"""
@@ -142,7 +139,7 @@ def __bytes__(self):
142139
from pandas._config import get_option
143140

144141
encoding = get_option("display.encoding")
145-
return self.__unicode__().encode(encoding, 'replace')
142+
return str(self).encode(encoding, 'replace')
146143

147144
def __repr__(self):
148145
"""
@@ -707,7 +704,7 @@ def construct_from_string(cls, string):
707704

708705
raise TypeError("Could not construct DatetimeTZDtype")
709706

710-
def __unicode__(self):
707+
def __str__(self):
711708
return "datetime64[{unit}, {tz}]".format(unit=self.unit, tz=self.tz)
712709

713710
@property
@@ -837,12 +834,12 @@ def construct_from_string(cls, string):
837834
pass
838835
raise TypeError("could not construct PeriodDtype")
839836

840-
def __unicode__(self):
841-
return str(self.name)
837+
def __str__(self):
838+
return self.name
842839

843840
@property
844841
def name(self):
845-
return str("period[{freq}]".format(freq=self.freq.freqstr))
842+
return "period[{freq}]".format(freq=self.freq.freqstr)
846843

847844
@property
848845
def na_value(self):
@@ -1007,7 +1004,7 @@ def construct_from_string(cls, string):
10071004
def type(self):
10081005
return Interval
10091006

1010-
def __unicode__(self):
1007+
def __str__(self):
10111008
if self.subtype is None:
10121009
return "interval"
10131010
return "interval[{subtype}]".format(subtype=self.subtype)

pandas/core/generic.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10177,11 +10177,14 @@ def mad(self, axis=None, skipna=None, level=None):
1017710177
nanops.nanstd)
1017810178

1017910179
@Substitution(desc="Return the compound percentage of the values for "
10180-
"the requested axis.", name1=name, name2=name2,
10181-
axis_descr=axis_descr,
10180+
"the requested axis.\n\n.. deprecated:: 0.25.0",
10181+
name1=name, name2=name2, axis_descr=axis_descr,
1018210182
min_count='', see_also='', examples='')
1018310183
@Appender(_num_doc)
1018410184
def compound(self, axis=None, skipna=None, level=None):
10185+
msg = ("The 'compound' method is deprecated and will be"
10186+
"removed in a future version.")
10187+
warnings.warn(msg, FutureWarning, stacklevel=2)
1018510188
if skipna is None:
1018610189
skipna = True
1018710190
return (1 + self).prod(axis=axis, skipna=skipna, level=level) - 1

pandas/core/groupby/grouper.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
split-apply-combine paradigm.
44
"""
55

6+
from typing import Tuple
67
import warnings
78

89
import numpy as np
@@ -84,7 +85,8 @@ class Grouper:
8485
8586
>>> df.groupby(Grouper(level='date', freq='60s', axis=1))
8687
"""
87-
_attributes = ('key', 'level', 'freq', 'axis', 'sort')
88+
_attributes = ('key', 'level', 'freq', 'axis',
89+
'sort') # type: Tuple[str, ...]
8890

8991
def __new__(cls, *args, **kwargs):
9092
if kwargs.get('freq') is not None:

pandas/core/indexes/multi.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -946,7 +946,9 @@ def _format_native_types(self, na_rep='nan', **kwargs):
946946
new_codes.append(level_codes)
947947

948948
if len(new_levels) == 1:
949-
return Index(new_levels[0])._format_native_types()
949+
# a single-level multi-index
950+
return Index(new_levels[0].take(
951+
new_codes[0]))._format_native_types()
950952
else:
951953
# reconstruct the multi-index
952954
mi = MultiIndex(levels=new_levels, codes=new_codes,

pandas/core/ops.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import datetime
77
import operator
88
import textwrap
9+
from typing import Dict, Optional
910
import warnings
1011

1112
import numpy as np
@@ -625,15 +626,13 @@ def _get_op_name(op, special):
625626
'desc': 'Greater than or equal to',
626627
'reverse': None,
627628
'series_examples': None}
628-
}
629+
} # type: Dict[str, Dict[str, Optional[str]]]
629630

630631
_op_names = list(_op_descriptions.keys())
631632
for key in _op_names:
632-
_op_descriptions[key]['reversed'] = False
633633
reverse_op = _op_descriptions[key]['reverse']
634634
if reverse_op is not None:
635635
_op_descriptions[reverse_op] = _op_descriptions[key].copy()
636-
_op_descriptions[reverse_op]['reversed'] = True
637636
_op_descriptions[reverse_op]['reverse'] = key
638637

639638
_flex_doc_SERIES = """
@@ -1010,7 +1009,7 @@ def _make_flex_doc(op_name, typ):
10101009
op_name = op_name.replace('__', '')
10111010
op_desc = _op_descriptions[op_name]
10121011

1013-
if op_desc['reversed']:
1012+
if op_name.startswith('r'):
10141013
equiv = 'other ' + op_desc['op'] + ' ' + typ
10151014
else:
10161015
equiv = typ + ' ' + op_desc['op'] + ' other'

pandas/core/resample.py

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import copy
22
from datetime import timedelta
33
from textwrap import dedent
4+
from typing import Dict, no_type_check
45
import warnings
56

67
import numpy as np
@@ -31,7 +32,7 @@
3132
from pandas.tseries.frequencies import to_offset
3233
from pandas.tseries.offsets import DateOffset, Day, Nano, Tick
3334

34-
_shared_docs_kwargs = dict()
35+
_shared_docs_kwargs = dict() # type: Dict[str, str]
3536

3637

3738
class Resampler(_GroupBy):
@@ -873,25 +874,25 @@ def f(self, _method=method, min_count=0, *args, **kwargs):
873874
for method in ['min', 'max', 'first', 'last', 'mean', 'sem',
874875
'median', 'ohlc']:
875876

876-
def f(self, _method=method, *args, **kwargs):
877+
def g(self, _method=method, *args, **kwargs):
877878
nv.validate_resampler_func(_method, args, kwargs)
878879
return self._downsample(_method)
879-
f.__doc__ = getattr(GroupBy, method).__doc__
880-
setattr(Resampler, method, f)
880+
g.__doc__ = getattr(GroupBy, method).__doc__
881+
setattr(Resampler, method, g)
881882

882883
# groupby & aggregate methods
883884
for method in ['count']:
884-
def f(self, _method=method):
885+
def h(self, _method=method):
885886
return self._downsample(_method)
886-
f.__doc__ = getattr(GroupBy, method).__doc__
887-
setattr(Resampler, method, f)
887+
h.__doc__ = getattr(GroupBy, method).__doc__
888+
setattr(Resampler, method, h)
888889

889890
# series only methods
890891
for method in ['nunique']:
891-
def f(self, _method=method):
892+
def h(self, _method=method):
892893
return self._downsample(_method)
893-
f.__doc__ = getattr(SeriesGroupBy, method).__doc__
894-
setattr(Resampler, method, f)
894+
h.__doc__ = getattr(SeriesGroupBy, method).__doc__
895+
setattr(Resampler, method, h)
895896

896897

897898
def _maybe_process_deprecations(r, how=None, fill_method=None, limit=None):
@@ -964,6 +965,7 @@ def __init__(self, obj, *args, **kwargs):
964965
self._groupby.grouper.mutated = True
965966
self.groupby = copy.copy(parent.groupby)
966967

968+
@no_type_check
967969
def _apply(self, f, grouper=None, *args, **kwargs):
968970
"""
969971
Dispatch to _upsample; we are stripping all of the _upsample kwargs and

pandas/tests/frame/test_to_csv.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1230,6 +1230,15 @@ def test_multi_index_header(self):
12301230
expected = tm.convert_rows_list_to_csv_str(expected_rows)
12311231
assert result == expected
12321232

1233+
def test_to_csv_single_level_multi_index(self):
1234+
# see gh-26303
1235+
index = pd.Index([(1,), (2,), (3,)])
1236+
df = pd.DataFrame([[1, 2, 3]], columns=index)
1237+
df = df.reindex(columns=[(1,), (3,)])
1238+
expected = ",1,3\n0,1,3\n"
1239+
result = df.to_csv(line_terminator='\n')
1240+
assert_almost_equal(result, expected)
1241+
12331242
def test_gz_lineend(self):
12341243
# GH 25311
12351244
df = pd.DataFrame({'a': [1, 2]})

pandas/tests/series/test_analytics.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1145,6 +1145,15 @@ def test_validate_stat_keepdims(self):
11451145
with pytest.raises(ValueError, match=msg):
11461146
np.sum(s, keepdims=True)
11471147

1148+
def test_compound_deprecated(self):
1149+
s = Series([.1, .2, .3, .4])
1150+
with tm.assert_produces_warning(FutureWarning):
1151+
s.compound()
1152+
1153+
df = pd.DataFrame({'s': s})
1154+
with tm.assert_produces_warning(FutureWarning):
1155+
df.compound()
1156+
11481157

11491158
main_dtypes = [
11501159
'datetime',

0 commit comments

Comments
 (0)