Repository: pandas-dev/pandas

Issue:
.replace() raises when replacing strings
#### Code Sample, a copy-pastable example if possible

```python
pd.Series(['a', 'b', 'c']).replace('a', 'x')
```
#### Problem description

This raises the following error:

> TypeError: Type aliases cannot be used with isinstance().

This behavior is exclusive to the new **version 0.23**. Previous versions work as expected.

Full traceback
```
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-75-761515b509b4> in <module>()
----> 1 pd.Series(['a','b','c']).replace('a', 'x')

~/.virtualenvs/new/lib/python3.5/site-packages/pandas/core/series.py in replace(self, to_replace, value, inplace, limit, regex, method)
   3427         return super(Series, self).replace(to_replace=to_replace, value=value,
   3428                                            inplace=inplace, limit=limit,
-> 3429                                            regex=regex, method=method)
   3430
   3431     @Appender(generic._shared_docs['shift'] % _shared_doc_kwargs)

~/.virtualenvs/new/lib/python3.5/site-packages/pandas/core/generic.py in replace(self, to_replace, value, inplace, limit, regex, method)
   5877                     new_data = self._data.replace(to_replace=to_replace,
   5878                                                   value=value, inplace=inplace,
-> 5879                                                   regex=regex)
   5880                 else:
   5881                     msg = ('Invalid "to_replace" type: '

~/.virtualenvs/new/lib/python3.5/site-packages/pandas/core/internals.py in replace(self, **kwargs)
   3718
   3719     def replace(self, **kwargs):
-> 3720         return self.apply('replace', **kwargs)
   3721
   3722     def replace_list(self, src_list, dest_list, inplace=False, regex=False,

~/.virtualenvs/new/lib/python3.5/site-packages/pandas/core/internals.py in apply(self, f, axes, filter, do_integrity_check, consolidate, **kwargs)
   3579
   3580             kwargs['mgr'] = self
-> 3581             applied = getattr(b, f)(**kwargs)
   3582             result_blocks = _extend_blocks(applied, result_blocks)
   3583

~/.virtualenvs/new/lib/python3.5/site-packages/pandas/core/internals.py in replace(self, to_replace, value, inplace, filter, regex, convert, mgr)
   2430         blocks = [self]
   2431
-> 2432         if not either_list and is_re(to_replace):
   2433             return self._replace_single(to_replace, value, inplace=inplace,
   2434                                         filter=filter, regex=True,

~/.virtualenvs/new/lib/python3.5/site-packages/pandas/core/dtypes/inference.py in is_re(obj)
    217     """
    218
--> 219     return isinstance(obj, re_type)
    220
    221

/usr/lib/python3.5/typing.py in __instancecheck__(self, obj)
    256
    257     def __instancecheck__(self, obj):
--> 258         raise TypeError("Type aliases cannot be used with isinstance().")
    259
    260     def __subclasscheck__(self, cls):

TypeError: Type aliases cannot be used with isinstance().
```

#### Expected Output

```
0    x
1    b
2    c
dtype: object
```

#### Output of ``pd.show_versions()``

<details>

INSTALLED VERSIONS
------------------
commit: None
python: 3.5.1.final.0
python-bits: 64
OS: Linux
OS-release: 4.13.13-5-pve
machine: x86_64
processor: x86_64
byteorder: little
LC_ALL: en_US.UTF-8
LANG: en_US.UTF-8
LOCALE: en_US.UTF-8

pandas: 0.23.0
pytest: None
pip: 8.1.1
setuptools: 20.7.0
Cython: None
numpy: 1.14.3
scipy: 1.1.0
pyarrow: None
xarray: None
IPython: 6.4.0
sphinx: None
patsy: None
dateutil: 2.6.1
pytz: 2018.4
blosc: None
bottleneck: None
tables: None
numexpr: None
feather: None
matplotlib: 2.2.2
openpyxl: None
xlrd: None
xlwt: None
xlsxwriter: None
lxml: None
bs4: None
html5lib: 0.999
sqlalchemy: None
pymysql: None
psycopg2: None
jinja2: 2.10
s3fs: None
fastparquet: None
pandas_gbq: None
pandas_datareader: None

</details>


Discussion:
Hmm I'm not able to reproduce on Python 3.6.

Can you past the full traceback?
I don't understand the bit about "type aliases". Are you overriding a builting with something from the `typing` module?
@TomAugspurger I added the full traceback
Does this raise for you?

```
In [10]: import re

In [11]: import typing

In [12]: isinstance(re.compile(''), typing.re.Pattern)
Out[12]: True
```

If so, can you check the Python issue tracker to see if this has been filed?
That works fine on 3.5.4 for me.

```python
Python 3.5.4 | packaged by conda-forge | (default, Aug 10 2017, 01:41:15)
[GCC 4.2.1 Compatible Apple LLVM 6.1.0 (clang-602.0.53)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import re
>>> import typing
>>> isinstance(re.compile(''), typing.re.Pattern)
True
>>>
```

Can you try upgrading from 3.5.1 to a later point release?
It definitely works with 3.5.4 but doesn't work with 3.5.2 either
OK. See https://github.com/pandas-dev/pandas/pull/20553 for reference.

If you want, you can make a PR using the old way for Python 3.5.2 (or 3) and older... Or upgrade to the latest point release
Will do, thanks!

Resolving patch:
diff --git a/pandas/compat/__init__.py b/pandas/compat/__init__.py
--- a/pandas/compat/__init__.py
+++ b/pandas/compat/__init__.py
@@ -425,7 +425,7 @@ def raise_with_traceback(exc, traceback=Ellipsis):
 
 # In Python 3.7, the private re._pattern_type is removed.
 # Python 3.5+ have typing.re.Pattern
-if PY35:
+if PY36:
     import typing
     re_type = typing.re.Pattern
 else:


Test patch:
diff --git a/pandas/tests/test_compat.py b/pandas/tests/test_compat.py
--- a/pandas/tests/test_compat.py
+++ b/pandas/tests/test_compat.py
@@ -4,9 +4,10 @@
 """
 
 import pytest
+import re
 from pandas.compat import (range, zip, map, filter, lrange, lzip, lmap,
                            lfilter, builtins, iterkeys, itervalues, iteritems,
-                           next, get_range_parameters, PY2)
+                           next, get_range_parameters, PY2, re_type)
 
 
 class TestBuiltinIterators(object):
@@ -89,3 +90,7 @@ def test_get_range_parameters(self, start, stop, step):
         assert start_result == start_expected
         assert stop_result == stop_expected
         assert step_result == step_expected
+
+
+def test_re_type():
+    assert isinstance(re.compile(''), re_type)