Repository: pandas-dev/pandas

Issue:
Setting CategoricalIndex with dtype=CategoricalDtype doesn't work (v0.21)
#### Code Sample, a copy-pastable example if possible

```python
>>> c = pd.api.types.CategoricalDtype('c b a'.split(), ordered=True)
>>> c
CategoricalDtype(categories=['c', 'b', 'a'], ordered=True)
>>> pd.CategoricalIndex('a b b c'.split(), dtype=c)
CategoricalIndex(['a', 'b', 'b', 'c'], categories=['a', 'b', 'c'], ordered=False, dtype='category')
```
Note that ``categories`` and ``ordered`` above do not follow the rules from ``c``.

#### Problem description

Using ``pd.Categorical(..., dtype=c)`` works in v0.21, so IMO ``pd.CategoricalIndex(..., dtype=c)`` should work as well, but deosn't.

#### Expected Output

```python
>>> pd.CategoricalIndex('a b b c'.split(), dtype=c)
CategoricalIndex(['a', 'b', 'b', 'c'], categories=['c', 'b', 'a'], ordered=True, dtype='category')
```
Note that ``categories`` and ``ordered`` **do** follow the rules from ``c`` in this expected version.

#### Output of ``pd.show_versions()``

<details>

INSTALLED VERSIONS
------------------
commit: None
python: 3.6.3.final.0
python-bits: 32
OS: Windows
OS-release: 10
machine: AMD64
processor: Intel64 Family 6 Model 78 Stepping 3, GenuineIntel
byteorder: little
LC_ALL: None
LANG: None
LOCALE: None.None

pandas: 0.21.0
pytest: 3.2.1
pip: 9.0.1
setuptools: 36.5.0.post20170922
Cython: None
numpy: 1.11.3
scipy: None
pyarrow: None
xarray: None
IPython: 6.1.0
sphinx: None
patsy: None
dateutil: 2.6.1
pytz: 2017.2
blosc: None
bottleneck: None
tables: None
numexpr: None
feather: None
matplotlib: None
openpyxl: 2.4.8
xlrd: None
xlwt: None
xlsxwriter: None
lxml: None
bs4: None
html5lib: None
sqlalchemy: None
pymysql: None
psycopg2: None
jinja2: 2.9.6
s3fs: None
fastparquet: None
pandas_gbq: None
pandas_datareader: None

</details>



Discussion:
``dtype`` needs to be passed thru here: https://github.com/pandas-dev/pandas/blob/master/pandas/core/indexes/category.py#L82

this case is only for list-likes (but should make sure have coverage for passing in CategoricalIndex/Categorical)

Resolving patch:
diff --git a/pandas/core/indexes/category.py b/pandas/core/indexes/category.py
--- a/pandas/core/indexes/category.py
+++ b/pandas/core/indexes/category.py
@@ -79,7 +79,8 @@ def __new__(cls, data=None, categories=None, ordered=None, dtype=None,
                 if data is not None or categories is None:
                     cls._scalar_data_error(data)
                 data = []
-            data = cls._create_categorical(cls, data, categories, ordered)
+            data = cls._create_categorical(cls, data, categories, ordered,
+                                           dtype)
 
         if copy:
             data = data.copy()


Test patch:
diff --git a/pandas/tests/indexes/test_category.py b/pandas/tests/indexes/test_category.py
--- a/pandas/tests/indexes/test_category.py
+++ b/pandas/tests/indexes/test_category.py
@@ -4,6 +4,7 @@
 
 import pandas.util.testing as tm
 from pandas.core.indexes.api import Index, CategoricalIndex
+from pandas.core.dtypes.dtypes import CategoricalDtype
 from .common import Base
 
 from pandas.compat import range, PY3
@@ -95,6 +96,11 @@ def test_construction(self):
                                               1, -1, 0], dtype='int8'))
         assert result.ordered
 
+        result = pd.CategoricalIndex(ci, categories=list('ab'), ordered=True)
+        expected = pd.CategoricalIndex(ci, categories=list('ab'), ordered=True,
+                                       dtype='category')
+        tm.assert_index_equal(result, expected, exact=True)
+
         # turn me to an Index
         result = Index(np.array(ci))
         assert isinstance(result, Index)
@@ -125,6 +131,25 @@ def test_construction_with_dtype(self):
         result = CategoricalIndex(idx, categories=idx, ordered=True)
         tm.assert_index_equal(result, expected, exact=True)
 
+    def test_construction_with_categorical_dtype(self):
+        # construction with CategoricalDtype
+        # GH18109
+        data, cats, ordered = 'a a b b'.split(), 'c b a'.split(), True
+        dtype = CategoricalDtype(categories=cats, ordered=ordered)
+
+        result = pd.CategoricalIndex(data, dtype=dtype)
+        expected = pd.CategoricalIndex(data, categories=cats,
+                                       ordered=ordered)
+        tm.assert_index_equal(result, expected, exact=True)
+
+        # error to combine categories or ordered and dtype keywords args
+        with pytest.raises(ValueError, match="Cannot specify both `dtype` and "
+                                             "`categories` or `ordered`."):
+            pd.CategoricalIndex(data, categories=cats, dtype=dtype)
+        with pytest.raises(ValueError, match="Cannot specify both `dtype` and "
+                                             "`categories` or `ordered`."):
+            pd.CategoricalIndex(data, ordered=ordered, dtype=dtype)
+
     def test_create_categorical(self):
         # https://github.com/pandas-dev/pandas/pull/17513
         # The public CI constructor doesn't hit this code path with