Upgrade python/mock to 4.0.2 am: 73ebb2ed5b am: f5ce53b581

Change-Id: Ia3ddfac945fbf3d4b5ed13257d6cf81bfbf2a23a
diff --git a/.circleci/config.yml b/.circleci/config.yml
index 8416914..9855ef7 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -25,23 +25,14 @@
 common: &common
   jobs:
     - python/pip-run-tests:
-        name: python27
-        image: circleci/python:2.7
-    - python/pip-run-tests:
-        name: python34
-        image: circleci/python:3.4
-    - python/pip-run-tests:
-        name: python35
-        image: circleci/python:3.5
-    - python/pip-run-tests:
         name: python36
         image: circleci/python:3.6
     - python/pip-run-tests:
         name: python37
         image: circleci/python:3.7
     - python/pip-run-tests:
-        name: pypy27
-        image: pypy:2.7
+        name: python38
+        image: circleci/python:3.8
     - python/pip-run-tests:
         name: pypy36
         image: pypy:3.6
@@ -49,12 +40,9 @@
     - python/coverage:
         name: coverage
         requires:
-          - python27
-          - python34
-          - python35
           - python36
           - python37
-          - pypy27
+          - python38
           - pypy36
 
     - python/pip-docs:
@@ -71,8 +59,8 @@
             only: master
 
     - check-package:
-        name: check-package-python27
-        image: circleci/python:2.7
+        name: check-package-python36
+        image: circleci/python:3.6
         requires:
           - package
 
@@ -83,9 +71,8 @@
           - package
 
     - check-package:
-        name: check-package-pypy27
-        image: pypy:2.7
-        python: pypy
+        name: check-package-python38
+        image: circleci/python:3.8
         requires:
           - package
 
@@ -100,9 +87,9 @@
         name: release
         config: .carthorse.yml
         requires:
-          - check-package-python27
+          - check-package-python36
           - check-package-python37
-          - check-package-pypy27
+          - check-package-python38
           - check-package-pypy36
 
 workflows:
diff --git a/.coveragerc b/.coveragerc
index 5a29219..7b4f0a2 100644
--- a/.coveragerc
+++ b/.coveragerc
@@ -1,12 +1,12 @@
 [run]
 source = mock
-omit = mock/tests/__main__.py
 
 [report]
 exclude_lines =
     pragma: no cover
     if __name__ == .__main__.:
     : pass
+    : yield
 
 [paths]
 source =
diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index 919648b..7439fe5 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -1,3 +1,126 @@
+4.0.2
+-----
+
+- Issue #39915: Ensure :attr:`unittest.mock.AsyncMock.await_args_list` has
+  call objects in the order of awaited arguments instead of using
+  :attr:`unittest.mock.Mock.call_args` which has the last value of the call.
+  Patch by Karthikeyan Singaravelan.
+
+4.0.1
+-----
+
+- Remove the universal marker from the wheel.
+
+4.0.0
+-----
+
+- No Changes from 4.0.0b1.
+
+4.0.0b1
+-------
+
+- The release is a fresh cut of cpython's `4a686504`__. All changes to :mod:`mock`
+  from that commit and before are included in this release along with the
+  subsequent changes listed below.
+
+  __ https://github.com/python/cpython/commit/4a686504eb2bbf69adf78077458508a7ba131667
+
+- Issue #37972: Subscripts to the `unittest.mock.call` objects now receive
+  the same chaining mechanism as any other custom attributes, so that the
+  following usage no longer raises a `TypeError`:
+
+  call().foo().__getitem__('bar')
+
+  Patch by blhsing
+
+- Issue #38839: Fix some unused functions in tests. Patch by Adam Johnson.
+
+- Issue #39485: Fix a bug in :func:`unittest.mock.create_autospec` that
+  would complain about the wrong number of arguments for custom descriptors
+  defined in an extension module returning functions.
+
+- Issue #39082: Allow AsyncMock to correctly patch static/class methods
+
+- Issue #38093: Fixes AsyncMock so it doesn't crash when used with
+  AsyncContextManagers or AsyncIterators.
+
+- Issue #38859: AsyncMock now returns StopAsyncIteration on the exaustion of
+  a side_effects iterable. Since PEP-479 its Impossible to raise a
+  StopIteration exception from a coroutine.
+
+- Issue #38163: Child mocks will now detect their type as either synchronous
+  or asynchronous, asynchronous child mocks will be AsyncMocks and
+  synchronous child mocks will be either MagicMock or Mock (depending on
+  their parent type).
+
+- Issue #38473: Use signature from inner mock for autospecced methods
+  attached with :func:`unittest.mock.attach_mock`. Patch by Karthikeyan
+  Singaravelan.
+
+- Issue #38136: Changes AsyncMock call count and await count to be two
+  different counters. Now await count only counts when a coroutine has been
+  awaited, not when it has been called, and vice-versa. Update the
+  documentation around this.
+
+- Issue #37555: Fix `NonCallableMock._call_matcher` returning tuple instead
+  of `_Call` object when `self._spec_signature` exists. Patch by Elizabeth
+  Uselton
+
+- Issue #37251: Remove `__code__` check in AsyncMock that incorrectly
+  evaluated function specs as async objects but failed to evaluate classes
+  with `__await__` but no `__code__` attribute defined as async objects.
+
+- Issue #38669: Raise :exc:`TypeError` when passing target as a string with
+  :meth:`unittest.mock.patch.object`.
+
+- Issue #25597: Ensure, if ``wraps`` is supplied to
+  :class:`unittest.mock.MagicMock`, it is used to calculate return values
+  for the magic methods instead of using the default return values. Patch by
+  Karthikeyan Singaravelan.
+
+- Issue #38108: Any synchronous magic methods on an AsyncMock now return a
+  MagicMock. Any asynchronous magic methods on a MagicMock now return an
+  AsyncMock.
+
+- Issue #21478: Record calls to parent when autospecced object is attached
+  to a mock using :func:`unittest.mock.attach_mock`. Patch by Karthikeyan
+  Singaravelan.
+
+- Issue #38857: AsyncMock fix for return values that are awaitable types.
+  This also covers side_effect iterable values that happend to be awaitable,
+  and wraps callables that return an awaitable type. Before these awaitables
+  were being awaited instead of being returned as is.
+
+- Issue #38932: Mock fully resets child objects on reset_mock(). Patch by
+  Vegard Stikbakke
+
+- Issue #37685: Fixed ``__eq__``, ``__lt__`` etc implementations in some
+  classes. They now return :data:`NotImplemented` for unsupported type of
+  the other operand. This allows the other operand to play role (for example
+  the equality comparison with :data:`~unittest.mock.ANY` will return
+  ``True``).
+
+- Issue #37212: :func:`unittest.mock.call` now preserves the order of
+  keyword arguments in repr output. Patch by Karthikeyan Singaravelan.
+
+- Issue #37828: Fix default mock name in
+  :meth:`unittest.mock.Mock.assert_called` exceptions. Patch by Abraham
+  Toriz Cruz.
+
+- Issue #36871: Improve error handling for the assert_has_calls and
+  assert_has_awaits methods of mocks. Fixed a bug where any errors
+  encountered while binding the expected calls to the mock's spec were
+  silently swallowed, leading to misleading error output.
+
+- Issue #21600: Fix :func:`mock.patch.stopall` to stop active patches that
+  were created with :func:`mock.patch.dict`.
+
+- Issue #38161: Removes _AwaitEvent from AsyncMock.
+
+- Issue #36871: Ensure method signature is used instead of constructor
+  signature of a class while asserting mock object against method calls.
+  Patch by Karthikeyan Singaravelan.
+
 3.0.5
 -----
 
diff --git a/MANIFEST.in b/MANIFEST.in
index 7f47ab6..27027db 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -1,2 +1,3 @@
 include LICENSE.txt
 include *.rst
+recursive-include mock/tests *.py
diff --git a/METADATA b/METADATA
index e0d0615..75c4841 100644
--- a/METADATA
+++ b/METADATA
@@ -1,9 +1,5 @@
 name: "mock"
-description:
-    "mock is a library for testing in Python. It allows you to replace parts of "
-    "your system under test with mock objects and make assertions about how "
-    "they have been used."
-
+description: "mock is a library for testing in Python. It allows you to replace parts of your system under test with mock objects and make assertions about how they have been used."
 third_party {
   url {
     type: HOMEPAGE
@@ -13,7 +9,11 @@
     type: GIT
     value: "https://github.com/testing-cabal/mock"
   }
-  version: "2.0.0"
-  last_upgrade_date { year: 2018 month: 8 day: 1 }
+  version: "4.0.2"
   license_type: NOTICE
+  last_upgrade_date {
+    year: 2020
+    month: 3
+    day: 11
+  }
 }
diff --git a/README.rst b/README.rst
index b4f3163..279f2dc 100644
--- a/README.rst
+++ b/README.rst
@@ -7,7 +7,7 @@
 onwards.
 
 This package contains a rolling backport of the standard library mock code
-compatible with Python 2.7 and 3.4 and up.
+compatible with Python 3.6 and up.
 
 Please see the standard library documentation for more details.
 
diff --git a/docs/conf.py b/docs/conf.py
index d2be5a5..e978b46 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -26,7 +26,13 @@
 
 # Add any Sphinx extension module names here, as strings. They can be extensions
 # coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
-extensions = ['sphinx.ext.doctest']
+extensions = [
+    'sphinx.ext.intersphinx',
+    ]
+
+intersphinx_mapping = {
+    'python': ('http://docs.python.org/dev', None),
+}
 
 doctest_global_setup = """
 import os
@@ -71,7 +77,7 @@
 # The default replacements for |version| and |release|, also used in various
 # other places throughout the built documents. Supplied by pbr.
 #
-version = release = mock.mock.__version__
+version = release = mock.__version__
 
 # There are two options for replacing |today|: either, you set today to some
 # non-false value, then it is used: (Set from pbr)
diff --git a/docs/index.txt b/docs/index.txt
index 4e8bc17..95f6817 100644
--- a/docs/index.txt
+++ b/docs/index.txt
@@ -25,6 +25,8 @@
 
 * Version 2.0.0 is the last version offering official Jython support.
 
+* version 3.0.5 is the last version supporting Python 3.5 and lower.
+
 .. index:: installing
 .. _installing:
 
@@ -77,9 +79,6 @@
 Committers can just push as desired: since all semantic development takes
 place in cPython, the backport process is as lightweight as we can make it.
 
-mock is CI tested using Travis-CI on Python versions 2.7, 3.4,
-3.5, 3.6, pypy, pypy3.
-
 If you end up fixing anything backport-specific, please add an entry
 to the top of ``CHANGELOG.rst`` so it shows up in the next release
 notes.
@@ -104,17 +103,6 @@
 Backporting rules
 -----------------
 
-- ``isinstance`` checks in cPython to ``type`` need to check ``ClassTypes``.
-  Code calling ``obj.isidentifier`` needs to change to ``_isidentifier(obj)``.
-
-- f-strings need to be rewritten using some other string substitution.
-
-- ``assertRaisesRegex`` needs to be ``assertRaisesRegexp`` for Python 2.
-
-- If test code won't compile on a particular version of Python, move it to
-  a matching ``_py{version}.py`` file. If ``{version}`` isn't 3, adjust
-  ``conftest.py``.
-
 - If code such as this causes coverage checking to drop below 100%:
 
   .. code-block:: python
@@ -129,6 +117,20 @@
 
       def will_never_be_called(): pass
 
+- If code such as this causes coverage checking to drop below 100%:
+
+  .. code-block:: python
+
+      def will_never_be_called():
+          yield
+
+  It should be adjusted to the following pattern, preferably upstream,
+  so that the ``.coveragerc`` in this repo knows to ignore it:
+
+  .. code-block:: python
+
+      def will_never_be_called(): yield
+
 Backporting process
 -------------------
 
@@ -141,7 +143,7 @@
        git clone https://github.com/python/cpython.git
        git clone https://github.com/testing-cabal/mock.git
 
-   Make sure they both on master and up to date!
+   Make sure they are both on master and up to date!
 
 2. Create a branch in your ``mock`` clone and switch to it.
 
@@ -177,5 +179,25 @@
 
 5. Rinse and repeat until ``backport.py`` reports no more patches need applying.
 
-6. If ``backport.py`` has updated ``lastsync.txt``, now would be a good time
-   to commit that change.
+6. If ``backport.py`` has updated ``lastsync.txt`` but not committed it,
+   now would be a good time to commit that change.
+
+Checking coverage in upstream
+-----------------------------
+
+Assuming you have the checkout structure as above, and you have compiled your cpython
+master branch, then roughly as follows:
+
+.. code-block:: bash
+
+   ~/vcs/cpython/python.exe -m venv ~/virtualenvs/cpython-master
+   source ~/virtualenvs/cpython-master/bin/activate
+   pip install -U setuptools pip
+   pip install pytest pytest-cov
+   cd vcs/cpython/Lib/unittest
+   pytest --cov unittest.mock --cov unittest.test.testmock \
+          --cov-config ~/vcs/git/mock/.coveragerc \
+          --cov-report term-missing:skip-covered \
+          test/testmock/test*
+
+Ignore ``test/testmock/__*__.py`` as these aren't present in the backport.
diff --git a/lastsync.txt b/lastsync.txt
index 1f18392..c2edac8 100644
--- a/lastsync.txt
+++ b/lastsync.txt
@@ -1 +1 @@
-11a8832c98b3db78727312154dd1d3ba76d639ec
+e553f204bf0e39b1d701a364bc71b286acb9433f
diff --git a/mock/__init__.py b/mock/__init__.py
index 8f383f0..180dee5 100644
--- a/mock/__init__.py
+++ b/mock/__init__.py
@@ -1,4 +1,15 @@
 from __future__ import absolute_import
+
+import re, sys
+
+IS_PYPY = 'PyPy' in sys.version
+
 import mock.mock as _mock
 from mock.mock import *
-__all__ = _mock.__all__
+
+__version__ = '4.0.2'
+version_info = tuple(int(p) for p in
+                     re.match(r'(\d+).(\d+).(\d+)', __version__).groups())
+
+
+__all__ = ('__version__', 'version_info') + _mock.__all__
diff --git a/mock/backports.py b/mock/backports.py
new file mode 100644
index 0000000..6f20494
--- /dev/null
+++ b/mock/backports.py
@@ -0,0 +1,89 @@
+import sys
+
+
+if sys.version_info[:2] < (3, 8):
+
+    import asyncio, functools
+    from asyncio.coroutines import _is_coroutine
+    from inspect import ismethod, isfunction, CO_COROUTINE
+    from unittest import TestCase
+
+    def _unwrap_partial(func):
+        while isinstance(func, functools.partial):
+            func = func.func
+        return func
+
+    def _has_code_flag(f, flag):
+        """Return true if ``f`` is a function (or a method or functools.partial
+        wrapper wrapping a function) whose code object has the given ``flag``
+        set in its flags."""
+        while ismethod(f):
+            f = f.__func__
+        f = _unwrap_partial(f)
+        if not isfunction(f):
+            return False
+        return bool(f.__code__.co_flags & flag)
+
+    def iscoroutinefunction(obj):
+        """Return true if the object is a coroutine function.
+
+        Coroutine functions are defined with "async def" syntax.
+        """
+        return (
+            _has_code_flag(obj, CO_COROUTINE) or
+            getattr(obj, '_is_coroutine', None) is _is_coroutine
+        )
+
+
+    class IsolatedAsyncioTestCase(TestCase):
+
+        def __init__(self, methodName='runTest'):
+            super().__init__(methodName)
+            self._asyncioTestLoop = None
+            self._asyncioCallsQueue = None
+
+        async def _asyncioLoopRunner(self, fut):
+            self._asyncioCallsQueue = queue = asyncio.Queue()
+            fut.set_result(None)
+            while True:
+                query = await queue.get()
+                queue.task_done()
+                assert query is None
+
+        def _setupAsyncioLoop(self):
+            assert self._asyncioTestLoop is None
+            loop = asyncio.new_event_loop()
+            asyncio.set_event_loop(loop)
+            loop.set_debug(True)
+            self._asyncioTestLoop = loop
+            fut = loop.create_future()
+            self._asyncioCallsTask = loop.create_task(self._asyncioLoopRunner(fut))
+            loop.run_until_complete(fut)
+
+        def _tearDownAsyncioLoop(self):
+            assert self._asyncioTestLoop is not None
+            loop = self._asyncioTestLoop
+            self._asyncioTestLoop = None
+            self._asyncioCallsQueue.put_nowait(None)
+            loop.run_until_complete(self._asyncioCallsQueue.join())
+
+            try:
+                # shutdown asyncgens
+                loop.run_until_complete(loop.shutdown_asyncgens())
+            finally:
+                asyncio.set_event_loop(None)
+                loop.close()
+
+        def run(self, result=None):
+            self._setupAsyncioLoop()
+            try:
+                return super().run(result)
+            finally:
+                self._tearDownAsyncioLoop()
+
+
+else:
+
+    from asyncio import iscoroutinefunction
+    from unittest import IsolatedAsyncioTestCase
+
diff --git a/mock/mock.py b/mock/mock.py
index 2d39253..4766672 100644
--- a/mock/mock.py
+++ b/mock/mock.py
@@ -1,41 +1,10 @@
 # mock.py
 # Test tools for mocking and patching.
-# E-mail: fuzzyman AT voidspace DOT org DOT uk
-#
-# http://www.voidspace.org.uk/python/mock/
-#
-# Copyright (c) 2007-2013, Michael Foord & the mock team
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-#     * Redistributions of source code must retain the above copyright
-#       notice, this list of conditions and the following disclaimer.
-#
-#     * Redistributions in binary form must reproduce the above
-#       copyright notice, this list of conditions and the following
-#       disclaimer in the documentation and/or other materials provided
-#       with the distribution.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-from __future__ import absolute_import
+# Maintained by Michael Foord
+# Backport for other versions of Python available from
+# https://pypi.org/project/mock
 
 __all__ = (
-    '__version__',
-    'version_info',
     'Mock',
     'MagicMock',
     'patch',
@@ -44,8 +13,8 @@
     'ANY',
     'call',
     'create_autospec',
+    'AsyncMock',
     'FILTER_DIR',
-    'CallableMixin',
     'NonCallableMock',
     'NonCallableMagicMock',
     'mock_open',
@@ -54,79 +23,44 @@
 )
 
 
-from functools import partial
+import asyncio
+import contextlib
 import io
 import inspect
 import pprint
 import sys
-try:
-    import builtins
-except ImportError:
-    import __builtin__ as builtins
-from types import ModuleType, MethodType
+import builtins
+from asyncio import iscoroutinefunction
+from types import CodeType, ModuleType, MethodType
 from unittest.util import safe_repr
+from functools import wraps, partial
 
-import six
-from six import wraps
-
-__version__ = '3.0.5'
-version_info = tuple(int(p) for p in __version__.split('.'))
-
-import mock
-
-try:
-    inspectsignature = inspect.signature
-except AttributeError:
-    import funcsigs
-    inspectsignature = funcsigs.signature
-
-
-# TODO: use six.
-try:
-    unicode
-except NameError:
-    # Python 3
-    basestring = unicode = str
-
-try:
-    long
-except NameError:
-    # Python 3
-    long = int
-
-if six.PY2:
-    # Python 2's next() can't handle a non-iterator with a __next__ method.
-    _next = next
-    def next(obj, _next=_next):
-        if getattr(obj, '__next__', None):
-            return obj.__next__()
-        return _next(obj)
-
-    del _next
-
+from mock import IS_PYPY
+from .backports import iscoroutinefunction
 
 _builtins = {name for name in dir(builtins) if not name.startswith('_')}
 
-try:
-    _isidentifier = str.isidentifier
-except AttributeError:
-    # Python 2.X
-    import keyword
-    import re
-    regex = re.compile(r'^[a-z_][a-z0-9_]*$', re.I)
-    def _isidentifier(string):
-        if string in keyword.kwlist:
-            return False
-        return regex.match(string)
-
-
-# NOTE: This FILTER_DIR is not used. The binding in mock.FILTER_DIR is.
 FILTER_DIR = True
 
-# Workaround for Python issue #12370
+# Workaround for issue #12370
 # Without this, the __class__ properties wouldn't be set correctly
 _safe_super = super
 
+def _is_async_obj(obj):
+    if _is_instance_mock(obj) and not isinstance(obj, AsyncMock):
+        return False
+    if hasattr(obj, '__func__'):
+        obj = getattr(obj, '__func__')
+    return iscoroutinefunction(obj) or inspect.isawaitable(obj)
+
+
+def _is_async_func(func):
+    if getattr(func, '__code__', None):
+        return iscoroutinefunction(func)
+    else:
+        return False
+
+
 def _is_instance_mock(obj):
     # can't use isinstance on Mock objects because they override __class__
     # The base class for all mocks is NonCallableMock
@@ -136,20 +70,17 @@
 def _is_exception(obj):
     return (
         isinstance(obj, BaseException) or
-        isinstance(obj, ClassTypes) and issubclass(obj, BaseException)
+        isinstance(obj, type) and issubclass(obj, BaseException)
     )
 
 
-class _slotted(object):
-    __slots__ = ['a']
-
-
-# Do not use this tuple.  It was never documented as a public API.
-# It will be removed.  It has no obvious signs of users on github.
-DescriptorTypes = (
-    type(_slotted.a),
-    property,
-)
+def _extract_mock(obj):
+    # Autospecced functions will return a FunctionType with "mock" attribute
+    # which is the actual mock object that needs to be used.
+    if isinstance(obj, FunctionTypes) and hasattr(obj, 'mock'):
+        return obj.mock
+    else:
+        return obj
 
 
 def _get_signature_object(func, as_instance, eat_self):
@@ -158,12 +89,9 @@
     signature object.
     Return a (reduced func, signature) tuple, or None.
     """
-    if isinstance(func, ClassTypes) and not as_instance:
+    if isinstance(func, type) and not as_instance:
         # If it's a type and should be modelled as a type, use __init__.
-        try:
-            func = func.__init__
-        except AttributeError:
-            return None
+        func = func.__init__
         # Skip the `self` argument in __init__
         eat_self = True
     elif not isinstance(func, FunctionTypes):
@@ -177,9 +105,8 @@
         sig_func = partial(func, None)
     else:
         sig_func = func
-
     try:
-        return func, inspectsignature(sig_func)
+        return func, inspect.signature(sig_func)
     except ValueError:
         # Certain callable types are not supported by inspect.signature()
         return None
@@ -208,15 +135,10 @@
             setattr(funcopy, attribute, getattr(func, attribute))
         except AttributeError:
             pass
-    if six.PY2:
-        try:
-            funcopy.func_defaults = func.func_defaults
-        except AttributeError:
-            pass
 
 
 def _callable(obj):
-    if isinstance(obj, ClassTypes):
+    if isinstance(obj, type):
         return True
     if isinstance(obj, (staticmethod, classmethod, MethodType)):
         return _callable(obj.__func__)
@@ -234,25 +156,15 @@
 def _instance_callable(obj):
     """Given an object, return True if the object is callable.
     For classes, return True if instances would be callable."""
-    if not isinstance(obj, ClassTypes):
+    if not isinstance(obj, type):
         # already an instance
         return getattr(obj, '__call__', None) is not None
 
