Remove various obsolete _compat helpers (#941)

* remove obsolete _compat.iteritems()

* remove obsolete _compat.TYPE

* remove obsolete _compat.isclass()

* remove obsolete _compat.new_class()

* remove obsolete _compat.metadata_proxy
diff --git a/src/attr/_cmp.py b/src/attr/_cmp.py
index 0060222..81b99e4 100644
--- a/src/attr/_cmp.py
+++ b/src/attr/_cmp.py
@@ -2,8 +2,8 @@
 
 
 import functools
+import types
 
-from ._compat import new_class
 from ._make import _make_ne
 
 
@@ -79,7 +79,9 @@
         num_order_functions += 1
         body["__ge__"] = _make_operator("ge", ge)
 
-    type_ = new_class(class_name, (object,), {}, lambda ns: ns.update(body))
+    type_ = types.new_class(
+        class_name, (object,), {}, lambda ns: ns.update(body)
+    )
 
     # Add same type requirement.
     if require_same_type:
diff --git a/src/attr/_compat.py b/src/attr/_compat.py
index b0d6908..f5f695a 100644
--- a/src/attr/_compat.py
+++ b/src/attr/_compat.py
@@ -39,24 +39,6 @@
     )
 
 
-def isclass(klass):
-    return isinstance(klass, type)
-
-
-TYPE = "class"
-
-
-def iteritems(d):
-    return d.items()
-
-
-new_class = types.new_class
-
-
-def metadata_proxy(d):
-    return types.MappingProxyType(dict(d))
-
-
 class _AnnotationExtractor:
     """
     Extract type annotations from a callable, returning None whenever there
diff --git a/src/attr/_funcs.py b/src/attr/_funcs.py
index 69a3cf6..a982d7c 100644
--- a/src/attr/_funcs.py
+++ b/src/attr/_funcs.py
@@ -3,7 +3,6 @@
 
 import copy
 
-from ._compat import iteritems
 from ._make import NOTHING, _obj_setattr, fields
 from .exceptions import AttrsAttributeNotFoundError
 
@@ -106,7 +105,7 @@
                             value_serializer=value_serializer,
                         ),
                     )
-                    for kk, vv in iteritems(v)
+                    for kk, vv in v.items()
                 )
             else:
                 rv[a.name] = v
@@ -178,7 +177,7 @@
                     value_serializer=value_serializer,
                 ),
             )
-            for kk, vv in iteritems(val)
+            for kk, vv in val.items()
         )
     else:
         rv = val
@@ -277,7 +276,7 @@
                             if has(vv.__class__)
                             else vv,
                         )
-                        for kk, vv in iteritems(v)
+                        for kk, vv in v.items()
                     )
                 )
             else:
@@ -328,7 +327,7 @@
     )
     new = copy.copy(inst)
     attrs = fields(inst.__class__)
-    for k, v in iteritems(changes):
+    for k, v in changes.items():
         a = getattr(attrs, k, NOTHING)
         if a is NOTHING:
             raise AttrsAttributeNotFoundError(
diff --git a/src/attr/_make.py b/src/attr/_make.py
index ab3f0be..4d1afe3 100644
--- a/src/attr/_make.py
+++ b/src/attr/_make.py
@@ -3,6 +3,7 @@
 import copy
 import linecache
 import sys
+import types
 import typing
 
 from operator import itemgetter
@@ -15,10 +16,6 @@
     PY310,
     PYPY,
     _AnnotationExtractor,
-    isclass,
-    iteritems,
-    metadata_proxy,
-    new_class,
     ordered_dict,
     set_closure_cell,
 )
@@ -48,7 +45,7 @@
 # (when slots=True)
 _hash_cache_field = "_attrs_cached_hash"
 
-_empty_metadata_singleton = metadata_proxy({})
+_empty_metadata_singleton = types.MappingProxyType({})
 
 # Unique object for unequivocal getattr() defaults.
 _sentinel = object()
@@ -504,7 +501,7 @@
     anns = _get_annotations(cls)
 
     if these is not None:
-        ca_list = [(name, ca) for name, ca in iteritems(these)]
+        ca_list = [(name, ca) for name, ca in these.items()]
 
         if not isinstance(these, ordered_dict):
             ca_list.sort(key=_counter_getter)
@@ -795,7 +792,7 @@
         """
         cd = {
             k: v
-            for k, v in iteritems(self._cls_dict)
+            for k, v in self._cls_dict.items()
             if k not in tuple(self._attr_names) + ("__dict__", "__weakref__")
         }
 
@@ -850,7 +847,7 @@
         # we collect them here and update the class dict
         reused_slots = {
             slot: slot_descriptor
-            for slot, slot_descriptor in iteritems(existing_slots)
+            for slot, slot_descriptor in existing_slots.items()
             if slot in slot_names
         }
         slot_names = [name for name in slot_names if name not in reused_slots]
