Attributes
Now the fun begins.
The injected
field uses metadata to give more instructions to the DI system.
Let’s put that to work to decrease the surface area between the dataclass and the system by getting just what we need off of Customer
.
We’ll change 4 lines in models.py
and nothing else:
# models.py
from dataclasses import dataclass
from wired.dataclasses import Context, factory, injected
@factory()
@dataclass
class Settings:
"""Store some configuration settings for the app"""
punctuation: str = '.'
@dataclass
class Customer:
"""A basic customer"""
name: str = 'Larry'
@dataclass
class FrenchCustomer:
"""A certain kind of customer"""
name: str = 'Anne'
@factory(context=Customer)
@dataclass
class Greeter:
"""A basic greeter"""
settings: Settings
customer_name: str = injected(Context, attr='name')
name: str = 'Mary'
def __call__(self):
punctuation = self.settings.punctuation
m = f'my name is {self.name}{punctuation}'
return f'Hello {self.customer_name} {m}'
@factory(for_=Greeter, context=FrenchCustomer)
@dataclass
class FrenchGreeter:
"""A greeter to use when the customer (context) is French"""
settings: Settings
customer_name: str = injected(Context, attr='name')
name: str = 'Henri'
def __call__(self):
punctuation = self.settings.punctuation
m = f'je m\'apelle {self.name}{punctuation}'
return f'Salut {self.customer_name} {m}'
Instead of storing the Customer
and later getting the customer’s name, we use attr
to get just the name
off the Context
.
The dataclass then has customer_name: str
as its constructed field, which is the only thing needed in the “template”.
Smaller surface are against the outside world.
Here is what wired.dataclasses
actually does behind the scenes:
from dataclasses import field
@factory()
@dataclass
class Greeter:
customer_name: str = field(metadata=dict(injected=dict(type_=Context, attr='name')))
Using injected
with an argument is easier on the eyes.
The injected
field uses the metadata
support in dataclass fields to make a custom protocol, giving special instructions to the DI system on how to construct the dataclass.
Note
attr
isn’t the only argument you can add to injected
. key=
also works for dictionary access.