diff --git a/pandas/core/common.py b/pandas/core/common.py index 28f3a19ab5298..5c2726e8e11a3 100644 --- a/pandas/core/common.py +++ b/pandas/core/common.py @@ -1729,6 +1729,42 @@ def in_qtconsole(): except: return False +class ReprMixin(object): + """ + Classes enowed with this mixin need only implement __unicode__ + and str,bytes, repr will return the right type of string in py2/py3 + + """ + def __str__(self): + """ + Return a string representation for a particular DataFrame + + Invoked by str(df) in both py2/py3. + Yields Bytestring in Py2, Unicode String in py3. + """ + if py3compat.PY3: + return self.__unicode__() + return self.__bytes__() + + def __bytes__(self): + """ + Return a string representation for a particular DataFrame + + Invoked by bytes(df) in py3 only. + Yields a bytestring in both py2/py3. + """ + encoding = get_option("display.encoding") + return self.__unicode__().encode(encoding, 'replace') + + def __repr__(self): + """ + Return a string representation for a particular DataFrame + + Yields Bytestring in Py2, Unicode String in py3. + """ + return str(self) + + # Unicode consolidation # --------------------- # diff --git a/pandas/core/frame.py b/pandas/core/frame.py index 4dc01beed9c7e..59a8239121386 100644 --- a/pandas/core/frame.py +++ b/pandas/core/frame.py @@ -638,28 +638,8 @@ def _need_info_repr_(self): else: return False - def __str__(self): - """ - Return a string representation for a particular DataFrame - - Invoked by str(df) in both py2/py3. - Yields Bytestring in Py2, Unicode String in py3. - """ - - if py3compat.PY3: - return self.__unicode__() - return self.__bytes__() - - def __bytes__(self): - """ - Return a string representation for a particular DataFrame - - Invoked by bytes(df) in py3 only. - Yields a bytestring in both py2/py3. - """ - encoding = com.get_option("display.encoding") - return self.__unicode__().encode(encoding, 'replace') - + # ReprMixin->PandasObject->NDFrame->DataFrame + # just define unicode, and str,bytes,repr work on py2/py3 def __unicode__(self): """ Return a string representation for a particular DataFrame @@ -688,14 +668,6 @@ def _need_wide_repr(self): return (get_option("display.expand_frame_repr") and com.in_interactive_session()) - def __repr__(self): - """ - Return a string representation for a particular DataFrame - - Yields Bytestring in Py2, Unicode String in py3. - """ - return str(self) - def _repr_html_(self): """ Return a html representation for a particular DataFrame. diff --git a/pandas/core/generic.py b/pandas/core/generic.py index 580148e11cc7c..c7e56a11fb106 100644 --- a/pandas/core/generic.py +++ b/pandas/core/generic.py @@ -14,7 +14,7 @@ class PandasError(Exception): pass -class PandasObject(object): +class PandasObject(com.ReprMixin, object): _AXIS_NUMBERS = { 'index': 0, @@ -539,7 +539,9 @@ def _constructor(self): def axes(self): return self._data.axes - def __repr__(self): + # ReprMixin->PandasObject->NDFrame + # just define unicode, and str,bytes,repr and everything works on py3/py3 + def __unicode__(self): return 'NDFrame' @property diff --git a/pandas/core/index.py b/pandas/core/index.py index 0c6e490f3eb50..19d3a94b7eab3 100644 --- a/pandas/core/index.py +++ b/pandas/core/index.py @@ -49,7 +49,7 @@ def _shouldbe_timestamp(obj): or tslib.is_timestamp_array(obj)) -class Index(np.ndarray): +class Index(com.ReprMixin,np.ndarray): """ Immutable ndarray implementing an ordered, sliceable set. The basic object storing axis labels for all pandas objects @@ -144,28 +144,8 @@ def __array_finalize__(self, obj): def _shallow_copy(self): return self.view() - def __str__(self): - """ - Return a string representation for a particular Index - - Invoked by str(df) in both py2/py3. - Yields Bytestring in Py2, Unicode String in py3. - """ - - if py3compat.PY3: - return self.__unicode__() - return self.__bytes__() - - def __bytes__(self): - """ - Return a string representation for a particular Index - - Invoked by bytes(df) in py3 only. - Yields a bytestring in both py2/py3. - """ - encoding = com.get_option("display.encoding") - return self.__unicode__().encode(encoding, 'replace') - + # ReprMixin->Series + # just define unicode, and str,bytes,repr work on py2/py3 def __unicode__(self): """ Return a string representation for a particular Index @@ -180,14 +160,6 @@ def __unicode__(self): prepr = com.pprint_thing(data, escape_chars=('\t', '\r', '\n')) return '%s(%s, dtype=%s)' % (type(self).__name__, prepr, self.dtype) - def __repr__(self): - """ - Return a string representation for a particular Index - - Yields Bytestring in Py2, Unicode String in py3. - """ - return str(self) - def astype(self, dtype): return Index(self.values.astype(dtype), name=self.name, dtype=dtype) @@ -1434,28 +1406,8 @@ def _array_values(self): def dtype(self): return np.dtype('O') - def __str__(self): - """ - Return a string representation for a particular Index - - Invoked by str(df) in both py2/py3. - Yields Bytestring in Py2, Unicode String in py3. - """ - - if py3compat.PY3: - return self.__unicode__() - return self.__bytes__() - - def __bytes__(self): - """ - Return a string representation for a particular Index - - Invoked by bytes(df) in py3 only. - Yields a bytestring in both py2/py3. - """ - encoding = com.get_option("display.encoding") - return self.__unicode__().encode(encoding, 'replace') - + # ReprMixin->Index->MultiIndex + # just define unicode, and str,bytes,repr work on py2/py3 def __unicode__(self): """ Return a string representation for a particular Index @@ -1478,14 +1430,6 @@ def __unicode__(self): return output % summary - def __repr__(self): - """ - Return a string representation for a particular Index - - Yields Bytestring in Py2, Unicode String in py3. - """ - return str(self) - def __len__(self): return len(self.labels[0]) diff --git a/pandas/core/internals.py b/pandas/core/internals.py index 7441134aab351..fc5f726db9ec8 100644 --- a/pandas/core/internals.py +++ b/pandas/core/internals.py @@ -797,7 +797,7 @@ def make_block(values, items, ref_items): # TODO: flexible with index=None and/or items=None -class BlockManager(object): +class BlockManager(com.ReprMixin,object): """ Core internal data structure to implement DataFrame @@ -894,7 +894,9 @@ def __setstate__(self, state): def __len__(self): return len(self.items) - def __repr__(self): + # ReprMixin->BlockManager + # just define unicode, and str,bytes,repr work on py2/py3 + def __unicode__(self): output = 'BlockManager' for i, ax in enumerate(self.axes): if i == 0: diff --git a/pandas/core/panel.py b/pandas/core/panel.py index d1f87e4e7c932..e05c563aa00cf 100644 --- a/pandas/core/panel.py +++ b/pandas/core/panel.py @@ -456,28 +456,8 @@ def __invert__(self): #---------------------------------------------------------------------- # Magic methods - def __str__(self): - """ - Return a string representation for a particular Panel - - Invoked by str(df) in both py2/py3. - Yields Bytestring in Py2, Unicode String in py3. - """ - - if py3compat.PY3: - return self.__unicode__() - return self.__bytes__() - - def __bytes__(self): - """ - Return a string representation for a particular Panel - - Invoked by bytes(df) in py3 only. - Yields a bytestring in both py2/py3. - """ - encoding = com.get_option("display.encoding") - return self.__unicode__().encode(encoding, 'replace') - + # ReprMixin->PandasObject->Panel + # just define unicode, and str,bytes,repr work on py2/py3 def __unicode__(self): """ Return a string representation for a particular Panel @@ -502,14 +482,6 @@ def axis_pretty(a): [class_name, dims] + [axis_pretty(a) for a in self._AXIS_ORDERS]) return output - def __repr__(self): - """ - Return a string representation for a particular Panel - - Yields Bytestring in Py2, Unicode String in py3. - """ - return str(self) - def __iter__(self): return iter(getattr(self, self._info_axis)) diff --git a/pandas/core/series.py b/pandas/core/series.py index acfc875fa45a1..a2e20f03c307f 100644 --- a/pandas/core/series.py +++ b/pandas/core/series.py @@ -1067,28 +1067,8 @@ def reset_index(self, level=None, drop=False, name=None, inplace=False): return df.reset_index(level=level, drop=drop) - def __str__(self): - """ - Return a string representation for a particular DataFrame - - Invoked by str(df) in both py2/py3. - Yields Bytestring in Py2, Unicode String in py3. - """ - - if py3compat.PY3: - return self.__unicode__() - return self.__bytes__() - - def __bytes__(self): - """ - Return a string representation for a particular DataFrame - - Invoked by bytes(df) in py3 only. - Yields a bytestring in both py2/py3. - """ - encoding = com.get_option("display.encoding") - return self.__unicode__().encode(encoding, 'replace') - + # ReprMixin->PandasObject->Series->DataFrame + # just define unicode, and str,bytes,repr work on py2/py3 def __unicode__(self): """ Return a string representation for a particular DataFrame @@ -1112,14 +1092,6 @@ def __unicode__(self): assert type(result) == unicode return result - def __repr__(self): - """ - Return a string representation for a particular Series - - Yields Bytestring in Py2, Unicode String in py3. - """ - return str(self) - def _tidy_repr(self, max_vals=20): """ diff --git a/pandas/io/pytables.py b/pandas/io/pytables.py index f9cc850cc6d27..c3f2f2fdd2171 100644 --- a/pandas/io/pytables.py +++ b/pandas/io/pytables.py @@ -147,7 +147,7 @@ def get_store(path, mode='a', complevel=None, complib=None, store.close() -class HDFStore(object): +class HDFStore(com.ReprMixin,object): """ dict-like IO interface for storing pandas objects in PyTables format. @@ -242,7 +242,9 @@ def __contains__(self, key): def __len__(self): return len(self.groups()) - def __repr__(self): + # ReprMixin->HDFStore + # just define unicode, and str,bytes,repr work on py2/py3 + def __unicode__(self): output = '%s\nFile path: %s\n' % (type(self), self._path) if len(self.keys()): @@ -885,9 +887,9 @@ def __iter__(self): def get_values(self): return self.func(self.start, self.stop) - -class IndexCol(object): + +class IndexCol(com.ReprMixin,object): """ an index column description class Parameters @@ -948,11 +950,11 @@ def set_table(self, table): self.table = table return self - def __repr__(self): + # ReprMixin->HDFStore + # just define unicode, and str,bytes,repr work on py2/py3 + def __unicode__(self): return "name->%s,cname->%s,axis->%s,pos->%s,kind->%s" % (self.name, self.cname, self.axis, self.pos, self.kind) - __str__ = __repr__ - def __eq__(self, other): """ compare 2 col items """ return all([getattr(self, a, None) == getattr(other, a, None) for a in ['name', 'cname', 'axis', 'pos']]) @@ -1128,7 +1130,9 @@ def __init__(self, values=None, kind=None, typ=None, cname=None, data=None, bloc self.dtype_attr = "%s_dtype" % self.name self.set_data(data) - def __repr__(self): + # ReprMixin->IndexCol->this + # just define unicode, and str,bytes,repr work on py2/py3 + def __unicode__(self): return "name->%s,cname->%s,dtype->%s,shape->%s" % (self.name, self.cname, self.dtype, self.shape) def __eq__(self, other): @@ -1349,7 +1353,7 @@ class GenericDataIndexableCol(DataIndexableCol): def get_attr(self): pass -class Storer(object): +class Storer(com.ReprMixin,object): """ represent an object in my store facilitate read/write of various types of objects this is an abstract base class @@ -1388,7 +1392,9 @@ def set_version(self): def pandas_type(self): return getattr(self.group._v_attrs, 'pandas_type', None) - def __repr__(self): + # ReprMixin->thisPandasObject->NDFrame->DataFrame + # just define unicode, and str,bytes,repr work on py2/py3 + def __unicode__(self): """ return a pretty representatgion of myself """ self.infer_axes() s = self.shape @@ -1397,9 +1403,6 @@ def __repr__(self): s = "[%s]" % ','.join([ str(x) for x in s ]) return "%-12.12s (shape->%s)" % (self.pandas_type,s) return self.pandas_type - - def __str__(self): - return self.__repr__() def set_info(self): """ set my pandas type & version """ @@ -1972,12 +1975,12 @@ class PanelStorer(BlockManagerStorer): pandas_kind = 'wide' obj_type = Panel is_shape_reversed = True - + def write(self, obj, **kwargs): obj._consolidate_inplace() return super(PanelStorer, self).write(obj, **kwargs) -class Table(Storer): +class Table(com.ReprMixin,Storer): """ represent a table: facilitate read/write of various types of tables @@ -2013,7 +2016,9 @@ def __init__(self, *args, **kwargs): def table_type_short(self): return self.table_type.split('_')[0] - def __repr__(self): + # ReprMixin->this + # just define unicode, and str,bytes,repr work on py2/py3 + def __unicode__(self): """ return a pretty representatgion of myself """ self.infer_axes() dc = ",dc->[%s]" % ','.join(self.data_columns) if len(self.data_columns) else '' @@ -3049,7 +3054,7 @@ def _need_convert(kind): return True return False -class Term(object): +class Term(com.ReprMixin,object): """ create a term object that holds a field, op, and value Parameters @@ -3153,11 +3158,11 @@ def __init__(self, field, op=None, value=None, queryables=None): if len(self.q): self.eval() - def __str__(self): + # ReprMixin->this + # just define unicode, and str,bytes,repr work on py2/py3 + def __unicode__(self): return "field->%s,op->%s,value->%s" % (self.field, self.op, self.value) - __repr__ = __str__ - @property def is_valid(self): """ return True if this is a valid field """ diff --git a/pandas/stats/ols.py b/pandas/stats/ols.py index 9ecf5c6ab715f..b46e1c45e15aa 100644 --- a/pandas/stats/ols.py +++ b/pandas/stats/ols.py @@ -11,6 +11,7 @@ from pandas.core.api import DataFrame, Series, isnull from pandas.core.common import _ensure_float64 +import pandas.core.common as com from pandas.core.index import MultiIndex from pandas.core.panel import Panel from pandas.util.decorators import cache_readonly @@ -22,7 +23,7 @@ _FP_ERR = 1e-8 -class OLS(object): +class OLS(com.ReprMixin,object): """ Runs a full sample ordinary least squares regression. @@ -574,7 +575,9 @@ def summary(self): return template % params - def __repr__(self): + # ReprMixin->OLS + # just define unicode, and str,bytes,repr work on py2/py3 + def __unicode__(self): return self.summary @cache_readonly diff --git a/pandas/stats/var.py b/pandas/stats/var.py index e993b60e18a39..1b2248874d74c 100644 --- a/pandas/stats/var.py +++ b/pandas/stats/var.py @@ -11,7 +11,7 @@ from pandas.stats.ols import _combine_rhs -class VAR(object): +class VAR(common.ReprMixin,object): """ Estimates VAR(p) regression on multivariate time series data presented in pandas data structures. @@ -477,7 +477,9 @@ def _sigma(self): return np.dot(resid, resid.T) / (n - k) - def __repr__(self): + # ReprMixin->VAR + # just define unicode, and str,bytes,repr work on py2/py3 + def __unicode__(self): return self.summary diff --git a/pandas/tseries/index.py b/pandas/tseries/index.py index 25c94900d159c..8c11521923aca 100644 --- a/pandas/tseries/index.py +++ b/pandas/tseries/index.py @@ -481,7 +481,9 @@ def _mpl_repr(self): # how to represent ourselves to matplotlib return tslib.ints_to_pydatetime(self.asi8, self.tz) - def __repr__(self): + #ReprMixin->Index->Int64Index->DatetimeIndex + # just define unicode, and str,bytes,repr work on py2/py3 + def __unicode__(self): from pandas.core.format import _format_datetime64 values = self.values @@ -507,8 +509,6 @@ def __repr__(self): return summary - __str__ = __repr__ - def __reduce__(self): """Necessary for making this object picklable""" object_state = list(np.ndarray.__reduce__(self)) diff --git a/pandas/tseries/offsets.py b/pandas/tseries/offsets.py index 592cc551aeb77..b44df5d2f77fc 100644 --- a/pandas/tseries/offsets.py +++ b/pandas/tseries/offsets.py @@ -6,6 +6,7 @@ from dateutil.relativedelta import relativedelta import pandas.lib as lib import pandas.tslib as tslib +import pandas.core.common as com __all__ = ['Day', 'BusinessDay', 'BDay', 'MonthBegin', 'BMonthBegin', 'MonthEnd', 'BMonthEnd', @@ -23,7 +24,7 @@ class CacheableOffset(object): _cacheable = True -class DateOffset(object): +class DateOffset(com.ReprMixin, object): """ Standard kind of date increment used for a date range. @@ -107,7 +108,9 @@ def _params(self): params = tuple([str(self.__class__)] + attrs) return params - def __repr__(self): + # ReprMixin->DateOffset + # just define unicode, and str,bytes,repr work on py2/py3 + def __unicode__(self): if hasattr(self, 'name') and len(self.name): return self.name @@ -230,7 +233,7 @@ def freqstr(self): return fstr -class BusinessDay(CacheableOffset, DateOffset): +class BusinessDay(com.ReprMixin,CacheableOffset, DateOffset): """ DateOffset subclass representing possibly n business days """ @@ -244,7 +247,7 @@ def __init__(self, n=1, **kwds): def rule_code(self): return 'B' - def __repr__(self): + def __unicode__(self): if hasattr(self, 'name') and len(self.name): return self.name diff --git a/pandas/tseries/period.py b/pandas/tseries/period.py index df5eb8743c9c8..6fdc25d27bc8b 100644 --- a/pandas/tseries/period.py +++ b/pandas/tseries/period.py @@ -38,7 +38,7 @@ def f(self): return property(f) -class Period(object): +class Period(com.ReprMixin, object): __slots__ = ['freq', 'ordinal'] @@ -236,17 +236,12 @@ def to_timestamp(self, freq=None, how='start',tz=None): def now(cls, freq=None): return Period(datetime.now(), freq=freq) - def __repr__(self): + def __unicode__(self): base, mult = _gfc(self.freq) formatted = tslib.period_format(self.ordinal, base) freqstr = _freq_mod._reverse_period_code_map[base] return "Period('%s', '%s')" % (formatted, freqstr) - def __str__(self): - base, mult = _gfc(self.freq) - formatted = tslib.period_format(self.ordinal, base) - return ("%s" % formatted) - def strftime(self, fmt): """ Returns the string representation of the :class:`Period`, depending @@ -1013,7 +1008,9 @@ def __array_finalize__(self, obj): self.freq = getattr(obj, 'freq', None) - def __repr__(self): + #ReprMixin->Index->Int64Index->PeriodIndex + # just define unicode, and str,bytes,repr work on py2/py3 + def __unicode__(self): output = str(self.__class__) + '\n' output += 'freq: ''%s''\n' % self.freq if len(self) > 0: diff --git a/pandas/util/compat.py b/pandas/util/compat.py index 41055f48c2fac..adde7a286f082 100644 --- a/pandas/util/compat.py +++ b/pandas/util/compat.py @@ -386,7 +386,9 @@ def __delitem__(self, elem): if elem in self: dict.__delitem__(self, elem) - def __repr__(self): + # ReprMixin->PandasObject->NDFrame->DataFrame + # just define unicode, and str,bytes,repr work on py2/py3 + def __unicode__(self): if not self: return '%s()' % self.__class__.__name__ items = ', '.join(map('%r: %r'.__mod__, self.most_common()))