Skip to content

Commit dfcf746

Browse files
committed
WIP: finish on #2856
1 parent 5c2be67 commit dfcf746

File tree

3 files changed

+79
-30
lines changed

3 files changed

+79
-30
lines changed

pandas/core/config_init.py

+31-7
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,12 @@
4040
pc_max_cols_doc = """
4141
: int
4242
max_rows and max_columns are used in __repr__() methods to decide if
43-
to_string() or info() is used to render an object to a string.
44-
Either one, or both can be set to 0 (experimental). Pandas will figure
45-
out how big the terminal is and will not display more rows or/and
46-
columns that can fit on it.
43+
to_string() or info() is used to render an object to a string. In case
44+
python/IPython is running in a terminal this can be set to 0 and pandas
45+
will correctly auto-detect the width the terminal and swap to a smaller
46+
format in case all columns would not fit vertically. The IPython notebook,
47+
IPython qtconsole, or IDLE do not run in a terminal and hence it is not
48+
possible to do correct auto-detection.
4749
"""
4850

4951
pc_max_info_cols_doc = """
@@ -119,6 +121,26 @@
119121
When printing wide DataFrames, this is the width of each line.
120122
"""
121123

124+
pc_line_width_deprecation_warning = """\
125+
use display.width instead (currently both are indentical)
126+
"""
127+
128+
pc_width_doc = """
129+
: int
130+
Width of the display. In case python/IPython is running in a terminal this
131+
can be set to 0 and pandas will correctly auto-detect the width. Note that
132+
the IPython notebook, IPython qtconsole, or IDLE do not run in a terminal
133+
and hence it is not possible to correctly detect the width.
134+
"""
135+
136+
pc_height_doc = """
137+
: int
138+
Height of the display. In case python/IPython is running in a terminal this
139+
can be set to 0 and pandas will auto-detect the width. Note that the
140+
IPython notebook, IPython qtconsole, or IDLE do not run in a terminal,
141+
and hence it is not possible to correctly detect the height.
142+
"""
143+
122144
pc_chop_threshold_doc = """
123145
: float or None
124146
if set to a float value, all float values smaller then the given threshold
@@ -212,9 +234,11 @@ def mpl_style_cb(key):
212234
cf.register_option('mpl_style', None, pc_mpl_style_doc,
213235
validator=is_one_of_factory([None, False, 'default']),
214236
cb=mpl_style_cb)
215-
cf.register_option('height', 100, 'TODO', validator=is_int)
216-
cf.register_option('width',80, 'TODO', validator=is_int)
217-
cf.deprecate_option('display.line_width', msg='TODO', rkey='display.width')
237+
cf.register_option('height', 100, pc_height_doc, validator=is_int)
238+
cf.register_option('width',80, pc_width_doc, validator=is_int)
239+
cf.deprecate_option('display.line_width',
240+
msg=pc_line_width_deprecation_warning,
241+
rkey='display.width')
218242

219243
tc_sim_interactive_doc = """
220244
: boolean

pandas/core/frame.py

+28-17
Original file line numberDiff line numberDiff line change
@@ -599,32 +599,38 @@ def empty(self):
599599
def __nonzero__(self):
600600
raise ValueError("Cannot call bool() on DataFrame.")
601601

602-
def _repr_fits_boundaries_(self):
602+
def _repr_fits_vertical_(self):
603603
"""
604-
Check if repr fits in boundaries imposed by the following sets of
605-
display options:
606-
* width, height
607-
* max_rows, max_columns
608-
In case off non-interactive session, no boundaries apply.
604+
Check if full repr fits in vertical boundaries imposed by the display
605+
options height and max_columns. In case off non-interactive session,
606+
no boundaries apply.
609607
"""
610608
if not com.in_interactive_session():
611609
return True
612610

613611
terminal_width, terminal_height = get_terminal_size()
614612

615-
# check vertical boundaries (excluding column axis area)
613+
# excluding column axis area
616614
max_rows = get_option("display.max_rows") or terminal_height
617615
display_height = get_option("display.height") or terminal_height
618-
if len(self.index) > min(max_rows, display_height):
619-
return False
616+
return len(self.index) <= min(max_rows, display_height)
617+
618+
def _repr_fits_horizontal_(self):
619+
"""
620+
Check if full repr fits in horizontal boundaries imposed by the display
621+
options width and max_columns. In case off non-interactive session, no
622+
boundaries apply.
623+
"""
624+
if not com.in_interactive_session():
625+
return True
626+
627+
terminal_width, terminal_height = get_terminal_size()
620628