-    if six.PY3:
-        # *could* be broken by a class overriding __mro__ or __dict__ via
-        # a metaclass
-        for base in (obj,) + obj.__mro__:
-            if base.__dict__.get('__call__') is not None:
-                return True
-    else:
-        klass = obj
-        # uses __bases__ instead of __mro__ so that we work with old style classes
-        if klass.__dict__.get('__call__') is not None:
+    # *could* be broken by a class overriding __mro__ or __dict__ via
+    # a metaclass
+    for base in (obj,) + obj.__mro__:
+        if base.__dict__.get('__call__') is not None:
             return True
-
-        for base in klass.__bases__:
-            if _instance_callable(base):
-                return True
     return False
 
 
@@ -261,7 +173,7 @@
     # mock. It still does signature checking by calling a lambda with the same
     # signature as the original.
 
-    skipfirst = isinstance(original, ClassTypes)
+    skipfirst = isinstance(original, type)
     result = _get_signature_object(original, instance, skipfirst)
     if result is None:
         return mock
@@ -271,13 +183,13 @@
     _copy_func_details(func, checksig)
 
     name = original.__name__
-    if not _isidentifier(name):
+    if not name.isidentifier():
         name = 'funcopy'
     context = {'_checksig_': checksig, 'mock': mock}
     src = """def %s(*args, **kwargs):
     _checksig_(*args, **kwargs)
     return mock(*args, **kwargs)""" % name
-    six.exec_(src, context)
+    exec (src, context)
     funcopy = context[name]
     _setup_func(funcopy, mock, sig)
     return funcopy
@@ -286,14 +198,14 @@
 def _setup_func(funcopy, mock, sig):
     funcopy.mock = mock
 
+    def assert_called_with(*args, **kwargs):
+        return mock.assert_called_with(*args, **kwargs)
     def assert_called(*args, **kwargs):
         return mock.assert_called(*args, **kwargs)
     def assert_not_called(*args, **kwargs):
         return mock.assert_not_called(*args, **kwargs)
     def assert_called_once(*args, **kwargs):
         return mock.assert_called_once(*args, **kwargs)
-    def assert_called_with(*args, **kwargs):
-        return mock.assert_called_with(*args, **kwargs)
     def assert_called_once_with(*args, **kwargs):
         return mock.assert_called_once_with(*args, **kwargs)
     def assert_has_calls(*args, **kwargs):
@@ -332,6 +244,33 @@
     mock._mock_delegate = funcopy
 
 
+def _setup_async_mock(mock):
+    mock._is_coroutine = asyncio.coroutines._is_coroutine
+    mock.await_count = 0
+    mock.await_args = None
+    mock.await_args_list = _CallList()
+
+    # Mock is not configured yet so the attributes are set
+    # to a function and then the corresponding mock helper function
+    # is called when the helper is accessed similar to _setup_func.
+    def wrapper(attr, *args, **kwargs):
+        return getattr(mock.mock, attr)(*args, **kwargs)
+
+    for attribute in ('assert_awaited',
+                      'assert_awaited_once',
+                      'assert_awaited_with',
+                      'assert_awaited_once_with',
+                      'assert_any_await',
+                      'assert_has_awaits',
+                      'assert_not_awaited'):
+
+        # setattr(mock, attribute, wrapper) causes late binding
+        # hence attribute will always be the last value in the loop
+        # Use partial(wrapper, attribute) to ensure the attribute is bound
+        # correctly.
+        setattr(mock, attribute, partial(wrapper, attribute))
+
+
 def _is_magic(name):
     return '__%s__' % name[2:-2] == name
 
@@ -345,11 +284,7 @@
         return 'sentinel.%s' % self.name
 
     def __reduce__(self):
-        return _unpickle_sentinel, (self.name, )
-
-
-def _unpickle_sentinel(name):
-    return getattr(sentinel, name)
+        return 'sentinel.%s' % self.name
 
 
 class _Sentinel(object):
@@ -363,6 +298,9 @@
             raise AttributeError
         return self._sentinels.setdefault(name, _SentinelObject(name))
 
+    def __reduce__(self):
+        return 'sentinel'
+
 
 sentinel = _Sentinel()
 
@@ -371,15 +309,6 @@
 _deleted = sentinel.DELETED
 
 
-class OldStyleClass:
-    pass
-ClassType = type(OldStyleClass)
-
-
-ClassTypes = (type,)
-if six.PY2:
-    ClassTypes = (type, ClassType)
-
 _allowed_names = {
     'return_value', '_mock_return_value', 'side_effect',
     '_mock_side_effect', '_mock_parent', '_mock_new_parent',
@@ -427,13 +356,7 @@
 
 
 def _check_and_set_parent(parent, value, name, new_name):
-    # function passed to create_autospec will have mock
-    # attribute attached to which parent must be set
-    if isinstance(value, FunctionTypes):
-        try:
-            value = value.mock
-        except AttributeError:
-            pass
+    value = _extract_mock(value)
 
     if not _is_instance_mock(value):
         return False
@@ -480,8 +403,15 @@
         # every instance has its own class
         # so we can create magic methods on the
         # class without stomping on other mocks
-        new = type(cls.__name__, (cls,), {'__doc__': cls.__doc__})
-        instance = object.__new__(new)
+        bases = (cls,)
+        if not issubclass(cls, AsyncMockMixin):
+            # Check if spec is an async object or function
+            bound_args = _MOCK_SIG.bind_partial(cls, *args, **kw).arguments
+            spec_arg = bound_args.get('spec_set', bound_args.get('spec'))
+            if spec_arg and _is_async_obj(spec_arg):
+                bases = (AsyncMockMixin, cls)
+        new = type(cls.__name__, bases, {'__doc__': cls.__doc__})
+        instance = _safe_super(NonCallableMock, cls).__new__(new)
         return instance
 
 
@@ -535,10 +465,12 @@
         Attach a mock as an attribute of this one, replacing its name and
         parent. Calls to the attached mock will be recorded in the
         `method_calls` and `mock_calls` attributes of this one."""
-        mock._mock_parent = None
-        mock._mock_new_parent = None
-        mock._mock_name = ''
-        mock._mock_new_name = None
+        inner_mock = _extract_mock(mock)
+
+        inner_mock._mock_parent = None
+        inner_mock._mock_new_parent = None
+        inner_mock._mock_name = ''
+        inner_mock._mock_new_name = None
 
         setattr(self, attribute, mock)
 
@@ -556,9 +488,14 @@
                        _eat_self=False):
         _spec_class = None
         _spec_signature = None
+        _spec_asyncs = []
+
+        for attr in dir(spec):
+            if iscoroutinefunction(getattr(spec, attr, None)):
+                _spec_asyncs.append(attr)
 
         if spec is not None and not _is_list(spec):
-            if isinstance(spec, ClassTypes):
+            if isinstance(spec, type):
                 _spec_class = spec
             else:
                 _spec_class = type(spec)
@@ -573,7 +510,7 @@
         __dict__['_spec_set'] = spec_set
         __dict__['_spec_signature'] = _spec_signature
         __dict__['_mock_methods'] = spec
-
+        __dict__['_spec_asyncs'] = _spec_asyncs
 
     def __get_return_value(self):
         ret = self._mock_return_value
@@ -635,7 +572,7 @@
     side_effect = property(__get_side_effect, __set_side_effect)
 
 
-    def reset_mock(self,  visited=None, return_value=False, side_effect=False):
+    def reset_mock(self,  visited=None,*, return_value=False, side_effect=False):
         "Restore the mock object to its initial state."
         if visited is None:
             visited = []
@@ -658,7 +595,7 @@
         for child in self._mock_children.values():
             if isinstance(child, _SpecState) or child is _deleted:
                 continue
-            child.reset_mock(visited)
+            child.reset_mock(visited, return_value=return_value, side_effect=side_effect)
 
         ret = self._mock_return_value
         if _is_instance_mock(ret) and ret is not self:
@@ -688,7 +625,7 @@
 
 
     def __getattr__(self, name):
-        if name in ('_mock_methods', '_mock_unsafe'):
+        if name in {'_mock_methods', '_mock_unsafe'}:
             raise AttributeError(name)
         elif self._mock_methods is not None:
             if name not in self._mock_methods or name in _all_magics:
@@ -697,7 +634,8 @@
             raise AttributeError(name)
         if not self._mock_unsafe:
             if name.startswith(('assert', 'assret')):
-                raise AttributeError(name)
+                raise AttributeError("Attributes cannot start with 'assert' "
+                                     "or 'assret'")
 
         result = self._mock_children.get(name)
         if result is _deleted:
@@ -765,7 +703,7 @@
             if self._spec_set:
                 spec_string = ' spec_set=%r'
             spec_string = spec_string % self._spec_class.__name__
-        return "<{}{}{} id='{}'>".format(
+        return "<%s%s%s id='%s'>" % (
             type(self).__name__,
             name_string,
             spec_string,
@@ -775,8 +713,7 @@
 
     def __dir__(self):
         """Filter the output of `dir(mock)` to only useful members."""
-        if not mock.FILTER_DIR and getattr(object, '__dir__', None):
-            # object.__dir__ is not in 2.7
+        if not FILTER_DIR:
             return object.__dir__(self)
 
         extras = self._mock_methods or []
@@ -786,12 +723,9 @@
             m_name for m_name, m_value in self._mock_children.items()
             if m_value is not _deleted]
 
-        if mock.FILTER_DIR:
-            # object.__dir__ is not in 2.7
-            from_type = [e for e in from_type if not e.startswith('_')]
-            from_dict = [e for e in from_dict if not e.startswith('_') or
-                         _is_magic(e)]
-
+        from_type = [e for e in from_type if not e.startswith('_')]
+        from_dict = [e for e in from_dict if not e.startswith('_') or
+                     _is_magic(e)]
         return sorted(set(extras + from_type + from_dict + from_child_mocks))
 
 
@@ -828,8 +762,8 @@
                 self._mock_children[name] = value
 
         if self._mock_sealed and not hasattr(self, name):
-            mock_name = self._extract_mock_name()+'.'+name
-            raise AttributeError('Cannot set '+mock_name)
+            mock_name = f'{self._extract_mock_name()}.{name}'
+            raise AttributeError(f'Cannot set {mock_name}')
 
         return object.__setattr__(self, name, value)
 
@@ -857,12 +791,45 @@
         return _format_call_signature(name, args, kwargs)
 
 
-    def _format_mock_failure_message(self, args, kwargs):
-        message = 'expected call not found.\nExpected: %s\nActual: %s'
+    def _format_mock_failure_message(self, args, kwargs, action='call'):
+        message = 'expected %s not found.\nExpected: %s\nActual: %s'
         expected_string = self._format_mock_call_signature(args, kwargs)
         call_args = self.call_args
         actual_string = self._format_mock_call_signature(*call_args)
-        return message % (expected_string, actual_string)
+        return message % (action, expected_string, actual_string)
+
+
+    def _get_call_signature_from_name(self, name):
+        """
+        * If call objects are asserted against a method/function like obj.meth1
+        then there could be no name for the call object to lookup. Hence just
+        return the spec_signature of the method/function being asserted against.
+        * If the name is not empty then remove () and split by '.' to get
+        list of names to iterate through the children until a potential
+        match is found. A child mock is created only during attribute access
+        so if we get a _SpecState then no attributes of the spec were accessed
+        and can be safely exited.
+        """
+        if not name:
+            return self._spec_signature
+
+        sig = None
+        names = name.replace('()', '').split('.')
+        children = self._mock_children
+
+        for name in names:
+            child = children.get(name)
+            if child is None or isinstance(child, _SpecState):
+                break
+            else:
+                # If an autospecced object is attached using attach_mock the
+                # child would be a function with mock object as attribute from
+                # which signature has to be derived.
+                child = _extract_mock(child)
+                children = child._mock_children
+                sig = child._spec_signature
+
+        return sig
 
 
     def _call_matcher(self, _call):
@@ -872,7 +839,12 @@
         This is a best effort method which relies on the spec's signature,
         if available, or falls back on the arguments themselves.
         """
-        sig = self._spec_signature
+
+        if isinstance(_call, tuple) and len(_call) > 2:
+            sig = self._get_call_signature_from_name(_call[0])
+        else:
+            sig = self._spec_signature
+
         if sig is not None:
             if len(_call) == 2:
                 name = ''
@@ -880,10 +852,10 @@
             else:
                 name, args, kwargs = _call
             try:
-                return name, sig.bind(*args, **kwargs)
+                bound_call = sig.bind(*args, **kwargs)
+                return call(name, bound_call.args, bound_call.kwargs)
             except TypeError as e:
-                e.__traceback__ = None
-                return e
+                return e.with_traceback(None)
         else:
             return _call
 
@@ -904,7 +876,7 @@
         self = _mock_self
         if self.call_count == 0:
             msg = ("Expected '%s' to have been called." %
-                   self._mock_name or 'mock')
+                  (self._mock_name or 'mock'))
             raise AssertionError(msg)
 
     def assert_called_once(_mock_self):
@@ -919,7 +891,7 @@
             raise AssertionError(msg)
 
     def assert_called_with(_mock_self, *args, **kwargs):
-        """assert that the mock was called with the specified arguments.
+        """assert that the last call was made with the specified arguments.
 
         Raises an AssertionError if the args and keyword args passed in are
         different to the last call to the mock."""
@@ -928,20 +900,17 @@
             expected = self._format_mock_call_signature(args, kwargs)
             actual = 'not called.'
             error_message = ('expected call not found.\nExpected: %s\nActual: %s'
-                             % (expected, actual))
+                    % (expected, actual))
             raise AssertionError(error_message)
 
-        def _error_message(cause):
+        def _error_message():
             msg = self._format_mock_failure_message(args, kwargs)
-            if six.PY2 and cause is not None:
-                # Tack on some diagnostics for Python without __cause__
-                msg = '{}\n{}'.format(msg, str(cause))
             return msg
-        expected = self._call_matcher((args, kwargs))
+        expected = self._call_matcher(_Call((args, kwargs), two=True))
         actual = self._call_matcher(self.call_args)
-        if expected != actual:
+        if actual != expected:
             cause = expected if isinstance(expected, Exception) else None
-            six.raise_from(AssertionError(_error_message(cause)), cause)
+            raise AssertionError(_error_message()) from cause
 
 
     def assert_called_once_with(_mock_self, *args, **kwargs):
@@ -968,14 +937,22 @@
         If `any_order` is True then the calls can be in any order, but
         they must all appear in `mock_calls`."""
         expected = [self._call_matcher(c) for c in calls]
-        cause = expected if isinstance(expected, Exception) else None
+        cause = next((e for e in expected if isinstance(e, Exception)), None)
         all_calls = _CallList(self._call_matcher(c) for c in self.mock_calls)
         if not any_order:
             if expected not in all_calls:
-                six.raise_from(AssertionError(
-                    'Calls not found.\nExpected: %r%s'
-                    % (_CallList(calls), self._calls_repr(prefix="Actual"))
-                ), cause)
+                if cause is None:
+                    problem = 'Calls not found.'
+                else:
+                    problem = ('Error processing expected calls.\n'
+                               'Errors: {}').format(
+                                   [e if isinstance(e, Exception) else None
+                                    for e in expected])
+                raise AssertionError(
+                    f'{problem}\n'
+                    f'Expected: {_CallList(calls)}'
+                    f'{self._calls_repr(prefix="Actual").rstrip(".")}'
+                ) from cause
             return
 
         all_calls = list(all_calls)
@@ -987,11 +964,11 @@
             except ValueError:
                 not_found.append(kall)
         if not_found:
-            six.raise_from(AssertionError(
+            raise AssertionError(
                 '%r does not contain all of %r in its call list, '
                 'found %r instead' % (self._mock_name or 'mock',
                                       tuple(not_found), all_calls)
-            ), cause)
+            ) from cause
 
 
     def assert_any_call(self, *args, **kwargs):
@@ -1000,14 +977,14 @@
         The assert passes if the mock has *ever* been called, unlike
         `assert_called_with` and `assert_called_once_with` that only pass if
         the call is the most recent one."""
-        expected = self._call_matcher((args, kwargs))
+        expected = self._call_matcher(_Call((args, kwargs), two=True))
+        cause = expected if isinstance(expected, Exception) else None
         actual = [self._call_matcher(c) for c in self.call_args_list]
-        if expected not in actual:
-            cause = expected if isinstance(expected, Exception) else None
+        if cause or expected not in _AnyComparer(actual):
             expected_string = self._format_mock_call_signature(args, kwargs)
-            six.raise_from(AssertionError(
+            raise AssertionError(
                 '%s call not found' % expected_string
-            ), cause)
+            ) from cause
 
 
     def _get_child_mock(self, **kw):
@@ -1018,11 +995,25 @@
 
         For non-callable mocks the callable variant will be used (rather than
         any custom subclass)."""
+        _new_name = kw.get("_new_name")
+        if _new_name in self.__dict__['_spec_asyncs']:
+            return AsyncMock(**kw)
+
         _type = type(self)
-        if not issubclass(_type, CallableMixin):
+        if issubclass(_type, MagicMock) and _new_name in _async_method_magics:
+            # Any asynchronous magic becomes an AsyncMock
+            klass = AsyncMock
+        elif issubclass(_type, AsyncMockMixin):
+            if (_new_name in _all_sync_magics or
+                    self._mock_methods and _new_name in self._mock_methods):
+                # Any synchronous method on AsyncMock becomes a MagicMock
+                klass = MagicMock
+            else:
+                klass = AsyncMock
+        elif not issubclass(_type, CallableMixin):
             if issubclass(_type, NonCallableMagicMock):
                 klass = MagicMock
-            elif issubclass(_type, NonCallableMock) :
+            elif issubclass(_type, NonCallableMock):
                 klass = Mock
         else:
             klass = _type.__mro__[1]
@@ -1045,9 +1036,27 @@
         """
         if not self.mock_calls:
             return ""
-        return "\n"+prefix+": "+safe_repr(self.mock_calls)+"."
+        return f"\n{prefix}: {safe_repr(self.mock_calls)}."
 
 
+_MOCK_SIG = inspect.signature(NonCallableMock.__init__)
+
+
+class _AnyComparer(list):
+    """A list which checks if it contains a call which may have an
+    argument of ANY, flipping the components of item and self from
+    their traditional locations so that ANY is guaranteed to be on
+    the left."""
+    def __contains__(self, item):
+        for _call in self:
+            assert len(item) == len(_call)
+            if all([
+                expected == actual
+                for expected, actual in zip(item, _call)
+            ]):
+                return True
+        return False
+
 
 def _try_iter(obj):
     if obj is None:
@@ -1064,14 +1073,12 @@
         return obj
 
 
-
 class CallableMixin(Base):
 
     def __init__(self, spec=None, side_effect=None, return_value=DEFAULT,
                  wraps=None, name=None, spec_set=None, parent=None,
                  _spec_state=None, _new_name='', _new_parent=None, **kwargs):
         self.__dict__['_mock_return_value'] = return_value
-
         _safe_super(CallableMixin, self).__init__(
             spec, wraps, name, spec_set, parent,
             _spec_state, _new_name, _new_parent, **kwargs
@@ -1089,15 +1096,21 @@
         # can't use self in-case a function / method we are mocking uses self
         # in the signature
         _mock_self._mock_check_sig(*args, **kwargs)
+        _mock_self._increment_mock_call(*args, **kwargs)
         return _mock_self._mock_call(*args, **kwargs)
 
 
     def _mock_call(_mock_self, *args, **kwargs):
+        return _mock_self._execute_mock_call(*args, **kwargs)
+
+    def _increment_mock_call(_mock_self, *args, **kwargs):
         self = _mock_self
         self.called = True
         self.call_count += 1
 
         # handle call_args
+        # needs to be set here so assertions on call arguments pass before
+        # execution in the case of awaited calls
         _call = _Call((args, kwargs), two=True)
         self.call_args = _call
         self.call_args_list.append(_call)
@@ -1137,6 +1150,11 @@
             # follow the parental chain:
             _new_parent = _new_parent._mock_new_parent
 
+    def _execute_mock_call(_mock_self, *args, **kwargs):
+        self = _mock_self
+        # separate from _increment_mock_call so that awaited functions are
+        # executed separately from their call, also AsyncMock overrides this method
+
         effect = self.side_effect
         if effect is not None:
             if _is_exception(effect):
@@ -1186,9 +1204,6 @@
       arguments as the mock, and unless it returns `DEFAULT`, the return
       value of this function is used as the return value.
 
-      Alternatively `side_effect` can be an exception class or instance. In
-      this case the exception will be raised when the mock is called.
-
       If `side_effect` is an iterable then each call to the mock will return
       the next value from the iterable. If any of the members of the iterable
       are exceptions they will be raised instead of returned.
@@ -1216,7 +1231,6 @@
     """
 
 
-
 def _dot_lookup(thing, comp, import_path):
     try:
         return getattr(thing, comp)
@@ -1287,8 +1301,10 @@
 
 
     def __call__(self, func):
-        if isinstance(func, ClassTypes):
+        if isinstance(func, type):
             return self.decorate_class(func)
+        if inspect.iscoroutinefunction(func):
+            return self.decorate_async_callable(func)
         return self.decorate_callable(func)
 
 
@@ -1306,41 +1322,68 @@
         return klass
 
 
+    @contextlib.contextmanager
+    def decoration_helper(self, patched, args, keywargs):
+        extra_args = []
+        entered_patchers = []
+        patching = None
+
+        exc_info = tuple()
+        try:
+            for patching in patched.patchings:
+                arg = patching.__enter__()
+                entered_patchers.append(patching)
+                if patching.attribute_name is not None:
+                    keywargs.update(arg)
+                elif patching.new is DEFAULT:
+                    extra_args.append(arg)
+
+            args += tuple(extra_args)
+            yield (args, keywargs)
+        except:
+            if (patching not in entered_patchers and
+                _is_started(patching)):
+                # the patcher may have been started, but an exception
+                # raised whilst entering one of its additional_patchers
+                entered_patchers.append(patching)
+            # Pass the exception to __exit__
+            exc_info = sys.exc_info()
+            # re-raise the exception
+            raise
+        finally:
+            for patching in reversed(entered_patchers):
+                patching.__exit__(*exc_info)
+
+
     def decorate_callable(self, func):
+        # NB. Keep the method in sync with decorate_async_callable()
         if hasattr(func, 'patchings'):
             func.patchings.append(self)
             return func
 
         @wraps(func)
         def patched(*args, **keywargs):
-            extra_args = []
-            entered_patchers = []
+            with self.decoration_helper(patched,
+                                        args,
+                                        keywargs) as (newargs, newkeywargs):
+                return func(*newargs, **newkeywargs)
 
-            exc_info = tuple()
-            try:
-                for patching in patched.patchings:
-                    arg = patching.__enter__()
-                    entered_patchers.append(patching)
-                    if patching.attribute_name is not None:
-                        keywargs.update(arg)
-                    elif patching.new is DEFAULT:
-                        extra_args.append(arg)
+        patched.patchings = [self]
+        return patched
 
-                args += tuple(extra_args)
-                return func(*args, **keywargs)
-            except:
-                if (patching not in entered_patchers and
-                    _is_started(patching)):
-                    # the patcher may have been started, but an exception
-                    # raised whilst entering one of its additional_patchers
-                    entered_patchers.append(patching)
-                # Pass the exception to __exit__
-                exc_info = sys.exc_info()
-                # re-raise the exception
-                raise
-            finally:
-                for patching in reversed(entered_patchers):
-                    patching.__exit__(*exc_info)
+
+    def decorate_async_callable(self, func):
+        # NB. Keep the method in sync with decorate_callable()
+        if hasattr(func, 'patchings'):
+            func.patchings.append(self)
+            return func
+
+        @wraps(func)
+        async def patched(*args, **keywargs):
+            with self.decoration_helper(patched,
+                                        args,
+                                        keywargs) as (newargs, newkeywargs):
+                return await func(*newargs, **newkeywargs)
 
         patched.patchings = [self]
         return patched
