diff --git a/pandas/core/indexes/interval.py b/pandas/core/indexes/interval.py index 18aa0580d7df7..24fcb32d09d27 100644 --- a/pandas/core/indexes/interval.py +++ b/pandas/core/indexes/interval.py @@ -1061,9 +1061,11 @@ def _format_with_header(self, header, **kwargs): def _format_native_types(self, na_rep='NaN', quoting=None, **kwargs): """ actually format my specific types """ - from pandas.io.formats.format import format_array - return format_array(values=self, na_rep=na_rep, justify='all', - leading_space=False) + from pandas.io.formats.format import ExtensionArrayFormatter + return ExtensionArrayFormatter(values=self, + na_rep=na_rep, + justify='all', + leading_space=False).get_result() def _format_data(self, name=None): diff --git a/pandas/io/formats/format.py b/pandas/io/formats/format.py index 66af6c2172344..f632bc13a5b24 100644 --- a/pandas/io/formats/format.py +++ b/pandas/io/formats/format.py @@ -849,7 +849,7 @@ def _get_column_name_list(self): # Array formatters -def format_array(values, formatter=None, float_format=None, na_rep='NaN', +def format_array(values, formatter, float_format=None, na_rep='NaN', digits=None, space=None, justify='right', decimal='.', leading_space=None): """ @@ -879,23 +879,14 @@ def format_array(values, formatter=None, float_format=None, na_rep='NaN', List[str] """ - if is_extension_array_dtype(values.dtype): - if isinstance(values, (ABCIndexClass, ABCSeries)): - values = values._values - - if is_categorical_dtype(values.dtype): - # Categorical is special for now, so that we can preserve tzinfo - values = values.get_values() - - if not is_datetime64tz_dtype(values.dtype): - values = np.asarray(values) - if is_datetime64_dtype(values.dtype): fmt_klass = Datetime64Formatter elif is_datetime64tz_dtype(values): fmt_klass = Datetime64TZFormatter elif is_timedelta64_dtype(values.dtype): fmt_klass = Timedelta64Formatter + elif is_extension_array_dtype(values.dtype): + fmt_klass = ExtensionArrayFormatter elif is_float_dtype(values.dtype) or is_complex_dtype(values.dtype): fmt_klass = FloatArrayFormatter elif is_integer_dtype(values.dtype): @@ -1190,6 +1181,29 @@ def _format_strings(self): return fmt_values.tolist() +class ExtensionArrayFormatter(GenericArrayFormatter): + def _format_strings(self): + values = self.values + if isinstance(values, (ABCIndexClass, ABCSeries)): + values = values._values + + formatter = values._formatter(boxed=True) + + if is_categorical_dtype(values.dtype): + # Categorical is special for now, so that we can preserve tzinfo + array = values.get_values() + else: + array = np.asarray(values) + + fmt_values = format_array(array, + formatter, + float_format=self.float_format, + na_rep=self.na_rep, digits=self.digits, + space=self.space, justify=self.justify, + leading_space=self.leading_space) + return fmt_values + + def format_percentiles(percentiles): """ Outputs rounded and formatted percentiles. diff --git a/pandas/tests/extension/decimal/array.py b/pandas/tests/extension/decimal/array.py index 1823eeb4d7fc0..3b95c8d919eb1 100644 --- a/pandas/tests/extension/decimal/array.py +++ b/pandas/tests/extension/decimal/array.py @@ -137,6 +137,11 @@ def isna(self): def _na_value(self): return decimal.Decimal('NaN') + def _formatter(self, boxed=False): + if boxed: + return "Decimal: {0}".format + return repr + @classmethod def _concat_same_type(cls, to_concat): return cls(np.concatenate([x._data for x in to_concat])) diff --git a/pandas/tests/extension/decimal/test_decimal.py b/pandas/tests/extension/decimal/test_decimal.py index 97fae41bcc720..94c0b61c6382a 100644 --- a/pandas/tests/extension/decimal/test_decimal.py +++ b/pandas/tests/extension/decimal/test_decimal.py @@ -200,7 +200,13 @@ class TestSetitem(BaseDecimal, base.BaseSetitemTests): class TestPrinting(BaseDecimal, base.BasePrintingTests): - pass + + def test_series_repr(self, data): + # Overriding this base test to explicitly test that + # the custom _formatter is used + ser = pd.Series(data) + assert data.dtype.name in repr(ser) + assert "Decimal: " in repr(ser) # TODO(extension)