thirdparty/mocker/mocker.py
changeset 104 5a2786fd5048
equal deleted inserted replaced
103:094c8f741a08 104:5a2786fd5048
       
     1 """
       
     2 Copyright (c) 2007  Gustavo Niemeyer <gustavo@niemeyer.net>
       
     3 
       
     4 Graceful platform for test doubles in Python (mocks, stubs, fakes, and dummies).
       
     5 """
       
     6 import __builtin__
       
     7 import tempfile
       
     8 import unittest
       
     9 import inspect
       
    10 import shutil
       
    11 import types
       
    12 import sys
       
    13 import os
       
    14 import gc
       
    15 
       
    16 
       
    17 if sys.version_info < (2, 4):
       
    18     from sets import Set as set # pragma: nocover
       
    19 
       
    20 
       
    21 __all__ = ["Mocker", "expect", "IS", "CONTAINS", "IN", "MATCH",
       
    22            "ANY", "ARGS", "KWARGS"]
       
    23 
       
    24 
       
    25 __author__ = "Gustavo Niemeyer <gustavo@niemeyer.net>"
       
    26 __license__ = "PSF License"
       
    27 __version__ = "0.10.1"
       
    28 
       
    29 
       
    30 ERROR_PREFIX = "[Mocker] "
       
    31 
       
    32 
       
    33 # --------------------------------------------------------------------
       
    34 # Exceptions
       
    35 
       
    36 class MatchError(AssertionError):
       
    37     """Raised when an unknown expression is seen in playback mode."""
       
    38 
       
    39 
       
    40 # --------------------------------------------------------------------
       
    41 # Helper for chained-style calling.
       
    42 
       
    43 class expect(object):
       
    44     """This is a simple helper that allows a different call-style.
       
    45 
       
    46     With this class one can comfortably do chaining of calls to the
       
    47     mocker object responsible by the object being handled. For instance::
       
    48 
       
    49         expect(obj.attr).result(3).count(1, 2)
       
    50 
       
    51     Is the same as::
       
    52 
       
    53         obj.attr
       
    54         mocker.result(3)
       
    55         mocker.count(1, 2)
       
    56 
       
    57     """
       
    58 
       
    59     def __init__(self, mock, attr=None):
       
    60         self._mock = mock
       
    61         self._attr = attr
       
    62 
       
    63     def __getattr__(self, attr):
       
    64         return self.__class__(self._mock, attr)
       
    65 
       
    66     def __call__(self, *args, **kwargs):
       
    67         getattr(self._mock.__mocker__, self._attr)(*args, **kwargs)
       
    68         return self
       
    69 
       
    70 
       
    71 # --------------------------------------------------------------------
       
    72 # Extensions to Python's unittest.
       
    73 
       
    74 class MockerTestCase(unittest.TestCase):
       
    75     """unittest.TestCase subclass with Mocker support.
       
    76 
       
    77     @ivar mocker: The mocker instance.
       
    78 
       
    79     This is a convenience only.  Mocker may easily be used with the
       
    80     standard C{unittest.TestCase} class if wanted.
       
    81 
       
    82     Test methods have a Mocker instance available on C{self.mocker}.
       
    83     At the end of each test method, expectations of the mocker will
       
    84     be verified, and any requested changes made to the environment
       
    85     will be restored.
       
    86 
       
    87     In addition to the integration with Mocker, this class provides
       
    88     a few additional helper methods.
       
    89     """
       
    90 
       
    91     expect = expect
       
    92 
       
    93     def __init__(self, methodName="runTest"):
       
    94         # So here is the trick: we take the real test method, wrap it on
       
    95         # a function that do the job we have to do, and insert it in the
       
    96         # *instance* dictionary, so that getattr() will return our
       
    97         # replacement rather than the class method.
       
    98         test_method = getattr(self, methodName, None)
       
    99         if test_method is not None:
       
   100             def test_method_wrapper():
       
   101                 try:
       
   102                     result = test_method()
       
   103                 except:
       
   104                     raise
       
   105                 else:
       
   106                     if (self.mocker.is_recording() and
       
   107                         self.mocker.get_events()):
       
   108                         raise RuntimeError("Mocker must be put in replay "
       
   109                                            "mode with self.mocker.replay()")
       
   110                     if (hasattr(result, "addCallback") and
       
   111                         hasattr(result, "addErrback")):
       
   112                         def verify(result):
       
   113                             self.mocker.verify()
       
   114                             return result
       
   115                         result.addCallback(verify)
       
   116                     else:
       
   117                         self.mocker.verify()
       
   118                     return result
       
   119             # Copy all attributes from the original method..
       
   120             for attr in dir(test_method):
       
   121                 # .. unless they're present in our wrapper already.
       
   122                 if not hasattr(test_method_wrapper, attr) or attr == "__doc__":
       
   123                     setattr(test_method_wrapper, attr,
       
   124                             getattr(test_method, attr))
       
   125             setattr(self, methodName, test_method_wrapper)
       
   126 
       
   127         # We could overload run() normally, but other well-known testing
       
   128         # frameworks do it as well, and some of them won't call the super,
       
   129         # which might mean that cleanup wouldn't happen.  With that in mind,
       
   130         # we make integration easier by using the following trick.
       
   131         run_method = self.run
       
   132         def run_wrapper(*args, **kwargs):
       
   133             try:
       
   134                 return run_method(*args, **kwargs)
       
   135             finally:
       
   136                 self.__cleanup()
       
   137         self.run = run_wrapper
       
   138 
       
   139         self.mocker = Mocker()
       
   140 
       
   141         self.__cleanup_funcs = []
       
   142         self.__cleanup_paths = []
       
   143 
       
   144         super(MockerTestCase, self).__init__(methodName)
       
   145 
       
   146     def __cleanup(self):
       
   147         for path in self.__cleanup_paths:
       
   148             if os.path.isfile(path):
       
   149                 os.unlink(path)
       
   150             elif os.path.isdir(path):
       
   151                 shutil.rmtree(path)
       
   152         self.mocker.restore()
       
   153         for func, args, kwargs in self.__cleanup_funcs:
       
   154             func(*args, **kwargs)
       
   155 
       
   156     def addCleanup(self, func, *args, **kwargs):
       
   157         self.__cleanup_funcs.append((func, args, kwargs))
       
   158 
       
   159     def makeFile(self, content=None, suffix="", prefix="tmp", basename=None,
       
   160                  dirname=None, path=None):
       
   161         """Create a temporary file and return the path to it.
       
   162 
       
   163         @param content: Initial content for the file.
       
   164         @param suffix: Suffix to be given to the file's basename.
       
   165         @param prefix: Prefix to be given to the file's basename.
       
   166         @param basename: Full basename for the file.
       
   167         @param dirname: Put file inside this directory.
       
   168 
       
   169         The file is removed after the test runs.
       
   170         """
       
   171         if path is not None:
       
   172             self.__cleanup_paths.append(path)
       
   173         elif basename is not None:
       
   174             if dirname is None:
       
   175                 dirname = tempfile.mkdtemp()
       
   176                 self.__cleanup_paths.append(dirname)
       
   177             path = os.path.join(dirname, basename)
       
   178         else:
       
   179             fd, path = tempfile.mkstemp(suffix, prefix, dirname)
       
   180             self.__cleanup_paths.append(path)
       
   181             os.close(fd)
       
   182             if content is None:
       
   183                 os.unlink(path)
       
   184         if content is not None:
       
   185             file = open(path, "w")
       
   186             file.write(content)
       
   187             file.close()
       
   188         return path
       
   189 
       
   190     def makeDir(self, suffix="", prefix="tmp", dirname=None, path=None):
       
   191         """Create a temporary directory and return the path to it.
       
   192 
       
   193         @param suffix: Suffix to be given to the file's basename.
       
   194         @param prefix: Prefix to be given to the file's basename.
       
   195         @param dirname: Put directory inside this parent directory.
       
   196 
       
   197         The directory is removed after the test runs.
       
   198         """
       
   199         if path is not None:
       
   200             os.makedirs(path)
       
   201         else:
       
   202             path = tempfile.mkdtemp(suffix, prefix, dirname)
       
   203         self.__cleanup_paths.append(path)
       
   204         return path
       
   205 
       
   206     def failUnlessIs(self, first, second, msg=None):
       
   207         """Assert that C{first} is the same object as C{second}."""
       
   208         if first is not second:
       
   209             raise self.failureException(msg or "%r is not %r" % (first, second))
       
   210 
       
   211     def failIfIs(self, first, second, msg=None):
       
   212         """Assert that C{first} is not the same object as C{second}."""
       
   213         if first is second:
       
   214             raise self.failureException(msg or "%r is %r" % (first, second))
       
   215 
       
   216     def failUnlessIn(self, first, second, msg=None):
       
   217         """Assert that C{first} is contained in C{second}."""
       
   218         if first not in second:
       
   219             raise self.failureException(msg or "%r not in %r" % (first, second))
       
   220 
       
   221     def failUnlessStartsWith(self, first, second, msg=None):
       
   222         """Assert that C{first} starts with C{second}."""
       
   223         if first[:len(second)] != second:
       
   224             raise self.failureException(msg or "%r doesn't start with %r" %
       
   225                                                (first, second))
       
   226 
       
   227     def failIfStartsWith(self, first, second, msg=None):
       
   228         """Assert that C{first} doesn't start with C{second}."""
       
   229         if first[:len(second)] == second:
       
   230             raise self.failureException(msg or "%r starts with %r" %
       
   231                                                (first, second))
       
   232 
       
   233     def failUnlessEndsWith(self, first, second, msg=None):
       
   234         """Assert that C{first} starts with C{second}."""
       
   235         if first[len(first)-len(second):] != second:
       
   236             raise self.failureException(msg or "%r doesn't end with %r" %
       
   237                                                (first, second))
       
   238 
       
   239     def failIfEndsWith(self, first, second, msg=None):
       
   240         """Assert that C{first} doesn't start with C{second}."""
       
   241         if first[len(first)-len(second):] == second:
       
   242             raise self.failureException(msg or "%r ends with %r" %
       
   243                                                (first, second))
       
   244 
       
   245     def failIfIn(self, first, second, msg=None):
       
   246         """Assert that C{first} is not contained in C{second}."""
       
   247         if first in second:
       
   248             raise self.failureException(msg or "%r in %r" % (first, second))
       
   249 
       
   250     def failUnlessApproximates(self, first, second, tolerance, msg=None):
       
   251         """Assert that C{first} is near C{second} by at most C{tolerance}."""
       
   252         if abs(first - second) > tolerance:
       
   253             raise self.failureException(msg or "abs(%r - %r) > %r" %
       
   254                                         (first, second, tolerance))
       
   255 
       
   256     def failIfApproximates(self, first, second, tolerance, msg=None):
       
   257         """Assert that C{first} is far from C{second} by at least C{tolerance}.
       
   258         """
       
   259         if abs(first - second) <= tolerance:
       
   260             raise self.failureException(msg or "abs(%r - %r) <= %r" %
       
   261                                         (first, second, tolerance))
       
   262 
       
   263     def failUnlessMethodsMatch(self, first, second):
       
   264         """Assert that public methods in C{first} are present in C{second}.
       
   265 
       
   266         This method asserts that all public methods found in C{first} are also
       
   267         present in C{second} and accept the same arguments.  C{first} may
       
   268         have its own private methods, though, and may not have all methods
       
   269         found in C{second}.  Note that if a private method in C{first} matches
       
   270         the name of one in C{second}, their specification is still compared.
       
   271 
       
   272         This is useful to verify if a fake or stub class have the same API as
       
   273         the real class being simulated.
       
   274         """
       
   275         first_methods = dict(inspect.getmembers(first, inspect.ismethod))
       
   276         second_methods = dict(inspect.getmembers(second, inspect.ismethod))
       
   277         for name, first_method in first_methods.items():
       
   278             first_argspec = inspect.getargspec(first_method)
       
   279             first_formatted = inspect.formatargspec(*first_argspec)
       
   280 
       
   281             second_method = second_methods.get(name)
       
   282             if second_method is None:
       
   283                 if name[:1] == "_":
       
   284                     continue # First may have its own private methods.
       
   285                 raise self.failureException("%s.%s%s not present in %s" %
       
   286                     (first.__name__, name, first_formatted, second.__name__))
       
   287 
       
   288             second_argspec = inspect.getargspec(second_method)
       
   289             if first_argspec != second_argspec:
       
   290                 second_formatted = inspect.formatargspec(*second_argspec)
       
   291                 raise self.failureException("%s.%s%s != %s.%s%s" %
       
   292                     (first.__name__, name, first_formatted,
       
   293                      second.__name__, name, second_formatted))
       
   294 
       
   295 
       
   296     assertIs = failUnlessIs
       
   297     assertIsNot = failIfIs
       
   298     assertIn = failUnlessIn
       
   299     assertNotIn = failIfIn
       
   300     assertStartsWith = failUnlessStartsWith
       
   301     assertNotStartsWith = failIfStartsWith
       
   302     assertEndsWith = failUnlessEndsWith
       
   303     assertNotEndsWith = failIfEndsWith
       
   304     assertApproximates = failUnlessApproximates
       
   305     assertNotApproximates = failIfApproximates
       
   306     assertMethodsMatch = failUnlessMethodsMatch
       
   307 
       
   308     # The following are missing in Python < 2.4.
       
   309     assertTrue = unittest.TestCase.failUnless
       
   310     assertFalse = unittest.TestCase.failIf
       
   311 
       
   312     # The following is provided for compatibility with Twisted's trial.
       
   313     assertIdentical = assertIs
       
   314     assertNotIdentical = assertIsNot
       
   315     failUnlessIdentical = failUnlessIs
       
   316     failIfIdentical = failIfIs
       
   317 
       
   318 
       
   319 # --------------------------------------------------------------------
       
   320 # Mocker.
       
   321 
       
   322 class classinstancemethod(object):
       
   323 
       
   324     def __init__(self, method):
       
   325         self.method = method
       
   326 
       
   327     def __get__(self, obj, cls=None):
       
   328         def bound_method(*args, **kwargs):
       
   329             return self.method(cls, obj, *args, **kwargs)
       
   330         return bound_method
       
   331 
       
   332 
       
   333 class MockerBase(object):
       
   334     """Controller of mock objects.
       
   335 
       
   336     A mocker instance is used to command recording and replay of
       
   337     expectations on any number of mock objects.
       
   338 
       
   339     Expectations should be expressed for the mock object while in
       
   340     record mode (the initial one) by using the mock object itself,
       
   341     and using the mocker (and/or C{expect()} as a helper) to define
       
   342     additional behavior for each event.  For instance::
       
   343 
       
   344         mock = mocker.mock()
       
   345         mock.hello()
       
   346         mocker.result("Hi!")
       
   347         mocker.replay()
       
   348         assert mock.hello() == "Hi!"
       
   349         mock.restore()
       
   350         mock.verify()
       
   351 
       
   352     In this short excerpt a mock object is being created, then an
       
   353     expectation of a call to the C{hello()} method was recorded, and
       
   354     when called the method should return the value C{10}.  Then, the
       
   355     mocker is put in replay mode, and the expectation is satisfied by
       
   356     calling the C{hello()} method, which indeed returns 10.  Finally,
       
   357     a call to the L{restore()} method is performed to undo any needed
       
   358     changes made in the environment, and the L{verify()} method is
       
   359     called to ensure that all defined expectations were met.
       
   360 
       
   361     The same logic can be expressed more elegantly using the
       
   362     C{with mocker:} statement, as follows::
       
   363 
       
   364         mock = mocker.mock()
       
   365         mock.hello()
       
   366         mocker.result("Hi!")
       
   367         with mocker:
       
   368             assert mock.hello() == "Hi!"
       
   369 
       
   370     Also, the MockerTestCase class, which integrates the mocker on
       
   371     a unittest.TestCase subclass, may be used to reduce the overhead
       
   372     of controlling the mocker.  A test could be written as follows::
       
   373 
       
   374         class SampleTest(MockerTestCase):
       
   375 
       
   376             def test_hello(self):
       
   377                 mock = self.mocker.mock()
       
   378                 mock.hello()
       
   379                 self.mocker.result("Hi!")
       
   380                 self.mocker.replay()
       
   381                 self.assertEquals(mock.hello(), "Hi!")
       
   382     """
       
   383 
       
   384     _recorders = []
       
   385 
       
   386     # For convenience only.
       
   387     on = expect
       
   388 
       
   389     class __metaclass__(type):
       
   390         def __init__(self, name, bases, dict):
       
   391             # Make independent lists on each subclass, inheriting from parent.
       
   392             self._recorders = list(getattr(self, "_recorders", ()))
       
   393 
       
   394     def __init__(self):
       
   395         self._recorders = self._recorders[:]
       
   396         self._events = []
       
   397         self._recording = True
       
   398         self._ordering = False
       
   399         self._last_orderer = None
       
   400 
       
   401     def is_recording(self):
       
   402         """Return True if in recording mode, False if in replay mode.
       
   403 
       
   404         Recording is the initial state.
       
   405         """
       
   406         return self._recording
       
   407 
       
   408     def replay(self):
       
   409         """Change to replay mode, where recorded events are reproduced.
       
   410 
       
   411         If already in replay mode, the mocker will be restored, with all
       
   412         expectations reset, and then put again in replay mode.
       
   413 
       
   414         An alternative and more comfortable way to replay changes is
       
   415         using the 'with' statement, as follows::
       
   416 
       
   417             mocker = Mocker()
       
   418             <record events>
       
   419             with mocker:
       
   420                 <reproduce events>
       
   421 
       
   422         The 'with' statement will automatically put mocker in replay
       
   423         mode, and will also verify if all events were correctly reproduced
       
   424         at the end (using L{verify()}), and also restore any changes done
       
   425         in the environment (with L{restore()}).
       
   426 
       
   427         Also check the MockerTestCase class, which integrates the
       
   428         unittest.TestCase class with mocker.
       
   429         """
       
   430         if not self._recording:
       
   431             for event in self._events:
       
   432                 event.restore()
       
   433         else:
       
   434             self._recording = False
       
   435         for event in self._events:
       
   436             event.replay()
       
   437 
       
   438     def restore(self):
       
   439         """Restore changes in the environment, and return to recording mode.
       
   440 
       
   441         This should always be called after the test is complete (succeeding
       
   442         or not).  There are ways to call this method automatically on
       
   443         completion (e.g. using a C{with mocker:} statement, or using the
       
   444         L{MockerTestCase} class.
       
   445         """
       
   446         if not self._recording:
       
   447             self._recording = True
       
   448             for event in self._events:
       
   449                 event.restore()
       
   450 
       
   451     def reset(self):
       
   452         """Reset the mocker state.
       
   453 
       
   454         This will restore environment changes, if currently in replay
       
   455         mode, and then remove all events previously recorded.
       
   456         """
       
   457         if not self._recording:
       
   458             self.restore()
       
   459         self.unorder()
       
   460         del self._events[:]
       
   461 
       
   462     def get_events(self):
       
   463         """Return all recorded events."""
       
   464         return self._events[:]
       
   465 
       
   466     def add_event(self, event):
       
   467         """Add an event.
       
   468 
       
   469         This method is used internally by the implementation, and
       
   470         shouldn't be needed on normal mocker usage.
       
   471         """
       
   472         self._events.append(event)
       
   473         if self._ordering:
       
   474             orderer = event.add_task(Orderer(event.path))
       
   475             if self._last_orderer:
       
   476                 orderer.add_dependency(self._last_orderer)
       
   477             self._last_orderer = orderer
       
   478         return event
       
   479 
       
   480     def verify(self):
       
   481         """Check if all expectations were met, and raise AssertionError if not.
       
   482 
       
   483         The exception message will include a nice description of which
       
   484         expectations were not met, and why.
       
   485         """
       
   486         errors = []
       
   487         for event in self._events:
       
   488             try:
       
   489                 event.verify()
       
   490             except AssertionError, e:
       
   491                 error = str(e)
       
   492                 if not error:
       
   493                     raise RuntimeError("Empty error message from %r"
       
   494                                        % event)
       
   495                 errors.append(error)
       
   496         if errors:
       
   497             message = [ERROR_PREFIX + "Unmet expectations:", ""]
       
   498             for error in errors:
       
   499                 lines = error.splitlines()
       
   500                 message.append("=> " + lines.pop(0))
       
   501                 message.extend([" " + line for line in lines])
       
   502                 message.append("")
       
   503             raise AssertionError(os.linesep.join(message))
       
   504 
       
   505     def mock(self, spec_and_type=None, spec=None, type=None,
       
   506              name=None, count=True):
       
   507         """Return a new mock object.
       
   508 
       
   509         @param spec_and_type: Handy positional argument which sets both
       
   510                      spec and type.
       
   511         @param spec: Method calls will be checked for correctness against
       
   512                      the given class.
       
   513         @param type: If set, the Mock's __class__ attribute will return
       
   514                      the given type.  This will make C{isinstance()} calls
       
   515                      on the object work.
       
   516         @param name: Name for the mock object, used in the representation of
       
   517                      expressions.  The name is rarely needed, as it's usually
       
   518                      guessed correctly from the variable name used.
       
   519         @param count: If set to false, expressions may be executed any number
       
   520                      of times, unless an expectation is explicitly set using
       
   521                      the L{count()} method.  By default, expressions are
       
   522                      expected once.
       
   523         """
       
   524         if spec_and_type is not None:
       
   525             spec = type = spec_and_type
       
   526         return Mock(self, spec=spec, type=type, name=name, count=count)
       
   527 
       
   528     def proxy(self, object, spec=True, type=True, name=None, count=True,
       
   529               passthrough=True):
       
   530         """Return a new mock object which proxies to the given object.
       
   531  
       
   532         Proxies are useful when only part of the behavior of an object
       
   533         is to be mocked.  Unknown expressions may be passed through to
       
   534         the real implementation implicitly (if the C{passthrough} argument
       
   535         is True), or explicitly (using the L{passthrough()} method
       
   536         on the event).
       
   537 
       
   538         @param object: Real object to be proxied, and replaced by the mock
       
   539                        on replay mode.  It may also be an "import path",
       
   540                        such as C{"time.time"}, in which case the object
       
   541                        will be the C{time} function from the C{time} module.
       
   542         @param spec: Method calls will be checked for correctness against
       
   543                      the given object, which may be a class or an instance
       
   544                      where attributes will be looked up.  Defaults to the
       
   545                      the C{object} parameter.  May be set to None explicitly,
       
   546                      in which case spec checking is disabled.  Checks may
       
   547                      also be disabled explicitly on a per-event basis with
       
   548                      the L{nospec()} method.
       
   549         @param type: If set, the Mock's __class__ attribute will return
       
   550                      the given type.  This will make C{isinstance()} calls
       
   551                      on the object work.  Defaults to the type of the
       
   552                      C{object} parameter.  May be set to None explicitly.
       
   553         @param name: Name for the mock object, used in the representation of
       
   554                      expressions.  The name is rarely needed, as it's usually
       
   555                      guessed correctly from the variable name used.
       
   556         @param count: If set to false, expressions may be executed any number
       
   557                      of times, unless an expectation is explicitly set using
       
   558                      the L{count()} method.  By default, expressions are
       
   559                      expected once.
       
   560         @param passthrough: If set to False, passthrough of actions on the
       
   561                             proxy to the real object will only happen when
       
   562                             explicitly requested via the L{passthrough()}
       
   563                             method.
       
   564         """
       
   565         if isinstance(object, basestring):
       
   566             if name is None:
       
   567                 name = object
       
   568             import_stack = object.split(".")
       
   569             attr_stack = []
       
   570             while import_stack:
       
   571                 module_path = ".".join(import_stack)
       
   572                 try:
       
   573                     object = __import__(module_path, {}, {}, [""])
       
   574                 except ImportError:
       
   575                     attr_stack.insert(0, import_stack.pop())
       
   576                     if not import_stack:
       
   577                         raise
       
   578                     continue
       
   579                 else:
       
   580                     for attr in attr_stack:
       
   581                         object = getattr(object, attr)
       
   582                     break
       
   583         if spec is True:
       
   584             spec = object
       
   585         if type is True:
       
   586             type = __builtin__.type(object)
       
   587         return Mock(self, spec=spec, type=type, object=object,
       
   588                     name=name, count=count, passthrough=passthrough)
       
   589 
       
   590     def replace(self, object, spec=True, type=True, name=None, count=True,
       
   591                 passthrough=True):
       
   592         """Create a proxy, and replace the original object with the mock.
       
   593 
       
   594         On replay, the original object will be replaced by the returned
       
   595         proxy in all dictionaries found in the running interpreter via
       
   596         the garbage collecting system.  This should cover module
       
   597         namespaces, class namespaces, instance namespaces, and so on.
       
   598 
       
   599         @param object: Real object to be proxied, and replaced by the mock
       
   600                        on replay mode.  It may also be an "import path",
       
   601                        such as C{"time.time"}, in which case the object
       
   602                        will be the C{time} function from the C{time} module.
       
   603         @param spec: Method calls will be checked for correctness against
       
   604                      the given object, which may be a class or an instance
       
   605                      where attributes will be looked up.  Defaults to the
       
   606                      the C{object} parameter.  May be set to None explicitly,
       
   607                      in which case spec checking is disabled.  Checks may
       
   608                      also be disabled explicitly on a per-event basis with
       
   609                      the L{nospec()} method.
       
   610         @param type: If set, the Mock's __class__ attribute will return
       
   611                      the given type.  This will make C{isinstance()} calls
       
   612                      on the object work.  Defaults to the type of the
       
   613                      C{object} parameter.  May be set to None explicitly.
       
   614         @param name: Name for the mock object, used in the representation of
       
   615                      expressions.  The name is rarely needed, as it's usually
       
   616                      guessed correctly from the variable name used.
       
   617         @param passthrough: If set to False, passthrough of actions on the
       
   618                             proxy to the real object will only happen when
       
   619                             explicitly requested via the L{passthrough()}
       
   620                             method.
       
   621         """
       
   622         mock = self.proxy(object, spec, type, name, count, passthrough)
       
   623         event = self._get_replay_restore_event()
       
   624         event.add_task(ProxyReplacer(mock))
       
   625         return mock
       
   626 
       
   627     def patch(self, object, spec=True):
       
   628         """Patch an existing object to reproduce recorded events.
       
   629 
       
   630         @param object: Class or instance to be patched.
       
   631         @param spec: Method calls will be checked for correctness against
       
   632                      the given object, which may be a class or an instance
       
   633                      where attributes will be looked up.  Defaults to the
       
   634                      the C{object} parameter.  May be set to None explicitly,
       
   635                      in which case spec checking is disabled.  Checks may
       
   636                      also be disabled explicitly on a per-event basis with
       
   637                      the L{nospec()} method.
       
   638 
       
   639         The result of this method is still a mock object, which can be
       
   640         used like any other mock object to record events.  The difference
       
   641         is that when the mocker is put on replay mode, the *real* object
       
   642         will be modified to behave according to recorded expectations.
       
   643 
       
   644         Patching works in individual instances, and also in classes.
       
   645         When an instance is patched, recorded events will only be
       
   646         considered on this specific instance, and other instances should
       
   647         behave normally.  When a class is patched, the reproduction of
       
   648         events will be considered on any instance of this class once
       
   649         created (collectively).
       
   650 
       
   651         Observe that, unlike with proxies which catch only events done
       
   652         through the mock object, *all* accesses to recorded expectations
       
   653         will be considered;  even these coming from the object itself
       
   654         (e.g. C{self.hello()} is considered if this method was patched).
       
   655         While this is a very powerful feature, and many times the reason
       
   656         to use patches in the first place, it's important to keep this
       
   657         behavior in mind.
       
   658 
       
   659         Patching of the original object only takes place when the mocker
       
   660         is put on replay mode, and the patched object will be restored
       
   661         to its original state once the L{restore()} method is called
       
   662         (explicitly, or implicitly with alternative conventions, such as
       
   663         a C{with mocker:} block, or a MockerTestCase class).
       
   664         """
       
   665         if spec is True:
       
   666             spec = object
       
   667         patcher = Patcher()
       
   668         event = self._get_replay_restore_event()
       
   669         event.add_task(patcher)
       
   670         mock = Mock(self, object=object, patcher=patcher,
       
   671                     passthrough=True, spec=spec)
       
   672         object.__mocker_mock__ = mock
       
   673         return mock
       
   674 
       
   675     def act(self, path):
       
   676         """This is called by mock objects whenever something happens to them.
       
   677 
       
   678         This method is part of the implementation between the mocker
       
   679         and mock objects.
       
   680         """
       
   681         if self._recording:
       
   682             event = self.add_event(Event(path))
       
   683             for recorder in self._recorders:
       
   684                 recorder(self, event)
       
   685             return Mock(self, path)
       
   686         else:
       
   687             # First run events that may run, then run unsatisfied events, then
       
   688             # ones not previously run. We put the index in the ordering tuple
       
   689             # instead of the actual event because we want a stable sort
       
   690             # (ordering between 2 events is undefined).
       
   691             events = self._events
       
   692             order = [(events[i].satisfied()*2 + events[i].has_run(), i)
       
   693                      for i in range(len(events))]
       
   694             order.sort()
       
   695             postponed = None
       
   696             for weight, i in order:
       
   697                 event = events[i]
       
   698                 if event.matches(path):
       
   699                     if event.may_run(path):
       
   700                         return event.run(path)
       
   701                     elif postponed is None:
       
   702                         postponed = event
       
   703             if postponed is not None:
       
   704                 return postponed.run(path)
       
   705             raise MatchError(ERROR_PREFIX + "Unexpected expression: %s" % path)
       
   706 
       
   707     def get_recorders(cls, self):
       
   708         """Return recorders associated with this mocker class or instance.
       
   709 
       
   710         This method may be called on mocker instances and also on mocker
       
   711         classes.  See the L{add_recorder()} method for more information.
       
   712         """
       
   713         return (self or cls)._recorders[:]
       
   714     get_recorders = classinstancemethod(get_recorders)
       
   715 
       
   716     def add_recorder(cls, self, recorder):
       
   717         """Add a recorder to this mocker class or instance.
       
   718 
       
   719         @param recorder: Callable accepting C{(mocker, event)} as parameters.
       
   720 
       
   721         This is part of the implementation of mocker.
       
   722 
       
   723         All registered recorders are called for translating events that
       
   724         happen during recording into expectations to be met once the state
       
   725         is switched to replay mode.
       
   726 
       
   727         This method may be called on mocker instances and also on mocker
       
   728         classes.  When called on a class, the recorder will be used by
       
   729         all instances, and also inherited on subclassing.  When called on
       
   730         instances, the recorder is added only to the given instance.
       
   731         """
       
   732         (self or cls)._recorders.append(recorder)
       
   733         return recorder
       
   734     add_recorder = classinstancemethod(add_recorder)
       
   735 
       
   736     def remove_recorder(cls, self, recorder):
       
   737         """Remove the given recorder from this mocker class or instance.
       
   738 
       
   739         This method may be called on mocker classes and also on mocker
       
   740         instances.  See the L{add_recorder()} method for more information.
       
   741         """
       
   742         (self or cls)._recorders.remove(recorder)
       
   743     remove_recorder = classinstancemethod(remove_recorder)
       
   744 
       
   745     def result(self, value):
       
   746         """Make the last recorded event return the given value on replay.
       
   747         
       
   748         @param value: Object to be returned when the event is replayed.
       
   749         """
       
   750         self.call(lambda *args, **kwargs: value)
       
   751 
       
   752     def generate(self, sequence):
       
   753         """Last recorded event will return a generator with the given sequence.
       
   754 
       
   755         @param sequence: Sequence of values to be generated.
       
   756         """
       
   757         def generate(*args, **kwargs):
       
   758             for value in sequence:
       
   759                 yield value
       
   760         self.call(generate)
       
   761 
       
   762     def throw(self, exception):
       
   763         """Make the last recorded event raise the given exception on replay.
       
   764 
       
   765         @param exception: Class or instance of exception to be raised.
       
   766         """
       
   767         def raise_exception(*args, **kwargs):
       
   768             raise exception
       
   769         self.call(raise_exception)
       
   770 
       
   771     def call(self, func):
       
   772         """Make the last recorded event cause the given function to be called.
       
   773 
       
   774         @param func: Function to be called.
       
   775 
       
   776         The result of the function will be used as the event result.
       
   777         """
       
   778         self._events[-1].add_task(FunctionRunner(func))
       
   779 
       
   780     def count(self, min, max=False):
       
   781         """Last recorded event must be replayed between min and max times.
       
   782 
       
   783         @param min: Minimum number of times that the event must happen.
       
   784         @param max: Maximum number of times that the event must happen.  If
       
   785                     not given, it defaults to the same value of the C{min}
       
   786                     parameter.  If set to None, there is no upper limit, and
       
   787                     the expectation is met as long as it happens at least
       
   788                     C{min} times.
       
   789         """
       
   790         event = self._events[-1]
       
   791         for task in event.get_tasks():
       
   792             if isinstance(task, RunCounter):
       
   793                 event.remove_task(task)
       
   794         event.add_task(RunCounter(min, max))
       
   795 
       
   796     def is_ordering(self):
       
   797         """Return true if all events are being ordered.
       
   798 
       
   799         See the L{order()} method.
       
   800         """
       
   801         return self._ordering
       
   802 
       
   803     def unorder(self):
       
   804         """Disable the ordered mode.
       
   805         
       
   806         See the L{order()} method for more information.
       
   807         """
       
   808         self._ordering = False
       
   809         self._last_orderer = None
       
   810 
       
   811     def order(self, *path_holders):
       
   812         """Create an expectation of order between two or more events.
       
   813 
       
   814         @param path_holders: Objects returned as the result of recorded events.
       
   815 
       
   816         By default, mocker won't force events to happen precisely in
       
   817         the order they were recorded.  Calling this method will change
       
   818         this behavior so that events will only match if reproduced in
       
   819         the correct order.
       
   820 
       
   821         There are two ways in which this method may be used.  Which one
       
   822         is used in a given occasion depends only on convenience.
       
   823 
       
   824         If no arguments are passed, the mocker will be put in a mode where
       
   825         all the recorded events following the method call will only be met
       
   826         if they happen in order.  When that's used, the mocker may be put
       
   827         back in unordered mode by calling the L{unorder()} method, or by
       
   828         using a 'with' block, like so::
       
   829 
       
   830             with mocker.ordered():
       
   831                 <record events>
       
   832 
       
   833         In this case, only expressions in <record events> will be ordered,
       
   834         and the mocker will be back in unordered mode after the 'with' block.
       
   835 
       
   836         The second way to use it is by specifying precisely which events
       
   837         should be ordered.  As an example::
       
   838 
       
   839             mock = mocker.mock()
       
   840             expr1 = mock.hello()
       
   841             expr2 = mock.world
       
   842             expr3 = mock.x.y.z
       
   843             mocker.order(expr1, expr2, expr3)
       
   844 
       
   845         This method of ordering only works when the expression returns
       
   846         another object.
       
   847 
       
   848         Also check the L{after()} and L{before()} methods, which are
       
   849         alternative ways to perform this.
       
   850         """
       
   851         if not path_holders:
       
   852             self._ordering = True
       
   853             return OrderedContext(self)
       
   854 
       
   855         last_orderer = None
       
   856         for path_holder in path_holders:
       
   857             if type(path_holder) is Path:
       
   858                 path = path_holder
       
   859             else:
       
   860                 path = path_holder.__mocker_path__
       
   861             for event in self._events:
       
   862                 if event.path is path:
       
   863                     for task in event.get_tasks():
       
   864                         if isinstance(task, Orderer):
       
   865                             orderer = task
       
   866                             break
       
   867                     else:
       
   868                         orderer = Orderer(path)
       
   869                         event.add_task(orderer)
       
   870                     if last_orderer:
       
   871                         orderer.add_dependency(last_orderer)
       
   872                     last_orderer = orderer
       
   873                     break
       
   874 
       
   875     def after(self, *path_holders):
       
   876         """Last recorded event must happen after events referred to.
       
   877 
       
   878         @param path_holders: Objects returned as the result of recorded events
       
   879                              which should happen before the last recorded event
       
   880 
       
   881         As an example, the idiom::
       
   882 
       
   883             expect(mock.x).after(mock.y, mock.z)
       
   884 
       
   885         is an alternative way to say::
       
   886 
       
   887             expr_x = mock.x
       
   888             expr_y = mock.y
       
   889             expr_z = mock.z
       
   890             mocker.order(expr_y, expr_x)
       
   891             mocker.order(expr_z, expr_x)
       
   892 
       
   893         See L{order()} for more information.
       
   894         """
       
   895         last_path = self._events[-1].path
       
   896         for path_holder in path_holders:
       
   897             self.order(path_holder, last_path)
       
   898 
       
   899     def before(self, *path_holders):
       
   900         """Last recorded event must happen before events referred to.
       
   901 
       
   902         @param path_holders: Objects returned as the result of recorded events
       
   903                              which should happen after the last recorded event
       
   904 
       
   905         As an example, the idiom::
       
   906 
       
   907             expect(mock.x).before(mock.y, mock.z)
       
   908 
       
   909         is an alternative way to say::
       
   910 
       
   911             expr_x = mock.x
       
   912             expr_y = mock.y
       
   913             expr_z = mock.z
       
   914             mocker.order(expr_x, expr_y)
       
   915             mocker.order(expr_x, expr_z)
       
   916 
       
   917         See L{order()} for more information.
       
   918         """
       
   919         last_path = self._events[-1].path
       
   920         for path_holder in path_holders:
       
   921             self.order(last_path, path_holder)
       
   922 
       
   923     def nospec(self):
       
   924         """Don't check method specification of real object on last event.
       
   925 
       
   926         By default, when using a mock created as the result of a call to
       
   927         L{proxy()}, L{replace()}, and C{patch()}, or when passing the spec
       
   928         attribute to the L{mock()} method, method calls on the given object
       
   929         are checked for correctness against the specification of the real
       
   930         object (or the explicitly provided spec).
       
   931 
       
   932         This method will disable that check specifically for the last
       
   933         recorded event.
       
   934         """
       
   935         event = self._events[-1]
       
   936         for task in event.get_tasks():
       
   937             if isinstance(task, SpecChecker):
       
   938                 event.remove_task(task)
       
   939 
       
   940     def passthrough(self, result_callback=None):
       
   941         """Make the last recorded event run on the real object once seen.
       
   942 
       
   943         @param result_callback: If given, this function will be called with
       
   944             the result of the *real* method call as the only argument.
       
   945 
       
   946         This can only be used on proxies, as returned by the L{proxy()}
       
   947         and L{replace()} methods, or on mocks representing patched objects,
       
   948         as returned by the L{patch()} method.
       
   949         """
       
   950         event = self._events[-1]
       
   951         if event.path.root_object is None:
       
   952             raise TypeError("Mock object isn't a proxy")
       
   953         event.add_task(PathExecuter(result_callback))
       
   954 
       
   955     def __enter__(self):
       
   956         """Enter in a 'with' context.  This will run replay()."""
       
   957         self.replay()
       
   958         return self
       
   959 
       
   960     def __exit__(self, type, value, traceback):
       
   961         """Exit from a 'with' context.
       
   962 
       
   963         This will run restore() at all times, but will only run verify()
       
   964         if the 'with' block itself hasn't raised an exception.  Exceptions
       
   965         in that block are never swallowed.
       
   966         """
       
   967         self.restore()
       
   968         if type is None:
       
   969             self.verify()
       
   970         return False
       
   971 
       
   972     def _get_replay_restore_event(self):
       
   973         """Return unique L{ReplayRestoreEvent}, creating if needed.
       
   974 
       
   975         Some tasks only want to replay/restore.  When that's the case,
       
   976         they shouldn't act on other events during replay.  Also, they
       
   977         can all be put in a single event when that's the case.  Thus,
       
   978         we add a single L{ReplayRestoreEvent} as the first element of
       
   979         the list.
       
   980         """
       
   981         if not self._events or type(self._events[0]) != ReplayRestoreEvent:
       
   982             self._events.insert(0, ReplayRestoreEvent())
       
   983         return self._events[0]
       
   984 
       
   985 
       
   986 class OrderedContext(object):
       
   987 
       
   988     def __init__(self, mocker):
       
   989         self._mocker = mocker
       
   990 
       
   991     def __enter__(self):
       
   992         return None
       
   993 
       
   994     def __exit__(self, type, value, traceback):
       
   995         self._mocker.unorder()
       
   996 
       
   997 
       
   998 class Mocker(MockerBase):
       
   999     __doc__ = MockerBase.__doc__
       
  1000 
       
  1001 # Decorator to add recorders on the standard Mocker class.
       
  1002 recorder = Mocker.add_recorder
       
  1003 
       
  1004 
       
  1005 # --------------------------------------------------------------------
       
  1006 # Mock object.
       
  1007 
       
  1008 class Mock(object):
       
  1009 
       
  1010     def __init__(self, mocker, path=None, name=None, spec=None, type=None,
       
  1011                  object=None, passthrough=False, patcher=None, count=True):
       
  1012         self.__mocker__ = mocker
       
  1013         self.__mocker_path__ = path or Path(self, object)
       
  1014         self.__mocker_name__ = name
       
  1015         self.__mocker_spec__ = spec
       
  1016         self.__mocker_object__ = object
       
  1017         self.__mocker_passthrough__ = passthrough
       
  1018         self.__mocker_patcher__ = patcher
       
  1019         self.__mocker_replace__ = False
       
  1020         self.__mocker_type__ = type
       
  1021         self.__mocker_count__ = count
       
  1022 
       
  1023     def __mocker_act__(self, kind, args=(), kwargs={}, object=None):
       
  1024         if self.__mocker_name__ is None:
       
  1025             self.__mocker_name__ = find_object_name(self, 2)
       
  1026         action = Action(kind, args, kwargs, self.__mocker_path__)
       
  1027         path = self.__mocker_path__ + action
       
  1028         if object is not None:
       
  1029             path.root_object = object
       
  1030         try:
       
  1031             return self.__mocker__.act(path)
       
  1032         except MatchError, exception:
       
  1033             root_mock = path.root_mock
       
  1034             if (path.root_object is not None and
       
  1035                 root_mock.__mocker_passthrough__):
       
  1036                 return path.execute(path.root_object)
       
  1037             # Reinstantiate to show raise statement on traceback, and
       
  1038             # also to make the traceback shown shorter.
       
  1039             raise MatchError(str(exception))
       
  1040         except AssertionError, e:
       
  1041             lines = str(e).splitlines()
       
  1042             message = [ERROR_PREFIX + "Unmet expectation:", ""]
       
  1043             message.append("=> " + lines.pop(0))
       
  1044             message.extend([" " + line for line in lines])
       
  1045             message.append("")
       
  1046             raise AssertionError(os.linesep.join(message))
       
  1047 
       
  1048     def __getattribute__(self, name):
       
  1049         if name.startswith("__mocker_"):
       
  1050             return super(Mock, self).__getattribute__(name)
       
  1051         if name == "__class__":
       
  1052             if self.__mocker__.is_recording() or self.__mocker_type__ is None:
       
  1053                 return type(self)
       
  1054             return self.__mocker_type__
       
  1055         return self.__mocker_act__("getattr", (name,))
       
  1056 
       
  1057     def __setattr__(self, name, value):
       
  1058         if name.startswith("__mocker_"):
       
  1059             return super(Mock, self).__setattr__(name, value)
       
  1060         return self.__mocker_act__("setattr", (name, value))
       
  1061 
       
  1062     def __delattr__(self, name):
       
  1063         return self.__mocker_act__("delattr", (name,))
       
  1064 
       
  1065     def __call__(self, *args, **kwargs):
       
  1066         return self.__mocker_act__("call", args, kwargs)
       
  1067 
       
  1068     def __contains__(self, value):
       
  1069         return self.__mocker_act__("contains", (value,))
       
  1070 
       
  1071     def __getitem__(self, key):
       
  1072         return self.__mocker_act__("getitem", (key,))
       
  1073 
       
  1074     def __setitem__(self, key, value):
       
  1075         return self.__mocker_act__("setitem", (key, value))
       
  1076 
       
  1077     def __delitem__(self, key):
       
  1078         return self.__mocker_act__("delitem", (key,))
       
  1079 
       
  1080     def __len__(self):
       
  1081         # MatchError is turned on an AttributeError so that list() and
       
  1082         # friends act properly when trying to get length hints on
       
  1083         # something that doesn't offer them.
       
  1084         try:
       
  1085             result = self.__mocker_act__("len")
       
  1086         except MatchError, e:
       
  1087             raise AttributeError(str(e))
       
  1088         if type(result) is Mock:
       
  1089             return 0
       
  1090         return result
       
  1091 
       
  1092     def __nonzero__(self):
       
  1093         try:
       
  1094             return self.__mocker_act__("nonzero")
       
  1095         except MatchError, e:
       
  1096             return True
       
  1097 
       
  1098     def __iter__(self):
       
  1099         # XXX On py3k, when next() becomes __next__(), we'll be able
       
  1100         #     to return the mock itself because it will be considered
       
  1101         #     an iterator (we'll be mocking __next__ as well, which we
       
  1102         #     can't now).
       
  1103         result = self.__mocker_act__("iter")
       
  1104         if type(result) is Mock:
       
  1105             return iter([])
       
  1106         return result
       
  1107 
       
  1108     # When adding a new action kind here, also add support for it on
       
  1109     # Action.execute() and Path.__str__().
       
  1110 
       
  1111 
       
  1112 def find_object_name(obj, depth=0):
       
  1113     """Try to detect how the object is named on a previous scope."""
       
  1114     try:
       
  1115         frame = sys._getframe(depth+1)
       
  1116     except:
       
  1117         return None
       
  1118     for name, frame_obj in frame.f_locals.iteritems():
       
  1119         if frame_obj is obj:
       
  1120             return name
       
  1121     self = frame.f_locals.get("self")
       
  1122     if self is not None:
       
  1123         try:
       
  1124             items = list(self.__dict__.iteritems())
       
  1125         except:
       
  1126             pass
       
  1127         else:
       
  1128             for name, self_obj in items:
       
  1129                 if self_obj is obj:
       
  1130                     return name
       
  1131     return None
       
  1132 
       
  1133 
       
  1134 # --------------------------------------------------------------------
       
  1135 # Action and path.
       
  1136 
       
  1137 class Action(object):
       
  1138 
       
  1139     def __init__(self, kind, args, kwargs, path=None):
       
  1140         self.kind = kind
       
  1141         self.args = args
       
  1142         self.kwargs = kwargs
       
  1143         self.path = path
       
  1144         self._execute_cache = {}
       
  1145 
       
  1146     def __repr__(self):
       
  1147         if self.path is None:
       
  1148             return "Action(%r, %r, %r)" % (self.kind, self.args, self.kwargs)
       
  1149         return "Action(%r, %r, %r, %r)" % \
       
  1150                (self.kind, self.args, self.kwargs, self.path)
       
  1151 
       
  1152     def __eq__(self, other):
       
  1153         return (self.kind == other.kind and
       
  1154                 self.args == other.args and
       
  1155                 self.kwargs == other.kwargs)
       
  1156 
       
  1157     def __ne__(self, other):
       
  1158         return not self.__eq__(other)
       
  1159 
       
  1160     def matches(self, other):
       
  1161         return (self.kind == other.kind and
       
  1162                 match_params(self.args, self.kwargs, other.args, other.kwargs))
       
  1163 
       
  1164     def execute(self, object):
       
  1165         # This caching scheme may fail if the object gets deallocated before
       
  1166         # the action, as the id might get reused.  It's somewhat easy to fix
       
  1167         # that with a weakref callback.  For our uses, though, the object
       
  1168         # should never get deallocated before the action itself, so we'll
       
  1169         # just keep it simple.
       
  1170         if id(object) in self._execute_cache:
       
  1171             return self._execute_cache[id(object)]
       
  1172         execute = getattr(object, "__mocker_execute__", None)
       
  1173         if execute is not None:
       
  1174             result = execute(self, object)
       
  1175         else:
       
  1176             kind = self.kind
       
  1177             if kind == "getattr":
       
  1178                 result = getattr(object, self.args[0])
       
  1179             elif kind == "setattr":
       
  1180                 result = setattr(object, self.args[0], self.args[1])
       
  1181             elif kind == "delattr":
       
  1182                 result = delattr(object, self.args[0])
       
  1183             elif kind == "call":
       
  1184                 result = object(*self.args, **self.kwargs)
       
  1185             elif kind == "contains":
       
  1186                 result = self.args[0] in object
       
  1187             elif kind == "getitem":
       
  1188                 result = object[self.args[0]]
       
  1189             elif kind == "setitem":
       
  1190                 result = object[self.args[0]] = self.args[1]
       
  1191             elif kind == "delitem":
       
  1192                 del object[self.args[0]]
       
  1193                 result = None
       
  1194             elif kind == "len":
       
  1195                 result = len(object)
       
  1196             elif kind == "nonzero":
       
  1197                 result = bool(object)
       
  1198             elif kind == "iter":
       
  1199                 result = iter(object)
       
  1200             else:
       
  1201                 raise RuntimeError("Don't know how to execute %r kind." % kind)
       
  1202         self._execute_cache[id(object)] = result
       
  1203         return result
       
  1204 
       
  1205 
       
  1206 class Path(object):
       
  1207 
       
  1208     def __init__(self, root_mock, root_object=None, actions=()):
       
  1209         self.root_mock = root_mock
       
  1210         self.root_object = root_object
       
  1211         self.actions = tuple(actions)
       
  1212         self.__mocker_replace__ = False
       
  1213 
       
  1214     def parent_path(self):
       
  1215         if not self.actions:
       
  1216             return None
       
  1217         return self.actions[-1].path
       
  1218     parent_path = property(parent_path)
       
  1219  
       
  1220     def __add__(self, action):
       
  1221         """Return a new path which includes the given action at the end."""
       
  1222         return self.__class__(self.root_mock, self.root_object,
       
  1223                               self.actions + (action,))
       
  1224 
       
  1225     def __eq__(self, other):
       
  1226         """Verify if the two paths are equal.
       
  1227         
       
  1228         Two paths are equal if they refer to the same mock object, and
       
  1229         have the actions with equal kind, args and kwargs.
       
  1230         """
       
  1231         if (self.root_mock is not other.root_mock or
       
  1232             self.root_object is not other.root_object or
       
  1233             len(self.actions) != len(other.actions)):
       
  1234             return False
       
  1235         for action, other_action in zip(self.actions, other.actions):
       
  1236             if action != other_action:
       
  1237                 return False
       
  1238         return True
       
  1239 
       
  1240     def matches(self, other):
       
  1241         """Verify if the two paths are equivalent.
       
  1242         
       
  1243         Two paths are equal if they refer to the same mock object, and
       
  1244         have the same actions performed on them.
       
  1245         """
       
  1246         if (self.root_mock is not other.root_mock or
       
  1247             len(self.actions) != len(other.actions)):
       
  1248             return False
       
  1249         for action, other_action in zip(self.actions, other.actions):
       
  1250             if not action.matches(other_action):
       
  1251                 return False
       
  1252         return True
       
  1253 
       
  1254     def execute(self, object):
       
  1255         """Execute all actions sequentially on object, and return result.
       
  1256         """
       
  1257         for action in self.actions:
       
  1258             object = action.execute(object)
       
  1259         return object
       
  1260 
       
  1261     def __str__(self):
       
  1262         """Transform the path into a nice string such as obj.x.y('z')."""
       
  1263         result = self.root_mock.__mocker_name__ or "<mock>"
       
  1264         for action in self.actions:
       
  1265             if action.kind == "getattr":
       
  1266                 result = "%s.%s" % (result, action.args[0])
       
  1267             elif action.kind == "setattr":
       
  1268                 result = "%s.%s = %r" % (result, action.args[0], action.args[1])
       
  1269             elif action.kind == "delattr":
       
  1270                 result = "del %s.%s" % (result, action.args[0])
       
  1271             elif action.kind == "call":
       
  1272                 args = [repr(x) for x in action.args]
       
  1273                 items = list(action.kwargs.iteritems())
       
  1274                 items.sort()
       
  1275                 for pair in items:
       
  1276                     args.append("%s=%r" % pair)
       
  1277                 result = "%s(%s)" % (result, ", ".join(args))
       
  1278             elif action.kind == "contains":
       
  1279                 result = "%r in %s" % (action.args[0], result)
       
  1280             elif action.kind == "getitem":
       
  1281                 result = "%s[%r]" % (result, action.args[0])
       
  1282             elif action.kind == "setitem":
       
  1283                 result = "%s[%r] = %r" % (result, action.args[0],
       
  1284                                           action.args[1])
       
  1285             elif action.kind == "delitem":
       
  1286                 result = "del %s[%r]" % (result, action.args[0])
       
  1287             elif action.kind == "len":
       
  1288                 result = "len(%s)" % result
       
  1289             elif action.kind == "nonzero":
       
  1290                 result = "bool(%s)" % result
       
  1291             elif action.kind == "iter":
       
  1292                 result = "iter(%s)" % result
       
  1293             else:
       
  1294                 raise RuntimeError("Don't know how to format kind %r" %
       
  1295                                    action.kind)
       
  1296         return result
       
  1297 
       
  1298 
       
  1299 class SpecialArgument(object):
       
  1300     """Base for special arguments for matching parameters."""
       
  1301 
       
  1302     def __init__(self, object=None):
       
  1303         self.object = object
       
  1304 
       
  1305     def __repr__(self):
       
  1306         if self.object is None:
       
  1307             return self.__class__.__name__
       
  1308         else:
       
  1309             return "%s(%r)" % (self.__class__.__name__, self.object)
       
  1310 
       
  1311     def matches(self, other):
       
  1312         return True
       
  1313 
       
  1314     def __eq__(self, other):
       
  1315         return type(other) == type(self) and self.object == other.object
       
  1316 
       
  1317 
       
  1318 class ANY(SpecialArgument):
       
  1319     """Matches any single argument."""
       
  1320 
       
  1321 ANY = ANY()
       
  1322 
       
  1323 
       
  1324 class ARGS(SpecialArgument):
       
  1325     """Matches zero or more positional arguments."""
       
  1326 
       
  1327 ARGS = ARGS()
       
  1328 
       
  1329 
       
  1330 class KWARGS(SpecialArgument):
       
  1331     """Matches zero or more keyword arguments."""
       
  1332 
       
  1333 KWARGS = KWARGS()
       
  1334 
       
  1335 
       
  1336 class IS(SpecialArgument):
       
  1337 
       
  1338     def matches(self, other):
       
  1339         return self.object is other
       
  1340 
       
  1341     def __eq__(self, other):
       
  1342         return type(other) == type(self) and self.object is other.object
       
  1343 
       
  1344 
       
  1345 class CONTAINS(SpecialArgument):
       
  1346 
       
  1347     def matches(self, other):
       
  1348         try:
       
  1349             other.__contains__
       
  1350         except AttributeError:
       
  1351             try:
       
  1352                 iter(other)
       
  1353             except TypeError:
       
  1354                 # If an object can't be iterated, and has no __contains__
       
  1355                 # hook, it'd blow up on the test below.  We test this in
       
  1356                 # advance to prevent catching more errors than we really
       
  1357                 # want.
       
  1358                 return False
       
  1359         return self.object in other
       
  1360 
       
  1361 
       
  1362 class IN(SpecialArgument):
       
  1363 
       
  1364     def matches(self, other):
       
  1365         return other in self.object
       
  1366 
       
  1367 
       
  1368 class MATCH(SpecialArgument):
       
  1369 
       
  1370     def matches(self, other):
       
  1371         return bool(self.object(other))
       
  1372 
       
  1373     def __eq__(self, other):
       
  1374         return type(other) == type(self) and self.object is other.object
       
  1375 
       
  1376 
       
  1377 def match_params(args1, kwargs1, args2, kwargs2):
       
  1378     """Match the two sets of parameters, considering special parameters."""
       
  1379 
       
  1380     has_args = ARGS in args1
       
  1381     has_kwargs = KWARGS in args1
       
  1382 
       
  1383     if has_kwargs:
       
  1384         args1 = [arg1 for arg1 in args1 if arg1 is not KWARGS]
       
  1385     elif len(kwargs1) != len(kwargs2):
       
  1386         return False
       
  1387 
       
  1388     if not has_args and len(args1) != len(args2):
       
  1389         return False
       
  1390 
       
  1391     # Either we have the same number of kwargs, or unknown keywords are
       
  1392     # accepted (KWARGS was used), so check just the ones in kwargs1.
       
  1393     for key, arg1 in kwargs1.iteritems():
       
  1394         if key not in kwargs2:
       
  1395             return False
       
  1396         arg2 = kwargs2[key]
       
  1397         if isinstance(arg1, SpecialArgument):
       
  1398             if not arg1.matches(arg2):
       
  1399                 return False
       
  1400         elif arg1 != arg2:
       
  1401             return False
       
  1402 
       
  1403     # Keywords match.  Now either we have the same number of
       
  1404     # arguments, or ARGS was used.  If ARGS wasn't used, arguments
       
  1405     # must match one-on-one necessarily.
       
  1406     if not has_args:
       
  1407         for arg1, arg2 in zip(args1, args2):
       
  1408             if isinstance(arg1, SpecialArgument):
       
  1409                 if not arg1.matches(arg2):
       
  1410                     return False
       
  1411             elif arg1 != arg2:
       
  1412                 return False
       
  1413         return True
       
  1414 
       
  1415     # Easy choice. Keywords are matching, and anything on args is accepted.
       
  1416     if (ARGS,) == args1:
       
  1417         return True
       
  1418 
       
  1419     # We have something different there. If we don't have positional
       
  1420     # arguments on the original call, it can't match.
       
  1421     if not args2:
       
  1422         # Unless we have just several ARGS (which is bizarre, but..).
       
  1423         for arg1 in args1:
       
  1424             if arg1 is not ARGS:
       
  1425                 return False
       
  1426         return True
       
  1427 
       
  1428     # Ok, all bets are lost.  We have to actually do the more expensive
       
  1429     # matching.  This is an algorithm based on the idea of the Levenshtein
       
  1430     # Distance between two strings, but heavily hacked for this purpose.
       
  1431     args2l = len(args2)
       
  1432     if args1[0] is ARGS:
       
  1433         args1 = args1[1:]
       
  1434         array = [0]*args2l
       
  1435     else:
       
  1436         array = [1]*args2l
       
  1437     for i in range(len(args1)):
       
  1438         last = array[0]
       
  1439         if args1[i] is ARGS:
       
  1440             for j in range(1, args2l):
       
  1441                 last, array[j] = array[j], min(array[j-1], array[j], last)
       
  1442         else:
       
  1443             array[0] = i or int(args1[i] != args2[0])
       
  1444             for j in range(1, args2l):
       
  1445                 last, array[j] = array[j], last or int(args1[i] != args2[j])
       
  1446         if 0 not in array:
       
  1447             return False
       
  1448     if array[-1] != 0:
       
  1449         return False
       
  1450     return True
       
  1451 
       
  1452 
       
  1453 # --------------------------------------------------------------------
       
  1454 # Event and task base.
       
  1455 
       
  1456 class Event(object):
       
  1457     """Aggregation of tasks that keep track of a recorded action.
       
  1458 
       
  1459     An event represents something that may or may not happen while the
       
  1460     mocked environment is running, such as an attribute access, or a
       
  1461     method call.  The event is composed of several tasks that are
       
  1462     orchestrated together to create a composed meaning for the event,
       
  1463     including for which actions it should be run, what happens when it
       
  1464     runs, and what's the expectations about the actions run.
       
  1465     """
       
  1466 
       
  1467     def __init__(self, path=None):
       
  1468         self.path = path
       
  1469         self._tasks = []
       
  1470         self._has_run = False
       
  1471 
       
  1472     def add_task(self, task):
       
  1473         """Add a new task to this taks."""
       
  1474         self._tasks.append(task)
       
  1475         return task
       
  1476 
       
  1477     def remove_task(self, task):
       
  1478         self._tasks.remove(task)
       
  1479 
       
  1480     def get_tasks(self):
       
  1481         return self._tasks[:]
       
  1482 
       
  1483     def matches(self, path):
       
  1484         """Return true if *all* tasks match the given path."""
       
  1485         for task in self._tasks:
       
  1486             if not task.matches(path):
       
  1487                 return False
       
  1488         return bool(self._tasks)
       
  1489 
       
  1490     def has_run(self):
       
  1491         return self._has_run
       
  1492 
       
  1493     def may_run(self, path):
       
  1494         """Verify if any task would certainly raise an error if run.
       
  1495 
       
  1496         This will call the C{may_run()} method on each task and return
       
  1497         false if any of them returns false.
       
  1498         """
       
  1499         for task in self._tasks:
       
  1500             if not task.may_run(path):
       
  1501                 return False
       
  1502         return True
       
  1503 
       
  1504     def run(self, path):
       
  1505         """Run all tasks with the given action.
       
  1506 
       
  1507         @param path: The path of the expression run.
       
  1508 
       
  1509         Running an event means running all of its tasks individually and in
       
  1510         order.  An event should only ever be run if all of its tasks claim to
       
  1511         match the given action.
       
  1512 
       
  1513         The result of this method will be the last result of a task
       
  1514         which isn't None, or None if they're all None.
       
  1515         """
       
  1516         self._has_run = True
       
  1517         result = None
       
  1518         errors = []
       
  1519         for task in self._tasks:
       
  1520             try:
       
  1521                 task_result = task.run(path)
       
  1522             except AssertionError, e:
       
  1523                 error = str(e)
       
  1524                 if not error:
       
  1525                     raise RuntimeError("Empty error message from %r" % task)
       
  1526                 errors.append(error)
       
  1527             else:
       
  1528                 if task_result is not None:
       
  1529                     result = task_result
       
  1530         if errors:
       
  1531             message = [str(self.path)]
       
  1532             if str(path) != message[0]:
       
  1533                 message.append("- Run: %s" % path)
       
  1534             for error in errors:
       
  1535                 lines = error.splitlines()
       
  1536                 message.append("- " + lines.pop(0))
       
  1537                 message.extend(["  " + line for line in lines])
       
  1538             raise AssertionError(os.linesep.join(message))
       
  1539         return result
       
  1540 
       
  1541     def satisfied(self):
       
  1542         """Return true if all tasks are satisfied.
       
  1543 
       
  1544         Being satisfied means that there are no unmet expectations.
       
  1545         """
       
  1546         for task in self._tasks:
       
  1547             try:
       
  1548                 task.verify()
       
  1549             except AssertionError:
       
  1550                 return False
       
  1551         return True
       
  1552 
       
  1553     def verify(self):
       
  1554         """Run verify on all tasks.
       
  1555 
       
  1556         The verify method is supposed to raise an AssertionError if the
       
  1557         task has unmet expectations, with a one-line explanation about
       
  1558         why this item is unmet.  This method should be safe to be called
       
  1559         multiple times without side effects.
       
  1560         """
       
  1561         errors = []
       
  1562         for task in self._tasks:
       
  1563             try:
       
  1564                 task.verify()
       
  1565             except AssertionError, e:
       
  1566                 error = str(e)
       
  1567                 if not error:
       
  1568                     raise RuntimeError("Empty error message from %r" % task)
       
  1569                 errors.append(error)
       
  1570         if errors:
       
  1571             message = [str(self.path)]
       
  1572             for error in errors:
       
  1573                 lines = error.splitlines()
       
  1574                 message.append("- " + lines.pop(0))
       
  1575                 message.extend(["  " + line for line in lines])
       
  1576             raise AssertionError(os.linesep.join(message))
       
  1577 
       
  1578     def replay(self):
       
  1579         """Put all tasks in replay mode."""
       
  1580         self._has_run = False
       
  1581         for task in self._tasks:
       
  1582             task.replay()
       
  1583 
       
  1584     def restore(self):
       
  1585         """Restore the state of all tasks."""
       
  1586         for task in self._tasks:
       
  1587             task.restore()
       
  1588 
       
  1589 
       
  1590 class ReplayRestoreEvent(Event):
       
  1591     """Helper event for tasks which need replay/restore but shouldn't match."""
       
  1592 
       
  1593     def matches(self, path):
       
  1594         return False
       
  1595 
       
  1596 
       
  1597 class Task(object):
       
  1598     """Element used to track one specific aspect on an event.
       
  1599 
       
  1600     A task is responsible for adding any kind of logic to an event.
       
  1601     Examples of that are counting the number of times the event was
       
  1602     made, verifying parameters if any, and so on.
       
  1603     """
       
  1604 
       
  1605     def matches(self, path):
       
  1606         """Return true if the task is supposed to be run for the given path.
       
  1607         """
       
  1608         return True
       
  1609 
       
  1610     def may_run(self, path):
       
  1611         """Return false if running this task would certainly raise an error."""
       
  1612         return True
       
  1613 
       
  1614     def run(self, path):
       
  1615         """Perform the task item, considering that the given action happened.
       
  1616         """
       
  1617 
       
  1618     def verify(self):
       
  1619         """Raise AssertionError if expectations for this item are unmet.
       
  1620 
       
  1621         The verify method is supposed to raise an AssertionError if the
       
  1622         task has unmet expectations, with a one-line explanation about
       
  1623         why this item is unmet.  This method should be safe to be called
       
  1624         multiple times without side effects.
       
  1625         """
       
  1626 
       
  1627     def replay(self):
       
  1628         """Put the task in replay mode.
       
  1629 
       
  1630         Any expectations of the task should be reset.
       
  1631         """
       
  1632 
       
  1633     def restore(self):
       
  1634         """Restore any environmental changes made by the task.
       
  1635 
       
  1636         Verify should continue to work after this is called.
       
  1637         """
       
  1638 
       
  1639 
       
  1640 # --------------------------------------------------------------------
       
  1641 # Task implementations.
       
  1642 
       
  1643 class OnRestoreCaller(Task):
       
  1644     """Call a given callback when restoring."""
       
  1645 
       
  1646     def __init__(self, callback):
       
  1647         self._callback = callback
       
  1648 
       
  1649     def restore(self):
       
  1650         self._callback()
       
  1651 
       
  1652 
       
  1653 class PathMatcher(Task):
       
  1654     """Match the action path against a given path."""
       
  1655 
       
  1656     def __init__(self, path):
       
  1657         self.path = path
       
  1658 
       
  1659     def matches(self, path):
       
  1660         return self.path.matches(path)
       
  1661 
       
  1662 def path_matcher_recorder(mocker, event):
       
  1663     event.add_task(PathMatcher(event.path))
       
  1664 
       
  1665 Mocker.add_recorder(path_matcher_recorder)
       
  1666 
       
  1667 
       
  1668 class RunCounter(Task):
       
  1669     """Task which verifies if the number of runs are within given boundaries.
       
  1670     """
       
  1671 
       
  1672     def __init__(self, min, max=False):
       
  1673         self.min = min
       
  1674         if max is None:
       
  1675             self.max = sys.maxint
       
  1676         elif max is False:
       
  1677             self.max = min
       
  1678         else:
       
  1679             self.max = max
       
  1680         self._runs = 0
       
  1681 
       
  1682     def replay(self):
       
  1683         self._runs = 0
       
  1684 
       
  1685     def may_run(self, path):
       
  1686         return self._runs < self.max
       
  1687 
       
  1688     def run(self, path):
       
  1689         self._runs += 1
       
  1690         if self._runs > self.max:
       
  1691             self.verify()
       
  1692 
       
  1693     def verify(self):
       
  1694         if not self.min <= self._runs <= self.max:
       
  1695             if self._runs < self.min:
       
  1696                 raise AssertionError("Performed fewer times than expected.")
       
  1697             raise AssertionError("Performed more times than expected.")
       
  1698 
       
  1699 
       
  1700 class ImplicitRunCounter(RunCounter):
       
  1701     """RunCounter inserted by default on any event.
       
  1702 
       
  1703     This is a way to differentiate explicitly added counters and
       
  1704     implicit ones.
       
  1705     """
       
  1706 
       
  1707 def run_counter_recorder(mocker, event):
       
  1708     """Any event may be repeated once, unless disabled by default."""
       
  1709     if event.path.root_mock.__mocker_count__:
       
  1710         event.add_task(ImplicitRunCounter(1))
       
  1711 
       
  1712 Mocker.add_recorder(run_counter_recorder)
       
  1713 
       
  1714 def run_counter_removal_recorder(mocker, event):
       
  1715     """
       
  1716     Events created by getattr actions which lead to other events
       
  1717     may be repeated any number of times. For that, we remove implicit
       
  1718     run counters of any getattr actions leading to the current one.
       
  1719     """
       
  1720     parent_path = event.path.parent_path
       
  1721     for event in mocker.get_events()[::-1]:
       
  1722         if (event.path is parent_path and
       
  1723             event.path.actions[-1].kind == "getattr"):
       
  1724             for task in event.get_tasks():
       
  1725                 if type(task) is ImplicitRunCounter:
       
  1726                     event.remove_task(task)
       
  1727 
       
  1728 Mocker.add_recorder(run_counter_removal_recorder)
       
  1729 
       
  1730 
       
  1731 class MockReturner(Task):
       
  1732     """Return a mock based on the action path."""
       
  1733 
       
  1734     def __init__(self, mocker):
       
  1735         self.mocker = mocker
       
  1736 
       
  1737     def run(self, path):
       
  1738         return Mock(self.mocker, path)
       
  1739 
       
  1740 def mock_returner_recorder(mocker, event):
       
  1741     """Events that lead to other events must return mock objects."""
       
  1742     parent_path = event.path.parent_path
       
  1743     for event in mocker.get_events():
       
  1744         if event.path is parent_path:
       
  1745             for task in event.get_tasks():
       
  1746                 if isinstance(task, MockReturner):
       
  1747                     break
       
  1748             else:
       
  1749                 event.add_task(MockReturner(mocker))
       
  1750             break
       
  1751 
       
  1752 Mocker.add_recorder(mock_returner_recorder)
       
  1753 
       
  1754 
       
  1755 class FunctionRunner(Task):
       
  1756     """Task that runs a function everything it's run.
       
  1757 
       
  1758     Arguments of the last action in the path are passed to the function,
       
  1759     and the function result is also returned.
       
  1760     """
       
  1761 
       
  1762     def __init__(self, func):
       
  1763         self._func = func
       
  1764 
       
  1765     def run(self, path):
       
  1766         action = path.actions[-1]
       
  1767         return self._func(*action.args, **action.kwargs)
       
  1768 
       
  1769 
       
  1770 class PathExecuter(Task):
       
  1771     """Task that executes a path in the real object, and returns the result."""
       
  1772 
       
  1773     def __init__(self, result_callback=None):
       
  1774         self._result_callback = result_callback
       
  1775 
       
  1776     def get_result_callback(self):
       
  1777         return self._result_callback
       
  1778 
       
  1779     def run(self, path):
       
  1780         result = path.execute(path.root_object)
       
  1781         if self._result_callback is not None:
       
  1782             self._result_callback(result)
       
  1783         return result
       
  1784 
       
  1785 
       
  1786 class Orderer(Task):
       
  1787     """Task to establish an order relation between two events.
       
  1788 
       
  1789     An orderer task will only match once all its dependencies have
       
  1790     been run.
       
  1791     """
       
  1792 
       
  1793     def __init__(self, path):
       
  1794         self.path = path
       
  1795         self._run = False 
       
  1796         self._dependencies = []
       
  1797 
       
  1798     def replay(self):
       
  1799         self._run = False
       
  1800 
       
  1801     def has_run(self):
       
  1802         return self._run
       
  1803 
       
  1804     def may_run(self, path):
       
  1805         for dependency in self._dependencies:
       
  1806             if not dependency.has_run():
       
  1807                 return False
       
  1808         return True
       
  1809 
       
  1810     def run(self, path):
       
  1811         for dependency in self._dependencies:
       
  1812             if not dependency.has_run():
       
  1813                 raise AssertionError("Should be after: %s" % dependency.path)
       
  1814         self._run = True
       
  1815 
       
  1816     def add_dependency(self, orderer):
       
  1817         self._dependencies.append(orderer)
       
  1818 
       
  1819     def get_dependencies(self):
       
  1820         return self._dependencies
       
  1821 
       
  1822 
       
  1823 class SpecChecker(Task):
       
  1824     """Task to check if arguments of the last action conform to a real method.
       
  1825     """
       
  1826 
       
  1827     def __init__(self, method):
       
  1828         self._method = method
       
  1829         self._unsupported = False
       
  1830 
       
  1831         if method:
       
  1832             try:
       
  1833                 self._args, self._varargs, self._varkwargs, self._defaults = \
       
  1834                     inspect.getargspec(method)
       
  1835             except TypeError:
       
  1836                 self._unsupported = True
       
  1837             else:
       
  1838                 if self._defaults is None:
       
  1839                     self._defaults = ()
       
  1840                 if type(method) is type(self.run):
       
  1841                     self._args = self._args[1:]
       
  1842 
       
  1843     def get_method(self):
       
  1844         return self._method
       
  1845 
       
  1846     def _raise(self, message):
       
  1847         spec = inspect.formatargspec(self._args, self._varargs,
       
  1848                                      self._varkwargs, self._defaults)
       
  1849         raise AssertionError("Specification is %s%s: %s" %
       
  1850                              (self._method.__name__, spec, message))
       
  1851 
       
  1852     def verify(self):
       
  1853         if not self._method:
       
  1854             raise AssertionError("Method not found in real specification")
       
  1855 
       
  1856     def may_run(self, path):
       
  1857         try:
       
  1858             self.run(path)
       
  1859         except AssertionError:
       
  1860             return False
       
  1861         return True
       
  1862 
       
  1863     def run(self, path):
       
  1864         if not self._method:
       
  1865             raise AssertionError("Method not found in real specification")
       
  1866         if self._unsupported:
       
  1867             return # Can't check it. Happens with builtin functions. :-(
       
  1868         action = path.actions[-1]
       
  1869         obtained_len = len(action.args)
       
  1870         obtained_kwargs = action.kwargs.copy()
       
  1871         nodefaults_len = len(self._args) - len(self._defaults)
       
  1872         for i, name in enumerate(self._args):
       
  1873             if i < obtained_len and name in action.kwargs:
       
  1874                 self._raise("%r provided twice" % name)
       
  1875             if (i >= obtained_len and i < nodefaults_len and
       
  1876                 name not in action.kwargs):
       
  1877                 self._raise("%r not provided" % name)
       
  1878             obtained_kwargs.pop(name, None)
       
  1879         if obtained_len > len(self._args) and not self._varargs:
       
  1880             self._raise("too many args provided")
       
  1881         if obtained_kwargs and not self._varkwargs:
       
  1882             self._raise("unknown kwargs: %s" % ", ".join(obtained_kwargs))
       
  1883 
       
  1884 def spec_checker_recorder(mocker, event):
       
  1885     spec = event.path.root_mock.__mocker_spec__
       
  1886     if spec:
       
  1887         actions = event.path.actions
       
  1888         if len(actions) == 1:
       
  1889             if actions[0].kind == "call":
       
  1890                 method = getattr(spec, "__call__", None)
       
  1891                 event.add_task(SpecChecker(method))
       
  1892         elif len(actions) == 2:
       
  1893             if actions[0].kind == "getattr" and actions[1].kind == "call":
       
  1894                 method = getattr(spec, actions[0].args[0], None)
       
  1895                 event.add_task(SpecChecker(method))
       
  1896 
       
  1897 Mocker.add_recorder(spec_checker_recorder)
       
  1898 
       
  1899 
       
  1900 class ProxyReplacer(Task):
       
  1901     """Task which installs and deinstalls proxy mocks.
       
  1902 
       
  1903     This task will replace a real object by a mock in all dictionaries
       
  1904     found in the running interpreter via the garbage collecting system.
       
  1905     """
       
  1906 
       
  1907     def __init__(self, mock):
       
  1908         self.mock = mock
       
  1909         self.__mocker_replace__ = False
       
  1910 
       
  1911     def replay(self):
       
  1912         global_replace(self.mock.__mocker_object__, self.mock)
       
  1913 
       
  1914     def restore(self):
       
  1915         global_replace(self.mock, self.mock.__mocker_object__)
       
  1916 
       
  1917 
       
  1918 def global_replace(remove, install):
       
  1919     """Replace object 'remove' with object 'install' on all dictionaries."""
       
  1920     for referrer in gc.get_referrers(remove):
       
  1921         if (type(referrer) is dict and
       
  1922             referrer.get("__mocker_replace__", True)):
       
  1923             for key, value in referrer.items():
       
  1924                 if value is remove:
       
  1925                     referrer[key] = install
       
  1926 
       
  1927 
       
  1928 class Undefined(object):
       
  1929 
       
  1930     def __repr__(self):
       
  1931         return "Undefined"
       
  1932 
       
  1933 Undefined = Undefined()
       
  1934 
       
  1935 
       
  1936 class Patcher(Task):
       
  1937 
       
  1938     def __init__(self):
       
  1939         super(Patcher, self).__init__()
       
  1940         self._monitored = {} # {kind: {id(object): object}}
       
  1941         self._patched = {}
       
  1942 
       
  1943     def is_monitoring(self, obj, kind):
       
  1944         monitored = self._monitored.get(kind)
       
  1945         if monitored:
       
  1946             if id(obj) in monitored:
       
  1947                 return True
       
  1948             cls = type(obj)
       
  1949             if issubclass(cls, type):
       
  1950                 cls = obj
       
  1951             bases = set([id(base) for base in cls.__mro__])
       
  1952             bases.intersection_update(monitored)
       
  1953             return bool(bases)
       
  1954         return False
       
  1955 
       
  1956     def monitor(self, obj, kind):
       
  1957         if kind not in self._monitored:
       
  1958             self._monitored[kind] = {}
       
  1959         self._monitored[kind][id(obj)] = obj
       
  1960 
       
  1961     def patch_attr(self, obj, attr, value):
       
  1962         original = obj.__dict__.get(attr, Undefined)
       
  1963         self._patched[id(obj), attr] = obj, attr, original
       
  1964         setattr(obj, attr, value)
       
  1965 
       
  1966     def get_unpatched_attr(self, obj, attr):
       
  1967         cls = type(obj)
       
  1968         if issubclass(cls, type):
       
  1969             cls = obj
       
  1970         result = Undefined
       
  1971         for mro_cls in cls.__mro__:
       
  1972             key = (id(mro_cls), attr)
       
  1973             if key in self._patched:
       
  1974                 result = self._patched[key][2]
       
  1975                 if result is not Undefined:
       
  1976                     break
       
  1977             elif attr in mro_cls.__dict__:
       
  1978                 result = mro_cls.__dict__.get(attr, Undefined)
       
  1979                 break
       
  1980         if isinstance(result, object) and hasattr(type(result), "__get__"):
       
  1981             if cls is obj:
       
  1982                 obj = None
       
  1983             return result.__get__(obj, cls)
       
  1984         return result
       
  1985 
       
  1986     def _get_kind_attr(self, kind):
       
  1987         if kind == "getattr":
       
  1988             return "__getattribute__"
       
  1989         return "__%s__" % kind
       
  1990 
       
  1991     def replay(self):
       
  1992         for kind in self._monitored:
       
  1993             attr = self._get_kind_attr(kind)
       
  1994             seen = set()
       
  1995             for obj in self._monitored[kind].itervalues():
       
  1996                 cls = type(obj)
       
  1997                 if issubclass(cls, type):
       
  1998                     cls = obj
       
  1999                 if cls not in seen:
       
  2000                     seen.add(cls)
       
  2001                     unpatched = getattr(cls, attr, Undefined)
       
  2002                     self.patch_attr(cls, attr,
       
  2003                                     PatchedMethod(kind, unpatched,
       
  2004                                                   self.is_monitoring))
       
  2005                     self.patch_attr(cls, "__mocker_execute__",
       
  2006                                     self.execute)
       
  2007 
       
  2008     def restore(self):
       
  2009         for obj, attr, original in self._patched.itervalues():
       
  2010             if original is Undefined:
       
  2011                 delattr(obj, attr)
       
  2012             else:
       
  2013                 setattr(obj, attr, original)
       
  2014         self._patched.clear()
       
  2015 
       
  2016     def execute(self, action, object):
       
  2017         attr = self._get_kind_attr(action.kind)
       
  2018         unpatched = self.get_unpatched_attr(object, attr)
       
  2019         try:
       
  2020             return unpatched(*action.args, **action.kwargs)
       
  2021         except AttributeError:
       
  2022             if action.kind == "getattr":
       
  2023                 # The normal behavior of Python is to try __getattribute__,
       
  2024                 # and if it raises AttributeError, try __getattr__.   We've
       
  2025                 # tried the unpatched __getattribute__ above, and we'll now
       
  2026                 # try __getattr__.
       
  2027                 try:
       
  2028                     __getattr__ = unpatched("__getattr__")
       
  2029                 except AttributeError:
       
  2030                     pass
       
  2031                 else:
       
  2032                     return __getattr__(*action.args, **action.kwargs)
       
  2033             raise
       
  2034 
       
  2035 
       
  2036 class PatchedMethod(object):
       
  2037 
       
  2038     def __init__(self, kind, unpatched, is_monitoring):
       
  2039         self._kind = kind
       
  2040         self._unpatched = unpatched
       
  2041         self._is_monitoring = is_monitoring
       
  2042 
       
  2043     def __get__(self, obj, cls=None):
       
  2044         object = obj or cls
       
  2045         if not self._is_monitoring(object, self._kind):
       
  2046             return self._unpatched.__get__(obj, cls)
       
  2047         def method(*args, **kwargs):
       
  2048             if self._kind == "getattr" and args[0].startswith("__mocker_"):
       
  2049                 return self._unpatched.__get__(obj, cls)(args[0])
       
  2050             mock = object.__mocker_mock__
       
  2051             return mock.__mocker_act__(self._kind, args, kwargs, object)
       
  2052         return method
       
  2053 
       
  2054     def __call__(self, obj, *args, **kwargs):
       
  2055         # At least with __getattribute__, Python seems to use *both* the
       
  2056         # descriptor API and also call the class attribute directly.  It
       
  2057         # looks like an interpreter bug, or at least an undocumented
       
  2058         # inconsistency.
       
  2059         return self.__get__(obj)(*args, **kwargs)
       
  2060 
       
  2061 
       
  2062 def patcher_recorder(mocker, event):
       
  2063     mock = event.path.root_mock
       
  2064     if mock.__mocker_patcher__ and len(event.path.actions) == 1:
       
  2065         patcher = mock.__mocker_patcher__
       
  2066         patcher.monitor(mock.__mocker_object__, event.path.actions[0].kind)
       
  2067 
       
  2068 Mocker.add_recorder(patcher_recorder)