@@ -1988,7 +1985,7 @@
     ..  versionchanged:: 16.2.0 Returned tuple allows accessing the fields
         by name.
     """
-    if not isclass(cls):
+    if not isinstance(cls, type):
         raise TypeError("Passed object must be a class.")
     attrs = getattr(cls, "__attrs_attrs__", None)
     if attrs is None:
@@ -2016,7 +2013,7 @@
 
     .. versionadded:: 18.1.0
     """
-    if not isclass(cls):
+    if not isinstance(cls, type):
         raise TypeError("Passed object must be a class.")
     attrs = getattr(cls, "__attrs_attrs__", None)
     if attrs is None:
@@ -2542,7 +2539,7 @@
         bound_setattr(
             "metadata",
             (
-                metadata_proxy(metadata)
+                types.MappingProxyType(dict(metadata))  # Shallow copy
                 if metadata
                 else _empty_metadata_singleton
             ),
@@ -2628,7 +2625,7 @@
             else:
                 bound_setattr(
                     name,
-                    metadata_proxy(value)
+                    types.MappingProxyType(dict(value))
                     if value
                     else _empty_metadata_singleton,
                 )
@@ -2904,7 +2901,7 @@
     if user_init is not None:
         body["__init__"] = user_init
 
-    type_ = new_class(name, bases, {}, lambda ns: ns.update(body))
+    type_ = types.new_class(name, bases, {}, lambda ns: ns.update(body))
 
     # For pickling to work, the __module__ variable needs to be set to the
     # frame where the class is created.  Bypass this step in environments where
diff --git a/src/attr/filters.py b/src/attr/filters.py
index e7432e4..baa25e9 100644
--- a/src/attr/filters.py
+++ b/src/attr/filters.py
@@ -4,8 +4,6 @@
 Commonly useful filters for `attr.asdict`.
 """
 
-
-from ._compat import isclass
 from ._make import Attribute
 
 
@@ -14,7 +12,7 @@
     Returns a tuple of `frozenset`s of classes and attributes.
     """
     return (
-        frozenset(cls for cls in what if isclass(cls)),
+        frozenset(cls for cls in what if isinstance(cls, type)),
         frozenset(cls for cls in what if isinstance(cls, Attribute)),
     )
 
diff --git a/tests/test_compat.py b/tests/test_compat.py
index 464b492..4a156c4 100644
--- a/tests/test_compat.py
+++ b/tests/test_compat.py
@@ -1,18 +1,18 @@
 # SPDX-License-Identifier: MIT
 
-import pytest
+import types
 
-from attr._compat import metadata_proxy
+import pytest
 
 
 @pytest.fixture(name="mp")
 def _mp():
-    return metadata_proxy({"x": 42, "y": "foo"})
+    return types.MappingProxyType({"x": 42, "y": "foo"})
 
 
 class TestMetadataProxy:
     """
-    Ensure properties of metadata_proxy independently of hypothesis strategies.
+    Ensure properties of metadata proxy independently of hypothesis strategies.
     """
 
     def test_repr(self, mp):
diff --git a/tests/test_funcs.py b/tests/test_funcs.py
index 40c5487..d73d94c 100644
--- a/tests/test_funcs.py
+++ b/tests/test_funcs.py
@@ -15,7 +15,7 @@
 import attr
 
 from attr import asdict, assoc, astuple, evolve, fields, has
-from attr._compat import TYPE, Mapping, Sequence, ordered_dict
+from attr._compat import Mapping, Sequence, ordered_dict
 from attr.exceptions import AttrsAttributeNotFoundError
 from attr.validators import instance_of
 
@@ -599,7 +599,7 @@
             evolve(C(a=1), a="some string")
         m = e.value.args[0]
 
-        assert m.startswith("'a' must be <{type} 'int'>".format(type=TYPE))
+        assert m.startswith("'a' must be <class 'int'>")
 
     def test_private(self):
         """
diff --git a/tests/test_functional.py b/tests/test_functional.py
index 0f3a48c..09f5048 100644
--- a/tests/test_functional.py
+++ b/tests/test_functional.py
@@ -17,7 +17,7 @@
 
 import attr
 
-from attr._compat import PY36, TYPE
+from attr._compat import PY36
 from attr._make import NOTHING, Attribute
 from attr.exceptions import FrozenInstanceError
 
@@ -161,8 +161,7 @@
 
         # Using C1 explicitly, since slotted classes don't support this.
         assert (
-            "'x' must be <{type} 'int'> (got '1' that is a <{type} "
-            "'str'>).".format(type=TYPE),
+            "'x' must be <class 'int'> (got '1' that is a <class 'str'>).",
             attr.fields(C1).x,
             int,
             "1",
diff --git a/tests/test_validators.py b/tests/test_validators.py
index 633f235..f3fe69c 100644
--- a/tests/test_validators.py
+++ b/tests/test_validators.py
@@ -13,7 +13,6 @@
 
 from attr import _config, fields, has
 from attr import validators as validator_module
-from attr._compat import TYPE
 from attr.validators import (
     and_,
     deep_iterable,
@@ -143,8 +142,7 @@
         with pytest.raises(TypeError) as e:
             v(None, a, "42")
         assert (
-            "'test' must be <{type} 'int'> (got '42' that is a <{type} "
-            "'str'>).".format(type=TYPE),
+            "'test' must be <class 'int'> (got '42' that is a <class 'str'>).",
             a,
             int,
             "42",
@@ -155,9 +153,7 @@
         Returned validator has a useful `__repr__`.
         """
         v = instance_of(int)
-        assert (
-            "<instance_of validator for type <{type} 'int'>>".format(type=TYPE)
-        ) == repr(v)
+        assert ("<instance_of validator for type <class 'int'>>") == repr(v)
 
 
 class TestMatchesRe:
@@ -422,8 +418,7 @@
         with pytest.raises(TypeError) as e:
             v(None, a, "42")
         assert (
-            "'test' must be <{type} 'int'> (got '42' that is a <{type} "
-            "'str'>).".format(type=TYPE),
+            "'test' must be <class 'int'> (got '42' that is a <class 'str'>).",
             a,
             int,
             "42",
@@ -438,13 +433,13 @@
         if isinstance(validator, list):
             repr_s = (
                 "<optional validator for _AndValidator(_validators=[{func}, "
-                "<instance_of validator for type <{type} 'int'>>]) or None>"
-            ).format(func=repr(always_pass), type=TYPE)
+                "<instance_of validator for type <class 'int'>>]) or None>"
+            ).format(func=repr(always_pass))
         else:
             repr_s = (
                 "<optional validator for <instance_of validator for type "
-                "<{type} 'int'>> or None>"
-            ).format(type=TYPE)
+                "<class 'int'>> or None>"
+            )
 
         assert repr_s == repr(v)
 