621-
# check horizontal boundaries (including index axis area)
622629
max_columns = get_option("display.max_columns")
623630
display_width = get_option("display.width") or terminal_width
624631
nb_columns = len(self.columns)
625-
if max_columns and nb_columns > max_columns:
626-
return False
627-
if nb_columns > (display_width // 2):
632+
if ((max_columns and nb_columns > max_columns) or
633+
(nb_columns > (display_width // 2))):
628634
return False
629635

630636
buf = StringIO()
@@ -663,15 +669,17 @@ def __unicode__(self):
663669
py2/py3.
664670
"""
665671
buf = StringIO(u"")
666-
if self._repr_fits_boundaries_():
672+
fits_vertical = self._repr_fits_vertical_()
673+
fits_horizontal = self._repr_fits_horizontal_()
674+
if fits_vertical and fits_horizontal:
667675
self.to_string(buf=buf)
668676
else:
669677
terminal_width, terminal_height = get_terminal_size()
670678
max_rows = get_option("display.max_rows") or terminal_height
671679
# Expand or info? Decide based on option display.expand_frame_repr
672680
# and keep it sane for the number of display rows used by the
673681
# expanded repr.
674-
if (get_option("display.expand_frame_repr") and
682+
if (get_option("display.expand_frame_repr") and fits_vertical and
675683
len(self.columns) < max_rows):
676684
line_width = get_option("display.width") or terminal_width
677685
self.to_string(buf=buf, line_width=line_width)
@@ -703,7 +711,7 @@ def _repr_html_(self):
703711
raise ValueError('Disable HTML output in QtConsole')
704712

705713
if get_option("display.notebook_repr_html"):
706-
if self._repr_fits_boundaries_():
714+
if self._repr_fits_horizontal_() and self._repr_fits_vertical_():
707715
return ('<div style="max-height:1000px;'
708716
'max-width:1500px;overflow:auto;">\n' +
709717
self.to_html() + '\n</div>')
@@ -713,7 +721,10 @@ def _repr_html_(self):
713721
verbose = (max_info_rows is None or
714722
self.shape[0] <= max_info_rows)
715723
self.info(buf=buf, verbose=verbose)
716-
info = buf.getvalue().replace('<', '&lt').replace('>', '&gt')
724+
info = buf.getvalue()
725+
info = info.replace('&', r'&amp;')
726+
info = info.replace('<', r'&lt')
727+
info = info.replace('>', r'&gt')
717728
return ('<pre>\n' + info + '\n</pre>')
718729
else:
719730
return None

pandas/tests/test_format.py

+20-6
Original file line numberDiff line numberDiff line change
@@ -159,20 +159,26 @@ def test_repr_no_backslash(self):
159159
def test_expand_frame_repr(self):
160160
df_small = DataFrame('hello', [0], [0])
161161
df_wide = DataFrame('hello', [0], range(10))
162+
df_tall = DataFrame('hello', range(30), range(5))
162163

163164
with option_context('mode.sim_interactive', True):
164-
with option_context('display.width', 50):
165+
with option_context('display.width', 50,
166+
'display.height', 20):
165167
with option_context('display.expand_frame_repr', True):
166168
self.assertFalse(has_info_repr(df_small))
167169
self.assertFalse(has_expanded_repr(df_small))
168170
self.assertFalse(has_info_repr(df_wide))
169171
self.assertTrue(has_expanded_repr(df_wide))
172+
self.assertTrue(has_info_repr(df_tall))
173+
self.assertFalse(has_expanded_repr(df_tall))
170174

171175
with option_context('display.expand_frame_repr', False):
172176
self.assertFalse(has_info_repr(df_small))
173177
self.assertFalse(has_expanded_repr(df_small))
174178
self.assertTrue(has_info_repr(df_wide))
175179
self.assertFalse(has_expanded_repr(df_wide))
180+
self.assertTrue(has_info_repr(df_tall))
181+
self.assertFalse(has_expanded_repr(df_tall))
176182

177183
def test_repr_max_columns_max_rows(self):
178184
term_width, term_height = get_terminal_size()
@@ -183,21 +189,29 @@ def mkframe(n):
183189
index = ['%05d' % i for i in range(n)]
184190
return DataFrame(0, index, index)
185191

192+
df6 = mkframe(6)
193+
df10 = mkframe(10)
186194
with option_context('mode.sim_interactive', True):
187195
with option_context('display.width', term_width * 2):
188196
with option_context('display.max_rows', 5,
189197
'display.max_columns', 5):
190198
self.assertFalse(has_expanded_repr(mkframe(4)))
191199
self.assertFalse(has_expanded_repr(mkframe(5)))
192-
self.assertFalse(has_expanded_repr(mkframe(6)))
193-
self.assertTrue(has_info_repr(mkframe(6)))
200+
self.assertFalse(has_expanded_repr(df6))
201+
self.assertTrue(has_info_repr(df6))
194202

195203
with option_context('display.max_rows', 20,
196204
'display.max_columns', 5):
197205
# Out off max_columns boundary, but no extending
198-
# occurs ... can improve?
199-
self.assertFalse(has_expanded_repr(mkframe(6)))
200-
self.assertFalse(has_info_repr(mkframe(6)))
206+
# since not exceeding width
207+
self.assertFalse(has_expanded_repr(df6))
208+
self.assertFalse(has_info_repr(df6))
209+
210+
with option_context('display.max_rows', 9,
211+
'display.max_columns', 10):
212+
# out vertical bounds can not result in exanded repr
213+
self.assertFalse(has_expanded_repr(df10))
214+
self.assertTrue(has_info_repr(df10))
201215

202216
with option_context('display.max_columns', 0,
203217
'display.max_rows', term_width * 20,

0 commit comments

Comments
 (0)