@@ -1365,7 +1408,7 @@
 
         if not self.create and original is DEFAULT:
             raise AttributeError(
-                "{} does not have the attribute {!r}".format(target, name)
+                "%s does not have the attribute %r" % (target, name)
             )
         return original, local
 
@@ -1411,11 +1454,13 @@
             if spec is not None or spec_set is not None:
                 if original is DEFAULT:
                     raise TypeError("Can't use 'spec' with create=True")
-                if isinstance(original, ClassTypes):
+                if isinstance(original, type):
                     # If we're patching out a class and there is a spec
                     inherit = True
-
-            Klass = MagicMock
+            if spec is None and _is_async_obj(original):
+                Klass = AsyncMock
+            else:
+                Klass = MagicMock
             _kwargs = {}
             if new_callable is not None:
                 Klass = new_callable
@@ -1426,8 +1471,10 @@
                 if _is_list(this_spec):
                     not_callable = '__call__' not in this_spec
                 else:
-                    not_callable = not _callable(this_spec)
-                if not_callable:
+                    not_callable = not callable(this_spec)
+                if _is_async_obj(this_spec):
+                    Klass = AsyncMock
+                elif not_callable:
                     Klass = NonCallableMagicMock
 
             if spec is not None:
@@ -1567,6 +1614,10 @@
     When used as a class decorator `patch.object` honours `patch.TEST_PREFIX`
     for choosing which methods to wrap.
     """
+    if type(target) is str:
+        raise TypeError(
+            f"{target!r} must be the actual object to be patched, not a str"
+        )
     getter = lambda: target
     return _patch(
         getter, attribute, new, spec, create,
@@ -1596,7 +1647,7 @@
     When used as a class decorator `patch.multiple` honours `patch.TEST_PREFIX`
     for choosing which methods to wrap.
     """
-    if type(target) in (unicode, str):
+    if type(target) is str:
         getter = lambda: _importer(target)
     else:
         getter = lambda: target
@@ -1633,8 +1684,9 @@
     is patched with a `new` object. When the function/with statement exits
     the patch is undone.
 