@@ -608,9 +603,7 @@
         when only member validator is set.
         """
         member_validator = instance_of(int)
-        member_repr = "<instance_of validator for type <{type} 'int'>>".format(
-            type=TYPE
-        )
+        member_repr = "<instance_of validator for type <class 'int'>>"
         v = deep_iterable(member_validator)
         expected_repr = (
             "<deep_iterable validator for iterables of {member_repr}>"
@@ -626,8 +619,8 @@
         member_validator = [always_pass, instance_of(int)]
         member_repr = (
             "_AndValidator(_validators=({func}, "
-            "<instance_of validator for type <{type} 'int'>>))"
-        ).format(func=repr(always_pass), type=TYPE)
+            "<instance_of validator for type <class 'int'>>))"
+        ).format(func=repr(always_pass))
         v = deep_iterable(member_validator)
         expected_repr = (
             "<deep_iterable validator for iterables of {member_repr}>"
@@ -640,13 +633,9 @@
         and iterable validators are set.
         """
         member_validator = instance_of(int)
-        member_repr = "<instance_of validator for type <{type} 'int'>>".format(
-            type=TYPE
-        )
+        member_repr = "<instance_of validator for type <class 'int'>>"
         iterable_validator = instance_of(list)
-        iterable_repr = (
-            "<instance_of validator for type <{type} 'list'>>"
-        ).format(type=TYPE)
+        iterable_repr = "<instance_of validator for type <class 'list'>>"
         v = deep_iterable(member_validator, iterable_validator)
         expected_repr = (
             "<deep_iterable validator for"
@@ -663,12 +652,10 @@
         member_validator = [always_pass, instance_of(int)]
         member_repr = (
             "_AndValidator(_validators=({func}, "
-            "<instance_of validator for type <{type} 'int'>>))"
-        ).format(func=repr(always_pass), type=TYPE)
+            "<instance_of validator for type <class 'int'>>))"
+        ).format(func=repr(always_pass))
         iterable_validator = instance_of(list)
-        iterable_repr = (
-            "<instance_of validator for type <{type} 'list'>>"
-        ).format(type=TYPE)
+        iterable_repr = "<instance_of validator for type <class 'list'>>"
         v = deep_iterable(member_validator, iterable_validator)
         expected_repr = (
             "<deep_iterable validator for"
@@ -767,13 +754,9 @@
         Returned validator has a useful `__repr__`.
         """
         key_validator = instance_of(str)
-        key_repr = "<instance_of validator for type <{type} 'str'>>".format(
-            type=TYPE
-        )
+        key_repr = "<instance_of validator for type <class 'str'>>"
         value_validator = instance_of(int)
-        value_repr = "<instance_of validator for type <{type} 'int'>>".format(
-            type=TYPE
-        )
+        value_repr = "<instance_of validator for type <class 'int'>>"
         v = deep_mapping(key_validator, value_validator)
         expected_repr = (
             "<deep_mapping validator for objects mapping "