#9018: os.path.normcase() now raises a TypeError if the argument is not str or bytes.
diff --git a/Lib/macpath.py b/Lib/macpath.py
index 3b3e4ff..4ab7c09 100644
--- a/Lib/macpath.py
+++ b/Lib/macpath.py
@@ -32,6 +32,9 @@
 # Normalize the case of a pathname.  Dummy in Posix, but <s>.lower() here.
 
 def normcase(path):
+    if not isinstance(path, (bytes, str)):
+        raise TypeError("normcase() argument must be str or bytes, "
+                        "not '{}'".format(path.__class__.__name__))
     return path.lower()
 
 
diff --git a/Lib/ntpath.py b/Lib/ntpath.py
index 8d50294..7972aa9 100644
--- a/Lib/ntpath.py
+++ b/Lib/ntpath.py
@@ -78,6 +78,9 @@
     """Normalize case of pathname.
 
     Makes all characters lowercase and all slashes into backslashes."""
+    if not isinstance(s, (bytes, str)):
+        raise TypeError("normcase() argument must be str or bytes, "
+                        "not '{}'".format(s.__class__.__name__))
     return s.replace(_get_altsep(s), _get_sep(s)).lower()
 
 
diff --git a/Lib/os2emxpath.py b/Lib/os2emxpath.py
index 184c9b1..0ccbf8a 100644
--- a/Lib/os2emxpath.py
+++ b/Lib/os2emxpath.py
@@ -36,6 +36,9 @@
     """Normalize case of pathname.
 
     Makes all characters lowercase and all altseps into seps."""
+    if not isinstance(s, (bytes, str)):
+        raise TypeError("normcase() argument must be str or bytes, "
+                        "not '{}'".format(s.__class__.__name__))
     return s.replace('\\', '/').lower()
 
 
diff --git a/Lib/posixpath.py b/Lib/posixpath.py
index 5783975..667f5c5 100644
--- a/Lib/posixpath.py
+++ b/Lib/posixpath.py
@@ -49,6 +49,9 @@
 def normcase(s):
     """Normalize case of pathname.  Has no effect under Posix"""
     # TODO: on Mac OS X, this should really return s.lower().
+    if not isinstance(s, (bytes, str)):
+        raise TypeError("normcase() argument must be str or bytes, "
+                        "not '{}'".format(s.__class__.__name__))
     return s
 
 
diff --git a/Lib/test/test_genericpath.py b/Lib/test/test_genericpath.py
index 9a0f226..2955f49 100644
--- a/Lib/test/test_genericpath.py
+++ b/Lib/test/test_genericpath.py
@@ -194,14 +194,18 @@
     ]
 
     def test_normcase(self):
-        # Check that normcase() is idempotent
-        p = "FoO/./BaR"
-        p = self.pathmodule.normcase(p)
-        self.assertEqual(p, self.pathmodule.normcase(p))
+        normcase = self.pathmodule.normcase
+        # check that normcase() is idempotent
+        for p in ["FoO/./BaR", b"FoO/./BaR"]:
+            p = normcase(p)
+            self.assertEqual(p, normcase(p))
 
-        p = b"FoO/./BaR"
-        p = self.pathmodule.normcase(p)
-        self.assertEqual(p, self.pathmodule.normcase(p))
+        self.assertEqual(normcase(''), '')
+        self.assertEqual(normcase(b''), b'')
+
+        # check that normcase raises a TypeError for invalid types
+        for path in (None, True, 0, 2.5, [], bytearray(b''), {'o','o'}):
+            self.assertRaises(TypeError, normcase, path)
 
     def test_splitdrive(self):
         # splitdrive for non-NT paths