Getting Started =============== The basic workhorse function of the :mod:`stub` library is :func:`stub.stub` Stubbing Callables ------------------- The basic syntax for stubbing function behaviour is:: >>> from stub import stub >>> target = lambda: 5 # This can be any callable object >>> repl = lambda: 6 # This can also be any callable object >>> f = stub(target, repl) >>> target() # The target object now has the behaviour of the replacement object 6 Where :obj:`target` and :obj:`repl` are any `callable` objects. This function actually modifies the code of :obj:`target` in place, so all imports in other libraries automagically get the newest version of the stubbed-out behaviour. Stubbing a bound function ''''''''''''''''''''''''''' To stub out a bound function, call :func:`stub.stub` with the target and a replacement function:: >>> from stub import stub >>> class A: ... def f(self): ... return 5 ... >>> repl = lambda x: 6 >>> a = A() >>> a.f() 5 >>> f = stub(a.f, repl) >>> a.f() 6 The :func:`stub.stub` function delegates to :func:`stub.stub_bound_function` when the :obj:`target` object is a bound function. .. autofunction:: stub.stub_bound_function :noindex: Stubbing unbound functions ''''''''''''''''''''''''''''' To stub an unbound function, call :func:`stub.stub(f, repl)` where `f` is the function to stub and `repl` is the function with which to replace it. >>> def f(x): ... return x + 1 ... >>> import stub >>> def f_replacement(x): ... return x + 2 ... >>> f(5) 6 >>> x = stub.stub(f, f_replacement) >>> f(5) 7 The :func:`stub.stub` function delegates to :func:`stub.stub_unbound_function` when the :obj:`target` object is an unbound function. .. autofunction:: stub.stub_unbound_function :noindex: Stubbing Attribute Values ------------------------- To stub out attribute values call :func:`stub.stub` with new attribute values as keyword-arguments:: >>> from stub import stub >>> class A(object): ... def __init__(self): ... self.x = 5 ... >>> a = A() >>> a.x 5 >>> x = stub(a, x=10) >>> a.x 10 The :func:`stub.stub` function delegates to :func:`stub.stub_attributes` when called with keyword-arguments. .. autofunction:: stub.stub_attributes :noindex: Unstubbing ------------- Once an attribute value or callable behaviour has been stubbed out, it can be useful to access the previous value or behaviour. The unstubbed behaviour of a stubbed function :obj:`f` can be accessed calling the :func:`f.unstubbed` function:: >>> from stub import stub >>> f = lambda: 5 >>> repl = lambda: 7 >>> x = stub(f, repl) >>> f() 7 >>> f.unstubbed() 5 The unstubbed value of a stubbed attribute :obj:`x` on an object :obj:`obj` can be accessed by calling :func:`obj.x.unstubbed()`:: >>> from stub import stub >>> class A(object): ... def __init__(self): ... self.x = 5 ... >>> a = A() >>> a.x 5 >>> x = stub(a, x=7) >>> a.x 7 >>> a.x.unstubbed() 5 To unstub a stubbed-out callable, :obj:`target`, call :func:`target.unstub`:: >>> from stub import stub >>> target = lambda: 5 >>> repl = lambda: 7 >>> x = stub(target, repl) >>> target() 7 >>> target.unstub() >>> target() 5 To unstub an individual attribute :obj:`x` on an object, :obj:`target`, call :func:`obj.x.unstub`:: >>> from stub import stub >>> class A(object): ... def __init__(self): ... self.x = 5 ... >>> a = A() >>> x = stub(a, x=7) >>> a.x 7 >>> a.x.unstub() >>> a.x 5 To unstub all stubbed-out attributes on an object, :obj:`target`, call :func:`obj.unstub`:: >>> from stub import stub >>> class A(object): ... def __init__(self): ... self.x = 5 ... self.y = 7 ... >>> a = A() >>> stub(a, x=7, y=10) >>> a.x, a.y (7, 10) >>> a.unstub() >>> a.x, a.y (5, 7) To unstub **all** stubbed-out functions and attributes, call :func:`stub.unstub_all` >>> from stub import stub, unstub_all >>> # Setup some base objects to stub >>> class A(object): ... def __init__(self): ... self.x = 5 ... self.y = 7 ... >>> a = A() >>> target = lambda: 5 >>> repl = lambda: 7 >>> # Stub out callable behaviour and object attributes >>> stub(a, x=7, y=10) >>> x = stub(target, repl) >>> a.x, a.y, target() # Check that stubbing worked (7, 10, 7) >>> unstub_all() # Unstub everything >>> a.x, a.y, target() # Check that unstubbing worked (5, 7, 5) .. warning:: The :func:`stub.unstub_all` function will affect **all** stubbed-out functions, methods and attributes **everywhere** in your current runtime. It is important also to **never** fiddle with :obj:`stub._stubbed_callables` and :obj:`stub._modified_objects` since these collections track stubbed-out objects.