Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

Already on GitHub? Sign in to your account

Series/DataFrame, make decision between full and short __repr__ configurable #453

Closed
wants to merge 3 commits into
from
View
@@ -346,21 +346,33 @@ def _try_sort(iterable):
except Exception:
return listed
-def set_printoptions(precision=None, column_space=None):
+def set_printoptions(precision=None, column_space=None, max_rows=None,
+ max_columns=None):
"""
Alter default behavior of DataFrame.toString
precision : int
Floating point output precision
column_space : int
Default space for DataFrame columns, defaults to 12
+ max_rows : int
+ max_columns : int
+ max_rows and max_columns are used in __repr__() methods to decide if
+ to_string() or info() is used to render an object to a string.
+ Either one, or both can be set to 0 (experimental). Pandas will figure
+ out how big the terminal is and will not display more rows or/and
+ columns that can fit on it.
"""
- global _float_format, _column_space
+ global _float_format, _column_space, _max_rows, _max_columns
if precision is not None:
float_format = '%.' + '%d' % precision + 'g'
_float_format = lambda x: float_format % x
if column_space is not None:
_column_space = column_space
+ if max_rows is not None:
+ _max_rows = max_rows
+ if max_columns is not None:
+ _max_columns = max_columns
class EngFormatter(object):
"""
@@ -467,6 +479,8 @@ def set_eng_float_format(precision=3, use_eng_prefix=False):
_float_format = lambda x: '%.4g' % x
_column_space = 12
+_max_rows = 500
+_max_columns = 10
def _pfixed(s, space, na_rep=None, float_format=None):
if isinstance(s, float):
View
@@ -23,14 +23,16 @@
import numpy.ma as ma
from pandas.core.common import (isnull, notnull, PandasError, _try_sort,
- _default_index, _stringify, _maybe_upcast)
+ _default_index, _stringify, _maybe_upcast,
+ _max_rows, _max_columns)
from pandas.core.daterange import DateRange
from pandas.core.generic import NDFrame, AxisProperty
from pandas.core.index import Index, MultiIndex, NULL_INDEX, _ensure_index
from pandas.core.indexing import _NDFrameIndexer, _maybe_droplevels
from pandas.core.internals import BlockManager, make_block, form_blocks
from pandas.core.series import Series, _is_bool_indexer
from pandas.util import py3compat
+from pandas.util.terminal import get_terminal_size
import pandas.core.nanops as nanops
import pandas.core.common as com
import pandas.core.datetools as datetools
@@ -316,13 +318,33 @@ def __repr__(self):
"""
Return a string representation for a particular DataFrame
"""
- buf = StringIO()
- if len(self.index) < 500 and len(self.columns) <= 10:
- self.to_string(buf=buf)
- else:
- self.info(buf=buf, verbose=self._verbose_info)
+ terminal_width, terminal_height = get_terminal_size()
+ max_rows = terminal_height if com._max_rows == 0 else com._max_rows
+ max_columns = com._max_columns
- return buf.getvalue()
+ if max_columns > 0:
+ buf = StringIO()
+ if len(self.index) < max_rows and \
+ len(self.columns) <= max_columns:
+ self.to_string(buf=buf)
+ else:
+ self.info(buf=buf, verbose=self._verbose_info)
+ return buf.getvalue()
+ else:
+ if len(self.index) > max_rows:
+ buf = StringIO()
+ self.info(buf=buf, verbose=self._verbose_info)
+ return buf.getvalue()
+ else:
+ buf = StringIO()
+ self.to_string(buf=buf)
+ value = buf.getvalue()
+ if max([len(l) for l in value.split('\n')]) <= terminal_width:
+ return value
+ else:
+ buf = StringIO()
+ self.info(buf=buf, verbose=self._verbose_info)
+ return buf.getvalue()
def __iter__(self):
"""
View
@@ -20,6 +20,7 @@
from pandas.core.index import Index, MultiIndex, _ensure_index
from pandas.core.indexing import _SeriesIndexer, _maybe_droplevels
from pandas.util import py3compat
+from pandas.util.terminal import get_terminal_size
import pandas.core.common as common
import pandas.core.datetools as datetools
import pandas.core.nanops as nanops
@@ -413,8 +414,10 @@ def __setslice__(self, i, j, value):
def __repr__(self):
"""Clean string representation of a Series"""
- if len(self.index) > 500:
- result = self._tidy_repr(30)
+ width, height = get_terminal_size()
+ max_rows = height if common._max_rows == 0 else common._max_rows
+ if len(self.index) > max_rows:
+ result = self._tidy_repr(min(30, max_rows - 4))
elif len(self.index) > 0:
result = self._get_repr(print_header=True,
length=len(self) > 50,
View
@@ -0,0 +1,105 @@
+"""
+get_terminal_size() -- return width and height of console as a tuple
+
+code from:
+http://stackoverflow.com/questions/566746/how-to-get-console- window-width-in-
+python
+
+written by
+Harco Kuppens (http://stackoverflow.com/users/825214/harco-kuppens)
+
+It is mentioned in the stackoverflow response that this code works
+on linux, os x, windows and cygwin (windows).
+"""
+
+__all__=['get_terminal_size']
+
+
+def get_terminal_size():
+ import platform
+ current_os = platform.system()
+ tuple_xy=None
+ if current_os == 'Windows':
+ tuple_xy = _get_terminal_size_windows()
+ if tuple_xy is None:
+ tuple_xy = _get_terminal_size_tput()
+ # needed for window's python in cygwin's xterm!
+ if current_os == 'Linux' or \
+ current_os == 'Darwin' or \
+ current_os.startswith('CYGWIN'):
+ tuple_xy = _get_terminal_size_linux()
+ if tuple_xy is None:
+ tuple_xy = (80, 25) # default value
+ return tuple_xy
+
+def _get_terminal_size_windows():
+ res=None
+ try:
+ from ctypes import windll, create_string_buffer
+
+ # stdin handle is -10
+ # stdout handle is -11
+ # stderr handle is -12
+
+ h = windll.kernel32.GetStdHandle(-12)
+ csbi = create_string_buffer(22)
+ res = windll.kernel32.GetConsoleScreenBufferInfo(h, csbi)
+ except:
+ return None
+ if res:
+ import struct
+ (bufx, bufy, curx, cury, wattr, left, top, right, bottom, maxx,
+ maxy) = struct.unpack("hhhhHhhhhhh", csbi.raw)
+ sizex = right - left + 1
+ sizey = bottom - top + 1
+ return sizex, sizey
+ else:
+ return None
+
+def _get_terminal_size_tput():
+ # get terminal width
+ # src: http://stackoverflow.com/questions/263890/how-do-i-find-the-width
+ # -height-of-a-terminal-window
+ try:
+ import subprocess
+ proc = subprocess.Popen(["tput", "cols"],
+ stdin=subprocess.PIPE,
+ stdout=subprocess.PIPE)
+ output=proc.communicate(input=None)
+ cols=int(output[0])
+ proc=subprocess.Popen(["tput", "lines"],
+ stdin=subprocess.PIPE,
+ stdout=subprocess.PIPE)
+ output=proc.communicate(input=None)
+ rows=int(output[0])
+ return (cols,rows)
+ except:
+ return None
+
+
+def _get_terminal_size_linux():
+ def ioctl_GWINSZ(fd):
+ try:
+ import fcntl, termios, struct, os
+ cr = struct.unpack('hh', fcntl.ioctl(fd, termios.TIOCGWINSZ,'1234'))
+ except:
+ return None
+ return cr
+ cr = ioctl_GWINSZ(0) or ioctl_GWINSZ(1) or ioctl_GWINSZ(2)
+ if not cr:
+ try:
+ fd = os.open(os.ctermid(), os.O_RDONLY)
+ cr = ioctl_GWINSZ(fd)
+ os.close(fd)
+ except:
+ pass
+ if not cr:
+ try:
+ cr = (env['LINES'], env['COLUMNS'])
+ except:
+ return None
+ return int(cr[1]), int(cr[0])
+
+if __name__ == "__main__":
+ sizex, sizey = get_terminal_size()
+ print 'width =', sizex, 'height =', sizey