Repository: pandas-dev/pandas

Issue:
awkward repring on python3 bytes types
might be an edge case as i'm not sure how useful storing byte strings in `Series` objects is, nonetheless they are repring like `tuple` objects in Python 3

```
In [37]: import string

In [38]: d = string.digits * 10

In [39]: s = Series([d, tm.rands(10), tm.rands(10000)])

In [40]: s
Out[40]:
0    0123456789012345678901234567890123456789012345...
1                                           c0HYcb0BlY
2    IghbSU964QRgNimc0jZn2etcTFhRgHnHQepH1dwAqVZLar...
dtype: object

In [41]: b = lambda x, encoding='utf8': bytes(x, encoding=encoding)

In [42]: s.map(b)
Out[42]:
0      (48, 49, 50, 51, 52, 53, 54, 55, 56, 57, ...)
1          (99, 48, 72, 89, 99, 98, 48, 66, 108, 89)
2    (73, 103, 104, 98, 83, 85, 57, 54, 52, 81, ...)
dtype: object
```

PR coming soon with a couple of other output formatting fixes as well regarding py3 compat



Discussion:

Resolving patch:
diff --git a/pandas/compat/__init__.py b/pandas/compat/__init__.py
--- a/pandas/compat/__init__.py
+++ b/pandas/compat/__init__.py
@@ -185,6 +185,10 @@ def u(s):
     def u(s):
         return unicode(s, "unicode_escape")
 
+
+string_and_binary_types = string_types + (binary_type,)
+
+
 try:
     # callable reintroduced in later versions of Python
     callable = callable
diff --git a/pandas/core/common.py b/pandas/core/common.py
--- a/pandas/core/common.py
+++ b/pandas/core/common.py
@@ -1612,9 +1612,9 @@ def is_list_like(arg):
 def _is_sequence(x):
     try:
         iter(x)
-        len(x) # it has a length
-        return not isinstance(x, compat.string_types) and True
-    except Exception:
+        len(x)  # it has a length
+        return not isinstance(x, compat.string_and_binary_types)
+    except (TypeError, AttributeError):
         return False
 
 _ensure_float64 = algos.ensure_float64
@@ -2053,8 +2053,7 @@ def as_escaped_unicode(thing,escape_chars=escape_chars):
 
         return compat.text_type(result)
 
-    if (compat.PY3 and hasattr(thing, '__next__')) or \
-            hasattr(thing, 'next'):
+    if (compat.PY3 and hasattr(thing, '__next__')) or hasattr(thing, 'next'):
         return compat.text_type(thing)
     elif (isinstance(thing, dict) and
           _nest_lvl < get_option("display.pprint_nest_depth")):


Test patch:
diff --git a/pandas/tests/test_common.py b/pandas/tests/test_common.py
--- a/pandas/tests/test_common.py
+++ b/pandas/tests/test_common.py
@@ -1,12 +1,12 @@
 from datetime import datetime
-import sys
 import re
 
 import nose
+from nose.tools import assert_equal
 import unittest
 
 from pandas import Series, DataFrame, date_range, DatetimeIndex, Timestamp
-from pandas.compat import range, long, lrange, lmap, u, map
+from pandas.compat import range, long, lrange, lmap, u
 from pandas.core.common import notnull, isnull
 import pandas.core.common as com
 import pandas.util.testing as tm
@@ -147,6 +147,21 @@ def test_all_not_none():
     assert(not com._all_not_none(None, None, None, None))
 
 
+def test_repr_binary_type():
+    import string
+    letters = string.ascii_letters
+    btype = compat.binary_type
+    try:
+        raw = btype(letters, encoding=cf.get_option('display.encoding'))
+    except TypeError:
+        raw = btype(letters)
+    b = compat.text_type(compat.bytes_to_str(raw))
+    res = com.pprint_thing(b, quote_strings=True)
+    assert_equal(res, repr(b))
+    res = com.pprint_thing(b, quote_strings=False)
+    assert_equal(res, b)
+
+
 def test_rands():
     r = com.rands(10)
     assert(len(r) == 10)