-    If `new` is omitted, then the target is replaced with a
-    `MagicMock`. If `patch` is used as a decorator and `new` is
+    If `new` is omitted, then the target is replaced with an
+    `AsyncMock if the patched object is an async function or a
+    `MagicMock` otherwise. If `patch` is used as a decorator and `new` is
     omitted, the created mock is passed in as an extra argument to the
     decorated function. If `patch` is used as a context manager the created
     mock is returned by the context manager.
@@ -1652,8 +1704,8 @@
     patch to pass in the object being mocked as the spec/spec_set object.
 
     `new_callable` allows you to specify a different class, or callable object,
-    that will be called to create the `new` object. By default `MagicMock` is
-    used.
+    that will be called to create the `new` object. By default `AsyncMock` is
+    used for async functions and `MagicMock` for the rest.
 
     A more powerful form of `spec` is `autospec`. If you set `autospec=True`
     then the mock will be created with a spec from the object being replaced.
@@ -1687,7 +1739,8 @@
     "as"; very useful if `patch` is creating a mock object for you.
 
     `patch` takes arbitrary keyword arguments. These will be passed to
-    the `Mock` (or `new_callable`) on construction.
+    `AsyncMock` if the patched object is asynchronous, to `MagicMock`
+    otherwise or to `new_callable` if specified.
 
     `patch.dict(...)`, `patch.multiple(...)` and `patch.object(...)` are
     available for alternate use-cases.
@@ -1738,7 +1791,7 @@
 
 
     def __call__(self, f):
-        if isinstance(f, ClassTypes):
+        if isinstance(f, type):
             return self.decorate_class(f)
         @wraps(f)
         def _inner(*args, **kw):
@@ -1765,11 +1818,12 @@
     def __enter__(self):
         """Patch the dict."""
         self._patch_dict()
+        return self.in_dict
 
 
     def _patch_dict(self):
         values = self.values
-        if isinstance(self.in_dict, basestring):
+        if isinstance(self.in_dict, str):
             self.in_dict = _importer(self.in_dict)
         in_dict = self.in_dict
         clear = self.clear
@@ -1810,11 +1864,27 @@
 
     def __exit__(self, *args):
         """Unpatch the dict."""
-        self._unpatch_dict()
+        if self._original is not None:
+            self._unpatch_dict()
         return False
 
-    start = __enter__
-    stop = __exit__
+
+    def start(self):
+        """Activate a patch, returning any created mock."""
+        result = self.__enter__()
+        _patch._active_patches.append(self)
+        return result
+
+
+    def stop(self):
+        """Stop an active patch."""
+        try:
+            _patch._active_patches.remove(self)
+        except ValueError:
+            # If the patch hasn't been started this will fail
+            pass
+
+        return self.__exit__()
 
 
 def _clear_dict(in_dict):
@@ -1849,29 +1919,26 @@
     "divmod rdivmod neg pos abs invert "
     "complex int float index "
     "round trunc floor ceil "
+    "bool next "
+    "fspath "
+    "aiter "
 )
 
+if IS_PYPY:
+    # PyPy has no __sizeof__: http://doc.pypy.org/en/latest/cpython_differences.html
+    magic_methods = magic_methods.replace('sizeof ', '')
+
 numerics = (
-    "add sub mul matmul div floordiv mod lshift rshift and xor or pow"
+    "add sub mul matmul div floordiv mod lshift rshift and xor or pow truediv"
 )
-if six.PY3:
-    numerics += ' truediv'
 inplace = ' '.join('i%s' % n for n in numerics.split())
 right = ' '.join('r%s' % n for n in numerics.split())
-extra = ''
-if six.PY3:
-    extra = 'bool next '
-    if sys.version_info >= (3, 6):
-        extra += 'fspath '
-else:
-    extra = 'unicode long nonzero oct hex truediv rtruediv '
 
 # not including __prepare__, __instancecheck__, __subclasscheck__
 # (as they are metaclass methods)
 # __del__ is not supported at all as it causes problems if it exists
 
 _non_defaults = {
-    '__cmp__', '__getslice__', '__setslice__', '__coerce__', # <3.x
     '__get__', '__set__', '__delete__', '__reversed__', '__missing__',
     '__reduce__', '__reduce_ex__', '__getinitargs__', '__getnewargs__',
     '__getstate__', '__setstate__', '__getformat__', '__setformat__',
@@ -1890,10 +1957,17 @@
 
 _magics = {
     '__%s__' % method for method in
-    ' '.join([magic_methods, numerics, inplace, right, extra]).split()
+    ' '.join([magic_methods, numerics, inplace, right]).split()
 }
 
-_all_magics = _magics | _non_defaults
+# Magic methods used for async `with` statements
+_async_method_magics = {"__aenter__", "__aexit__", "__anext__"}
+# Magic methods that are only used with async calls but are synchronous functions themselves
+_sync_async_magics = {"__aiter__"}
+_async_magics = _async_method_magics | _sync_async_magics
+
+_all_sync_magics = _magics | _non_defaults
+_all_magics = _all_sync_magics | _async_magics
 
 _unsupported_magics = {
     '__getattr__', '__setattr__',
@@ -1906,8 +1980,7 @@
     '__hash__': lambda self: object.__hash__(self),
     '__str__': lambda self: object.__str__(self),
     '__sizeof__': lambda self: object.__sizeof__(self),
-    '__unicode__': lambda self: unicode(object.__str__(self)),
-    '__fspath__': lambda self: type(self).__name__+'/'+self._extract_mock_name()+'/'+str(id(self)),
+    '__fspath__': lambda self: f"{type(self).__name__}/{self._extract_mock_name()}/{id(self)}",
 }
 
 _return_values = {
@@ -1922,11 +1995,8 @@
     '__complex__': 1j,
     '__float__': 1.0,
     '__bool__': True,
-    '__nonzero__': True,
-    '__oct__': '1',
-    '__hex__': '0x1',
-    '__long__': long(1),
     '__index__': 1,
+    '__aexit__': False,
 }
 
 
@@ -1959,29 +2029,38 @@
         return iter(ret_val)
     return __iter__
 
+def _get_async_iter(self):
+    def __aiter__():
+        ret_val = self.__aiter__._mock_return_value
+        if ret_val is DEFAULT:
+            return _AsyncIterator(iter([]))
+        return _AsyncIterator(iter(ret_val))
+    return __aiter__
+
 _side_effect_methods = {
     '__eq__': _get_eq,
     '__ne__': _get_ne,
     '__iter__': _get_iter,
+    '__aiter__': _get_async_iter
 }
 
 
 
 def _set_return_value(mock, method, name):
+    # If _mock_wraps is present then attach it so that wrapped object
+    # is used for return value is used when called.
+    if mock._mock_wraps is not None:
+        method._mock_wraps = getattr(mock._mock_wraps, name)
+        return
+
     fixed = _return_values.get(name, DEFAULT)
     if fixed is not DEFAULT:
         method.return_value = fixed
         return
 
-    return_calulator = _calculate_return_value.get(name)
-    if return_calulator is not None:
-        try:
-            return_value = return_calulator(mock)
-        except AttributeError:
-            # XXXX why do we return AttributeError here?
-            #      set it as a side_effect instead?
-            # Answer: it makes magic mocks work on pypy?!
-            return_value = AttributeError(name)
+    return_calculator = _calculate_return_value.get(name)
+    if return_calculator is not None:
+        return_value = return_calculator(mock)
         method.return_value = return_value
         return
 
@@ -1991,7 +2070,7 @@
 
 
 
-class MagicMixin(object):
+class MagicMixin(Base):
     def __init__(self, *args, **kw):
         self._mock_set_magics()  # make magic work for kwargs in init
         _safe_super(MagicMixin, self).__init__(*args, **kw)
@@ -1999,13 +2078,14 @@
 
 
     def _mock_set_magics(self):
-        these_magics = _magics
+        orig_magics = _magics | _async_method_magics
+        these_magics = orig_magics
 
         if getattr(self, "_mock_methods", None) is not None:
-            these_magics = _magics.intersection(self._mock_methods)
+            these_magics = orig_magics.intersection(self._mock_methods)
 
             remove_magics = set()
-            remove_magics = _magics - these_magics
+            remove_magics = orig_magics - these_magics
 
             for entry in remove_magics:
                 if entry in type(self).__dict__:
@@ -2033,6 +2113,12 @@
         self._mock_set_magics()
 
 
+class AsyncMagicMixin(MagicMixin):
+    def __init__(self, *args, **kw):
+        self._mock_set_magics()  # make magic work for kwargs in init
+        _safe_super(AsyncMagicMixin, self).__init__(*args, **kw)
+        self._mock_set_magics()  # fix magic broken by upper level init
+
 
 class MagicMock(MagicMixin, Mock):
     """
@@ -2056,7 +2142,7 @@
 
 
 
-class MagicProxy(object):
+class MagicProxy(Base):
     def __init__(self, name, parent):
         self.name = name
         self.parent = parent
@@ -2074,6 +2160,239 @@
         return self.create_mock()
 
 
+class AsyncMockMixin(Base):
+    await_count = _delegating_property('await_count')
+    await_args = _delegating_property('await_args')
+    await_args_list = _delegating_property('await_args_list')
+
+    def __init__(self, *args, **kwargs):
+        super().__init__(*args, **kwargs)
+        # iscoroutinefunction() checks _is_coroutine property to say if an
+        # object is a coroutine. Without this check it looks to see if it is a
+        # function/method, which in this case it is not (since it is an
+        # AsyncMock).
+        # It is set through __dict__ because when spec_set is True, this
+        # attribute is likely undefined.
+        self.__dict__['_is_coroutine'] = asyncio.coroutines._is_coroutine
+        self.__dict__['_mock_await_count'] = 0
+        self.__dict__['_mock_await_args'] = None
+        self.__dict__['_mock_await_args_list'] = _CallList()
+        code_mock = NonCallableMock(spec_set=CodeType)
+        code_mock.co_flags = inspect.CO_COROUTINE
+        self.__dict__['__code__'] = code_mock
+
+    async def _execute_mock_call(_mock_self, *args, **kwargs):
+        self = _mock_self
+        # This is nearly just like super(), except for special handling
+        # of coroutines
+
+        _call = _Call((args, kwargs), two=True)
+        self.await_count += 1
+        self.await_args = _call
+        self.await_args_list.append(_call)
+
+        effect = self.side_effect
+        if effect is not None:
+            if _is_exception(effect):
+                raise effect
+            elif not _callable(effect):
+                try:
+                    result = next(effect)
+                except StopIteration:
+                    # It is impossible to propogate a StopIteration
+                    # through coroutines because of PEP 479
+                    raise StopAsyncIteration
+                if _is_exception(result):
+                    raise result
+            elif iscoroutinefunction(effect):
+                result = await effect(*args, **kwargs)
+            else:
+                result = effect(*args, **kwargs)
+
+            if result is not DEFAULT:
+                return result
+
+        if self._mock_return_value is not DEFAULT:
+            return self.return_value
+
+        if self._mock_wraps is not None:
+            if iscoroutinefunction(self._mock_wraps):
+                return await self._mock_wraps(*args, **kwargs)
+            return self._mock_wraps(*args, **kwargs)
+
+        return self.return_value
+
+    def assert_awaited(_mock_self):
+        """
+        Assert that the mock was awaited at least once.
+        """
+        self = _mock_self
+        if self.await_count == 0:
+            msg = f"Expected {self._mock_name or 'mock'} to have been awaited."
+            raise AssertionError(msg)
+
+    def assert_awaited_once(_mock_self):
+        """
+        Assert that the mock was awaited exactly once.
+        """
+        self = _mock_self
+        if not self.await_count == 1:
+            msg = (f"Expected {self._mock_name or 'mock'} to have been awaited once."
+                   f" Awaited {self.await_count} times.")
+            raise AssertionError(msg)
+
+    def assert_awaited_with(_mock_self, *args, **kwargs):
+        """
+        Assert that the last await was with the specified arguments.
+        """
+        self = _mock_self
+        if self.await_args is None:
+            expected = self._format_mock_call_signature(args, kwargs)
+            raise AssertionError(f'Expected await: {expected}\nNot awaited')
+
+        def _error_message():
+            msg = self._format_mock_failure_message(args, kwargs, action='await')
+            return msg
+
+        expected = self._call_matcher(_Call((args, kwargs), two=True))
+        actual = self._call_matcher(self.await_args)
+        if actual != expected:
+            cause = expected if isinstance(expected, Exception) else None
+            raise AssertionError(_error_message()) from cause
+
+    def assert_awaited_once_with(_mock_self, *args, **kwargs):
+        """
+        Assert that the mock was awaited exactly once and with the specified
+        arguments.
+        """
+        self = _mock_self
+        if not self.await_count == 1:
+            msg = (f"Expected {self._mock_name or 'mock'} to have been awaited once."
+                   f" Awaited {self.await_count} times.")
+            raise AssertionError(msg)
+        return self.assert_awaited_with(*args, **kwargs)
+
+    def assert_any_await(_mock_self, *args, **kwargs):
+        """
+        Assert the mock has ever been awaited with the specified arguments.
+        """
+        self = _mock_self
+        expected = self._call_matcher(_Call((args, kwargs), two=True))
+        cause = expected if isinstance(expected, Exception) else None
+        actual = [self._call_matcher(c) for c in self.await_args_list]
+        if cause or expected not in _AnyComparer(actual):
+            expected_string = self._format_mock_call_signature(args, kwargs)
+            raise AssertionError(
+                '%s await not found' % expected_string
+            ) from cause
+
+    def assert_has_awaits(_mock_self, calls, any_order=False):
+        """
+        Assert the mock has been awaited with the specified calls.
+        The :attr:`await_args_list` list is checked for the awaits.
+
+        If `any_order` is False (the default) then the awaits must be
+        sequential. There can be extra calls before or after the
+        specified awaits.
+
+        If `any_order` is True then the awaits can be in any order, but
+        they must all appear in :attr:`await_args_list`.
+        """
+        self = _mock_self
+        expected = [self._call_matcher(c) for c in calls]
+        cause = cause = next((e for e in expected if isinstance(e, Exception)), None)
+        all_awaits = _CallList(self._call_matcher(c) for c in self.await_args_list)
+        if not any_order:
+            if expected not in all_awaits:
+                if cause is None:
+                    problem = 'Awaits not found.'
+                else:
+                    problem = ('Error processing expected awaits.\n'
+                               'Errors: {}').format(
+                                   [e if isinstance(e, Exception) else None
+                                    for e in expected])
+                raise AssertionError(
+                    f'{problem}\n'
+                    f'Expected: {_CallList(calls)}\n'
+                    f'Actual: {self.await_args_list}'
+                ) from cause
+            return
+
+        all_awaits = list(all_awaits)
+
+        not_found = []
+        for kall in expected:
+            try:
+                all_awaits.remove(kall)
+            except ValueError:
+                not_found.append(kall)
+        if not_found:
+            raise AssertionError(
+                '%r not all found in await list' % (tuple(not_found),)
+            ) from cause
+
+    def assert_not_awaited(_mock_self):
+        """
+        Assert that the mock was never awaited.
+        """
+        self = _mock_self
+        if self.await_count != 0:
+            msg = (f"Expected {self._mock_name or 'mock'} to not have been awaited."
+                   f" Awaited {self.await_count} times.")
+            raise AssertionError(msg)
+
+    def reset_mock(self, *args, **kwargs):
+        """
+        See :func:`.Mock.reset_mock()`
+        """
+        super().reset_mock(*args, **kwargs)
+        self.await_count = 0
+        self.await_args = None
+        self.await_args_list = _CallList()
+
+
+class AsyncMock(AsyncMockMixin, AsyncMagicMixin, Mock):
+    """
+    Enhance :class:`Mock` with features allowing to mock
+    an async function.
+
+    The :class:`AsyncMock` object will behave so the object is
+    recognized as an async function, and the result of a call is an awaitable:
+
+    >>> mock = AsyncMock()
+    >>> iscoroutinefunction(mock)
+    True
+    >>> inspect.isawaitable(mock())
+    True
+
+
+    The result of ``mock()`` is an async function which will have the outcome
+    of ``side_effect`` or ``return_value``:
+
+    - if ``side_effect`` is a function, the async function will return the
+      result of that function,
+    - if ``side_effect`` is an exception, the async function will raise the
+      exception,
+    - if ``side_effect`` is an iterable, the async function will return the
+      next value of the iterable, however, if the sequence of result is
+      exhausted, ``StopIteration`` is raised immediately,
+    - if ``side_effect`` is not defined, the async function will return the
+      value defined by ``return_value``, hence, by default, the async function
+      returns a new :class:`AsyncMock` object.
+
+    If the outcome of ``side_effect`` or ``return_value`` is an async function,
+    the mock async function obtained when the mock object is called will be this
+    async function itself (and not an async function returning an async
+    function).
+
+    The test author can also specify a wrapped object with ``wraps``. In this
+    case, the :class:`Mock` object behavior is the same as with an
+    :class:`.Mock` object: the wrapped object may have methods
+    defined as async function functions.
+
+    Based on Martin Richard's asynctest project.
+    """
+
 
 class _ANY(object):
     "A helper object that compares equal to everything."
@@ -2087,8 +2406,6 @@
     def __repr__(self):
         return '<ANY>'
 
-    __hash__ = None
-
 ANY = _ANY()
 
 
@@ -2097,15 +2414,8 @@
     message = '%s(%%s)' % name
     formatted_args = ''
     args_string = ', '.join([repr(arg) for arg in args])
-
-    def encode_item(item):
-        if six.PY2 and isinstance(item, unicode):
-            return item.encode("utf-8")
-        else:
-            return item
-
     kwargs_string = ', '.join([
-        '{}={!r}'.format(encode_item(key), value) for key, value in sorted(kwargs.items())
+        '%s=%r' % (key, value) for key, value in kwargs.items()
     ])
     if args_string:
         formatted_args = args_string
@@ -2146,7 +2456,7 @@
             name, args, kwargs = value
         elif _len == 2:
             first, second = value
-            if isinstance(first, basestring):
+            if isinstance(first, str):
                 name = first
                 if isinstance(second, tuple):
                     args = second
@@ -2156,7 +2466,7 @@
                 args, kwargs = first, second
         elif _len == 1:
             value, = value
-            if isinstance(value, basestring):
+            if isinstance(value, str):
                 name = value
             elif isinstance(value, tuple):
                 args = value
@@ -2177,12 +2487,10 @@
 
 
     def __eq__(self, other):
-        if other is ANY:
-            return True
         try:
             len_other = len(other)
         except TypeError:
-            return False
+            return NotImplemented
 
         self_name = ''
         if len(self) == 2:
@@ -2204,7 +2512,7 @@
             if isinstance(value, tuple):
                 other_args = value
                 other_kwargs = {}
-            elif isinstance(value, basestring):
+            elif isinstance(value, str):
                 other_name = value
                 other_args, other_kwargs = (), {}
             else:
@@ -2213,7 +2521,7 @@
         elif len_other == 2:
             # could be (name, args) or (name, kwargs) or (args, kwargs)
             first, second = other
-            if isinstance(first, basestring):
+            if isinstance(first, str):
                 other_name = first
                 if isinstance(second, tuple):
                     other_args, other_kwargs = second, {}
@@ -2231,10 +2539,8 @@
         return (other_args, other_kwargs) == (self_args, self_kwargs)
 
 
-    def __ne__(self, other):
-        return not self.__eq__(other)
+    __ne__ = object.__ne__
 
-    __hash__ = None
 
     def __call__(self, *args, **kwargs):
         if self._mock_name is None:
@@ -2247,15 +2553,15 @@
     def __getattr__(self, attr):
         if self._mock_name is None:
             return _Call(name=attr, from_kall=False)
-        name = '{}.{}'.format(self._mock_name, attr)
+        name = '%s.%s' % (self._mock_name, attr)
         return _Call(name=name, parent=self, from_kall=False)
 
 
-    def count(self, *args, **kwargs):
-        return self.__getattr__('count')(*args, **kwargs)
+    def __getattribute__(self, attr):
+        if attr in tuple.__dict__:
+            raise AttributeError
+        return tuple.__getattribute__(self, attr)
 
-    def index(self, *args, **kwargs):
-        return self.__getattr__('index')(*args, **kwargs)
 
     def _get_call_arguments(self):
         if len(self) == 2:
@@ -2310,7 +2616,6 @@
 call = _Call(from_kall=False)
 
 
-
 def create_autospec(spec, spec_set=False, instance=False, _parent=None,
                     _name=None, **kwargs):
     """Create a mock object using another object as a spec. Attributes on the
@@ -2335,8 +2640,8 @@
         # interpreted as a list of strings
         spec = type(spec)
 
-    is_type = isinstance(spec, ClassTypes)
-
+    is_type = isinstance(spec, type)
+    is_async_func = _is_async_func(spec)
     _kwargs = {'spec': spec}
     if spec_set:
         _kwargs = {'spec_set': spec}
@@ -2353,6 +2658,11 @@
         # descriptors don't have a spec
         # because we don't know what type they return
         _kwargs = {}
+    elif is_async_func:
+        if instance:
+            raise RuntimeError("Instance can not be True when create_autospec "
+                               "is mocking an async function")
+        Klass = AsyncMock
     elif not _callable(spec):
         Klass = NonCallableMagicMock
     elif is_type and instance and not _instance_callable(spec):
@@ -2372,6 +2682,8 @@
         # should only happen at the top level because we don't
         # recurse for functions
         mock = _set_signature(mock, spec)
+        if is_async_func:
+            _setup_async_mock(mock)
     else:
         _check_signature(spec, mock, is_type, instance)
 
@@ -2383,12 +2695,6 @@
                                             _name='()', _parent=mock)
 
     for entry in dir(spec):
-
-        # This are __ and so treated as magic on Py3, on Py2 we need to
-        # explicitly ignore them:
-        if six.PY2 and (entry.startswith('im_') or entry.startswith('func_')):
-            continue
-
         if _is_magic(entry):
             # MagicMock already does the useful magic methods for us
             continue
@@ -2421,9 +2727,13 @@
 
             skipfirst = _must_skip(spec, entry, is_type)
             kwargs['_eat_self'] = skipfirst
-            new = MagicMock(parent=parent, name=entry, _new_name=entry,
-                            _new_parent=parent,
-                            **kwargs)
+            if iscoroutinefunction(original):
+                child_klass = AsyncMock
+            else:
+                child_klass = MagicMock
+            new = child_klass(parent=parent, name=entry, _new_name=entry,
+                              _new_parent=parent,
+                              **kwargs)
             mock._mock_children[entry] = new
             _check_signature(original, new, skipfirst=skipfirst)
 
@@ -2442,14 +2752,11 @@
     Return whether we should skip the first argument on spec's `entry`
     attribute.
     """
-    if not isinstance(spec, ClassTypes):
+    if not isinstance(spec, type):
         if entry in getattr(spec, '__dict__', {}):
             # instance attribute - shouldn't skip
             return False
         spec = spec.__class__
-    if not hasattr(spec, '__mro__'):
-        # old style class: can't have descriptors anyway
-        return is_type
 
     for klass in spec.__mro__:
         result = klass.__dict__.get(entry, DEFAULT)
@@ -2457,7 +2764,7 @@
             continue
         if isinstance(result, (staticmethod, classmethod)):
             return False
-        elif isinstance(getattr(result, '__get__', None), MethodWrapperTypes):
+        elif isinstance(result, FunctionTypes):
             # Normal method => skip if looked up on type
             # (if looked up on instance, self is already skipped)
             return is_type
@@ -2487,10 +2794,6 @@
     type(ANY.__eq__),
 )
 
-MethodWrapperTypes = (
-    type(ANY.__eq__.__get__),
-)
-
 
 file_spec = None
 
@@ -2527,9 +2830,8 @@
             return handle.read.return_value
         return _state[0].read(*args, **kwargs)
 
-    def  _readline_side_effect(*args, **kwargs):
-        for item in _iter_side_effect():
-            yield item
+    def _readline_side_effect(*args, **kwargs):
+        yield from _iter_side_effect()
         while True:
             yield _state[0].readline(*args, **kwargs)
 
@@ -2540,14 +2842,15 @@
         for line in _state[0]:
             yield line
 
+    def _next_side_effect():
+        if handle.readline.return_value is not None:
+            return handle.readline.return_value
+        return next(_state[0])
+
     global file_spec
     if file_spec is None:
-        # set on first use
-        if six.PY3:
-            import _io
-            file_spec = list(set(dir(_io.TextIOWrapper)).union(set(dir(_io.BytesIO))))
-        else:
-            file_spec = file
+        import _io
+        file_spec = list(set(dir(_io.TextIOWrapper)).union(set(dir(_io.BytesIO))))
 
     if mock is None:
         mock = MagicMock(name='open', spec=open)
@@ -2565,6 +2868,7 @@
     handle.readline.side_effect = _state[1]
     handle.readlines.side_effect = _readlines_side_effect
     handle.__iter__.side_effect = _iter_side_effect
+    handle.__next__.side_effect = _next_side_effect
 
     def reset_data(*args, **kwargs):
         _state[0] = _to_stream(read_data)
@@ -2591,7 +2895,7 @@
     def _get_child_mock(self, **kwargs):
         return MagicMock(**kwargs)
 
-    def __get__(self, obj, obj_type):
+    def __get__(self, obj, obj_type=None):
         return self()
     def __set__(self, obj, val):
         self(val)
@@ -2617,3 +2921,21 @@
             continue
         if m._mock_new_parent is mock:
             seal(m)
+
+
+class _AsyncIterator:
+    """
+    Wraps an iterator in an asynchronous iterator.
+    """
+    def __init__(self, iterator):
+        self.iterator = iterator
+        code_mock = NonCallableMock(spec_set=CodeType)
+        code_mock.co_flags = inspect.CO_ITERABLE_COROUTINE
+        self.__dict__['__code__'] = code_mock
+
+    async def __anext__(self):
+        try:
+            return next(self.iterator)
+        except StopIteration:
+            pass
+        raise StopAsyncIteration
diff --git a/mock/tests/__init__.py b/mock/tests/__init__.py
index 54ddf2e..e69de29 100644
--- a/mock/tests/__init__.py
+++ b/mock/tests/__init__.py
@@ -1,3 +0,0 @@
-# Copyright (C) 2007-2012 Michael Foord & the mock team
-# E-mail: fuzzyman AT voidspace DOT org DOT uk
-# http://www.voidspace.org.uk/python/mock/
diff --git a/mock/tests/__main__.py b/mock/tests/__main__.py
deleted file mode 100644
index 45c633a..0000000
--- a/mock/tests/__main__.py
+++ /dev/null
@@ -1,18 +0,0 @@
-import os
-import unittest
-
-
-def load_tests(loader, standard_tests, pattern):
-    # top level directory cached on loader instance
-    this_dir = os.path.dirname(__file__)
-    pattern = pattern or "test*.py"
-    # We are inside unittest.test.testmock, so the top-level is three notches up
-    top_level_dir = os.path.dirname(os.path.dirname(os.path.dirname(this_dir)))
-    package_tests = loader.discover(start_dir=this_dir, pattern=pattern,
-                                    top_level_dir=top_level_dir)
-    standard_tests.addTests(package_tests)
-    return standard_tests
-
-
-if __name__ == '__main__':
-    unittest.main()
diff --git a/mock/tests/conftest.py b/mock/tests/conftest.py
deleted file mode 100644
index 78831f6..0000000
--- a/mock/tests/conftest.py
+++ /dev/null
@@ -1,6 +0,0 @@
-import six
-
-
-def pytest_ignore_collect(path):
-    if 'py3' in path.basename and six.PY2:
-        return True
diff --git a/mock/tests/support.py b/mock/tests/support.py
index d57a372..85fd0a3 100644
--- a/mock/tests/support.py
+++ b/mock/tests/support.py
@@ -1,7 +1,6 @@
 import contextlib
 import sys
 
-
 target = {'foo': 'FOO'}
 
 
@@ -29,9 +28,7 @@
 
     """
     for name in names:
-        if name in ('sys', 'marshal', 'imp'):
-            raise ValueError(
-                "cannot uncache {0}".format(name))
+        assert name not in ('sys', 'marshal', 'imp')
         try:
             del sys.modules[name]
         except KeyError:
@@ -40,7 +37,16 @@
         yield
     finally:
         for name in names:
-            try:
-                del sys.modules[name]
-            except KeyError:
-                pass
+            del sys.modules[name]
+
+
+class _ALWAYS_EQ:
+    """
+    Object that is equal to anything.
+    """
+    def __eq__(self, other):
+        return True
+    def __ne__(self, other):
+        return False
+
+ALWAYS_EQ = _ALWAYS_EQ()
diff --git a/mock/tests/testasync.py b/mock/tests/testasync.py
new file mode 100644
index 0000000..9fd2b65
--- /dev/null
+++ b/mock/tests/testasync.py
@@ -0,0 +1,1074 @@
+
+import asyncio
+import gc
+import inspect
+import re
+import unittest
+from contextlib import contextmanager
+
+from mock import (ANY, call, AsyncMock, patch, MagicMock, Mock,
+                  create_autospec, sentinel)
+from mock.backports import IsolatedAsyncioTestCase, iscoroutinefunction
+from mock.mock import _CallList
+
+
+try:
+    from asyncio import run
+except ImportError:
+    def run(main):
+        loop = asyncio.new_event_loop()
+        try:
+            return_value = loop.run_until_complete(main)
+        finally:
+            loop.close()
+        return return_value
+
+
+def tearDownModule():
+    asyncio.set_event_loop_policy(None)
+
+
+class AsyncClass:
+    def __init__(self): pass
+    async def async_method(self): pass
+    def normal_method(self): pass
+
+    @classmethod
+    async def async_class_method(cls): pass
+
+    @staticmethod
+    async def async_static_method(): pass
+
+
+class AwaitableClass:
+    def __await__(self): yield
+
+async def async_func(): pass
+
+async def async_func_args(a, b, *, c): pass
+
+def normal_func(): pass
+
+class NormalClass(object):
+    def a(self): pass
+
+
+async_foo_name = f'{__name__}.AsyncClass'
+normal_foo_name = f'{__name__}.NormalClass'
+
+
+@contextmanager
+def assertNeverAwaited(test):
+    with test.assertWarnsRegex(RuntimeWarning, "was never awaited$"):
+        yield
+        # In non-CPython implementations of Python, this is needed because timely
+        # deallocation is not guaranteed by the garbage collector.
+        gc.collect()
+
+
+class AsyncPatchDecoratorTest(unittest.TestCase):
+    def test_is_coroutine_function_patch(self):
+        @patch.object(AsyncClass, 'async_method')
+        def test_async(mock_method):
+            self.assertTrue(iscoroutinefunction(mock_method))
+        test_async()
+
+    def test_is_async_patch(self):
+        @patch.object(AsyncClass, 'async_method')
+        def test_async(mock_method):
+            m = mock_method()
+            self.assertTrue(inspect.isawaitable(m))
+            run(m)
+
+        @patch(f'{async_foo_name}.async_method')
+        def test_no_parent_attribute(mock_method):
+            m = mock_method()
+            self.assertTrue(inspect.isawaitable(m))
+            run(m)
+
+        test_async()
+        test_no_parent_attribute()
+
+    def test_is_AsyncMock_patch(self):
+        @patch.object(AsyncClass, 'async_method')
+        def test_async(mock_method):
+            self.assertIsInstance(mock_method, AsyncMock)
+
+        test_async()
+
+    def test_is_AsyncMock_patch_staticmethod(self):
+        @patch.object(AsyncClass, 'async_static_method')
+        def test_async(mock_method):
+            self.assertIsInstance(mock_method, AsyncMock)
+
+        test_async()
+
+    def test_is_AsyncMock_patch_classmethod(self):
+        @patch.object(AsyncClass, 'async_class_method')
+        def test_async(mock_method):
+            self.assertIsInstance(mock_method, AsyncMock)
+
+        test_async()
+
+    def test_async_def_patch(self):
+        @patch(f"{__name__}.async_func", return_value=1)
+        @patch(f"{__name__}.async_func_args", return_value=2)
+        async def test_async(func_args_mock, func_mock):
+            self.assertEqual(func_args_mock._mock_name, "async_func_args")
+            self.assertEqual(func_mock._mock_name, "async_func")
+
+            self.assertIsInstance(async_func, AsyncMock)
+            self.assertIsInstance(async_func_args, AsyncMock)
+
+            self.assertEqual(await async_func(), 1)
+            self.assertEqual(await async_func_args(1, 2, c=3), 2)
+
+        run(test_async())
+        self.assertTrue(inspect.iscoroutinefunction(async_func))
+
+
+class AsyncPatchCMTest(unittest.TestCase):
+    def test_is_async_function_cm(self):
+        def test_async():
+            with patch.object(AsyncClass, 'async_method') as mock_method:
+                self.assertTrue(iscoroutinefunction(mock_method))
+
+        test_async()
+
+    def test_is_async_cm(self):
+        def test_async():
+            with patch.object(AsyncClass, 'async_method') as mock_method:
+                m = mock_method()
+                self.assertTrue(inspect.isawaitable(m))
+                run(m)
+
+        test_async()
+
+    def test_is_AsyncMock_cm(self):
+        def test_async():
+            with patch.object(AsyncClass, 'async_method') as mock_method:
+                self.assertIsInstance(mock_method, AsyncMock)
+
+        test_async()
+
+    def test_async_def_cm(self):
+        async def test_async():
+            with patch(f"{__name__}.async_func", AsyncMock()):
+                self.assertIsInstance(async_func, AsyncMock)
+            self.assertTrue(inspect.iscoroutinefunction(async_func))
+
+        run(test_async())
+
+
+class AsyncMockTest(unittest.TestCase):
+    def test_iscoroutinefunction_default(self):
+        mock = AsyncMock()
+        self.assertTrue(iscoroutinefunction(mock))
+
+    def test_iscoroutinefunction_function(self):
+        async def foo(): pass
+        mock = AsyncMock(foo)
+        self.assertTrue(iscoroutinefunction(mock))
+        self.assertTrue(inspect.iscoroutinefunction(mock))
+
+    def test_isawaitable(self):
+        mock = AsyncMock()
+        m = mock()
+        self.assertTrue(inspect.isawaitable(m))
+        run(m)
+        self.assertIn('assert_awaited', dir(mock))
+
+    def test_iscoroutinefunction_normal_function(self):
+        def foo(): pass
+        mock = AsyncMock(foo)
+        self.assertTrue(iscoroutinefunction(mock))
+        self.assertTrue(inspect.iscoroutinefunction(mock))
+
+    def test_future_isfuture(self):
+        loop = asyncio.new_event_loop()
+        asyncio.set_event_loop(loop)
+        fut = asyncio.Future()
+        loop.stop()
+        loop.close()
+        mock = AsyncMock(fut)
+        self.assertIsInstance(mock, asyncio.Future)
+
+
+class AsyncAutospecTest(unittest.TestCase):
+    def test_is_AsyncMock_patch(self):
+        @patch(async_foo_name, autospec=True)
+        def test_async(mock_method):
+            self.assertIsInstance(mock_method.async_method, AsyncMock)
+            self.assertIsInstance(mock_method, MagicMock)
+
+        @patch(async_foo_name, autospec=True)
+        def test_normal_method(mock_method):
+            self.assertIsInstance(mock_method.normal_method, MagicMock)
+
+        test_async()
+        test_normal_method()
+
+    def test_create_autospec_instance(self):
+        with self.assertRaises(RuntimeError):
+            create_autospec(async_func, instance=True)
+
+    def test_create_autospec_awaitable_class(self):
+        awaitable_mock = create_autospec(spec=AwaitableClass())
+        self.assertIsInstance(create_autospec(awaitable_mock), AsyncMock)
+
+    def test_create_autospec(self):
+        spec = create_autospec(async_func_args)
+        awaitable = spec(1, 2, c=3)
+        async def main():
+            await awaitable
+
+        self.assertEqual(spec.await_count, 0)
+        self.assertIsNone(spec.await_args)
+        self.assertEqual(spec.await_args_list, [])
+        spec.assert_not_awaited()
+
+        run(main())
+
+        self.assertTrue(iscoroutinefunction(spec))
+        self.assertTrue(asyncio.iscoroutine(awaitable))
+        self.assertEqual(spec.await_count, 1)
+        self.assertEqual(spec.await_args, call(1, 2, c=3))
+        self.assertEqual(spec.await_args_list, [call(1, 2, c=3)])
+        spec.assert_awaited_once()
+        spec.assert_awaited_once_with(1, 2, c=3)
+        spec.assert_awaited_with(1, 2, c=3)
+        spec.assert_awaited()
+
+        with self.assertRaises(AssertionError):
+            spec.assert_any_await(e=1)
+
+
+    def test_patch_with_autospec(self):
+
+        async def test_async():
+            with patch(f"{__name__}.async_func_args", autospec=True) as mock_method:
+                awaitable = mock_method(1, 2, c=3)
+                self.assertIsInstance(mock_method.mock, AsyncMock)
+
+                self.assertTrue(iscoroutinefunction(mock_method))
+                self.assertTrue(asyncio.iscoroutine(awaitable))
+                self.assertTrue(inspect.isawaitable(awaitable))
+
+                # Verify the default values during mock setup
+                self.assertEqual(mock_method.await_count, 0)
+                self.assertEqual(mock_method.await_args_list, [])
+                self.assertIsNone(mock_method.await_args)
+                mock_method.assert_not_awaited()
+
+                await awaitable
+
+            self.assertEqual(mock_method.await_count, 1)
+            self.assertEqual(mock_method.await_args, call(1, 2, c=3))
+            self.assertEqual(mock_method.await_args_list, [call(1, 2, c=3)])
+            mock_method.assert_awaited_once()
+            mock_method.assert_awaited_once_with(1, 2, c=3)
+            mock_method.assert_awaited_with(1, 2, c=3)
+            mock_method.assert_awaited()
+
+            mock_method.reset_mock()
+            self.assertEqual(mock_method.await_count, 0)
+            self.assertIsNone(mock_method.await_args)
+            self.assertEqual(mock_method.await_args_list, [])
+
+        run(test_async())
+
+
+class AsyncSpecTest(unittest.TestCase):
+    def test_spec_normal_methods_on_class(self):
+        def inner_test(mock_type):
+            mock = mock_type(AsyncClass)
+            self.assertIsInstance(mock.async_method, AsyncMock)
+            self.assertIsInstance(mock.normal_method, MagicMock)
+
+        for mock_type in [AsyncMock, MagicMock]:
+            with self.subTest(f"test method types with {mock_type}"):
+                inner_test(mock_type)
+
+    def test_spec_normal_methods_on_class_with_mock(self):
+        mock = Mock(AsyncClass)
+        self.assertIsInstance(mock.async_method, AsyncMock)
+        self.assertIsInstance(mock.normal_method, Mock)
+
+    def test_spec_mock_type_kw(self):
+        def inner_test(mock_type):
+            async_mock = mock_type(spec=async_func)
+            self.assertIsInstance(async_mock, mock_type)
+            with assertNeverAwaited(self):
+                self.assertTrue(inspect.isawaitable(async_mock()))
+
+            sync_mock = mock_type(spec=normal_func)
+            self.assertIsInstance(sync_mock, mock_type)
+
+        for mock_type in [AsyncMock, MagicMock, Mock]:
+            with self.subTest(f"test spec kwarg with {mock_type}"):
+                inner_test(mock_type)
+
+    def test_spec_mock_type_positional(self):
+        def inner_test(mock_type):
+            async_mock = mock_type(async_func)
+            self.assertIsInstance(async_mock, mock_type)
+            with assertNeverAwaited(self):
+                self.assertTrue(inspect.isawaitable(async_mock()))
+
+            sync_mock = mock_type(normal_func)
+            self.assertIsInstance(sync_mock, mock_type)
+
+        for mock_type in [AsyncMock, MagicMock, Mock]:
+            with self.subTest(f"test spec positional with {mock_type}"):
+                inner_test(mock_type)
+
+    def test_spec_as_normal_kw_AsyncMock(self):
+        mock = AsyncMock(spec=normal_func)
+        self.assertIsInstance(mock, AsyncMock)
+        m = mock()
+        self.assertTrue(inspect.isawaitable(m))
+        run(m)
+
+    def test_spec_as_normal_positional_AsyncMock(self):
+        mock = AsyncMock(normal_func)
+        self.assertIsInstance(mock, AsyncMock)
+        m = mock()
+        self.assertTrue(inspect.isawaitable(m))
+        run(m)
+
+    def test_spec_async_mock(self):
+        @patch.object(AsyncClass, 'async_method', spec=True)
+        def test_async(mock_method):
+            self.assertIsInstance(mock_method, AsyncMock)
+
+        test_async()
+
+    def test_spec_parent_not_async_attribute_is(self):
+        @patch(async_foo_name, spec=True)
+        def test_async(mock_method):
+            self.assertIsInstance(mock_method, MagicMock)
+            self.assertIsInstance(mock_method.async_method, AsyncMock)
+
+        test_async()
+
+    def test_target_async_spec_not(self):
+        @patch.object(AsyncClass, 'async_method', spec=NormalClass.a)
+        def test_async_attribute(mock_method):
+            self.assertIsInstance(mock_method, MagicMock)
+            self.assertFalse(inspect.iscoroutine(mock_method))
+            self.assertFalse(inspect.isawaitable(mock_method))
+
+        test_async_attribute()
+
+    def test_target_not_async_spec_is(self):
+        @patch.object(NormalClass, 'a', spec=async_func)
+        def test_attribute_not_async_spec_is(mock_async_func):
+            self.assertIsInstance(mock_async_func, AsyncMock)
+        test_attribute_not_async_spec_is()
+
+    def test_spec_async_attributes(self):
+        @patch(normal_foo_name, spec=AsyncClass)
+        def test_async_attributes_coroutines(MockNormalClass):
+            self.assertIsInstance(MockNormalClass.async_method, AsyncMock)
+            self.assertIsInstance(MockNormalClass, MagicMock)
+
+        test_async_attributes_coroutines()
+
+
+class AsyncSpecSetTest(unittest.TestCase):
+    def test_is_AsyncMock_patch(self):
+        @patch.object(AsyncClass, 'async_method', spec_set=True)
+        def test_async(async_method):
+            self.assertIsInstance(async_method, AsyncMock)
+        test_async()
+
+    def test_is_async_AsyncMock(self):
+        mock = AsyncMock(spec_set=AsyncClass.async_method)
+        self.assertTrue(iscoroutinefunction(mock))
+        self.assertIsInstance(mock, AsyncMock)
+
+    def test_is_child_AsyncMock(self):
+        mock = MagicMock(spec_set=AsyncClass)
+        self.assertTrue(iscoroutinefunction(mock.async_method))
+        self.assertFalse(iscoroutinefunction(mock.normal_method))
+        self.assertIsInstance(mock.async_method, AsyncMock)
+        self.assertIsInstance(mock.normal_method, MagicMock)
+        self.assertIsInstance(mock, MagicMock)
+
+    def test_magicmock_lambda_spec(self):
+        mock_obj = MagicMock()
+        mock_obj.mock_func = MagicMock(spec=lambda x: x)
+
+        with patch.object(mock_obj, "mock_func") as cm:
+            self.assertIsInstance(cm, MagicMock)
+
+
+class AsyncArguments(IsolatedAsyncioTestCase):
+    async def test_add_return_value(self):
+        async def addition(self, var): pass
+
+        mock = AsyncMock(addition, return_value=10)
+        output = await mock(5)
+
+        self.assertEqual(output, 10)
+
+    async def test_add_side_effect_exception(self):
+        async def addition(var): pass
+        mock = AsyncMock(addition, side_effect=Exception('err'))
+        with self.assertRaises(Exception):
+            await mock(5)
+
+    async def test_add_side_effect_coroutine(self):
+        async def addition(var):
+            return var + 1
+        mock = AsyncMock(side_effect=addition)
+        result = await mock(5)
+        self.assertEqual(result, 6)
+
+    async def test_add_side_effect_normal_function(self):
+        def addition(var):
+            return var + 1
+        mock = AsyncMock(side_effect=addition)
+        result = await mock(5)
+        self.assertEqual(result, 6)
+
+    async def test_add_side_effect_iterable(self):
+        vals = [1, 2, 3]
+        mock = AsyncMock(side_effect=vals)
+        for item in vals:
+            self.assertEqual(await mock(), item)
+
+        with self.assertRaises(StopAsyncIteration) as e:
+            await mock()
+
+    async def test_add_side_effect_exception_iterable(self):
+        class SampleException(Exception):
+            pass
+
+        vals = [1, SampleException("foo")]
+        mock = AsyncMock(side_effect=vals)
+        self.assertEqual(await mock(), 1)
+
+        with self.assertRaises(SampleException) as e:
+            await mock()
+
+    async def test_return_value_AsyncMock(self):
+        value = AsyncMock(return_value=10)
+        mock = AsyncMock(return_value=value)
+        result = await mock()
+        self.assertIs(result, value)
+
+    async def test_return_value_awaitable(self):
+        fut = asyncio.Future()
+        fut.set_result(None)
+        mock = AsyncMock(return_value=fut)
+        result = await mock()
+        self.assertIsInstance(result, asyncio.Future)
+
+    async def test_side_effect_awaitable_values(self):
+        fut = asyncio.Future()
+        fut.set_result(None)
+
+        mock = AsyncMock(side_effect=[fut])
+        result = await mock()
+        self.assertIsInstance(result, asyncio.Future)
+
+        with self.assertRaises(StopAsyncIteration):
+            await mock()
+
+    async def test_side_effect_is_AsyncMock(self):
+        effect = AsyncMock(return_value=10)
+        mock = AsyncMock(side_effect=effect)
+
+        result = await mock()
+        self.assertEqual(result, 10)
+
+    async def test_wraps_coroutine(self):
+        value = asyncio.Future()
+
+        ran = False
+        async def inner():
+            nonlocal ran
+            ran = True
+            return value
+
+        mock = AsyncMock(wraps=inner)
+        result = await mock()
+        self.assertEqual(result, value)
+        mock.assert_awaited()
+        self.assertTrue(ran)
+
+    async def test_wraps_normal_function(self):
+        value = 1
+
+        ran = False
+        def inner():
+            nonlocal ran
+            ran = True
+            return value
+
+        mock = AsyncMock(wraps=inner)
+        result = await mock()
+        self.assertEqual(result, value)
+        mock.assert_awaited()
+        self.assertTrue(ran)
+
+    async def test_await_args_list_order(self):
+        async_mock = AsyncMock()
+        mock2 = async_mock(2)
+        mock1 = async_mock(1)
+        await mock1
+        await mock2
+        async_mock.assert_has_awaits([call(1), call(2)])
+        self.assertEqual(async_mock.await_args_list, [call(1), call(2)])
+        self.assertEqual(async_mock.call_args_list, [call(2), call(1)])
+
+
+class AsyncMagicMethods(unittest.TestCase):
+    def test_async_magic_methods_return_async_mocks(self):
+        m_mock = MagicMock()
+        self.assertIsInstance(m_mock.__aenter__, AsyncMock)
+        self.assertIsInstance(m_mock.__aexit__, AsyncMock)
+        self.assertIsInstance(m_mock.__anext__, AsyncMock)
+        # __aiter__ is actually a synchronous object
+        # so should return a MagicMock
+        self.assertIsInstance(m_mock.__aiter__, MagicMock)
+
+    def test_sync_magic_methods_return_magic_mocks(self):
+        a_mock = AsyncMock()
+        self.assertIsInstance(a_mock.__enter__, MagicMock)
+        self.assertIsInstance(a_mock.__exit__, MagicMock)
+        self.assertIsInstance(a_mock.__next__, MagicMock)
+        self.assertIsInstance(a_mock.__len__, MagicMock)
+
+    def test_magicmock_has_async_magic_methods(self):
+        m_mock = MagicMock()
+        self.assertTrue(hasattr(m_mock, "__aenter__"))
+        self.assertTrue(hasattr(m_mock, "__aexit__"))
+        self.assertTrue(hasattr(m_mock, "__anext__"))
+
+    def test_asyncmock_has_sync_magic_methods(self):
+        a_mock = AsyncMock()
+        self.assertTrue(hasattr(a_mock, "__enter__"))
+        self.assertTrue(hasattr(a_mock, "__exit__"))
+        self.assertTrue(hasattr(a_mock, "__next__"))
+        self.assertTrue(hasattr(a_mock, "__len__"))
+
+    def test_magic_methods_are_async_functions(self):
+        m_mock = MagicMock()
+        self.assertIsInstance(m_mock.__aenter__, AsyncMock)
+        self.assertIsInstance(m_mock.__aexit__, AsyncMock)
+        # AsyncMocks are also coroutine functions
+        self.assertTrue(iscoroutinefunction(m_mock.__aenter__))
+        self.assertTrue(iscoroutinefunction(m_mock.__aexit__))
+
+class AsyncContextManagerTest(unittest.TestCase):
+
+    class WithAsyncContextManager:
+        async def __aenter__(self, *args, **kwargs): pass
+
+        async def __aexit__(self, *args, **kwargs): pass
+
+    class WithSyncContextManager:
+        def __enter__(self, *args, **kwargs): pass
+
+        def __exit__(self, *args, **kwargs): pass
+
+    class ProductionCode:
+        # Example real-world(ish) code
+        def __init__(self):
+            self.session = None
+
+        async def main(self):
+            async with self.session.post('https://python.org') as response:
+                val = await response.json()
+                return val
+
+    def test_set_return_value_of_aenter(self):
+        def inner_test(mock_type):
+            pc = self.ProductionCode()
+            pc.session = MagicMock(name='sessionmock')
+            cm = mock_type(name='magic_cm')
+            response = AsyncMock(name='response')
+            response.json = AsyncMock(return_value={'json': 123})
+            cm.__aenter__.return_value = response
+            pc.session.post.return_value = cm
+            result = run(pc.main())
+            self.assertEqual(result, {'json': 123})
+
+        for mock_type in [AsyncMock, MagicMock]:
+            with self.subTest(f"test set return value of aenter with {mock_type}"):
+                inner_test(mock_type)
+
+    def test_mock_supports_async_context_manager(self):
+
+        def inner_test(mock_type):
+            called = False
+            cm = self.WithAsyncContextManager()
+            cm_mock = mock_type(cm)
+
+            async def use_context_manager():
+                nonlocal called
+                async with cm_mock as result:
+                    called = True
+                return result
+
+            cm_result = run(use_context_manager())
+            self.assertTrue(called)
+            self.assertTrue(cm_mock.__aenter__.called)
+            self.assertTrue(cm_mock.__aexit__.called)
+            cm_mock.__aenter__.assert_awaited()
+            cm_mock.__aexit__.assert_awaited()
+            # We mock __aenter__ so it does not return self
+            self.assertIsNot(cm_mock, cm_result)
+
+        for mock_type in [AsyncMock, MagicMock]:
+            with self.subTest(f"test context manager magics with {mock_type}"):
+                inner_test(mock_type)
+ 
+    def test_mock_customize_async_context_manager(self):
+        instance = self.WithAsyncContextManager()
+        mock_instance = MagicMock(instance)
+
+        expected_result = object()
+        mock_instance.__aenter__.return_value = expected_result
+
+        async def use_context_manager():
+            async with mock_instance as result:
+                return result
+
+        self.assertIs(run(use_context_manager()), expected_result)
+
+    def test_mock_customize_async_context_manager_with_coroutine(self):
+        enter_called = False
+        exit_called = False
+
+        async def enter_coroutine(*args):
+            nonlocal enter_called
+            enter_called = True
+
+        async def exit_coroutine(*args):
+            nonlocal exit_called
+            exit_called = True
+
+        instance = self.WithAsyncContextManager()
+        mock_instance = MagicMock(instance)
+
+        mock_instance.__aenter__ = enter_coroutine
+        mock_instance.__aexit__ = exit_coroutine
+
+        async def use_context_manager():
+            async with mock_instance:
+                pass
+
+        run(use_context_manager())
+        self.assertTrue(enter_called)
+        self.assertTrue(exit_called)
+
+    def test_context_manager_raise_exception_by_default(self):
+        async def raise_in(context_manager):
+            async with context_manager:
+                raise TypeError()
+
+        instance = self.WithAsyncContextManager()
+        mock_instance = MagicMock(instance)
+        with self.assertRaises(TypeError):
+            run(raise_in(mock_instance))
+
+
+class AsyncIteratorTest(unittest.TestCase):
+    class WithAsyncIterator(object):
+        def __init__(self):
+            self.items = ["foo", "NormalFoo", "baz"]
+
+        def __aiter__(self): pass
+
+        async def __anext__(self): pass
+
+    def test_aiter_set_return_value(self):
+        mock_iter = AsyncMock(name="tester")
+        mock_iter.__aiter__.return_value = [1, 2, 3]
+        async def main():
+            return [i async for i in mock_iter]
+        result = run(main())
+        self.assertEqual(result, [1, 2, 3])
+
+    def test_mock_aiter_and_anext_asyncmock(self):
+        def inner_test(mock_type):
+            instance = self.WithAsyncIterator()
+            mock_instance = mock_type(instance)
+            # Check that the mock and the real thing bahave the same
+            # __aiter__ is not actually async, so not a coroutinefunction
+            self.assertFalse(iscoroutinefunction(instance.__aiter__))
+            self.assertFalse(iscoroutinefunction(mock_instance.__aiter__))
+            # __anext__ is async
+            self.assertTrue(iscoroutinefunction(instance.__anext__))
+            self.assertTrue(iscoroutinefunction(mock_instance.__anext__))
+
+        for mock_type in [AsyncMock, MagicMock]:
+            with self.subTest(f"test aiter and anext corourtine with {mock_type}"):
+                inner_test(mock_type)
+
+
+    def test_mock_async_for(self):
+        async def iterate(iterator):
+            accumulator = []
+            async for item in iterator:
+                accumulator.append(item)
+
+            return accumulator
+
+        expected = ["FOO", "BAR", "BAZ"]
+        def test_default(mock_type):
+            mock_instance = mock_type(self.WithAsyncIterator())
+            self.assertEqual(run(iterate(mock_instance)), [])
+
+
+        def test_set_return_value(mock_type):
+            mock_instance = mock_type(self.WithAsyncIterator())
+            mock_instance.__aiter__.return_value = expected[:]
+            self.assertEqual(run(iterate(mock_instance)), expected)
+
+        def test_set_return_value_iter(mock_type):
+            mock_instance = mock_type(self.WithAsyncIterator())
+            mock_instance.__aiter__.return_value = iter(expected[:])
+            self.assertEqual(run(iterate(mock_instance)), expected)
+
+        for mock_type in [AsyncMock, MagicMock]:
+            with self.subTest(f"default value with {mock_type}"):
+                test_default(mock_type)
+
+            with self.subTest(f"set return_value with {mock_type}"):
+                test_set_return_value(mock_type)
+
+            with self.subTest(f"set return_value iterator with {mock_type}"):
+                test_set_return_value_iter(mock_type)
+
+
+class AsyncMockAssert(unittest.TestCase):
+    def setUp(self):
+        self.mock = AsyncMock()
+
+    async def _runnable_test(self, *args, **kwargs):
+        await self.mock(*args, **kwargs)
+
+    async def _await_coroutine(self, coroutine):
+        return await coroutine
+
+    def test_assert_called_but_not_awaited(self):
+        mock = AsyncMock(AsyncClass)
+        with assertNeverAwaited(self):
+            mock.async_method()
+        self.assertTrue(iscoroutinefunction(mock.async_method))
+        mock.async_method.assert_called()
+        mock.async_method.assert_called_once()
+        mock.async_method.assert_called_once_with()
+        with self.assertRaises(AssertionError):
+            mock.assert_awaited()
+        with self.assertRaises(AssertionError):
+            mock.async_method.assert_awaited()
+
+    def test_assert_called_then_awaited(self):
+        mock = AsyncMock(AsyncClass)
+        mock_coroutine = mock.async_method()
+        mock.async_method.assert_called()
+        mock.async_method.assert_called_once()
+        mock.async_method.assert_called_once_with()
+        with self.assertRaises(AssertionError):
+            mock.async_method.assert_awaited()
+
+        run(self._await_coroutine(mock_coroutine))
+        # Assert we haven't re-called the function
+        mock.async_method.assert_called_once()
+        mock.async_method.assert_awaited()
+        mock.async_method.assert_awaited_once()
+        mock.async_method.assert_awaited_once_with()
+
+    def test_assert_called_and_awaited_at_same_time(self):
+        with self.assertRaises(AssertionError):
+            self.mock.assert_awaited()
+
+        with self.assertRaises(AssertionError):
+            self.mock.assert_called()
+
+        run(self._runnable_test())
+        self.mock.assert_called_once()
+        self.mock.assert_awaited_once()
+
+    def test_assert_called_twice_and_awaited_once(self):
+        mock = AsyncMock(AsyncClass)
+        coroutine = mock.async_method()
+        # The first call will be awaited so no warning there
+        # But this call will never get awaited, so it will warn here
+        with assertNeverAwaited(self):
+            mock.async_method()
+        with self.assertRaises(AssertionError):
+            mock.async_method.assert_awaited()
+        mock.async_method.assert_called()
+        run(self._await_coroutine(coroutine))
+        mock.async_method.assert_awaited()
+        mock.async_method.assert_awaited_once()
+
+    def test_assert_called_once_and_awaited_twice(self):
+        mock = AsyncMock(AsyncClass)
+        coroutine = mock.async_method()
+        mock.async_method.assert_called_once()
+        run(self._await_coroutine(coroutine))
+        with self.assertRaises(RuntimeError):
+            # Cannot reuse already awaited coroutine
+            run(self._await_coroutine(coroutine))
+        mock.async_method.assert_awaited()
+
+    def test_assert_awaited_but_not_called(self):
+        with self.assertRaises(AssertionError):
+            self.mock.assert_awaited()
+        with self.assertRaises(AssertionError):
+            self.mock.assert_called()
+        with self.assertRaises(TypeError):
+            # You cannot await an AsyncMock, it must be a coroutine
+            run(self._await_coroutine(self.mock))
+
+        with self.assertRaises(AssertionError):
+            self.mock.assert_awaited()
+        with self.assertRaises(AssertionError):
+            self.mock.assert_called()
+
+    def test_assert_has_calls_not_awaits(self):
+        kalls = [call('foo')]
+        with assertNeverAwaited(self):
+            self.mock('foo')
+        self.mock.assert_has_calls(kalls)
+        with self.assertRaises(AssertionError):
+            self.mock.assert_has_awaits(kalls)
+
+    def test_assert_has_mock_calls_on_async_mock_no_spec(self):
+        with assertNeverAwaited(self):
+            self.mock()
+        kalls_empty = [('', (), {})]
+        self.assertEqual(self.mock.mock_calls, kalls_empty)
+
+        with assertNeverAwaited(self):
+            self.mock('foo')
+        with assertNeverAwaited(self):
+            self.mock('baz')
+        mock_kalls = ([call(), call('foo'), call('baz')])
+        self.assertEqual(self.mock.mock_calls, mock_kalls)
+
+    def test_assert_has_mock_calls_on_async_mock_with_spec(self):
+        a_class_mock = AsyncMock(AsyncClass)
+        with assertNeverAwaited(self):
+            a_class_mock.async_method()
+        kalls_empty = [('', (), {})]
+        self.assertEqual(a_class_mock.async_method.mock_calls, kalls_empty)
+        self.assertEqual(a_class_mock.mock_calls, [call.async_method()])
+
+        with assertNeverAwaited(self):
+            a_class_mock.async_method(1, 2, 3, a=4, b=5)
+        method_kalls = [call(), call(1, 2, 3, a=4, b=5)]
+        mock_kalls = [call.async_method(), call.async_method(1, 2, 3, a=4, b=5)]
+        self.assertEqual(a_class_mock.async_method.mock_calls, method_kalls)
+        self.assertEqual(a_class_mock.mock_calls, mock_kalls)
+
+    def test_async_method_calls_recorded(self):
+        with assertNeverAwaited(self):
+            self.mock.something(3, fish=None)
+        with assertNeverAwaited(self):
+            self.mock.something_else.something(6, cake=sentinel.Cake)
+
+        self.assertEqual(self.mock.method_calls, [
+            ("something", (3,), {'fish': None}),
+            ("something_else.something", (6,), {'cake': sentinel.Cake})
+        ],
+            "method calls not recorded correctly")
+        self.assertEqual(self.mock.something_else.method_calls,
+                         [("something", (6,), {'cake': sentinel.Cake})],
+                         "method calls not recorded correctly")
+
+    def test_async_arg_lists(self):
+        def assert_attrs(mock):
+            names = ('call_args_list', 'method_calls', 'mock_calls')
+            for name in names:
+                attr = getattr(mock, name)
+                self.assertIsInstance(attr, _CallList)
+                self.assertIsInstance(attr, list)
+                self.assertEqual(attr, [])
+
+        assert_attrs(self.mock)
+        with assertNeverAwaited(self):
+            self.mock()
+        with assertNeverAwaited(self):
+            self.mock(1, 2)
+        with assertNeverAwaited(self):
+            self.mock(a=3)
+
+        self.mock.reset_mock()
+        assert_attrs(self.mock)
+
+        a_mock = AsyncMock(AsyncClass)
+        with assertNeverAwaited(self):
+            a_mock.async_method()
+        with assertNeverAwaited(self):
+            a_mock.async_method(1, a=3)
+
+        a_mock.reset_mock()
+        assert_attrs(a_mock)
+
+    def test_assert_awaited(self):
+        with self.assertRaises(AssertionError):
+            self.mock.assert_awaited()
+
+        run(self._runnable_test())
+        self.mock.assert_awaited()
+
+    def test_assert_awaited_once(self):
+        with self.assertRaises(AssertionError):
+            self.mock.assert_awaited_once()
+
+        run(self._runnable_test())
+        self.mock.assert_awaited_once()
+
+        run(self._runnable_test())
+        with self.assertRaises(AssertionError):
+            self.mock.assert_awaited_once()
+
+    def test_assert_awaited_with(self):
+        msg = 'Not awaited'
+        with self.assertRaisesRegex(AssertionError, msg):
+            self.mock.assert_awaited_with('foo')
+
+        run(self._runnable_test())
+        msg = 'expected await not found'
+        with self.assertRaisesRegex(AssertionError, msg):
+            self.mock.assert_awaited_with('foo')
+
+        run(self._runnable_test('foo'))
+        self.mock.assert_awaited_with('foo')
+
+        run(self._runnable_test('SomethingElse'))
+        with self.assertRaises(AssertionError):
+            self.mock.assert_awaited_with('foo')
+
+    def test_assert_awaited_once_with(self):
+        with self.assertRaises(AssertionError):
+            self.mock.assert_awaited_once_with('foo')
+
+        run(self._runnable_test('foo'))
+        self.mock.assert_awaited_once_with('foo')
+
+        run(self._runnable_test('foo'))
+        with self.assertRaises(AssertionError):
+            self.mock.assert_awaited_once_with('foo')
+
+    def test_assert_any_wait(self):
+        with self.assertRaises(AssertionError):
+            self.mock.assert_any_await('foo')
+
+        run(self._runnable_test('baz'))
+        with self.assertRaises(AssertionError):
+            self.mock.assert_any_await('foo')
+
+        run(self._runnable_test('foo'))
+        self.mock.assert_any_await('foo')
+
+        run(self._runnable_test('SomethingElse'))
+        self.mock.assert_any_await('foo')
+
+    def test_assert_has_awaits_no_order(self):
+        calls = [call('foo'), call('baz')]
+
+        with self.assertRaises(AssertionError) as cm:
+            self.mock.assert_has_awaits(calls)
+        self.assertEqual(len(cm.exception.args), 1)
+
+        run(self._runnable_test('foo'))
+        with self.assertRaises(AssertionError):
+            self.mock.assert_has_awaits(calls)
+
+        run(self._runnable_test('foo'))
+        with self.assertRaises(AssertionError):
+            self.mock.assert_has_awaits(calls)
+
+        run(self._runnable_test('baz'))
+        self.mock.assert_has_awaits(calls)
+
+        run(self._runnable_test('SomethingElse'))
+        self.mock.assert_has_awaits(calls)
+
+    def test_awaits_asserts_with_any(self):
+        class Foo:
+            def __eq__(self, other): pass
+
+        run(self._runnable_test(Foo(), 1))
+
+        self.mock.assert_has_awaits([call(ANY, 1)])
+        self.mock.assert_awaited_with(ANY, 1)
+        self.mock.assert_any_await(ANY, 1)
+
+    def test_awaits_asserts_with_spec_and_any(self):
+        class Foo:
+            def __eq__(self, other): pass
+
+        mock_with_spec = AsyncMock(spec=Foo)
+
+        async def _custom_mock_runnable_test(*args):
+            await mock_with_spec(*args)
+
+        run(_custom_mock_runnable_test(Foo(), 1))
+        mock_with_spec.assert_has_awaits([call(ANY, 1)])
+        mock_with_spec.assert_awaited_with(ANY, 1)
+        mock_with_spec.assert_any_await(ANY, 1)
+
+    def test_assert_has_awaits_ordered(self):
+        calls = [call('foo'), call('baz')]
+        with self.assertRaises(AssertionError):
+            self.mock.assert_has_awaits(calls, any_order=True)
+
+        run(self._runnable_test('baz'))
+        with self.assertRaises(AssertionError):
+            self.mock.assert_has_awaits(calls, any_order=True)
+
+        run(self._runnable_test('bamf'))
+        with self.assertRaises(AssertionError):
+            self.mock.assert_has_awaits(calls, any_order=True)
+
+        run(self._runnable_test('foo'))
+        self.mock.assert_has_awaits(calls, any_order=True)
+
+        run(self._runnable_test('qux'))
+        self.mock.assert_has_awaits(calls, any_order=True)
+
+    def test_assert_not_awaited(self):
+        self.mock.assert_not_awaited()
+
+        run(self._runnable_test())
+        with self.assertRaises(AssertionError):
+            self.mock.assert_not_awaited()
+
+    def test_assert_has_awaits_not_matching_spec_error(self):
+        async def f(x=None): pass
+
+        self.mock = AsyncMock(spec=f)
+        run(self._runnable_test(1))
+
+        with self.assertRaisesRegex(
+                AssertionError,
+                '^{}$'.format(
+                    re.escape('Awaits not found.\n'
+                              'Expected: [call()]\n'
+                              'Actual: [call(1)]'))) as cm:
+            self.mock.assert_has_awaits([call()])
+        self.assertIsNone(cm.exception.__cause__)
+
+        with self.assertRaisesRegex(
+                AssertionError,
+                '^{}$'.format(
+                    re.escape(
+                        'Error processing expected awaits.\n'
+                        "Errors: [None, TypeError('too many positional "
+                        "arguments')]\n"
+                        'Expected: [call(), call(1, 2)]\n'
+                        'Actual: [call(1)]').replace(
+                            "arguments\\'", "arguments\\',?")
+                )) as cm:
+            self.mock.assert_has_awaits([call(), call(1, 2)])
+        self.assertIsInstance(cm.exception.__cause__, TypeError)
diff --git a/mock/tests/testcallable.py b/mock/tests/testcallable.py
index 729947e..41715ed 100644
--- a/mock/tests/testcallable.py
+++ b/mock/tests/testcallable.py
@@ -8,9 +8,8 @@
 from mock import (
     Mock, MagicMock, NonCallableMagicMock,
     NonCallableMock, patch, create_autospec,
-    CallableMixin
 )
-
+from mock.mock import CallableMixin
 
 
 class TestCallable(unittest.TestCase):
@@ -106,14 +105,8 @@
         class Multi(SomeClass, Sub):
             pass
 
-        class OldStyle:
-            def __call__(self): pass
-
-        class OldStyleSub(OldStyle):
-            pass
-
         for arg in 'spec', 'spec_set':
-            for Klass in CallableX, Sub, Multi, OldStyle, OldStyleSub:
+            for Klass in CallableX, Sub, Multi:
                 with patch('%s.X' % __name__, **{arg: Klass}) as mock:
                     instance = mock()
                     mock.assert_called_once_with()
diff --git a/mock/tests/testhelpers.py b/mock/tests/testhelpers.py
index d56a47f..2a28796 100644
--- a/mock/tests/testhelpers.py
+++ b/mock/tests/testhelpers.py
@@ -1,12 +1,6 @@
-# Copyright (C) 2007-2012 Michael Foord & the mock team
-# E-mail: fuzzyman AT voidspace DOT org DOT uk
-# http://www.voidspace.org.uk/python/mock/
-import socket
-
 import inspect
-import six
-import sys
 import time
+import types
 import unittest
 
 from mock import (
@@ -14,13 +8,12 @@
     Mock, ANY, patch, PropertyMock
 )
 from mock.mock import _Call, _CallList, _callable
+from mock import IS_PYPY
 
 from datetime import datetime
 from functools import partial
 
-
-if six.PY2:
-    import funcsigs
+import pytest
 
 
 class SomeClass(object):
@@ -29,7 +22,6 @@
     def three(self, a=None): pass
 
 
-
 class AnyTest(unittest.TestCase):
 
     def test_any(self):
@@ -76,7 +68,28 @@
             self.assertEqual(expected, mock.mock_calls)
             self.assertEqual(mock.mock_calls, expected)
 
+    def test_any_no_spec(self):
+        # This is a regression test for bpo-37555
+        class Foo:
+            def __eq__(self, other): pass
 
+        mock = Mock()
+        mock(Foo(), 1)
+        mock.assert_has_calls([call(ANY, 1)])
+        mock.assert_called_with(ANY, 1)
+        mock.assert_any_call(ANY, 1)
+
+    def test_any_and_spec_set(self):
+        # This is a regression test for bpo-37555
+        class Foo:
+            def __eq__(self, other): pass
+
+        mock = Mock(spec=Foo)
+
+        mock(Foo(), 1)
+        mock.assert_has_calls([call(ANY, 1)])
+        mock.assert_called_with(ANY, 1)
+        mock.assert_any_call(ANY, 1)
 
 class CallTest(unittest.TestCase):
 
@@ -346,6 +359,26 @@
         self.assertEqual(_Call((('bar', 'barz'),),)[0], '')
         self.assertEqual(_Call((('bar', 'barz'), {'hello': 'world'}),)[0], '')
 
+    def test_dunder_call(self):
+        m = MagicMock()
+        m().foo()['bar']()
+        self.assertEqual(
+            m.mock_calls,
+            [call(), call().foo(), call().foo().__getitem__('bar'), call().foo().__getitem__()()]
+        )
+        m = MagicMock()
+        m().foo()['bar'] = 1
+        self.assertEqual(
+            m.mock_calls,
+            [call(), call().foo(), call().foo().__setitem__('bar', 1)]
+        )
+        m = MagicMock()
+        iter(m().foo())
+        self.assertEqual(
+            m.mock_calls,
+            [call(), call().foo(), call().foo().__iter__()]
+        )
+
 
 class SpecSignatureTest(unittest.TestCase):
 
@@ -418,12 +451,9 @@
         m = create_autospec(Foo, a='3')
         self.assertEqual(m.a, '3')
 
-    @unittest.skipUnless(six.PY3, "Keyword only arguments Python 3 specific")
+
     def test_create_autospec_keyword_only_arguments(self):
-        func_def = "def foo(a, *, b=None): pass\n"
-        namespace = {}
-        exec (func_def, namespace)
-        foo = namespace['foo']
+        def foo(a, *, b=None): pass
 
         m = create_autospec(foo)
         m(1)
@@ -433,6 +463,7 @@
         m(2, b=3)
         m.assert_called_with(2, b=3)
 
+
     def test_function_as_instance_attribute(self):
         obj = SomeClass()
         def f(a): pass
@@ -471,16 +502,16 @@
             self._check_someclass_mock(mock)
 
 
-    @unittest.skipIf('PyPy' in sys.version,
-                     "This fails on pypy, "
-                     "see https://github.com/testing-cabal/mock/issues/452")
     def test_spec_has_descriptor_returning_function(self):
+
         class CrazyDescriptor(object):
+
             def __get__(self, obj, type_):
                 if obj is None:
                     return lambda x: None
 
         class MyClass(object):
+
             some_attr = CrazyDescriptor()
 
         mock = create_autospec(MyClass)
@@ -490,11 +521,13 @@
         with self.assertRaises(TypeError):
             mock.some_attr(1, 2)
 
-    @unittest.skipIf(six.PY2, "object.__dir__ doesn't exist in Python 2")
+
     def test_spec_has_function_not_in_bases(self):
+
         class CrazyClass(object):
+
             def __dir__(self):
-                return super(CrazyClass, self).__dir__() + ['crazy']
+                return super(CrazyClass, self).__dir__()+['crazy']
 
             def __getattr__(self, item):
                 if item == 'crazy':
@@ -505,6 +538,7 @@
         with self.assertRaises(AttributeError):
             inst.other
         self.assertEqual(inst.crazy(42), 42)
+
         mock = create_autospec(inst)
         mock.crazy(42)
         with self.assertRaises(TypeError):
@@ -513,8 +547,6 @@
             mock.crazy(1, 2)
 
 
-    @unittest.skipIf('PyPy' in sys.version and sys.version_info < (3, 0),
-                     "Fails on pypy2 due to incorrect signature for dict.pop from funcsigs")
     def test_builtin_functions_types(self):
         # we could replace builtin functions / methods with a function
         # with *args / **kwargs signature. Using the builtin method type
@@ -611,27 +643,6 @@
             mock.g.assert_called_once_with(3, 4)
 
 
-    @unittest.skipIf(six.PY3, "No old style classes in Python 3")
-    def test_old_style_classes(self):
-        class Foo:
-            def f(self, a, b): pass
-
-        class Bar(Foo):
-            g = Foo()
-
-        for spec in (Foo, Foo(), Bar, Bar()):
-            mock = create_autospec(spec)
-            mock.f(1, 2)
-            mock.f.assert_called_once_with(1, 2)
-
-            self.assertRaises(AttributeError, getattr, mock, 'foo')
-            self.assertRaises(AttributeError, getattr, mock.f, 'foo')
-
-        mock.g.f(1, 2)
-        mock.g.f.assert_called_once_with(1, 2)
-        self.assertRaises(AttributeError, getattr, mock.g, 'foo')
-
-
     def test_recursive(self):
         class A(object):
             def a(self): pass
@@ -788,21 +799,6 @@
         self.assertRaises(TypeError, mock)
         mock(1)
         mock.assert_called_once_with(1)
-
-        mock(4, 5)
-        mock.assert_called_with(4, 5)
-
-
-    @unittest.skipIf(six.PY3, 'no old style classes in Python 3')
-    def test_signature_old_style_class(self):
-        class Foo:
-            def __init__(self, a, b=3): pass
-
-        mock = create_autospec(Foo)
-
-        self.assertRaises(TypeError, mock)
-        mock(1)
-        mock.assert_called_once_with(1)
         mock.assert_called_once_with(a=1)
         self.assertRaises(AssertionError, mock.assert_called_once_with, 2)
 
@@ -820,15 +816,6 @@
         create_autospec(Foo)
 
 
-    @unittest.skipIf(six.PY3, 'no old style classes in Python 3')
-    def test_old_style_class_with_no_init(self):
-        # this used to raise an exception
-        # due to Foo.__init__ raising an AttributeError
-        class Foo:
-            pass
-        create_autospec(Foo)
-
-
     def test_signature_callable(self):
         class Callable(object):
             def __init__(self, x, y): pass
@@ -899,36 +886,6 @@
         a.f.assert_called_with(self=10)
 
 
-    def test_autospec_property(self):
-        class Foo(object):
-            @property
-            def foo(self): pass
-
-        foo = create_autospec(Foo)
-        mock_property = foo.foo
-
-        # no spec on properties
-        self.assertIsInstance(mock_property, MagicMock)
-        mock_property(1, 2, 3)
-        mock_property.abc(4, 5, 6)
-        mock_property.assert_called_once_with(1, 2, 3)
-        mock_property.abc.assert_called_once_with(4, 5, 6)
-
-
-    def test_autospec_slots(self):
-        class Foo(object):
-            __slots__ = ['a']
-
-        foo = create_autospec(Foo)
-        mock_slot = foo.a
-
-        # no spec on slots
-        mock_slot(1, 2, 3)
-        mock_slot.abc(4, 5, 6)
-        mock_slot.assert_called_once_with(1, 2, 3)
-        mock_slot.abc.assert_called_once_with(4, 5, 6)
-
-
     def test_autospec_data_descriptor(self):
         class Descriptor(object):
             def __init__(self, value):
@@ -973,10 +930,8 @@
         check_data_descriptor(foo.desc)
 
 
-    @unittest.skipIf('PyPy' in sys.version and sys.version_info > (3, 0),
-                     "See https://github.com/testing-cabal/mock/issues/452")
     def test_autospec_on_bound_builtin_function(self):
-        meth = six.create_bound_method(time.ctime, time.time())
+        meth = types.MethodType(time.ctime, time.time())
         self.assertIsInstance(meth(), str)
         mocked = create_autospec(meth)
 
@@ -984,20 +939,23 @@
         mocked()
         mocked.assert_called_once_with()
         mocked.reset_mock()
-        mocked(4, 5, 6)
-        mocked.assert_called_once_with(4, 5, 6)
-
-    def test_autospec_socket(self):
-        sock_class = create_autospec(socket.socket)
-        self.assertRaises(TypeError, sock_class, foo=1)
+        # but pypy gets this right:
+        if IS_PYPY:
+            with self.assertRaises(TypeError):
+                mocked(4, 5, 6)
+        else:
+            mocked(4, 5, 6)
+            mocked.assert_called_once_with(4, 5, 6)
 
 
     def test_autospec_getattr_partial_function(self):
         # bpo-32153 : getattr returning partial functions without
         # __name__ should not create AttributeError in create_autospec
-        class Foo(object):
+        class Foo:
+
             def __getattr__(self, attribute):
                 return partial(lambda name: name, attribute)
+
         proxy = Foo()
         autospec = create_autospec(proxy)
         self.assertFalse(hasattr(autospec, '__name__'))
@@ -1011,28 +969,33 @@
         mock(1, 2)
         mock(x=1, y=2)
 
-        if six.PY2:
-            self.assertEqual(funcsigs.signature(mock), funcsigs.signature(myfunc))
-        else:
-            self.assertEqual(inspect.getfullargspec(mock), inspect.getfullargspec(myfunc))
+        self.assertEqual(inspect.signature(mock), inspect.signature(myfunc))
         self.assertEqual(mock.mock_calls, [call(1, 2), call(x=1, y=2)])
         self.assertRaises(TypeError, mock, 1)
 
 
+    def test_spec_inspect_signature_annotations(self):
+
+        def foo(a: int, b: int=10, *, c:int) -> int:
+            return a + b + c
+
+        self.assertEqual(foo(1, 2 , c=3), 6)
+        mock = create_autospec(foo)
+        mock(1, 2, c=3)
+        mock(1, c=3)
+
+        self.assertEqual(inspect.signature(mock), inspect.signature(foo))
+        self.assertEqual(mock.mock_calls, [call(1, 2, c=3), call(1, c=3)])
+        self.assertRaises(TypeError, mock, 1)
+        self.assertRaises(TypeError, mock, 1, 2, 3, c=4)
+
+
     def test_spec_function_no_name(self):
         func = lambda: 'nope'
         mock = create_autospec(func)
         self.assertEqual(mock.__name__, 'funcopy')
 
 
-    @unittest.skipIf(six.PY3, "Here to test our Py2 _isidentifier")
-    def test_spec_function_has_identifier_name(self):
-        func = lambda: 'nope'
-        func.__name__ = 'global'
-        mock = create_autospec(func)
-        self.assertEqual(mock.__name__, 'funcopy')
-
-
     def test_spec_function_assert_has_calls(self):
         def f(a): pass
         mock = create_autospec(f)
@@ -1105,20 +1068,6 @@
         self.assertEqual(str(mock.mock_calls), expected)
 
 
-    @unittest.skipIf(six.PY3, "Unicode is properly handled with Python 3")
-    def test_call_list_unicode(self):
-        # See github issue #328
-        mock = Mock()
-
-        class NonAsciiRepr(object):
-            def __repr__(self):
-                return "\xe9"
-
-        mock(**{unicode("a"): NonAsciiRepr()})
-
-        self.assertEqual(str(mock.mock_calls), "[call(a=\xe9)]")
-
-
     def test_propertymock(self):
         p = patch('%s.SomeClass.one' % __name__, new_callable=PropertyMock)
         mock = p.start()
diff --git a/mock/tests/testhelpers_py3.py b/mock/tests/testhelpers_py3.py
deleted file mode 100644
index 64d62f8..0000000
--- a/mock/tests/testhelpers_py3.py
+++ /dev/null
@@ -1,23 +0,0 @@
-import inspect
-import unittest
-
-from mock import call, create_autospec
-
-
-class CallTest(unittest.TestCase):
-
-
-    def test_spec_inspect_signature_annotations(self):
-
-        def foo(a: int, b: int=10, *, c:int) -> int:
-            return a + b + c
-
-        self.assertEqual(foo(1, 2, c=3), 6)
-        mock = create_autospec(foo)
-        mock(1, 2, c=3)
-        mock(1, c=3)
-
-        self.assertEqual(inspect.getfullargspec(mock), inspect.getfullargspec(foo))
-        self.assertEqual(mock.mock_calls, [call(1, 2, c=3), call(1, c=3)])
-        self.assertRaises(TypeError, mock, 1)
-        self.assertRaises(TypeError, mock, 1, 2, 3, c=4)
diff --git a/mock/tests/testmagicmethods.py b/mock/tests/testmagicmethods.py
index f6c25fb..e1f1ee0 100644
--- a/mock/tests/testmagicmethods.py
+++ b/mock/tests/testmagicmethods.py
@@ -1,29 +1,11 @@
-# Copyright (C) 2007-2012 Michael Foord & the mock team
-# E-mail: fuzzyman AT voidspace DOT org DOT uk
-# http://www.voidspace.org.uk/python/mock/
-
-from __future__ import division
-
-try:
-    unicode
-except NameError:
-    # Python 3
-    unicode = str
-    long = int
-
 import math
-import os
-import sys
-import textwrap
 import unittest
-
-import six
-
-from mock import Mock, MagicMock
+import os
+from mock import AsyncMock, Mock, MagicMock
+from mock.backports import iscoroutinefunction
 from mock.mock import _magics
 
 
-
 class TestMockingMagicMethods(unittest.TestCase):
 
     def test_deleting_magic_methods(self):
@@ -87,15 +69,6 @@
         self.assertEqual(str(mock), 'foo')
 
 
-    @unittest.skipIf(six.PY3, "no unicode in Python 3")
-    def test_unicode(self):
-        mock = Mock()
-        self.assertEqual(unicode(mock), unicode(str(mock)))
-
-        mock.__unicode__ = lambda s: unicode('foo')
-        self.assertEqual(unicode(mock), unicode('foo'))
-
-
     def test_dict_methods(self):
         mock = Mock()
 
@@ -167,16 +140,13 @@
         self.assertEqual(mock.value, 16)
 
         del mock.__truediv__
-        if six.PY3:
-            def itruediv(mock):
-                mock /= 4
-            self.assertRaises(TypeError, itruediv, mock)
-            mock.__itruediv__ = truediv
-            mock /= 8
-            self.assertEqual(mock, original)
-            self.assertEqual(mock.value, 2)
-        else:
-            mock.value = 2
+        def itruediv(mock):
+            mock /= 4
+        self.assertRaises(TypeError, itruediv, mock)
+        mock.__itruediv__ = truediv
+        mock /= 8
+        self.assertEqual(mock, original)
+        self.assertEqual(mock.value, 2)
 
         self.assertRaises(TypeError, lambda: 8 / mock)
         mock.__rtruediv__ = truediv
@@ -198,12 +168,7 @@
         m = Mock()
         self.assertTrue(bool(m))
 
-        nonzero = lambda s: False
-        if six.PY2:
-            m.__nonzero__ = nonzero
-        else:
-            m.__bool__ = nonzero
-
+        m.__bool__ = lambda s: False
         self.assertFalse(bool(m))
 
 
@@ -217,25 +182,18 @@
         self. assertTrue(mock <= 3)
         self. assertTrue(mock >= 3)
 
-        if six.PY2:
-            # incomparable in Python 3
-            self.assertEqual(Mock() < 3, object() < 3)
-            self.assertEqual(Mock() > 3, object() > 3)
-            self.assertEqual(Mock() <= 3, object() <= 3)
-            self.assertEqual(Mock() >= 3, object() >= 3)
-        else:
-            self.assertRaises(TypeError, lambda: MagicMock() < object())
-            self.assertRaises(TypeError, lambda: object() < MagicMock())
-            self.assertRaises(TypeError, lambda: MagicMock() < MagicMock())
-            self.assertRaises(TypeError, lambda: MagicMock() > object())
-            self.assertRaises(TypeError, lambda: object() > MagicMock())
-            self.assertRaises(TypeError, lambda: MagicMock() > MagicMock())
-            self.assertRaises(TypeError, lambda: MagicMock() <= object())
-            self.assertRaises(TypeError, lambda: object() <= MagicMock())
-            self.assertRaises(TypeError, lambda: MagicMock() <= MagicMock())
-            self.assertRaises(TypeError, lambda: MagicMock() >= object())
-            self.assertRaises(TypeError, lambda: object() >= MagicMock())
-            self.assertRaises(TypeError, lambda: MagicMock() >= MagicMock())
+        self.assertRaises(TypeError, lambda: MagicMock() < object())
+        self.assertRaises(TypeError, lambda: object() < MagicMock())
+        self.assertRaises(TypeError, lambda: MagicMock() < MagicMock())
+        self.assertRaises(TypeError, lambda: MagicMock() > object())
+        self.assertRaises(TypeError, lambda: object() > MagicMock())
+        self.assertRaises(TypeError, lambda: MagicMock() > MagicMock())
+        self.assertRaises(TypeError, lambda: MagicMock() <= object())
+        self.assertRaises(TypeError, lambda: object() <= MagicMock())
+        self.assertRaises(TypeError, lambda: MagicMock() <= MagicMock())
+        self.assertRaises(TypeError, lambda: MagicMock() >= object())
+        self.assertRaises(TypeError, lambda: object() >= MagicMock())
+        self.assertRaises(TypeError, lambda: MagicMock() >= MagicMock())
 
 
     def test_equality(self):
@@ -293,12 +251,8 @@
         mock.__iter__.return_value = iter([1, 2, 3])
         self.assertEqual(list(mock), [1, 2, 3])
 
-        name = '__nonzero__'
-        other = '__bool__'
-        if six.PY3:
-            name, other = other, name
-        getattr(mock, name).return_value = False
-        self.assertFalse(hasattr(mock, other))
+        getattr(mock, '__bool__').return_value = False
+        self.assertFalse(hasattr(mock, '__nonzero__'))
         self.assertFalse(bool(mock))
 
         for entry in _magics:
@@ -316,61 +270,66 @@
         self.assertEqual(mock == mock, True)
         self.assertEqual(mock != mock, False)
 
+    def test_asyncmock_defaults(self):
+        mock = AsyncMock()
+        self.assertEqual(int(mock), 1)
+        self.assertEqual(complex(mock), 1j)
+        self.assertEqual(float(mock), 1.0)
+        self.assertNotIn(object(), mock)
+        self.assertEqual(len(mock), 0)
+        self.assertEqual(list(mock), [])
+        self.assertEqual(hash(mock), object.__hash__(mock))
+        self.assertEqual(str(mock), object.__str__(mock))
+        self.assertTrue(bool(mock))
+        self.assertEqual(round(mock), mock.__round__())
+        self.assertEqual(math.trunc(mock), mock.__trunc__())
+        self.assertEqual(math.floor(mock), mock.__floor__())
+        self.assertEqual(math.ceil(mock), mock.__ceil__())
+        self.assertTrue(iscoroutinefunction(mock.__aexit__))
+        self.assertTrue(iscoroutinefunction(mock.__aenter__))
+        self.assertIsInstance(mock.__aenter__, AsyncMock)
+        self.assertIsInstance(mock.__aexit__, AsyncMock)
+
+        # in Python 3 oct and hex use __index__
+        # so these tests are for __index__ in py3k
+        self.assertEqual(oct(mock), '0o1')
+        self.assertEqual(hex(mock), '0x1')
+        # how to test __sizeof__ ?
 
     def test_magicmock_defaults(self):
         mock = MagicMock()
         self.assertEqual(int(mock), 1)
         self.assertEqual(complex(mock), 1j)
         self.assertEqual(float(mock), 1.0)
-        self.assertEqual(long(mock), long(1))
         self.assertNotIn(object(), mock)
         self.assertEqual(len(mock), 0)
         self.assertEqual(list(mock), [])
         self.assertEqual(hash(mock), object.__hash__(mock))
         self.assertEqual(str(mock), object.__str__(mock))
-        self.assertEqual(unicode(mock), object.__str__(mock))
-        self.assertIsInstance(unicode(mock), unicode)
         self.assertTrue(bool(mock))
+        self.assertEqual(round(mock), mock.__round__())
         self.assertEqual(math.trunc(mock), mock.__trunc__())
-        if six.PY2:
-            # These fall back to __float__ in Python 2:
-            self.assertEqual(round(mock), 1.0)
-            self.assertEqual(math.floor(mock), 1.0)
-            self.assertEqual(math.ceil(mock), 1.0)
-        else:
-            self.assertEqual(round(mock), mock.__round__())
-            self.assertEqual(math.floor(mock), mock.__floor__())
-            self.assertEqual(math.ceil(mock), mock.__ceil__())
-        if six.PY2:
-            self.assertEqual(oct(mock), '1')
-        else:
-            # in Python 3 oct and hex use __index__
-            # so these tests are for __index__ in py3k
-            self.assertEqual(oct(mock), '0o1')
+        self.assertEqual(math.floor(mock), mock.__floor__())
+        self.assertEqual(math.ceil(mock), mock.__ceil__())
+        self.assertTrue(iscoroutinefunction(mock.__aexit__))
+        self.assertTrue(iscoroutinefunction(mock.__aenter__))
+        self.assertIsInstance(mock.__aenter__, AsyncMock)
+        self.assertIsInstance(mock.__aexit__, AsyncMock)
+
+        # in Python 3 oct and hex use __index__
+        # so these tests are for __index__ in py3k
+        self.assertEqual(oct(mock), '0o1')
         self.assertEqual(hex(mock), '0x1')
         # how to test __sizeof__ ?
 
 
-    @unittest.skipIf(six.PY3, "no __cmp__ in Python 3")
-    def test_non_default_magic_methods(self):
-        mock = MagicMock()
-        self.assertRaises(AttributeError, lambda: mock.__cmp__)
-
-        mock = Mock()
-        mock.__cmp__ = lambda s, o: 0
-
-        self.assertEqual(mock, object())
-
-
     def test_magic_methods_fspath(self):
         mock = MagicMock()
-        if sys.version_info < (3, 6):
-            self.assertRaises(AttributeError, lambda: mock.__fspath__)
-        else:
-            expected_path = mock.__fspath__()
-            mock.reset_mock()
-            self.assertEqual(os.fspath(mock), expected_path)
-            mock.__fspath__.assert_called_once()
+        expected_path = mock.__fspath__()
+        mock.reset_mock()
+
+        self.assertEqual(os.fspath(mock), expected_path)
+        mock.__fspath__.assert_called_once()
 
 
     def test_magic_methods_and_spec(self):
@@ -425,7 +384,7 @@
         mock = MagicMock()
         def set_setattr():
             mock.__setattr__ = lambda self, name: None
-        self.assertRaisesRegexp(AttributeError,
+        self.assertRaisesRegex(AttributeError,
             "Attempting to set unsupported magic method '__setattr__'.",
             set_setattr
         )
@@ -459,6 +418,7 @@
         mock.reset_mock()
         self.assertFalse(mock.__str__.called)
 
+
     def test_dir(self):
         # overriding the default implementation
         for mock in Mock(), MagicMock():
@@ -468,7 +428,6 @@
             self.assertEqual(dir(mock), ['foo'])
 
 
-    @unittest.skipIf('PyPy' in sys.version, "This fails differently on pypy")
     def test_bound_methods(self):
         m = Mock()
 
@@ -504,20 +463,17 @@
         self.assertEqual(list(m), [4, 5, 6])
         self.assertEqual(list(m), [])
 
-    @unittest.skipIf(sys.version_info < (3, 5), "@ added in Python 3.5")
+
     def test_matmul(self):
-        src = textwrap.dedent("""\
-            m = MagicMock()
-            self.assertIsInstance(m @ 1, MagicMock)
-            m.__matmul__.return_value = 42
-            m.__rmatmul__.return_value = 666
-            m.__imatmul__.return_value = 24
-            self.assertEqual(m @ 1, 42)
-            self.assertEqual(1 @ m, 666)
-            m @= 24
-            self.assertEqual(m, 24)
-        """)
-        exec(src)
+        m = MagicMock()
+        self.assertIsInstance(m @ 1, MagicMock)
+        m.__matmul__.return_value = 42
+        m.__rmatmul__.return_value = 666
+        m.__imatmul__.return_value = 24
+        self.assertEqual(m @ 1, 42)
+        self.assertEqual(1 @ m, 666)
+        m @= 24
+        self.assertEqual(m, 24)
 
     def test_divmod_and_rdivmod(self):
         m = MagicMock()
diff --git a/mock/tests/testmock.py b/mock/tests/testmock.py
index 5f6045a..8bb8759 100644
--- a/mock/tests/testmock.py
+++ b/mock/tests/testmock.py
@@ -1,30 +1,18 @@
-# Copyright (C) 2007-2012 Michael Foord & the mock team
-# E-mail: fuzzyman AT voidspace DOT org DOT uk
-# http://www.voidspace.org.uk/python/mock/
-
 import copy
-import pickle
 import re
 import sys
 import tempfile
 
-import six
 import unittest
-
-import mock
-from mock.mock import (
+from mock.tests.support import ALWAYS_EQ
+from mock.tests.support import is_instance
+from mock import (
     call, DEFAULT, patch, sentinel,
     MagicMock, Mock, NonCallableMock,
-    NonCallableMagicMock, _Call, _CallList,
-    create_autospec
+    NonCallableMagicMock, AsyncMock,
+    create_autospec, mock
 )
-from mock.tests.support import is_instance
-
-
-try:
-    unicode
-except NameError:
-    unicode = str
+from mock.mock import _Call, _CallList
 
 
 class Iter(object):
@@ -50,14 +38,7 @@
     def smeth(a, b, c, d=None): pass
 
 
-class Subclass(MagicMock):
-    pass
-
-
-class Thing(object):
-    attribute = 6
-    foo = 'bar'
-
+def something(a): pass
 
 
 class MockTest(unittest.TestCase):
@@ -66,7 +47,7 @@
         # if __all__ is badly defined then import * will raise an error
         # We have to exec it because you can't import * inside a method
         # in Python 3
-        exec("from mock import *")
+        exec("from unittest.mock import *")
 
 
     def test_constructor(self):
@@ -215,7 +196,8 @@
 
         mock = create_autospec(f)
         mock.side_effect = ValueError('Bazinga!')
-        self.assertRaisesRegexp(ValueError, 'Bazinga!', mock)
+        self.assertRaisesRegex(ValueError, 'Bazinga!', mock)
+
 
     def test_reset_mock(self):
         parent = Mock()
@@ -281,7 +263,7 @@
 
         ret_val = mock(sentinel.Arg)
         self.assertTrue(mock.called, "called not set")
-        self.assertEqual(mock.call_count, 1, "call_count incoreect")
+        self.assertEqual(mock.call_count, 1, "call_count incorrect")
         self.assertEqual(mock.call_args, ((sentinel.Arg,), {}),
                          "call_args not set")
         self.assertEqual(mock.call_args.args, (sentinel.Arg,),
@@ -341,6 +323,8 @@
         self.assertFalse(mm != mock.ANY)
         self.assertTrue(mock.ANY == mm)
         self.assertFalse(mock.ANY != mm)
+        self.assertTrue(mm == ALWAYS_EQ)
+        self.assertFalse(mm != ALWAYS_EQ)
 
         call1 = mock.call(mock.MagicMock())
         call2 = mock.call(mock.ANY)
@@ -349,6 +333,11 @@
         self.assertTrue(call2 == call1)
         self.assertFalse(call2 != call1)
 
+        self.assertTrue(call1 == ALWAYS_EQ)
+        self.assertFalse(call1 != ALWAYS_EQ)
+        self.assertFalse(call1 == 1)
+        self.assertTrue(call1 != 1)
+
 
     def test_assert_called_with(self):
         mock = Mock()
@@ -384,8 +373,7 @@
         # Expected call doesn't match the spec's signature
         with self.assertRaises(AssertionError) as cm:
             mock.assert_called_with(e=8)
-        if hasattr(cm.exception, '__cause__'):
-            self.assertIsInstance(cm.exception.__cause__, TypeError)
+        self.assertIsInstance(cm.exception.__cause__, TypeError)
 
 
     def test_assert_called_with_method_spec(self):
@@ -408,6 +396,14 @@
         _check(mock)
 
 
+    def test_assert_called_exception_message(self):
+        msg = "Expected '{0}' to have been called"
+        with self.assertRaisesRegex(AssertionError, msg.format('mock')):
+            Mock().assert_called()
+        with self.assertRaisesRegex(AssertionError, msg.format('test_name')):
+            Mock(name="test_name").assert_called()
+
+
     def test_assert_called_once_with(self):
         mock = Mock()
         mock()
@@ -435,7 +431,7 @@
         m = Mock()
         m(1)
         m(2)
-        self.assertRaisesRegexp(AssertionError,
+        self.assertRaisesRegex(AssertionError,
             re.escape("Calls: [call(1), call(2)]"),
             lambda: m.assert_called_once_with(2))
 
@@ -453,8 +449,7 @@
         # Expected call doesn't match the spec's signature
         with self.assertRaises(AssertionError) as cm:
             mock.assert_called_once_with(e=8)
-        if hasattr(cm.exception, '__cause__'):
-            self.assertIsInstance(cm.exception.__cause__, TypeError)
+        self.assertIsInstance(cm.exception.__cause__, TypeError)
         # Mock called more than once => always fails
         mock(4, 5, 6)
         self.assertRaises(AssertionError, mock.assert_called_once_with,
@@ -535,7 +530,7 @@
 
                 # this should be allowed
                 mock.something
-                self.assertRaisesRegexp(
+                self.assertRaisesRegex(
                     AttributeError,
                     "Mock object has no attribute 'something_else'",
                     getattr, mock, 'something_else'
@@ -553,12 +548,12 @@
             mock.x
             mock.y
             mock.__something__
-            self.assertRaisesRegexp(
+            self.assertRaisesRegex(
                 AttributeError,
                 "Mock object has no attribute 'z'",
                 getattr, mock, 'z'
             )
-            self.assertRaisesRegexp(
+            self.assertRaisesRegex(
                 AttributeError,
                 "Mock object has no attribute '__foobar__'",
                 getattr, mock, '__foobar__'
@@ -720,6 +715,53 @@
         self.assertRaises(StopIteration, mock.method)
 
 
+    def test_magic_method_wraps_dict(self):
+        data = {'foo': 'bar'}
+
+        wrapped_dict = MagicMock(wraps=data)
+        self.assertEqual(wrapped_dict.get('foo'), 'bar')
+        self.assertEqual(wrapped_dict['foo'], 'bar')
+        self.assertTrue('foo' in wrapped_dict)
+
+        # return_value is non-sentinel and takes precedence over wrapped value.
+        wrapped_dict.get.return_value = 'return_value'
+        self.assertEqual(wrapped_dict.get('foo'), 'return_value')
+
+        # return_value is sentinel and hence wrapped value is returned.
+        wrapped_dict.get.return_value = sentinel.DEFAULT
+        self.assertEqual(wrapped_dict.get('foo'), 'bar')
+
+        self.assertEqual(wrapped_dict.get('baz'), None)
+        with self.assertRaises(KeyError):
+            wrapped_dict['baz']
+        self.assertFalse('bar' in wrapped_dict)
+
+        data['baz'] = 'spam'
+        self.assertEqual(wrapped_dict.get('baz'), 'spam')
+        self.assertEqual(wrapped_dict['baz'], 'spam')
+        self.assertTrue('baz' in wrapped_dict)
+
+        del data['baz']
+        self.assertEqual(wrapped_dict.get('baz'), None)
+
+
+    def test_magic_method_wraps_class(self):
+
+        class Foo:
+
+            def __getitem__(self, index):
+                return index
+
+            def __custom_method__(self):
+                return "foo"
+
+
+        klass = MagicMock(wraps=Foo)
+        obj = klass()
+        self.assertEqual(obj.__getitem__(2), 2)
+        self.assertEqual(obj.__custom_method__(), "foo")
+
+
     def test_exceptional_side_effect(self):
         mock = Mock(side_effect=AttributeError)
         self.assertRaises(AttributeError, mock)
@@ -738,13 +780,13 @@
 
     def test_assert_called_with_message(self):
         mock = Mock()
-        self.assertRaisesRegexp(AssertionError, 'not called',
+        self.assertRaisesRegex(AssertionError, 'not called',
                                 mock.assert_called_with)
 
 
     def test_assert_called_once_with_message(self):
         mock = Mock(name='geoffrey')
-        self.assertRaisesRegexp(AssertionError,
+        self.assertRaisesRegex(AssertionError,
                      r"Expected 'geoffrey' to be called once\.",
                      mock.assert_called_once_with)
 
@@ -794,10 +836,8 @@
         mock = Mock(spec=X)
         self.assertIsInstance(mock, X)
 
-        if not six.PY2:
-            # This isn't true on Py2, we should fix if anyone complains:
-            mock = Mock(spec=X())
-            self.assertIsInstance(mock, X)
+        mock = Mock(spec=X())
+        self.assertIsInstance(mock, X)
 
         self.assertIs(mock.__class__, X)
         self.assertEqual(Mock().__class__.__name__, 'Mock')
@@ -805,10 +845,8 @@
         mock = Mock(spec_set=X)
         self.assertIsInstance(mock, X)
 
-        if not six.PY2:
-        # This isn't true on Py2, we should fix if anyone complains:
-            mock = Mock(spec_set=X())
-            self.assertIsInstance(mock, X)
+        mock = Mock(spec_set=X())
+        self.assertIsInstance(mock, X)
 
 
     def test_setting_attribute_with_spec_set(self):
@@ -836,42 +874,6 @@
         copy.copy(Mock())
 
 
-    @unittest.skipIf(six.PY3, "no old style classes in Python 3")
-    def test_spec_old_style_classes(self):
-        class Foo:
-            bar = 7
-
-        mock = Mock(spec=Foo)
-        mock.bar = 6
-        self.assertRaises(AttributeError, lambda: mock.foo)
-
-        mock = Mock(spec=Foo())
-        mock.bar = 6
-        self.assertRaises(AttributeError, lambda: mock.foo)
-
-
-    @unittest.skipIf(six.PY3, "no old style classes in Python 3")
-    def test_spec_set_old_style_classes(self):
-        class Foo:
-            bar = 7
-
-        mock = Mock(spec_set=Foo)
-        mock.bar = 6
-        self.assertRaises(AttributeError, lambda: mock.foo)
-
-        def _set():
-            mock.foo = 3
-        self.assertRaises(AttributeError, _set)
-
-        mock = Mock(spec_set=Foo())
-        mock.bar = 6
-        self.assertRaises(AttributeError, lambda: mock.foo)
-
-        def _set():
-            mock.foo = 3
-        self.assertRaises(AttributeError, _set)
-
-
     def test_subclass_with_properties(self):
         class SubClass(Mock):
             def _get(self):
@@ -895,6 +897,7 @@
     def test_setting_call(self):
         mock = Mock()
         def __call__(self, a):
+            self._increment_mock_call(a)
             return self._mock_call(a)
 
         type(mock).__call__ = __call__
@@ -907,7 +910,7 @@
     def test_dir(self):
         mock = Mock()
         attrs = set(dir(mock))
-        type_attrs = {m for m in dir(Mock) if not m.startswith('_')}
+        type_attrs = set([m for m in dir(Mock) if not m.startswith('_')])
 
         # all public attributes from the type are included
         self.assertEqual(set(), type_attrs - attrs)
@@ -1180,7 +1183,7 @@
         m = Mock()
         m.foo = m
         repr(m.foo())
-        self.assertRegexpMatches(repr(m.foo()), r"<Mock name='mock\(\)' id='\d+'>")
+        self.assertRegex(repr(m.foo()), r"<Mock name='mock\(\)' id='\d+'>")
 
 
     def test_mock_calls_contains(self):
@@ -1280,6 +1283,16 @@
         self.assertRaises(StopIteration, mock)
 
 
+    def test_side_effect_iterator_exceptions(self):
+        for Klass in Mock, MagicMock:
+            iterable = (ValueError, 3, KeyError, 6)
+            m = Klass(side_effect=iterable)
+            self.assertRaises(ValueError, m)
+            self.assertEqual(m(), 3)
+            self.assertRaises(KeyError, m)
+            self.assertEqual(m(), 6)
+
+
     def test_side_effect_setting_iterator(self):
         mock = Mock()
         mock.side_effect = iter([1, 2, 3])
@@ -1301,17 +1314,6 @@
         self.assertRaises(StopIteration, mock)
         self.assertIs(mock.side_effect, this_iter)
 
-
-    def test_side_effect_iterator_exceptions(self):
-        for Klass in Mock, MagicMock:
-            iterable = (ValueError, 3, KeyError, 6)
-            m = Klass(side_effect=iterable)
-            self.assertRaises(ValueError, m)
-            self.assertEqual(m(), 3)
-            self.assertRaises(KeyError, m)
-            self.assertEqual(m(), 6)
-
-
     def test_side_effect_iterator_default(self):
         mock = Mock(return_value=2)
         mock.side_effect = iter([1, DEFAULT])
@@ -1401,6 +1403,54 @@
                         )
 
 
+    def test_assert_has_calls_nested_spec(self):
+        class Something:
+
+            def __init__(self): pass
+            def meth(self, a, b, c, d=None): pass
+
+            class Foo:
+
+                def __init__(self, a): pass
+                def meth1(self, a, b): pass
+
+        mock_class = create_autospec(Something)
+
+        for m in [mock_class, mock_class()]:
+            m.meth(1, 2, 3, d=1)
+            m.assert_has_calls([call.meth(1, 2, 3, d=1)])
+            m.assert_has_calls([call.meth(1, 2, 3, 1)])
+
+        mock_class.reset_mock()
+
+        for m in [mock_class, mock_class()]:
+            self.assertRaises(AssertionError, m.assert_has_calls, [call.Foo()])
+            m.Foo(1).meth1(1, 2)
+            m.assert_has_calls([call.Foo(1), call.Foo(1).meth1(1, 2)])
+            m.Foo.assert_has_calls([call(1), call().meth1(1, 2)])
+
+        mock_class.reset_mock()
+
+        invalid_calls = [call.meth(1),
+                         call.non_existent(1),
+                         call.Foo().non_existent(1),
+                         call.Foo().meth(1, 2, 3, 4)]
+
+        for kall in invalid_calls:
+            self.assertRaises(AssertionError,
+                              mock_class.assert_has_calls,
+                              [kall]
+            )
+
+
+    def test_assert_has_calls_nested_without_spec(self):
+        m = MagicMock()
+        m().foo().bar().baz()
+        m.one().two().three()
+        calls = call.one().two().three().call_list()
+        m.assert_has_calls(calls)
+
+
     def test_assert_has_calls_with_function_spec(self):
         def f(a, b, c, d=None): pass
 
@@ -1432,6 +1482,34 @@
             mock.assert_has_calls(calls[:-1])
         mock.assert_has_calls(calls[:-1], any_order=True)
 
+    def test_assert_has_calls_not_matching_spec_error(self):
+        def f(x=None): pass
+
+        mock = Mock(spec=f)
+        mock(1)
+
+        with self.assertRaisesRegex(
+                AssertionError,
+                '^{}$'.format(
+                    re.escape('Calls not found.\n'
+                              'Expected: [call()]\n'
+                              'Actual: [call(1)]'))) as cm:
+            mock.assert_has_calls([call()])
+        self.assertIsNone(cm.exception.__cause__)
+
+
+        with self.assertRaisesRegex(
+                AssertionError,
+                '^{}$'.format(
+                    re.escape(
+                        'Error processing expected calls.\n'
+                        "Errors: [None, TypeError('too many positional arguments')]\n"
+                        "Expected: [call(), call(1, 2)]\n"
+                        'Actual: [call(1)]').replace(
+                            "arguments\\'", "arguments\\',?"
+                    ))) as cm:
+            mock.assert_has_calls([call(), call(1, 2)])
+        self.assertIsInstance(cm.exception.__cause__, TypeError)
 
     def test_assert_any_call(self):
         mock = Mock()
@@ -1475,8 +1553,7 @@
         # Expected call doesn't match the spec's signature
         with self.assertRaises(AssertionError) as cm:
             mock.assert_any_call(e=8)
-        if hasattr(cm.exception, '__cause__'):
-            self.assertIsInstance(cm.exception.__cause__, TypeError)
+        self.assertIsInstance(cm.exception.__cause__, TypeError)
 
 
     def test_mock_calls_create_autospec(self):
@@ -1510,6 +1587,7 @@
             @staticmethod
             def static_method(): pass
         for method in ('class_method', 'static_method'):
+            with self.subTest(method=method):
                 mock_method = mock.create_autospec(getattr(TestClass, method))
                 mock_method()
                 mock_method.assert_called_once_with()
@@ -1518,9 +1596,10 @@
     #Issue21238
     def test_mock_unsafe(self):
         m = Mock()
-        with self.assertRaises(AttributeError):
+        msg = "Attributes cannot start with 'assert' or 'assret'"
+        with self.assertRaisesRegex(AttributeError, msg):
             m.assert_foo_call()
-        with self.assertRaises(AttributeError):
+        with self.assertRaisesRegex(AttributeError, msg):
             m.assret_foo_call()
         m = Mock(unsafe=True)
         m.assert_foo_call()
@@ -1537,7 +1616,7 @@
     def test_assert_not_called_message(self):
         m = Mock()
         m(1, 2)
-        self.assertRaisesRegexp(AssertionError,
+        self.assertRaisesRegex(AssertionError,
             re.escape("Calls: [call(1, 2)]"),
             m.assert_not_called)
 
@@ -1566,7 +1645,7 @@
         m = Mock()
         m(1, 2)
         m(3)
-        self.assertRaisesRegexp(AssertionError,
+        self.assertRaisesRegex(AssertionError,
             re.escape("Calls: [call(1, 2), call(3)]"),
             m.assert_called_once)
 
@@ -1576,11 +1655,11 @@
             m.assert_called_once()
         self.assertNotIn("Calls:", str(e.exception))
 
-    #Issue21256 printout of keyword args should be in deterministic order
-    def test_sorted_call_signature(self):
+    #Issue37212 printout of keyword args now preserves the original order
+    def test_ordered_call_signature(self):
         m = Mock()
         m.hello(name='hello', daddy='hero')
-        text = "call(daddy='hero', name='hello')"
+        text = "call(name='hello', daddy='hero')"
         self.assertEqual(repr(m.hello.call_args), text)
 
     #Issue21270 overrides tuple methods for mock.call objects
@@ -1606,11 +1685,23 @@
         self.assertNotEqual(m.side_effect, None)
 
     def test_reset_sideeffect(self):
-        m = Mock(return_value=10, side_effect=[2,3])
+        m = Mock(return_value=10, side_effect=[2, 3])
         m.reset_mock(side_effect=True)
         self.assertEqual(m.return_value, 10)
         self.assertEqual(m.side_effect, None)
 
+    def test_reset_return_with_children(self):
+        m = MagicMock(f=MagicMock(return_value=1))
+        self.assertEqual(m.f(), 1)
+        m.reset_mock(return_value=True)
+        self.assertNotEqual(m.f(), 1)
+
+    def test_reset_return_with_children_side_effect(self):
+        m = MagicMock(f=MagicMock(side_effect=[2, 3]))
+        self.assertNotEqual(m.f.side_effect, None)
+        m.reset_mock(side_effect=True)
+        self.assertEqual(m.f.side_effect, None)
+
     def test_mock_add_spec(self):
         class _One(object):
             one = 1
@@ -1682,7 +1773,8 @@
 
 
     def test_adding_child_mock(self):
-        for Klass in NonCallableMock, Mock, MagicMock, NonCallableMagicMock:
+        for Klass in (NonCallableMock, Mock, MagicMock, NonCallableMagicMock,
+                      AsyncMock):
             mock = Klass()
 
             mock.foo = Mock()
@@ -1765,6 +1857,24 @@
         self.assertEqual(lines[1], 'Norwegian Blue')
         self.assertEqual(list(f1), [])
 
+    def test_mock_open_using_next(self):
+        mocked_open = mock.mock_open(read_data='1st line\n2nd line\n3rd line')
+        f1 = mocked_open('a-name')
+        line1 = next(f1)
+        line2 = f1.__next__()
+        lines = [line for line in f1]
+        self.assertEqual(line1, '1st line\n')
+        self.assertEqual(line2, '2nd line\n')
+        self.assertEqual(lines[0], '3rd line')
+        self.assertEqual(list(f1), [])
+        with self.assertRaises(StopIteration):
+            next(f1)
+
+    def test_mock_open_next_with_readline_with_return_value(self):
+        mopen = mock.mock_open(read_data='foo\nbarn')
+        mopen.return_value.readline.return_value = 'abc'
+        self.assertEqual('abc', next(mopen()))
+
     def test_mock_open_write(self):
         # Test exception in file writing write()
         mock_namedtemp = mock.mock_open(mock.MagicMock(name='JLV'))
@@ -1784,7 +1894,6 @@
         self.assertEqual('abc', first)
         self.assertEqual('abc', second)
 
-
     def test_mock_open_after_eof(self):
         # read, readline and readlines should work after end of file.
         _open = mock.mock_open(read_data='foo')
@@ -1797,7 +1906,6 @@
         self.assertEqual([], h.readlines())
         self.assertEqual([], h.readlines())
 
-
     def test_mock_parents(self):
         for Klass in Mock, MagicMock:
             m = Klass()
@@ -1860,6 +1968,55 @@
                 self.assertEqual(m.mock_calls, call().foo().call_list())
 
 
+    def test_attach_mock_patch_autospec(self):
+        parent = Mock()
+
+        with mock.patch(f'{__name__}.something', autospec=True) as mock_func:
+            self.assertEqual(mock_func.mock._extract_mock_name(), 'something')
+            parent.attach_mock(mock_func, 'child')
+            parent.child(1)
+            something(2)
+            mock_func(3)
+
+            parent_calls = [call.child(1), call.child(2), call.child(3)]
+            child_calls = [call(1), call(2), call(3)]
+            self.assertEqual(parent.mock_calls, parent_calls)
+            self.assertEqual(parent.child.mock_calls, child_calls)
+            self.assertEqual(something.mock_calls, child_calls)
+            self.assertEqual(mock_func.mock_calls, child_calls)
+            self.assertIn('mock.child', repr(parent.child.mock))
+            self.assertEqual(mock_func.mock._extract_mock_name(), 'mock.child')
+
+
+    def test_attach_mock_patch_autospec_signature(self):
+        with mock.patch(f'{__name__}.Something.meth', autospec=True) as mocked:
+            manager = Mock()
+            manager.attach_mock(mocked, 'attach_meth')
+            obj = Something()
+            obj.meth(1, 2, 3, d=4)
+            manager.assert_has_calls([call.attach_meth(mock.ANY, 1, 2, 3, d=4)])
+            obj.meth.assert_has_calls([call(mock.ANY, 1, 2, 3, d=4)])
+            mocked.assert_has_calls([call(mock.ANY, 1, 2, 3, d=4)])
+
+        with mock.patch(f'{__name__}.something', autospec=True) as mocked:
+            manager = Mock()
+            manager.attach_mock(mocked, 'attach_func')
+            something(1)
+            manager.assert_has_calls([call.attach_func(1)])
+            something.assert_has_calls([call(1)])
+            mocked.assert_has_calls([call(1)])
+
+        with mock.patch(f'{__name__}.Something', autospec=True) as mocked:
+            manager = Mock()
+            manager.attach_mock(mocked, 'attach_obj')
+            obj = Something()
+            obj.meth(1, 2, 3, d=4)
+            manager.assert_has_calls([call.attach_obj(),
+                                      call.attach_obj().meth(1, 2, 3, d=4)])
+            obj.meth.assert_has_calls([call(1, 2, 3, d=4)])
+            mocked.assert_has_calls([call(), call().meth(1, 2, 3, d=4)])
+
+
     def test_attribute_deletion(self):
         for mock in (Mock(), MagicMock(), NonCallableMagicMock(),
                      NonCallableMock()):
@@ -1932,14 +2089,31 @@
         self.assertEqual(type(call.parent), _Call)
         self.assertEqual(type(call.parent().parent), _Call)
 
+
     def test_parent_propagation_with_create_autospec(self):
+
         def foo(a, b): pass
 
         mock = Mock()
         mock.child = create_autospec(foo)
         mock.child(1, 2)
+
         self.assertRaises(TypeError, mock.child, 1)
         self.assertEqual(mock.mock_calls, [call.child(1, 2)])
+        self.assertIn('mock.child', repr(mock.child.mock))
+
+    def test_parent_propagation_with_autospec_attach_mock(self):
+
+        def foo(a, b): pass
+
+        parent = Mock()
+        parent.attach_mock(create_autospec(foo, name='bar'), 'child')
+        parent.child(1, 2)
+
+        self.assertRaises(TypeError, parent.child, 1)
+        self.assertEqual(parent.child.mock_calls, [call.child(1, 2)])
+        self.assertIn('mock.child', repr(parent.child.mock))
+
 
     def test_isinstance_under_settrace(self):
         # bpo-36593 : __class__ is not set for a class that has __class__
@@ -1949,27 +2123,35 @@
         # dependent on unittest.mock.patch. In testpatch.PatchTest
         # test_patch_dict_test_prefix and test_patch_test_prefix not restoring
         # causes the objects patched to go out of sync
-        old_patch = mock.patch
+
+        old_patch = unittest.mock.patch
+
         # Directly using __setattr__ on unittest.mock causes current imported
         # reference to be updated. Use a lambda so that during cleanup the
         # re-imported new reference is updated.
-        self.addCleanup(lambda patch: setattr(mock, 'patch', patch),
+        self.addCleanup(lambda patch: setattr(unittest.mock, 'patch', patch),
                         old_patch)
+
         with patch.dict('sys.modules'):
-            del sys.modules['mock.mock']
+            del sys.modules['unittest.mock']
+
             # This trace will stop coverage being measured ;-)
             def trace(frame, event, arg):  # pragma: no cover
                 return trace
+
             self.addCleanup(sys.settrace, sys.gettrace())
             sys.settrace(trace)
-            from mock.mock import (
+
+            from unittest.mock import (
                 Mock, MagicMock, NonCallableMock, NonCallableMagicMock
             )
+
             mocks = [
-                Mock, MagicMock, NonCallableMock, NonCallableMagicMock
+                Mock, MagicMock, NonCallableMock, NonCallableMagicMock, AsyncMock
             ]
-            for mock_ in mocks:
-                obj = mock_(spec=Something)
+
+            for mock in mocks:
+                obj = mock(spec=Something)
                 self.assertIsInstance(obj, Something)
 
 
diff --git a/mock/tests/testpatch.py b/mock/tests/testpatch.py
index bbd6d26..fbf4a53 100644
--- a/mock/tests/testpatch.py
+++ b/mock/tests/testpatch.py
@@ -4,24 +4,21 @@
 
 import os
 import sys
+from collections import OrderedDict
 
-import six
 import unittest
-
 from mock.tests import support
-from mock.tests.support import SomeClass, is_instance, uncache
+from mock.tests.support import SomeClass, is_instance
 
+from .support import uncache
 from mock import (
-    NonCallableMock, CallableMixin, patch, sentinel,
-    MagicMock, Mock, NonCallableMagicMock,
+    NonCallableMock, sentinel,
+    MagicMock, Mock, NonCallableMagicMock, patch,
     DEFAULT, call
 )
-from mock.mock import _patch, _get_target
+from mock.mock import CallableMixin, _patch, _get_target
 
-builtin_string = '__builtin__'
-if six.PY3:
-    builtin_string = 'builtins'
-    unicode = str
+builtin_string = 'builtins'
 
 PTModule = sys.modules[__name__]
 MODNAME = '%s.PTModule' % __name__
@@ -109,6 +106,10 @@
         self.assertEqual(Something.attribute, sentinel.Original,
                          "patch not restored")
 
+    def test_patchobject_with_string_as_target(self):
+        msg = "'Something' must be the actual object to be patched, not a str"
+        with self.assertRaisesRegex(TypeError, msg):
+            patch.object('Something', 'do_something')
 
     def test_patchobject_with_none(self):
         class Something(object):
@@ -623,6 +624,13 @@
         self.assertEqual(foo.values, original)
 
 
+    def test_patch_dict_as_context_manager(self):
+        foo = {'a': 'b'}
+        with patch.dict(foo, a='c') as patched:
+            self.assertEqual(patched, {'a': 'c'})
+        self.assertEqual(foo, {'a': 'b'})
+
+
     def test_name_preserved(self):
         foo = {}
 
@@ -656,21 +664,15 @@
         test()
 
 
-    def test_patch_dict_with_unicode(self):
-        @patch.dict(u'os.environ', {'konrad_delong': 'some value'})
-        def test():
-            self.assertIn('konrad_delong', os.environ)
-
-        test()
-
-
     def test_patch_dict_decorator_resolution(self):
         # bpo-35512: Ensure that patch with a string target resolves to
         # the new dictionary during function call
         original = support.target.copy()
+
         @patch.dict('mock.tests.support.target', {'bar': 'BAR'})
         def test():
             self.assertEqual(support.target, {'foo': 'BAZ', 'bar': 'BAR'})
+
         try:
             support.target = {'foo': 'BAZ'}
             test()
@@ -768,6 +770,14 @@
         self.assertEqual(d, original)
 
 
+    def test_patch_dict_stop_without_start(self):
+        d = {'foo': 'bar'}
+        original = d.copy()
+        patcher = patch.dict(d, [('spam', 'eggs')], clear=True)
+        self.assertEqual(patcher.stop(), False)
+        self.assertEqual(d, original)
+
+
     def test_patch_dict_class_decorator(self):
         this = self
         d = {'spam': 'eggs'}
@@ -1329,7 +1339,7 @@
         try:
             f = result['f']
             foo = result['foo']
-            self.assertEqual(set(result), {'f', 'foo'})
+            self.assertEqual(set(result), set(['f', 'foo']))
 
             self.assertIs(Foo, original_foo)
             self.assertIs(Foo.f, f)
@@ -1533,15 +1543,14 @@
 
 
     def test_patch_multiple_string_subclasses(self):
-        for base in (str, unicode):
-            Foo = type('Foo', (base,), {'fish': 'tasty'})
-            foo = Foo()
-            @patch.multiple(foo, fish='nearly gone')
-            def test():
-                self.assertEqual(foo.fish, 'nearly gone')
+        Foo = type('Foo', (str,), {'fish': 'tasty'})
+        foo = Foo()
+        @patch.multiple(foo, fish='nearly gone')
+        def test():
+            self.assertEqual(foo.fish, 'nearly gone')
 
-            test()
-            self.assertEqual(foo.fish, 'tasty')
+        test()
+        self.assertEqual(foo.fish, 'tasty')
 
 
     @patch('mock.patch.TEST_PREFIX', 'foo')
@@ -1605,15 +1614,12 @@
 
 
     def test_patch_nested_autospec_repr(self):
-        p = patch('mock.tests.support', autospec=True)
-        m = p.start()
-        try:
+        with patch('mock.tests.support', autospec=True) as m:
             self.assertIn(" name='support.SomeClass.wibble()'",
                           repr(m.SomeClass.wibble()))
             self.assertIn(" name='support.SomeClass().wibble()'",
                           repr(m.SomeClass().wibble()))
-        finally:
-            p.stop()
+
 
 
     def test_mock_calls_with_patch(self):
@@ -1658,7 +1664,7 @@
             p1.stop()
         self.assertEqual(squizz.squozz, 3)
 
-    def test_patch_propogrates_exc_on_exit(self):
+    def test_patch_propagates_exc_on_exit(self):
         class holder:
             exc_info = None, None, None
 
@@ -1687,9 +1693,9 @@
 
         self.assertIs(holder.exc_info[0], RuntimeError)
         self.assertIsNotNone(holder.exc_info[1],
-                            'exception value not propgated')
+                            'exception value not propagated')
         self.assertIsNotNone(holder.exc_info[2],
-                            'exception traceback not propgated')
+                            'exception traceback not propagated')
 
 
     def test_create_and_specs(self):
@@ -1793,32 +1799,6 @@
         patched()
         self.assertIs(os.path, path)
 
-
-    def test_wrapped_patch(self):
-        decorated = patch('sys.modules')(function)
-        self.assertIs(decorated.__wrapped__, function)
-
-
-    def test_wrapped_several_times_patch(self):
-        decorated = patch('sys.modules')(function)
-        decorated = patch('sys.modules')(decorated)
-        self.assertIs(decorated.__wrapped__, function)
-
-
-    def test_wrapped_patch_object(self):
-        decorated = patch.object(sys, 'modules')(function)
-        self.assertIs(decorated.__wrapped__, function)
-
-
-    def test_wrapped_patch_dict(self):
-        decorated = patch.dict('sys.modules')(function)
-        self.assertIs(decorated.__wrapped__, function)
-
-
-    def test_wrapped_patch_multiple(self):
-        decorated = patch.multiple('sys', modules={})(function)
-        self.assertIs(decorated.__wrapped__, function)
-
     def test_stopall_lifo(self):
         stopped = []
         class thing(object):
@@ -1836,6 +1816,56 @@
 
         self.assertEqual(stopped, ["three", "two", "one"])
 
+    def test_patch_dict_stopall(self):
+        dic1 = {}
+        dic2 = {1: 'a'}
+        dic3 = {1: 'A', 2: 'B'}
+        origdic1 = dic1.copy()
+        origdic2 = dic2.copy()
+        origdic3 = dic3.copy()
+        patch.dict(dic1, {1: 'I', 2: 'II'}).start()
+        patch.dict(dic2, {2: 'b'}).start()
+
+        @patch.dict(dic3)
+        def patched():
+            del dic3[1]
+
+        patched()
+        self.assertNotEqual(dic1, origdic1)
+        self.assertNotEqual(dic2, origdic2)
+        self.assertEqual(dic3, origdic3)
+
+        patch.stopall()
+
+        self.assertEqual(dic1, origdic1)
+        self.assertEqual(dic2, origdic2)
+        self.assertEqual(dic3, origdic3)
+
+
+    def test_patch_and_patch_dict_stopall(self):
+        original_unlink = os.unlink
+        original_chdir = os.chdir
+        dic1 = {}
+        dic2 = {1: 'A', 2: 'B'}
+        origdic1 = dic1.copy()
+        origdic2 = dic2.copy()
+
+        patch('os.unlink', something).start()
+        patch('os.chdir', something_else).start()
+        patch.dict(dic1, {1: 'I', 2: 'II'}).start()
+        patch.dict(dic2).start()
+        del dic2[1]
+
+        self.assertIsNot(os.unlink, original_unlink)
+        self.assertIsNot(os.chdir, original_chdir)
+        self.assertNotEqual(dic1, origdic1)
+        self.assertNotEqual(dic2, origdic2)
+        patch.stopall()
+        self.assertIs(os.unlink, original_unlink)
+        self.assertIs(os.chdir, original_chdir)
+        self.assertEqual(dic1, origdic1)
+        self.assertEqual(dic2, origdic2)
+
 
     def test_special_attrs(self):
         def foo(x=0):
@@ -1851,22 +1881,40 @@
 
         with patch.object(foo, '__module__', "testpatch2"):
             self.assertEqual(foo.__module__, "testpatch2")
-        self.assertEqual(foo.__module__, __name__)
+        self.assertEqual(foo.__module__, 'mock.tests.testpatch')
 
-        if hasattr(self.test_special_attrs, '__annotations__'):
-            with patch.object(foo, '__annotations__', dict([('s', 1, )])):
-                self.assertEqual(foo.__annotations__, dict([('s', 1, )]))
-            self.assertEqual(foo.__annotations__, dict())
+        with patch.object(foo, '__annotations__', dict([('s', 1, )])):
+            self.assertEqual(foo.__annotations__, dict([('s', 1, )]))
+        self.assertEqual(foo.__annotations__, dict())
 
-        if hasattr(self.test_special_attrs, '__kwdefaults__'):
-            foo = eval("lambda *a, x=0: x")
-            with patch.object(foo, '__kwdefaults__', dict([('x', 1, )])):
-                self.assertEqual(foo(), 1)
-            self.assertEqual(foo(), 0)
+        def foo(*a, x=0):
+            return x
+        with patch.object(foo, '__kwdefaults__', dict([('x', 1, )])):
+            self.assertEqual(foo(), 1)
+        self.assertEqual(foo(), 0)
 
+    def test_patch_orderdict(self):
+        foo = OrderedDict()
+        foo['a'] = object()
+        foo['b'] = 'python'
+
+        original = foo.copy()
+        update_values = list(zip('cdefghijklmnopqrstuvwxyz', range(26)))
+        patched_values = list(foo.items()) + update_values
+
+        with patch.dict(foo, OrderedDict(update_values)):
+            self.assertEqual(list(foo.items()), patched_values)
+
+        self.assertEqual(foo, original)
+
+        with patch.dict(foo, update_values):
+            self.assertEqual(list(foo.items()), patched_values)
+
+        self.assertEqual(foo, original)
 
     def test_dotted_but_module_not_loaded(self):
         # This exercises the AttributeError branch of _dot_lookup.
+
         # make sure it's there
         import mock.tests.support
         # now make sure it's not:
@@ -1875,6 +1923,7 @@
             del sys.modules['mock.tests']
             del sys.modules['mock.mock']
             del sys.modules['mock']
+
             # now make sure we can patch based on a dotted path:
             @patch('mock.tests.support.X')
             def test(mock):
diff --git a/mock/tests/testsentinel.py b/mock/tests/testsentinel.py
index 1411445..5666434 100644
--- a/mock/tests/testsentinel.py
+++ b/mock/tests/testsentinel.py
@@ -1,7 +1,3 @@
-# Copyright (C) 2007-2012 Michael Foord & the mock team
-# E-mail: fuzzyman AT voidspace DOT org DOT uk
-# http://www.voidspace.org.uk/python/mock/
-
 import unittest
 import copy
 import pickle
@@ -31,6 +27,7 @@
 
     def testPickle(self):
         for proto in range(pickle.HIGHEST_PROTOCOL+1):
+            with self.subTest(protocol=proto):
                 pickled = pickle.dumps(sentinel.whatever, proto)
                 unpickled = pickle.loads(pickled)
                 self.assertIs(unpickled, sentinel.whatever)
diff --git a/mock/tests/testsupport.py b/mock/tests/testsupport.py
deleted file mode 100644
index 4882572..0000000
--- a/mock/tests/testsupport.py
+++ /dev/null
@@ -1,14 +0,0 @@
-# Tests to make sure helpers we backport are actually working!
-from unittest import TestCase
-
-from .support import uncache
-
-
-class TestUncache(TestCase):
-
-    def test_cant_uncache_sys(self):
-        with self.assertRaises(ValueError):
-            with uncache('sys'): pass
-
-    def test_uncache_non_existent(self):
-        with uncache('mock.tests.support.bad'): pass
diff --git a/mock/tests/testwith.py b/mock/tests/testwith.py
index 587fde9..825387b 100644
--- a/mock/tests/testwith.py
+++ b/mock/tests/testwith.py
@@ -1,15 +1,11 @@
-# Copyright (C) 2007-2012 Michael Foord & the mock team
-# E-mail: fuzzyman AT voidspace DOT org DOT uk
-# http://www.voidspace.org.uk/python/mock/
-
-from warnings import catch_warnings
-
 import unittest
+from warnings import catch_warnings
 
 from mock.tests.support import is_instance
 from mock import MagicMock, Mock, patch, sentinel, mock_open, call
 
 
+
 something  = sentinel.Something
 something_else  = sentinel.SomethingElse
 
@@ -52,11 +48,10 @@
 
     def test_with_statement_nested(self):
         with catch_warnings(record=True):
-            with patch('%s.something' % __name__) as mock_something:
-                with patch('%s.something_else' % __name__) as mock_something_else:
-                    self.assertEqual(something, mock_something, "unpatched")
-                    self.assertEqual(something_else, mock_something_else,
-                                     "unpatched")
+            with patch('%s.something' % __name__) as mock_something, patch('%s.something_else' % __name__) as mock_something_else:
+                self.assertEqual(something, mock_something, "unpatched")
+                self.assertEqual(something_else, mock_something_else,
+                                 "unpatched")
 
         self.assertEqual(something, sentinel.Something)
         self.assertEqual(something_else, sentinel.SomethingElse)
@@ -235,7 +230,22 @@
         self.assertEqual(lines[1], 'bar\n')
         self.assertEqual(lines[2], 'baz\n')
         self.assertEqual(h.readline(), '')
+        with self.assertRaises(StopIteration):
+            next(h)
 
+    def test_next_data(self):
+        # Check that next will correctly return the next available
+        # line and plays well with the dunder_iter part.
+        mock = mock_open(read_data='foo\nbar\nbaz\n')
+        with patch('%s.open' % __name__, mock, create=True):
+            h = open('bar')
+            line1 = next(h)
+            line2 = next(h)
+            lines = [l for l in h]
+        self.assertEqual(line1, 'foo\n')
+        self.assertEqual(line2, 'bar\n')
+        self.assertEqual(lines[0], 'baz\n')
+        self.assertEqual(h.readline(), '')
 
     def test_readlines_data(self):
         # Test that emulating a file that ends in a newline character works
diff --git a/release.py b/release.py
index 2556d50..3fa9406 100644
--- a/release.py
+++ b/release.py
@@ -12,7 +12,7 @@
 
 def incremented_version(version_info, type_):
     type_index = VERSION_TYPES.index(type_)
-    version_info = tuple(e+(1 if i==type_index else 0)
+    version_info = tuple(0 if i>type_index else (e+(1 if i==type_index else 0))
                          for i, e in enumerate(version_info))
     return '.'.join(str(p) for p in version_info)
 
@@ -50,7 +50,7 @@
 
 
 def update_version(new_version):
-    path = join('mock', 'mock.py')
+    path = join('mock', '__init__.py')
     with open(path) as source:
         text = source.read()
 
@@ -69,7 +69,7 @@
 def git_commit(new_version):
     git('rm NEWS.d/*')
     git('add CHANGELOG.rst')
-    git('add mock/mock.py')
+    git('add mock/__init__.py')
     git(f'commit -m "Preparing for {new_version} release."')
 
 
diff --git a/setup.cfg b/setup.cfg
index 7283b79..e25e6cc 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -5,21 +5,16 @@
 description-file = README.rst
 author = Testing Cabal
 author-email = testing-in-python@lists.idyll.org
-license = OSI Approved :: BSD License
-classifier =
+classifiers =
     Development Status :: 5 - Production/Stable
     Environment :: Console
     Intended Audience :: Developers
     License :: OSI Approved :: BSD License
     Operating System :: OS Independent
     Programming Language :: Python
-    Programming Language :: Python :: 2
-    Programming Language :: Python :: 2.7
-    Programming Language :: Python :: 3
-    Programming Language :: Python :: 3.4
-    Programming Language :: Python :: 3.5
     Programming Language :: Python :: 3.6
     Programming Language :: Python :: 3.7
+    Programming Language :: Python :: 3.8
     Programming Language :: Python :: Implementation :: CPython
     Programming Language :: Python :: Implementation :: PyPy
     Topic :: Software Development :: Libraries
@@ -29,10 +24,7 @@
     testing, test, mock, mocking, unittest, patching, stubs, fakes, doubles
 
 [options]
-install_requires =
-  six
-  funcsigs>=1;python_version<"3.3"
-python_requires=>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*
+python_requires=>=3.6
 packages = mock
 
 [options.extras_require]
@@ -46,10 +38,8 @@
   wheel
   blurb
 
-[bdist_wheel]
-universal = 1
-
 [tool:pytest]
 python_files=test*.py
 filterwarnings =
+    error::RuntimeWarning
     ignore::DeprecationWarning
diff --git a/setup.py b/setup.py
index d47345f..6f5ff41 100755
--- a/setup.py
+++ b/setup.py
@@ -5,6 +5,6 @@
 
 setuptools.setup(
     version=re.search("__version__ = '([^']+)'",
-                      open(join('mock', 'mock.py')).read()).group(1),
+                      open(join('mock', '__init__.py')).read()).group(1),
     long_description=open('README.rst').read(),
 )
diff --git a/tox.ini b/tox.ini
index 90ca455..14eb4f4 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,5 +1,5 @@
 [tox]
-envlist = py27,pypy,py34,py35,py36,py37,docs
+envlist = py36,py37,py38,docs
 
 [testenv]
 commands =