Transaction Context¶
TransactionContext()
is a core building block in lato
. It’s main purpose is to inject dependencies into a handler function.
When TransactionContext
is calling a function using call method, it will inspect all its arguments and
it will try to inject all matching dependencies into it. This greatly simplifies testing.
You can instantiate TransactionContext()
with any args and kwargs. These arguments will be injected to a handler
during a call. Any arguments passed to TransactionContext.call
that match the function
signature will be passed to the called function, and will replace the ones passed in the constructor.
from lato import TransactionContext
def greet(name, greeting):
return f"{greeting}, {name}!"
ctx = TransactionContext()
result = ctx.call(greet, greeting="Hello", name="Alice")
assert result == "Hello, Alice!"
As you can see, greeting
and name
arguments in TransactionContext.call()
are actually passed to the greet
function.
You can use both keyword and positional arguments:
ctx.call(greet, "Alice", "Hello")
ctx.call(greet, "Alice", greeting="Hello")
Instead of passing passing dependencies to TransactionContext.call()
, it’s often more convenient to pass them to TransactionContext
constructor:
from lato import TransactionContext
def greet(name, greeting):
return f"{greeting}, {name}!"
ctx = TransactionContext(greeting="Hola")
print(ctx.call(greet, "Bob"))
print(ctx.call(greet, "Charlie"))
Note
Any arguments passed to TransactionContext.call()
will override arguments passed to the TransactionContext constructor.
class FooService:
...
def do_something(foo_service):
...
def do_something_else(service: FooService):
...
ctx = TransactionContext(foo_service=FooService())
ctx.call(do_something) # will inject an instance of FooService using name `foo_service`
ctx.call(do_something_else) # will inject an instance of FooService using type `FooService`
TransactionContext
is also a context manager, so you can use it with with
statement:
from lato import TransactionContext
def greet(name, greeting):
return f"{greeting}, {name}!"
with TransactionContext(greeting="Hola") as ctx:
print(ctx.call(greet, "Bob"))
print(ctx.call(greet, "Charlie"))
It is rarely needed to instantiate transaction context directly. In most cases, it is sufficient to call
any of the Application methods: call()
,
execute()
, or publish()
, which creates the transaction context under the
hood.