Skip to content
Snippets Groups Projects
mock.py 74.2 KiB
Newer Older
# mock.py
# Test tools for mocking and patching.
# E-mail: fuzzyman AT voidspace DOT org DOT uk
Michael Foord's avatar
Michael Foord committed
#
Michael Foord's avatar
Michael Foord committed
# mock 1.0.1
# http://www.voidspace.org.uk/python/mock/
Michael Foord's avatar
Michael Foord committed
#
# 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.

__all__ = (
    'Mock',
    'MagicMock',
    'patch',
    'sentinel',
    'DEFAULT',
    'ANY',
    'call',
    'create_autospec',
    'FILTER_DIR',
    'NonCallableMock',
    'NonCallableMagicMock',
Michael Foord's avatar
Michael Foord committed
    'mock_open',
Michael Foord's avatar
Michael Foord committed
    'PropertyMock',
import inspect
from functools import wraps as original_wraps
if sys.version_info[:2] >= (3, 2):
    wraps = original_wraps
else:
    # Emulate 3.2+ functools.
    def wraps(func):
            f = original_wraps(func)(f)
            wrapped = getattr(func, '__wrapped__', func)
            f.__wrapped__ = wrapped
# TODO: use six.
try:
    unicode
except NameError:
    # Python 3
    basestring = unicode = str

try:
    long
except NameError:
    # Python 3
    long = int

try:
    BaseException
except NameError:
    # Python 2.4 compatibility
    BaseException = Exception

try:
    next
except NameError:
    def next(obj):
        return obj.next()


BaseExceptions = (BaseException,)
if 'java' in sys.platform:
    # jython
    import java
    BaseExceptions = (BaseException, java.lang.Throwable)

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)


inPy3k = sys.version_info[0] == 3

# Needed to work around Python 3 bug where use of "super" interferes with
# defining __class__ as a descriptor
_super = super

self = 'im_self'
builtin = '__builtin__'
if inPy3k:
    self = '__self__'
    builtin = 'builtins'

FILTER_DIR = True


def _is_instance_mock(obj):
    # can't use isinstance on Mock objects because they override __class__
    # The base class for all mocks is NonCallableMock
    return issubclass(type(obj), NonCallableMock)


def _is_exception(obj):
    return (
        isinstance(obj, BaseExceptions) or
        isinstance(obj, ClassTypes) and issubclass(obj, BaseExceptions)
    )


class _slotted(object):
    __slots__ = ['a']


DescriptorTypes = (
    type(_slotted.a),
    property,
)


def _getsignature(func, skipfirst, instance=False):
    if isinstance(func, ClassTypes) and not instance:
        try:
            func = func.__init__
        except AttributeError:
            return
        skipfirst = True
    elif not isinstance(func, FunctionTypes):
        # for classes where instance is True we end up here too
        try:
            func = func.__call__
        except AttributeError:
            return

    if inPy3k:
        try:
            argspec = inspect.getfullargspec(func)
        except TypeError:
            # C function / method, possibly inherited object().__init__
            return
        regargs, varargs, varkw, defaults, kwonly, kwonlydef, ann = argspec
    else:
        try:
            regargs, varargs, varkwargs, defaults = inspect.getargspec(func)
        except TypeError:
            # C function / method, possibly inherited object().__init__
            return

    # instance methods and classmethods need to lose the self argument
    if getattr(func, self, None) is not None:
        regargs = regargs[1:]
    if skipfirst:
        # this condition and the above one are never both True - why?
        regargs = regargs[1:]

    if inPy3k:
        signature = inspect.formatargspec(
            regargs, varargs, varkw, defaults,
            kwonly, kwonlydef, ann, formatvalue=lambda value: "")
    else:
        signature = inspect.formatargspec(
            regargs, varargs, varkwargs, defaults,
            formatvalue=lambda value: "")
Loading
Loading full blame...