bpo-28556: Various updates to typing (#28) (#77)

various updates from upstream python/typing repo:

- Added typing.Counter and typing.ChainMap generics
- More flexible typing.NamedTuple
- Improved generic ABC caching
- More tests
- Bugfixes
- Other updates
* Add Misc/NEWS entry


(cherry picked from commit b692dc8475a032740576129d0990ddc3edccab2b)
diff --git a/Lib/typing.py b/Lib/typing.py
index c9e3417..efe358f 100644
--- a/Lib/typing.py
+++ b/Lib/typing.py
@@ -10,6 +10,12 @@
     import collections.abc as collections_abc
 except ImportError:
     import collections as collections_abc  # Fallback for PY3.2.
+try:
+    from types import SlotWrapperType, MethodWrapperType, MethodDescriptorType
+except ImportError:
+    SlotWrapperType = type(object.__init__)
+    MethodWrapperType = type(object().__str__)
+    MethodDescriptorType = type(str.join)
 
 
 # Please keep __all__ alphabetized within each category.
@@ -62,6 +68,7 @@
     'SupportsRound',
 
     # Concrete collection types.
+    'Counter',
     'Deque',
     'Dict',
     'DefaultDict',
@@ -849,19 +856,6 @@
     return next_in_mro
 
 
-def _valid_for_check(cls):
-    """An internal helper to prohibit isinstance([1], List[str]) etc."""
-    if cls is Generic:
-        raise TypeError("Class %r cannot be used with class "
-                        "or instance checks" % cls)
-    if (
-        cls.__origin__ is not None and
-        sys._getframe(3).f_globals['__name__'] not in ['abc', 'functools']
-    ):
-        raise TypeError("Parameterized generics cannot be used with class "
-                        "or instance checks")
-
-
 def _make_subclasshook(cls):
     """Construct a __subclasshook__ callable that incorporates
     the associated __extra__ class in subclass checks performed
@@ -872,7 +866,6 @@
         # Registered classes need not be checked here because
         # cls and its extra share the same _abc_registry.
         def __extrahook__(subclass):
-            _valid_for_check(cls)
             res = cls.__extra__.__subclasshook__(subclass)
             if res is not NotImplemented:
                 return res
@@ -887,7 +880,6 @@
     else:
         # For non-ABC extras we'll just call issubclass().
         def __extrahook__(subclass):
-            _valid_for_check(cls)
             if cls.__extra__ and issubclass(subclass, cls.__extra__):
                 return True
             return NotImplemented
@@ -974,6 +966,7 @@
         # remove bare Generic from bases if there are other generic bases
         if any(isinstance(b, GenericMeta) and b is not Generic for b in bases):
             bases = tuple(b for b in bases if b is not Generic)
+        namespace.update({'__origin__': origin, '__extra__': extra})
         self = super().__new__(cls, name, bases, namespace, _root=True)
 
         self.__parameters__ = tvars
@@ -982,8 +975,6 @@
         self.__args__ = tuple(... if a is _TypingEllipsis else
                               () if a is _TypingEmpty else
                               a for a in args) if args else None
-        self.__origin__ = origin
-        self.__extra__ = extra
         # Speed hack (https://github.com/python/typing/issues/196).
         self.__next_in_mro__ = _next_in_mro(self)
         # Preserve base classes on subclassing (__bases__ are type erased now).
@@ -994,20 +985,56 @@
         # with issubclass() and isinstance() in the same way as their
         # collections.abc counterparts (e.g., isinstance([], Iterable)).
         if (
-            # allow overriding
             '__subclasshook__' not in namespace and extra or
-            hasattr(self.__subclasshook__, '__name__') and
-            self.__subclasshook__.__name__ == '__extrahook__'
+            # allow overriding
+            getattr(self.__subclasshook__, '__name__', '') == '__extrahook__'
         ):
             self.__subclasshook__ = _make_subclasshook(self)
         if isinstance(extra, abc.ABCMeta):
             self._abc_registry = extra._abc_registry
+            self._abc_cache = extra._abc_cache
+        elif origin is not None:
+            self._abc_registry = origin._abc_registry
+            self._abc_cache = origin._abc_cache
 
         if origin and hasattr(origin, '__qualname__'):  # Fix for Python 3.2.
             self.__qualname__ = origin.__qualname__
-        self.__tree_hash__ = hash(self._subs_tree()) if origin else hash((self.__name__,))
+        self.__tree_hash__ = (hash(self._subs_tree()) if origin else
+                              super(GenericMeta, self).__hash__())
         return self
 
+    # _abc_negative_cache and _abc_negative_cache_version
+    # realised as descriptors, since GenClass[t1, t2, ...] always
+    # share subclass info with GenClass.
+    # This is an important memory optimization.
+    @property
+    def _abc_negative_cache(self):
+        if isinstance(self.__extra__, abc.ABCMeta):
+            return self.__extra__._abc_negative_cache
+        return _gorg(self)._abc_generic_negative_cache
+
+    @_abc_negative_cache.setter
+    def _abc_negative_cache(self, value):
+        if self.__origin__ is None:
+            if isinstance(self.__extra__, abc.ABCMeta):
+                self.__extra__._abc_negative_cache = value
+            else:
+                self._abc_generic_negative_cache = value
+
+    @property
+    def _abc_negative_cache_version(self):
+        if isinstance(self.__extra__, abc.ABCMeta):
+            return self.__extra__._abc_negative_cache_version
+        return _gorg(self)._abc_generic_negative_cache_version
+
+    @_abc_negative_cache_version.setter
+    def _abc_negative_cache_version(self, value):
+        if self.__origin__ is None:
+            if isinstance(self.__extra__, abc.ABCMeta):
+                self.__extra__._abc_negative_cache_version = value
+            else:
+                self._abc_generic_negative_cache_version = value
+
     def _get_type_vars(self, tvars):
         if self.__origin__ and self.__parameters__:
             _get_type_vars(self.__parameters__, tvars)
@@ -1095,8 +1122,10 @@
             _check_generic(self, params)
             tvars = _type_vars(params)
             args = params
+
+        prepend = (self,) if self.__origin__ is None else ()
         return self.__class__(self.__name__,
-                              self.__bases__,
+                              prepend + self.__bases__,
                               _no_slots_copy(self.__dict__),
                               tvars=tvars,
                               args=args,
@@ -1104,6 +1133,17 @@
                               extra=self.__extra__,
                               orig_bases=self.__orig_bases__)
 
+    def __subclasscheck__(self, cls):
+        if self.__origin__ is not None:
+            if sys._getframe(1).f_globals['__name__'] not in ['abc', 'functools']:
+                raise TypeError("Parameterized generics cannot be used with class "
+                                "or instance checks")
+            return False
+        if self is Generic:
+            raise TypeError("Class %r cannot be used with class "
+                            "or instance checks" % self)
+        return super().__subclasscheck__(cls)
+
     def __instancecheck__(self, instance):
         # Since we extend ABC.__subclasscheck__ and
         # ABC.__instancecheck__ inlines the cache checking done by the
@@ -1398,6 +1438,11 @@
     return res
 
 
+_allowed_types = (types.FunctionType, types.BuiltinFunctionType,
+                  types.MethodType, types.ModuleType,
+                  SlotWrapperType, MethodWrapperType, MethodDescriptorType)
+
+
 def get_type_hints(obj, globalns=None, localns=None):
     """Return type hints for an object.
 
@@ -1452,12 +1497,7 @@
     hints = getattr(obj, '__annotations__', None)
     if hints is None:
         # Return empty annotations for something that _could_ have them.
-        if (
-            isinstance(obj, types.FunctionType) or
-            isinstance(obj, types.BuiltinFunctionType) or
-            isinstance(obj, types.MethodType) or
-            isinstance(obj, types.ModuleType)
-        ):
+        if isinstance(obj, _allowed_types):
             return {}
         else:
             raise TypeError('{!r} is not a module, class, method, '
@@ -1824,8 +1864,7 @@
 
     def __new__(cls, *args, **kwds):
         if _geqv(cls, Deque):
-            raise TypeError("Type Deque cannot be instantiated; "
-                            "use deque() instead")
+            return collections.deque(*args, **kwds)
         return _generic_new(collections.deque, cls, *args, **kwds)
 
 
@@ -1894,11 +1933,35 @@
 
     def __new__(cls, *args, **kwds):
         if _geqv(cls, DefaultDict):
-            raise TypeError("Type DefaultDict cannot be instantiated; "
-                            "use collections.defaultdict() instead")
+            return collections.defaultdict(*args, **kwds)
         return _generic_new(collections.defaultdict, cls, *args, **kwds)
 
 
+class Counter(collections.Counter, Dict[T, int], extra=collections.Counter):
+
+    __slots__ = ()
+
+    def __new__(cls, *args, **kwds):
+        if _geqv(cls, Counter):
+            return collections.Counter(*args, **kwds)
+        return _generic_new(collections.Counter, cls, *args, **kwds)
+
+
+if hasattr(collections, 'ChainMap'):
+    # ChainMap only exists in 3.3+
+    __all__.append('ChainMap')
+
+    class ChainMap(collections.ChainMap, MutableMapping[KT, VT],
+                   extra=collections.ChainMap):
+
+        __slots__ = ()
+
+        def __new__(cls, *args, **kwds):
+            if _geqv(cls, ChainMap):
+                return collections.ChainMap(*args, **kwds)
+            return _generic_new(collections.ChainMap, cls, *args, **kwds)
+
+
 # Determine what base class to use for Generator.
 if hasattr(collections_abc, 'Generator'):
     # Sufficiently recent versions of 3.5 have a Generator ABC.
@@ -1975,6 +2038,13 @@
 
 _PY36 = sys.version_info[:2] >= (3, 6)
 
+# attributes prohibited to set in NamedTuple class syntax
+_prohibited = ('__new__', '__init__', '__slots__', '__getnewargs__',
+               '_fields', '_field_defaults', '_field_types',
+               '_make', '_replace', '_asdict')
+
+_special = ('__module__', '__name__', '__qualname__', '__annotations__')
+
 
 class NamedTupleMeta(type):
 
@@ -2002,7 +2072,9 @@
         nm_tpl._field_defaults = defaults_dict
         # update from user namespace without overriding special namedtuple attributes
         for key in ns:
-            if not hasattr(nm_tpl, key):
+            if key in _prohibited:
+                raise AttributeError("Cannot overwrite NamedTuple attribute " + key)
+            elif key not in _special and key not in nm_tpl._fields:
                 setattr(nm_tpl, key, ns[key])
         return nm_tpl